From 87a93a5670dde2dc0087e275912be07c9310865f Mon Sep 17 00:00:00 2001 From: Lynne Date: Sat, 16 Mar 2024 04:17:30 +0100 Subject: [PATCH] aacdec: split off channel coupling into a new file --- libavcodec/aac/aacdec_dsp_template.c | 3 + libavcodec/aac/aacdec_fixed.c | 12 +++ libavcodec/aac/aacdec_fixed_coupling.h | 137 +++++++++++++++++++++++++ libavcodec/aac/aacdec_float.c | 1 + libavcodec/aac/aacdec_float_coupling.h | 90 ++++++++++++++++ libavcodec/aacdec.c | 53 ---------- libavcodec/aacdec.h | 7 ++ libavcodec/aacdec_fixed.c | 112 -------------------- libavcodec/aacdec_template.c | 6 +- 9 files changed, 253 insertions(+), 168 deletions(-) create mode 100644 libavcodec/aac/aacdec_fixed_coupling.h create mode 100644 libavcodec/aac/aacdec_float_coupling.h diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c index a04d358883..a72ccf891c 100644 --- a/libavcodec/aac/aacdec_dsp_template.c +++ b/libavcodec/aac/aacdec_dsp_template.c @@ -568,4 +568,7 @@ const AACDecDSP AAC_RENAME(aac_dsp) = { .imdct_and_windowing_960 = AAC_RENAME(imdct_and_windowing_960), .imdct_and_windowing_ld = AAC_RENAME(imdct_and_windowing_ld), .imdct_and_windowing_eld = AAC_RENAME(imdct_and_windowing_eld), + + .apply_dependent_coupling = AAC_RENAME(apply_dependent_coupling), + .apply_independent_coupling = AAC_RENAME(apply_independent_coupling), }; diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c index 08e9c3a03f..dc3e8eaab6 100644 --- a/libavcodec/aac/aacdec_fixed.c +++ b/libavcodec/aac/aacdec_fixed.c @@ -64,8 +64,20 @@ static void init_tables_fixed(void) ff_thread_once(&init_fixed_once, init_tables_fixed_fn); } +static const int cce_scale_fixed[8] = { + Q30(1.0), //2^(0/8) + Q30(1.0905077327), //2^(1/8) + Q30(1.1892071150), //2^(2/8) + Q30(1.2968395547), //2^(3/8) + Q30(1.4142135624), //2^(4/8) + Q30(1.5422108254), //2^(5/8) + Q30(1.6817928305), //2^(6/8) + Q30(1.8340080864), //2^(7/8) +}; + /** Dequantization-related */ #include "aacdec_fixed_dequant.h" +#include "aacdec_fixed_coupling.h" #include "aacdec_dsp_template.c" #include "aacdec_proc_template.c" diff --git a/libavcodec/aac/aacdec_fixed_coupling.h b/libavcodec/aac/aacdec_fixed_coupling.h new file mode 100644 index 0000000000..b6a54b35bd --- /dev/null +++ b/libavcodec/aac/aacdec_fixed_coupling.h @@ -0,0 +1,137 @@ +/* + * AAC decoder + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * Copyright (c) 2008-2013 Alex Converse + * + * AAC LATM decoder + * Copyright (c) 2008-2010 Paul Kendall + * Copyright (c) 2010 Janne Grunau + * + * AAC decoder fixed-point implementation + * Copyright (c) 2013 + * MIPS Technologies, Inc., California. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AAC_AACDEC_FIXED_COUPLING_H +#define AVCODEC_AAC_AACDEC_FIXED_COUPLING_H + +#include "libavcodec/aacdec.h" + +/** + * Apply dependent channel coupling (applied before IMDCT). + * + * @param index index into coupling gain array + */ +static void AAC_RENAME(apply_dependent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + IndividualChannelStream *ics = &cce->ch[0].ics; + const uint16_t *offsets = ics->swb_offset; + int *dest = target->coeffs_fixed; + const int *src = cce->ch[0].coeffs_fixed; + int g, i, group, k, idx = 0; + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { + av_log(ac->avctx, AV_LOG_ERROR, + "Dependent coupling is not supported together with LTP\n"); + return; + } + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb; i++, idx++) { + if (cce->ch[0].band_type[idx] != ZERO_BT) { + const int gain = cce->coup.gain[index][idx]; + int shift, round, c, tmp; + + if (gain < 0) { + c = -cce_scale_fixed[-gain & 7]; + shift = (-gain-1024) >> 3; + } + else { + c = cce_scale_fixed[gain & 7]; + shift = (gain-1024) >> 3; + } + + if (shift < -31) { + // Nothing to do + } else if (shift < 0) { + shift = -shift; + round = 1 << (shift - 1); + + for (group = 0; group < ics->group_len[g]; group++) { + for (k = offsets[i]; k < offsets[i + 1]; k++) { + tmp = (int)(((int64_t)src[group * 128 + k] * c + \ + (int64_t)0x1000000000) >> 37); + dest[group * 128 + k] += (tmp + (int64_t)round) >> shift; + } + } + } + else { + for (group = 0; group < ics->group_len[g]; group++) { + for (k = offsets[i]; k < offsets[i + 1]; k++) { + tmp = (int)(((int64_t)src[group * 128 + k] * c + \ + (int64_t)0x1000000000) >> 37); + dest[group * 128 + k] += tmp * (1U << shift); + } + } + } + } + } + dest += ics->group_len[g] * 128; + src += ics->group_len[g] * 128; + } +} + +/** + * Apply independent channel coupling (applied after IMDCT). + * + * @param index index into coupling gain array + */ +static void AAC_RENAME(apply_independent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + int i, c, shift, round, tmp; + const int gain = cce->coup.gain[index][0]; + const int *src = cce->ch[0].output_fixed; + unsigned int *dest = target->output_fixed; + const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); + + c = cce_scale_fixed[gain & 7]; + shift = (gain-1024) >> 3; + if (shift < -31) { + return; + } else if (shift < 0) { + shift = -shift; + round = 1 << (shift - 1); + + for (i = 0; i < len; i++) { + tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37); + dest[i] += (tmp + round) >> shift; + } + } + else { + for (i = 0; i < len; i++) { + tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37); + dest[i] += tmp * (1U << shift); + } + } +} + +#endif /* AVCODEC_AAC_AACDEC_FIXED_COUPLING_H */ diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c index d1cc5ce929..865a57deb1 100644 --- a/libavcodec/aac/aacdec_float.c +++ b/libavcodec/aac/aacdec_float.c @@ -138,5 +138,6 @@ static inline float *VMUL4S(float *dst, const float *v, unsigned idx, } #endif +#include "aacdec_float_coupling.h" #include "aacdec_dsp_template.c" #include "aacdec_proc_template.c" diff --git a/libavcodec/aac/aacdec_float_coupling.h b/libavcodec/aac/aacdec_float_coupling.h new file mode 100644 index 0000000000..475d987a66 --- /dev/null +++ b/libavcodec/aac/aacdec_float_coupling.h @@ -0,0 +1,90 @@ +/* + * AAC decoder + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * Copyright (c) 2008-2013 Alex Converse + * + * AAC LATM decoder + * Copyright (c) 2008-2010 Paul Kendall + * Copyright (c) 2010 Janne Grunau + * + * AAC decoder fixed-point implementation + * Copyright (c) 2013 + * MIPS Technologies, Inc., California. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AAC_AACDEC_FLOAT_COUPLING_H +#define AVCODEC_AAC_AACDEC_FLOAT_COUPLING_H + +#include "libavcodec/aacdec.h" + +/** + * Apply dependent channel coupling (applied before IMDCT). + * + * @param index index into coupling gain array + */ +static void AAC_RENAME(apply_dependent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + IndividualChannelStream *ics = &cce->ch[0].ics; + const uint16_t *offsets = ics->swb_offset; + float *dest = target->coeffs; + const float *src = cce->ch[0].coeffs; + int g, i, group, k, idx = 0; + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { + av_log(ac->avctx, AV_LOG_ERROR, + "Dependent coupling is not supported together with LTP\n"); + return; + } + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb; i++, idx++) { + if (cce->ch[0].band_type[idx] != ZERO_BT) { + const float gain = cce->coup.gain[index][idx]; + for (group = 0; group < ics->group_len[g]; group++) { + for (k = offsets[i]; k < offsets[i + 1]; k++) { + // FIXME: SIMDify + dest[group * 128 + k] += gain * src[group * 128 + k]; + } + } + } + } + dest += ics->group_len[g] * 128; + src += ics->group_len[g] * 128; + } +} + +/** + * Apply independent channel coupling (applied after IMDCT). + * + * @param index index into coupling gain array + */ +static void AAC_RENAME(apply_independent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + const float gain = cce->coup.gain[index][0]; + const float *src = cce->ch[0].output; + float *dest = target->output; + const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); + + ac->fdsp->vector_fmac_scalar(dest, src, gain, len); +} + +#endif /* AVCODEC_AAC_AACDEC_FLOAT_COUPLING_H */ diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 13d53c6cfc..d269b93564 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -128,59 +128,6 @@ static av_always_inline void predict(PredictorState *ps, float *coef, ps->r0 = flt16_trunc(a * e0); } -/** - * Apply dependent channel coupling (applied before IMDCT). - * - * @param index index into coupling gain array - */ -static void apply_dependent_coupling(AACDecContext *ac, - SingleChannelElement *target, - ChannelElement *cce, int index) -{ - IndividualChannelStream *ics = &cce->ch[0].ics; - const uint16_t *offsets = ics->swb_offset; - float *dest = target->coeffs; - const float *src = cce->ch[0].coeffs; - int g, i, group, k, idx = 0; - if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { - av_log(ac->avctx, AV_LOG_ERROR, - "Dependent coupling is not supported together with LTP\n"); - return; - } - for (g = 0; g < ics->num_window_groups; g++) { - for (i = 0; i < ics->max_sfb; i++, idx++) { - if (cce->ch[0].band_type[idx] != ZERO_BT) { - const float gain = cce->coup.gain[index][idx]; - for (group = 0; group < ics->group_len[g]; group++) { - for (k = offsets[i]; k < offsets[i + 1]; k++) { - // FIXME: SIMDify - dest[group * 128 + k] += gain * src[group * 128 + k]; - } - } - } - } - dest += ics->group_len[g] * 128; - src += ics->group_len[g] * 128; - } -} - -/** - * Apply independent channel coupling (applied after IMDCT). - * - * @param index index into coupling gain array - */ -static void apply_independent_coupling(AACDecContext *ac, - SingleChannelElement *target, - ChannelElement *cce, int index) -{ - const float gain = cce->coup.gain[index][0]; - const float *src = cce->ch[0].output; - float *dest = target->output; - const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); - - ac->fdsp->vector_fmac_scalar(dest, src, gain, len); -} - #include "aacdec_template.c" #define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h index 811beb77f2..91ffb877da 100644 --- a/libavcodec/aacdec.h +++ b/libavcodec/aacdec.h @@ -228,6 +228,13 @@ typedef struct AACDecDSP { void (*apply_ltp)(AACDecContext *ac, SingleChannelElement *sce); void (*update_ltp)(AACDecContext *ac, SingleChannelElement *sce); + void (*apply_dependent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index); + void (*apply_independent_coupling)(AACDecContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index); + void (*imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce); void (*imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce); void (*imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce); diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index f1eb072103..03b39854f8 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -245,118 +245,6 @@ static av_always_inline void predict(PredictorState *ps, int *coef, ps->r0 = flt16_trunc(av_mul_sf(a, e0)); } - -static const int cce_scale_fixed[8] = { - Q30(1.0), //2^(0/8) - Q30(1.0905077327), //2^(1/8) - Q30(1.1892071150), //2^(2/8) - Q30(1.2968395547), //2^(3/8) - Q30(1.4142135624), //2^(4/8) - Q30(1.5422108254), //2^(5/8) - Q30(1.6817928305), //2^(6/8) - Q30(1.8340080864), //2^(7/8) -}; - -/** - * Apply dependent channel coupling (applied before IMDCT). - * - * @param index index into coupling gain array - */ -static void apply_dependent_coupling_fixed(AACDecContext *ac, - SingleChannelElement *target, - ChannelElement *cce, int index) -{ - IndividualChannelStream *ics = &cce->ch[0].ics; - const uint16_t *offsets = ics->swb_offset; - int *dest = target->coeffs_fixed; - const int *src = cce->ch[0].coeffs_fixed; - int g, i, group, k, idx = 0; - if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { - av_log(ac->avctx, AV_LOG_ERROR, - "Dependent coupling is not supported together with LTP\n"); - return; - } - for (g = 0; g < ics->num_window_groups; g++) { - for (i = 0; i < ics->max_sfb; i++, idx++) { - if (cce->ch[0].band_type[idx] != ZERO_BT) { - const int gain = cce->coup.gain[index][idx]; - int shift, round, c, tmp; - - if (gain < 0) { - c = -cce_scale_fixed[-gain & 7]; - shift = (-gain-1024) >> 3; - } - else { - c = cce_scale_fixed[gain & 7]; - shift = (gain-1024) >> 3; - } - - if (shift < -31) { - // Nothing to do - } else if (shift < 0) { - shift = -shift; - round = 1 << (shift - 1); - - for (group = 0; group < ics->group_len[g]; group++) { - for (k = offsets[i]; k < offsets[i + 1]; k++) { - tmp = (int)(((int64_t)src[group * 128 + k] * c + \ - (int64_t)0x1000000000) >> 37); - dest[group * 128 + k] += (tmp + (int64_t)round) >> shift; - } - } - } - else { - for (group = 0; group < ics->group_len[g]; group++) { - for (k = offsets[i]; k < offsets[i + 1]; k++) { - tmp = (int)(((int64_t)src[group * 128 + k] * c + \ - (int64_t)0x1000000000) >> 37); - dest[group * 128 + k] += tmp * (1U << shift); - } - } - } - } - } - dest += ics->group_len[g] * 128; - src += ics->group_len[g] * 128; - } -} - -/** - * Apply independent channel coupling (applied after IMDCT). - * - * @param index index into coupling gain array - */ -static void apply_independent_coupling_fixed(AACDecContext *ac, - SingleChannelElement *target, - ChannelElement *cce, int index) -{ - int i, c, shift, round, tmp; - const int gain = cce->coup.gain[index][0]; - const int *src = cce->ch[0].output_fixed; - unsigned int *dest = target->output_fixed; - const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); - - c = cce_scale_fixed[gain & 7]; - shift = (gain-1024) >> 3; - if (shift < -31) { - return; - } else if (shift < 0) { - shift = -shift; - round = 1 << (shift - 1); - - for (i = 0; i < len; i++) { - tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37); - dest[i] += (tmp + round) >> shift; - } - } - else { - for (i = 0; i < len; i++) { - tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37); - dest[i] += tmp * (1U << shift); - } - } -} - #include "aacdec_template.c" const FFCodec ff_aac_fixed_decoder = { diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index c3ab1ed4c6..3c77b41694 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -2095,7 +2095,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples) ChannelElement *che = ac->che[type][i]; if (che && che->present) { if (type <= TYPE_CPE) - apply_channel_coupling(ac, che, type, i, BEFORE_TNS, AAC_RENAME(apply_dependent_coupling)); + apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling); if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { if (che->ch[0].ics.predictor_present) { if (che->ch[0].ics.ltp.present) @@ -2111,7 +2111,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples) ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs), &che->ch[1].tns, &che->ch[1].ics, 1); if (type <= TYPE_CPE) - apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, AAC_RENAME(apply_dependent_coupling)); + apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling); if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) { imdct_and_window(ac, &che->ch[0]); if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) @@ -2128,7 +2128,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples) } } if (type <= TYPE_CCE) - apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, AAC_RENAME(apply_independent_coupling)); + apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling); #if USE_FIXED {