2024-03-13 22:53:49 +02:00
|
|
|
/*
|
|
|
|
* 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 <alex.converse@gmail.com>
|
|
|
|
*
|
|
|
|
* AAC LATM decoder
|
|
|
|
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
|
|
|
|
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2024-03-19 21:19:06 +02:00
|
|
|
#include "aacdec.h"
|
2024-03-13 23:20:59 +02:00
|
|
|
#include "libavcodec/lpc_functions.h"
|
2024-03-13 22:53:49 +02:00
|
|
|
|
|
|
|
#include "libavcodec/aactab.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert integer scalefactors to the decoder's native expected
|
|
|
|
* scalefactor values.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(dequant_scalefactors)(SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
const int *sfo = sce->sfo;
|
|
|
|
INTFLOAT *sf = sce->AAC_RENAME(sf);
|
|
|
|
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
int idx = 0;
|
|
|
|
for (int g = 0; g < ics->num_window_groups; g++) {
|
|
|
|
for (int sfb = 0; sfb < ics->max_sfb; sfb++, idx++) {
|
|
|
|
switch (sce->band_type[g*ics->max_sfb + sfb]) {
|
2024-03-13 22:53:49 +02:00
|
|
|
case ZERO_BT:
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = FIXR(0.);
|
2024-03-13 22:53:49 +02:00
|
|
|
break;
|
|
|
|
case INTENSITY_BT: /* fallthrough */
|
|
|
|
case INTENSITY_BT2:
|
|
|
|
#if USE_FIXED
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = 100 - (sfo[idx] + 100);
|
2024-03-13 22:53:49 +02:00
|
|
|
#else
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = ff_aac_pow2sf_tab[-sfo[idx] - 100 + POW_SF2_ZERO];
|
2024-03-13 22:53:49 +02:00
|
|
|
#endif /* USE_FIXED */
|
|
|
|
break;
|
|
|
|
case NOISE_BT:
|
|
|
|
#if USE_FIXED
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = -(100 + sfo[idx]);
|
2024-03-13 22:53:49 +02:00
|
|
|
#else
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
|
2024-03-13 22:53:49 +02:00
|
|
|
#endif /* USE_FIXED */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
#if USE_FIXED
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = -sfo[idx] - 100;
|
2024-03-13 22:53:49 +02:00
|
|
|
#else
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
|
2024-03-13 22:53:49 +02:00
|
|
|
#endif /* USE_FIXED */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 22:59:35 +02:00
|
|
|
/**
|
|
|
|
* Mid/Side stereo decoding; reference: 4.6.8.1.3.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe)
|
|
|
|
{
|
|
|
|
const IndividualChannelStream *ics = &cpe->ch[0].ics;
|
|
|
|
INTFLOAT *ch0 = cpe->ch[0].AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *ch1 = cpe->ch[1].AAC_RENAME(coeffs);
|
|
|
|
const uint16_t *offsets = ics->swb_offset;
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
for (int g = 0; g < ics->num_window_groups; g++) {
|
2024-05-16 11:36:12 +02:00
|
|
|
for (int sfb = 0; sfb < cpe->max_sfb_ste; sfb++) {
|
|
|
|
const int idx = g*cpe->max_sfb_ste + sfb;
|
2024-03-13 22:59:35 +02:00
|
|
|
if (cpe->ms_mask[idx] &&
|
|
|
|
cpe->ch[0].band_type[idx] < NOISE_BT &&
|
|
|
|
cpe->ch[1].band_type[idx] < NOISE_BT) {
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
for (int group = 0; group < ics->group_len[g]; group++)
|
2024-03-13 22:59:35 +02:00
|
|
|
#if USE_FIXED
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
ac->fdsp->butterflies_fixed(ch0 + group * 128 + offsets[sfb],
|
|
|
|
ch1 + group * 128 + offsets[sfb],
|
|
|
|
offsets[sfb+1] - offsets[sfb]);
|
2024-03-13 22:59:35 +02:00
|
|
|
#else
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
ac->fdsp->butterflies_float(ch0 + group * 128 + offsets[sfb],
|
|
|
|
ch1 + group * 128 + offsets[sfb],
|
|
|
|
offsets[sfb+1] - offsets[sfb]);
|
2024-03-13 22:59:35 +02:00
|
|
|
#endif /* USE_FIXED */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ch0 += ics->group_len[g] * 128;
|
|
|
|
ch1 += ics->group_len[g] * 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 23:01:44 +02:00
|
|
|
/**
|
|
|
|
* intensity stereo decoding; reference: 4.6.8.2.3
|
|
|
|
*
|
|
|
|
* @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
|
|
|
|
* [1] mask is decoded from bitstream; [2] mask is all 1s;
|
|
|
|
* [3] reserved for scalable AAC
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(apply_intensity_stereo)(AACDecContext *ac,
|
|
|
|
ChannelElement *cpe, int ms_present)
|
|
|
|
{
|
|
|
|
const IndividualChannelStream *ics = &cpe->ch[1].ics;
|
|
|
|
SingleChannelElement *sce1 = &cpe->ch[1];
|
|
|
|
INTFLOAT *coef0 = cpe->ch[0].AAC_RENAME(coeffs), *coef1 = cpe->ch[1].AAC_RENAME(coeffs);
|
|
|
|
const uint16_t *offsets = ics->swb_offset;
|
|
|
|
int c;
|
|
|
|
INTFLOAT scale;
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
for (int g = 0; g < ics->num_window_groups; g++) {
|
|
|
|
for (int sfb = 0; sfb < ics->max_sfb; sfb++) {
|
|
|
|
const int idx = g*ics->max_sfb + sfb;
|
2024-03-13 23:01:44 +02:00
|
|
|
if (sce1->band_type[idx] == INTENSITY_BT ||
|
|
|
|
sce1->band_type[idx] == INTENSITY_BT2) {
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
c = -1 + 2 * (sce1->band_type[idx] - 14);
|
|
|
|
if (ms_present)
|
|
|
|
c *= 1 - 2 * cpe->ms_mask[idx];
|
|
|
|
scale = c * sce1->AAC_RENAME(sf)[idx];
|
|
|
|
for (int group = 0; group < ics->group_len[g]; group++)
|
2024-03-13 23:01:44 +02:00
|
|
|
#if USE_FIXED
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
subband_scale(coef1 + group * 128 + offsets[sfb],
|
|
|
|
coef0 + group * 128 + offsets[sfb],
|
|
|
|
scale,
|
|
|
|
23,
|
|
|
|
offsets[sfb + 1] - offsets[sfb], ac->avctx);
|
2024-03-13 23:01:44 +02:00
|
|
|
#else
|
aacdec: move from scalefactor ranged arrays to flat arrays
AAC uses an unconventional system to send scalefactors
(the volume+quantization value for each band).
Each window is split into either 1 or 8 blocks (long vs short),
and transformed separately from one another, with the coefficients
for each being also completely independent. The scalefactors
slightly increase from 64 (long) to 128 (short) to accomodate
better per-block-per-band volume for each window.
To reduce overhead, the codec signals scalefactor sizes in an obtuse way,
where each group's scalefactor types are sent via a variable length decoding,
with a range.
But our decoder was written in a way where those ranges were carried through
the entire decoder, and to actually read them you had to use the range.
Instead of having a dedicated array with a range for each scalefactor,
just let the decoder directly index each scalefactor.
This also switches the form of quantized scalefactors to the format
the spec uses, where for intensity stereo and regular, scalefactors
are stored in a scalefactor - 100 form, rather than as-is.
USAC gets rid of the complex scalefactor handling. This commit permits
for code sharing between both.
2024-05-14 19:07:43 +02:00
|
|
|
ac->fdsp->vector_fmul_scalar(coef1 + group * 128 + offsets[sfb],
|
|
|
|
coef0 + group * 128 + offsets[sfb],
|
|
|
|
scale,
|
|
|
|
offsets[sfb + 1] - offsets[sfb]);
|
2024-03-13 23:01:44 +02:00
|
|
|
#endif /* USE_FIXED */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
coef0 += ics->group_len[g] * 128;
|
|
|
|
coef1 += ics->group_len[g] * 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 23:20:59 +02:00
|
|
|
/**
|
|
|
|
* Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3.
|
|
|
|
*
|
|
|
|
* @param decode 1 if tool is used normally, 0 if tool is used in LTP.
|
|
|
|
* @param coef spectral coefficients
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
|
|
|
|
IndividualChannelStream *ics, int decode)
|
|
|
|
{
|
|
|
|
const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
|
|
|
|
int w, filt, m, i;
|
|
|
|
int bottom, top, order, start, end, size, inc;
|
|
|
|
INTFLOAT *coef_param = _coef_param;
|
|
|
|
INTFLOAT lpc[TNS_MAX_ORDER];
|
|
|
|
INTFLOAT tmp[TNS_MAX_ORDER+1];
|
|
|
|
UINTFLOAT *coef = coef_param;
|
|
|
|
|
|
|
|
if(!mmm)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (w = 0; w < ics->num_windows; w++) {
|
|
|
|
bottom = ics->num_swb;
|
|
|
|
for (filt = 0; filt < tns->n_filt[w]; filt++) {
|
|
|
|
top = bottom;
|
|
|
|
bottom = FFMAX(0, top - tns->length[w][filt]);
|
|
|
|
order = tns->order[w][filt];
|
|
|
|
if (order == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// tns_decode_coef
|
|
|
|
compute_lpc_coefs(tns->AAC_RENAME(coef)[w][filt], order, lpc, 0, 0, 0);
|
|
|
|
|
|
|
|
start = ics->swb_offset[FFMIN(bottom, mmm)];
|
|
|
|
end = ics->swb_offset[FFMIN( top, mmm)];
|
|
|
|
if ((size = end - start) <= 0)
|
|
|
|
continue;
|
|
|
|
if (tns->direction[w][filt]) {
|
|
|
|
inc = -1;
|
|
|
|
start = end - 1;
|
|
|
|
} else {
|
|
|
|
inc = 1;
|
|
|
|
}
|
|
|
|
start += w * 128;
|
|
|
|
|
|
|
|
if (decode) {
|
|
|
|
// ar filter
|
|
|
|
for (m = 0; m < size; m++, start += inc)
|
|
|
|
for (i = 1; i <= FFMIN(m, order); i++)
|
|
|
|
coef[start] -= AAC_MUL26((INTFLOAT)coef[start - i * inc], lpc[i - 1]);
|
|
|
|
} else {
|
|
|
|
// ma filter
|
|
|
|
for (m = 0; m < size; m++, start += inc) {
|
|
|
|
tmp[0] = coef[start];
|
|
|
|
for (i = 1; i <= FFMIN(m, order); i++)
|
|
|
|
coef[start] += AAC_MUL26(tmp[i], lpc[i - 1]);
|
|
|
|
for (i = order; i > 0; i--)
|
|
|
|
tmp[i] = tmp[i - 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-16 02:28:41 +02:00
|
|
|
/**
|
|
|
|
* Apply windowing and MDCT to obtain the spectral
|
|
|
|
* coefficient from the predicted sample by LTP.
|
|
|
|
*/
|
|
|
|
static inline void AAC_RENAME(windowing_and_mdct_ltp)(AACDecContext *ac,
|
|
|
|
INTFLOAT *out, INTFLOAT *in,
|
|
|
|
IndividualChannelStream *ics)
|
|
|
|
{
|
|
|
|
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
|
|
|
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
|
|
|
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
|
|
|
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
|
|
|
|
|
|
|
if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
|
|
|
|
ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
|
|
|
|
} else {
|
|
|
|
memset(in, 0, 448 * sizeof(*in));
|
|
|
|
ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
|
|
|
|
}
|
|
|
|
if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
|
|
|
|
ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
|
|
|
|
} else {
|
|
|
|
ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
|
|
|
|
memset(in + 1024 + 576, 0, 448 * sizeof(*in));
|
|
|
|
}
|
|
|
|
ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
|
|
|
|
}
|
|
|
|
|
2024-03-14 05:52:28 +02:00
|
|
|
/**
|
|
|
|
* Apply the long term prediction
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(apply_ltp)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
const LongTermPrediction *ltp = &sce->ics.ltp;
|
|
|
|
const uint16_t *offsets = sce->ics.swb_offset;
|
|
|
|
int i, sfb;
|
|
|
|
|
|
|
|
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
|
|
|
|
INTFLOAT *predTime = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *predFreq = ac->AAC_RENAME(buf_mdct);
|
|
|
|
int16_t num_samples = 2048;
|
|
|
|
|
|
|
|
if (ltp->lag < 1024)
|
|
|
|
num_samples = ltp->lag + 1024;
|
|
|
|
for (i = 0; i < num_samples; i++)
|
|
|
|
predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
|
|
|
|
memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
|
|
|
|
|
2024-03-16 02:28:41 +02:00
|
|
|
AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
|
2024-03-14 05:52:28 +02:00
|
|
|
|
|
|
|
if (sce->tns.present)
|
|
|
|
AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
|
|
|
|
|
|
|
|
for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
|
|
|
|
if (ltp->used[sfb])
|
|
|
|
for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
|
|
|
|
sce->AAC_RENAME(coeffs)[i] += (UINTFLOAT)predFreq[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the LTP buffer for next frame
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(update_ltp)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
INTFLOAT *saved_ltp = sce->AAC_RENAME(coeffs);
|
|
|
|
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
|
|
|
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
memcpy(saved_ltp, saved, 512 * sizeof(*saved_ltp));
|
|
|
|
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
|
|
|
|
ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
|
|
|
|
} else if (1 && ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
|
|
|
memcpy(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, 448 * sizeof(*saved_ltp));
|
|
|
|
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
|
|
|
|
ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
|
|
|
|
} else if (1) { // LONG_STOP or ONLY_LONG
|
|
|
|
ac->fdsp->vector_fmul_reverse(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, &lwindow[512], 512);
|
|
|
|
|
|
|
|
for (i = 0; i < 512; i++)
|
|
|
|
saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], lwindow[511 - i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(sce->AAC_RENAME(ltp_state), sce->AAC_RENAME(ltp_state)+1024,
|
|
|
|
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
|
|
|
memcpy(sce->AAC_RENAME(ltp_state) + 1024, sce->AAC_RENAME(output),
|
|
|
|
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
|
|
|
memcpy(sce->AAC_RENAME(ltp_state) + 2048, saved_ltp,
|
|
|
|
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
|
|
|
|
}
|
|
|
|
|
2024-03-16 01:14:32 +02:00
|
|
|
/**
|
|
|
|
* Conduct IMDCT and windowing.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *out = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
|
|
|
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
|
|
|
|
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
|
|
|
|
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
|
|
|
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// imdct
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
for (i = 0; i < 1024; i += 128)
|
|
|
|
ac->mdct128_fn(ac->mdct128, buf + i, in + i, sizeof(INTFLOAT));
|
|
|
|
} else {
|
|
|
|
ac->mdct1024_fn(ac->mdct1024, buf, in, sizeof(INTFLOAT));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* window overlapping
|
|
|
|
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
|
|
|
* and long to short transitions are considered to be short to short
|
|
|
|
* transitions. This leaves just two cases (long to long and short to short)
|
|
|
|
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
|
|
|
*/
|
|
|
|
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
|
|
|
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
|
|
|
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 512);
|
|
|
|
} else {
|
|
|
|
memcpy( out, saved, 448 * sizeof(*out));
|
|
|
|
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64);
|
|
|
|
memcpy( out + 448 + 4*128, temp, 64 * sizeof(*out));
|
|
|
|
} else {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
|
|
|
|
memcpy( out + 576, buf + 64, 448 * sizeof(*out));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// buffer update
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
memcpy( saved, temp + 64, 64 * sizeof(*saved));
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
|
|
|
|
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
|
|
|
|
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
|
|
|
memcpy( saved, buf + 512, 448 * sizeof(*saved));
|
|
|
|
memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
|
|
|
|
} else { // LONG_STOP or ONLY_LONG
|
|
|
|
memcpy( saved, buf + 512, 512 * sizeof(*saved));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-25 07:13:38 +02:00
|
|
|
/**
|
|
|
|
* Conduct IMDCT and windowing for 768-point frames.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(imdct_and_windowing_768)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *out = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_96) : AAC_RENAME(sine_96);
|
|
|
|
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_768) : AAC_RENAME(sine_768);
|
|
|
|
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_96) : AAC_RENAME(sine_96);
|
|
|
|
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
|
|
|
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// imdct
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
ac->mdct96_fn(ac->mdct96, buf + i * 96, in + i * 96, sizeof(INTFLOAT));
|
|
|
|
} else {
|
|
|
|
ac->mdct768_fn(ac->mdct768, buf, in, sizeof(INTFLOAT));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* window overlapping
|
|
|
|
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
|
|
|
* and long to short transitions are considered to be short to short
|
|
|
|
* transitions. This leaves just two cases (long to long and short to short)
|
|
|
|
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
|
|
|
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
|
|
|
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 384);
|
|
|
|
} else {
|
|
|
|
memcpy( out, saved, 336 * sizeof(*out));
|
|
|
|
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 336 + 0*96, saved + 336, buf + 0*96, swindow_prev, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 336 + 1*96, buf + 0*96 + 48, buf + 1*96, swindow, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 336 + 2*96, buf + 1*96 + 48, buf + 2*96, swindow, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 336 + 3*96, buf + 2*96 + 48, buf + 3*96, swindow, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(temp, buf + 3*96 + 48, buf + 4*96, swindow, 48);
|
|
|
|
memcpy( out + 336 + 4*96, temp, 48 * sizeof(*out));
|
|
|
|
} else {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 336, saved + 336, buf, swindow_prev, 48);
|
|
|
|
memcpy( out + 432, buf + 48, 336 * sizeof(*out));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// buffer update
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
memcpy( saved, temp + 48, 48 * sizeof(*saved));
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 48, buf + 4*96 + 48, buf + 5*96, swindow, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 144, buf + 5*96 + 48, buf + 6*96, swindow, 48);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 240, buf + 6*96 + 48, buf + 7*96, swindow, 48);
|
|
|
|
memcpy( saved + 336, buf + 7*96 + 48, 48 * sizeof(*saved));
|
|
|
|
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
|
|
|
memcpy( saved, buf + 384, 336 * sizeof(*saved));
|
|
|
|
memcpy( saved + 336, buf + 7*96 + 48, 48 * sizeof(*saved));
|
|
|
|
} else { // LONG_STOP or ONLY_LONG
|
|
|
|
memcpy( saved, buf + 384, 384 * sizeof(*saved));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-16 01:14:32 +02:00
|
|
|
/**
|
|
|
|
* Conduct IMDCT and windowing.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *out = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
|
|
|
|
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960);
|
|
|
|
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
|
|
|
|
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
|
|
|
INTFLOAT *temp = ac->AAC_RENAME(temp);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// imdct
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
ac->mdct120_fn(ac->mdct120, buf + i * 120, in + i * 128, sizeof(INTFLOAT));
|
|
|
|
} else {
|
|
|
|
ac->mdct960_fn(ac->mdct960, buf, in, sizeof(INTFLOAT));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* window overlapping
|
|
|
|
* NOTE: To simplify the overlapping code, all 'meaningless' short to long
|
|
|
|
* and long to short transitions are considered to be short to short
|
|
|
|
* transitions. This leaves just two cases (long to long and short to short)
|
|
|
|
* with a little special sauce for EIGHT_SHORT_SEQUENCE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
|
|
|
|
(ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
|
|
|
|
ac->fdsp->vector_fmul_window( out, saved, buf, lwindow_prev, 480);
|
|
|
|
} else {
|
|
|
|
memcpy( out, saved, 420 * sizeof(*out));
|
|
|
|
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 420 + 0*120, saved + 420, buf + 0*120, swindow_prev, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 420 + 1*120, buf + 0*120 + 60, buf + 1*120, swindow, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 420 + 2*120, buf + 1*120 + 60, buf + 2*120, swindow, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(out + 420 + 3*120, buf + 2*120 + 60, buf + 3*120, swindow, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(temp, buf + 3*120 + 60, buf + 4*120, swindow, 60);
|
|
|
|
memcpy( out + 420 + 4*120, temp, 60 * sizeof(*out));
|
|
|
|
} else {
|
|
|
|
ac->fdsp->vector_fmul_window(out + 420, saved + 420, buf, swindow_prev, 60);
|
|
|
|
memcpy( out + 540, buf + 60, 420 * sizeof(*out));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// buffer update
|
|
|
|
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
|
|
|
|
memcpy( saved, temp + 60, 60 * sizeof(*saved));
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 60, buf + 4*120 + 60, buf + 5*120, swindow, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 180, buf + 5*120 + 60, buf + 6*120, swindow, 60);
|
|
|
|
ac->fdsp->vector_fmul_window(saved + 300, buf + 6*120 + 60, buf + 7*120, swindow, 60);
|
|
|
|
memcpy( saved + 420, buf + 7*120 + 60, 60 * sizeof(*saved));
|
|
|
|
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
|
|
|
|
memcpy( saved, buf + 480, 420 * sizeof(*saved));
|
|
|
|
memcpy( saved + 420, buf + 7*120 + 60, 60 * sizeof(*saved));
|
|
|
|
} else { // LONG_STOP or ONLY_LONG
|
|
|
|
memcpy( saved, buf + 480, 480 * sizeof(*saved));
|
|
|
|
}
|
|
|
|
}
|
2024-03-25 07:13:38 +02:00
|
|
|
|
2024-03-16 01:14:32 +02:00
|
|
|
static void AAC_RENAME(imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
IndividualChannelStream *ics = &sce->ics;
|
|
|
|
INTFLOAT *in = sce->AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *out = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
|
|
|
|
|
|
|
// imdct
|
|
|
|
ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
|
|
|
|
|
|
|
|
// window overlapping
|
|
|
|
if (ics->use_kb_window[1]) {
|
|
|
|
// AAC LD uses a low overlap sine window instead of a KBD window
|
|
|
|
memcpy(out, saved, 192 * sizeof(*out));
|
|
|
|
ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME2(sine_128), 64);
|
|
|
|
memcpy( out + 320, buf + 64, 192 * sizeof(*out));
|
|
|
|
} else {
|
|
|
|
ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME2(sine_512), 256);
|
|
|
|
}
|
|
|
|
|
|
|
|
// buffer update
|
|
|
|
memcpy(saved, buf + 256, 256 * sizeof(*saved));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AAC_RENAME(imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
UINTFLOAT *in = sce->AAC_RENAME(coeffs);
|
|
|
|
INTFLOAT *out = sce->AAC_RENAME(output);
|
|
|
|
INTFLOAT *saved = sce->AAC_RENAME(saved);
|
|
|
|
INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
|
|
|
|
int i;
|
|
|
|
const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512;
|
|
|
|
const int n2 = n >> 1;
|
|
|
|
const int n4 = n >> 2;
|
|
|
|
const INTFLOAT *const window = n == 480 ? AAC_RENAME(ff_aac_eld_window_480) :
|
|
|
|
AAC_RENAME(ff_aac_eld_window_512);
|
|
|
|
|
|
|
|
// Inverse transform, mapped to the conventional IMDCT by
|
|
|
|
// Chivukula, R.K.; Reznik, Y.A.; Devarajan, V.,
|
|
|
|
// "Efficient algorithms for MPEG-4 AAC-ELD, AAC-LD and AAC-LC filterbanks,"
|
|
|
|
// International Conference on Audio, Language and Image Processing, ICALIP 2008.
|
|
|
|
// URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4590245&isnumber=4589950
|
|
|
|
for (i = 0; i < n2; i+=2) {
|
|
|
|
INTFLOAT temp;
|
|
|
|
temp = in[i ]; in[i ] = -in[n - 1 - i]; in[n - 1 - i] = temp;
|
|
|
|
temp = -in[i + 1]; in[i + 1] = in[n - 2 - i]; in[n - 2 - i] = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n == 480)
|
|
|
|
ac->mdct480_fn(ac->mdct480, buf, in, sizeof(INTFLOAT));
|
|
|
|
else
|
|
|
|
ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
|
|
|
|
|
|
|
|
for (i = 0; i < n; i+=2) {
|
|
|
|
buf[i + 0] = -(UINTFLOAT)(USE_FIXED + 1)*buf[i + 0];
|
|
|
|
buf[i + 1] = (UINTFLOAT)(USE_FIXED + 1)*buf[i + 1];
|
|
|
|
}
|
|
|
|
// Like with the regular IMDCT at this point we still have the middle half
|
|
|
|
// of a transform but with even symmetry on the left and odd symmetry on
|
|
|
|
// the right
|
|
|
|
|
|
|
|
// window overlapping
|
|
|
|
// The spec says to use samples [0..511] but the reference decoder uses
|
|
|
|
// samples [128..639].
|
|
|
|
for (i = n4; i < n2; i ++) {
|
|
|
|
out[i - n4] = AAC_MUL31( buf[ n2 - 1 - i] , window[i - n4]) +
|
|
|
|
AAC_MUL31( saved[ i + n2] , window[i + n - n4]) +
|
|
|
|
AAC_MUL31(-saved[n + n2 - 1 - i] , window[i + 2*n - n4]) +
|
|
|
|
AAC_MUL31(-saved[ 2*n + n2 + i] , window[i + 3*n - n4]);
|
|
|
|
}
|
|
|
|
for (i = 0; i < n2; i ++) {
|
|
|
|
out[n4 + i] = AAC_MUL31( buf[ i] , window[i + n2 - n4]) +
|
|
|
|
AAC_MUL31(-saved[ n - 1 - i] , window[i + n2 + n - n4]) +
|
|
|
|
AAC_MUL31(-saved[ n + i] , window[i + n2 + 2*n - n4]) +
|
|
|
|
AAC_MUL31( saved[2*n + n - 1 - i] , window[i + n2 + 3*n - n4]);
|
|
|
|
}
|
|
|
|
for (i = 0; i < n4; i ++) {
|
|
|
|
out[n2 + n4 + i] = AAC_MUL31( buf[ i + n2] , window[i + n - n4]) +
|
|
|
|
AAC_MUL31(-saved[n2 - 1 - i] , window[i + 2*n - n4]) +
|
|
|
|
AAC_MUL31(-saved[n + n2 + i] , window[i + 3*n - n4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// buffer update
|
|
|
|
memmove(saved + n, saved, 2 * n * sizeof(*saved));
|
|
|
|
memcpy( saved, buf, n * sizeof(*saved));
|
|
|
|
}
|
|
|
|
|
2024-03-16 05:29:07 +02:00
|
|
|
static void AAC_RENAME(clip_output)(AACDecContext *ac, ChannelElement *che,
|
|
|
|
int type, int samples)
|
|
|
|
{
|
|
|
|
#if USE_FIXED
|
|
|
|
/* preparation for resampler */
|
|
|
|
for (int j = 0; j < samples; j++){
|
|
|
|
che->ch[0].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[0].output_fixed[j]*128,
|
|
|
|
INT32_MIN, INT32_MAX-0x8000)+0x8000;
|
|
|
|
if (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))
|
|
|
|
che->ch[1].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[1].output_fixed[j]*128,
|
|
|
|
INT32_MIN, INT32_MAX-0x8000)+0x8000;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-03-16 06:16:50 +02:00
|
|
|
static inline void reset_all_predictors(PredictorState *ps)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_PREDICTORS; i++)
|
|
|
|
reset_predict_state(&ps[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void reset_predictor_group(PredictorState *ps, int group_num)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = group_num - 1; i < MAX_PREDICTORS; i += 30)
|
|
|
|
reset_predict_state(&ps[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Apply AAC-Main style frequency domain prediction.
|
|
|
|
*/
|
|
|
|
static void AAC_RENAME(apply_prediction)(AACDecContext *ac, SingleChannelElement *sce)
|
|
|
|
{
|
|
|
|
int sfb, k;
|
|
|
|
|
|
|
|
if (!sce->ics.predictor_initialized) {
|
|
|
|
reset_all_predictors(sce->AAC_RENAME(predictor_state));
|
|
|
|
sce->ics.predictor_initialized = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
|
|
|
|
for (sfb = 0;
|
|
|
|
sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index];
|
|
|
|
sfb++) {
|
|
|
|
for (k = sce->ics.swb_offset[sfb];
|
|
|
|
k < sce->ics.swb_offset[sfb + 1];
|
|
|
|
k++) {
|
|
|
|
predict(&sce->AAC_RENAME(predictor_state)[k],
|
|
|
|
&sce->AAC_RENAME(coeffs)[k],
|
|
|
|
sce->ics.predictor_present &&
|
|
|
|
sce->ics.prediction_used[sfb]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sce->ics.predictor_reset_group)
|
|
|
|
reset_predictor_group(sce->AAC_RENAME(predictor_state),
|
|
|
|
sce->ics.predictor_reset_group);
|
|
|
|
} else
|
|
|
|
reset_all_predictors(sce->AAC_RENAME(predictor_state));
|
|
|
|
}
|
|
|
|
|
2024-05-06 13:59:08 +02:00
|
|
|
static av_cold void AAC_RENAME(aac_dsp_init)(AACDecDSP *aac_dsp)
|
|
|
|
{
|
|
|
|
#define SET(member) aac_dsp->member = AAC_RENAME(member)
|
|
|
|
SET(dequant_scalefactors);
|
|
|
|
SET(apply_mid_side_stereo);
|
|
|
|
SET(apply_intensity_stereo);
|
|
|
|
SET(apply_tns);
|
|
|
|
SET(apply_ltp);
|
|
|
|
SET(update_ltp);
|
|
|
|
|
|
|
|
SET(apply_prediction);
|
|
|
|
|
|
|
|
SET(imdct_and_windowing);
|
2024-03-25 07:13:38 +02:00
|
|
|
SET(imdct_and_windowing_768);
|
2024-05-06 13:59:08 +02:00
|
|
|
SET(imdct_and_windowing_960);
|
|
|
|
SET(imdct_and_windowing_ld);
|
|
|
|
SET(imdct_and_windowing_eld);
|
|
|
|
|
|
|
|
SET(apply_dependent_coupling);
|
|
|
|
SET(apply_independent_coupling);
|
|
|
|
|
|
|
|
SET(clip_output);
|
|
|
|
#undef SET
|
|
|
|
}
|