diff options
author | Djordje Pesut <djordje.pesut@imgtec.com> | 2015-07-20 13:36:17 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2015-07-20 17:20:16 +0200 |
commit | f85bc147fb87de048ccc5767e186ac59ec0284ef (patch) | |
tree | b94b04d6110ec84a79fa1466d29c700d04d1f841 | |
parent | b0414da90d6da34144ad9dadd5445fe62cf755a6 (diff) | |
download | ffmpeg-f85bc147fb87de048ccc5767e186ac59ec0284ef.tar.gz |
avcodec: Implementation of AAC_fixed_decoder (SBR-module)
Add fixed poind code.
Signed-off-by: Nedeljko Babic <nedeljko.babic@imgtec.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r-- | libavcodec/Makefile | 5 | ||||
-rw-r--r-- | libavcodec/aac.h | 52 | ||||
-rw-r--r-- | libavcodec/aac_defines.h | 78 | ||||
-rw-r--r-- | libavcodec/aacdec_template.c | 14 | ||||
-rw-r--r-- | libavcodec/aacsbr.c | 1 | ||||
-rw-r--r-- | libavcodec/aacsbr.h | 12 | ||||
-rw-r--r-- | libavcodec/aacsbr_fixed.c | 586 | ||||
-rw-r--r-- | libavcodec/aacsbr_template.c | 211 | ||||
-rw-r--r-- | libavcodec/lpc.h | 15 | ||||
-rw-r--r-- | libavcodec/sbr.h | 78 | ||||
-rw-r--r-- | libavcodec/sbrdsp.c | 3 | ||||
-rw-r--r-- | libavcodec/sbrdsp.h | 36 | ||||
-rw-r--r-- | libavcodec/sbrdsp_fixed.c | 286 | ||||
-rw-r--r-- | libavcodec/sbrdsp_template.c | 42 | ||||
-rw-r--r-- | libavutil/softfloat.h | 8 |
15 files changed, 1237 insertions, 190 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c47d206b52..f91af3fee3 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -126,8 +126,9 @@ OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps.o \ aacadtsdec.o mpeg4audio.o kbdwin.o \ sbrdsp.o aacpsdsp.o -OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o \ - aacadtsdec.o mpeg4audio.o kbdwin.o +OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o \ + aacadtsdec.o mpeg4audio.o kbdwin.o \ + sbrdsp_fixed.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \ aacpsy.o aactab.o \ psymodel.o mpeg4audio.o kbdwin.o diff --git a/libavcodec/aac.h b/libavcodec/aac.h index f6fd446952..d62455d1ec 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -30,58 +30,8 @@ #ifndef AVCODEC_AAC_H #define AVCODEC_AAC_H -#ifndef USE_FIXED -#define USE_FIXED 0 -#endif - -#if USE_FIXED - -#include "libavutil/softfloat.h" - -#define FFT_FLOAT 0 -#define FFT_FIXED_32 1 - -#define AAC_RENAME(x) x ## _fixed -#define AAC_RENAME_32(x) x ## _fixed_32 -#define AAC_FLOAT SoftFloat -#define INTFLOAT int -#define SHORTFLOAT int16_t -#define AAC_SIGNE int -#define FIXR(a) ((int)((a) * 1 + 0.5)) -#define FIXR10(a) ((int)((a) * 1024.0 + 0.5)) -#define Q23(a) (int)((a) * 8388608.0 + 0.5) -#define Q30(x) (int)((x)*1073741824.0 + 0.5) -#define Q31(x) (int)((x)*2147483648.0 + 0.5) -#define RANGE15(x) x -#define GET_GAIN(x, y) (-(y) << (x)) + 1024 -#define AAC_MUL26(x, y) (int)(((int64_t)(x) * (y) + 0x2000000) >> 26) -#define AAC_MUL30(x, y) (int)(((int64_t)(x) * (y) + 0x20000000) >> 30) -#define AAC_MUL31(x, y) (int)(((int64_t)(x) * (y) + 0x40000000) >> 31) - -#else - -#define FFT_FLOAT 1 -#define FFT_FIXED_32 0 - -#define AAC_RENAME(x) x -#define AAC_RENAME_32(x) x -#define AAC_FLOAT float -#define INTFLOAT float -#define SHORTFLOAT float -#define AAC_SIGNE unsigned -#define FIXR(x) ((float)(x)) -#define FIXR10(x) ((float)(x)) -#define Q23(x) x -#define Q30(x) x -#define Q31(x) x -#define RANGE15(x) (32768.0 * (x)) -#define GET_GAIN(x, y) powf((x), -(y)) -#define AAC_MUL26(x, y) ((x) * (y)) -#define AAC_MUL30(x, y) ((x) * (y)) -#define AAC_MUL31(x, y) ((x) * (y)) - -#endif /* USE_FIXED */ +#include "aac_defines.h" #include "libavutil/float_dsp.h" #include "libavutil/fixed_dsp.h" #include "avcodec.h" diff --git a/libavcodec/aac_defines.h b/libavcodec/aac_defines.h new file mode 100644 index 0000000000..0f3905fe0b --- /dev/null +++ b/libavcodec/aac_defines.h @@ -0,0 +1,78 @@ +/* + * AAC defines + * + * 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_DEFINES_H +#define AVCODEC_AAC_DEFINES_H + +#ifndef USE_FIXED +#define USE_FIXED 0 +#endif + +#if USE_FIXED + +#include "libavutil/softfloat.h" + +#define FFT_FLOAT 0 +#define FFT_FIXED_32 1 + +#define AAC_RENAME(x) x ## _fixed +#define AAC_RENAME_32(x) x ## _fixed_32 +#define INTFLOAT int +#define SHORTFLOAT int16_t +#define AAC_FLOAT SoftFloat +#define AAC_SIGNE int +#define FIXR(a) ((int)((a) * 1 + 0.5)) +#define FIXR10(a) ((int)((a) * 1024.0 + 0.5)) +#define Q23(a) (int)((a) * 8388608.0 + 0.5) +#define Q30(x) (int)((x)*1073741824.0 + 0.5) +#define Q31(x) (int)((x)*2147483648.0 + 0.5) +#define RANGE15(x) x +#define GET_GAIN(x, y) (-(y) << (x)) + 1024 +#define AAC_MUL26(x, y) (int)(((int64_t)(x) * (y) + 0x2000000) >> 26) +#define AAC_MUL30(x, y) (int)(((int64_t)(x) * (y) + 0x20000000) >> 30) +#define AAC_MUL31(x, y) (int)(((int64_t)(x) * (y) + 0x40000000) >> 31) +#define AAC_SRA_R(x, y) (int)(((x) + (1 << ((y) - 1))) >> (y)) + +#else + +#define FFT_FLOAT 1 +#define FFT_FIXED_32 0 + +#define AAC_RENAME(x) x +#define AAC_RENAME_32(x) x +#define INTFLOAT float +#define SHORTFLOAT float +#define AAC_FLOAT float +#define AAC_SIGNE unsigned +#define FIXR(x) ((float)(x)) +#define FIXR10(x) ((float)(x)) +#define Q23(x) x +#define Q30(x) x +#define Q31(x) x +#define RANGE15(x) (32768.0 * (x)) +#define GET_GAIN(x, y) powf((x), -(y)) +#define AAC_MUL26(x, y) ((x) * (y)) +#define AAC_MUL30(x, y) ((x) * (y)) +#define AAC_MUL31(x, y) ((x) * (y)) +#define AAC_SRA_R(x, y) (x) + +#endif /* USE_FIXED */ + +#endif /* AVCODEC_AAC_DEFINES_H */ diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index d8eaca381a..b4eee85518 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -132,7 +132,7 @@ static av_cold int che_configure(AACContext *ac, if (!ac->che[type][id]) { if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement)))) return AVERROR(ENOMEM); - ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr); + AAC_RENAME(ff_aac_sbr_ctx_init)(ac, &ac->che[type][id]->sbr); } if (type != TYPE_CCE) { if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) { @@ -147,7 +147,7 @@ static av_cold int che_configure(AACContext *ac, } } else { if (ac->che[type][id]) - ff_aac_sbr_ctx_close(&ac->che[type][id]->sbr); + AAC_RENAME(ff_aac_sbr_ctx_close)(&ac->che[type][id]->sbr); av_freep(&ac->che[type][id]); } return 0; @@ -1126,7 +1126,7 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) AAC_INIT_VLC_STATIC( 9, 366); AAC_INIT_VLC_STATIC(10, 462); - ff_aac_sbr_init(); + AAC_RENAME(ff_aac_sbr_init)(); #if USE_FIXED ac->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & CODEC_FLAG_BITEXACT); @@ -2315,7 +2315,7 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, ac->oc[1].m4ac.sbr = 1; ac->avctx->profile = FF_PROFILE_AAC_HE; } - res = ff_decode_sbr_extension(ac, &che->sbr, gb, crc_flag, cnt, elem_type); + res = AAC_RENAME(ff_decode_sbr_extension)(ac, &che->sbr, gb, crc_flag, cnt, elem_type); break; case EXT_DYNAMIC_RANGE: res = decode_dynamic_range(&ac->che_drc, gb); @@ -2357,7 +2357,7 @@ static void apply_tns(INTFLOAT coef[1024], TemporalNoiseShaping *tns, continue; // tns_decode_coef - compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0); + AAC_RENAME(compute_lpc_coefs)(tns->coef[w][filt], order, lpc, 0, 0, 0); start = ics->swb_offset[FFMIN(bottom, mmm)]; end = ics->swb_offset[FFMIN( top, mmm)]; @@ -2738,7 +2738,7 @@ static void spectral_to_sample(AACContext *ac) ac->update_ltp(ac, &che->ch[1]); } if (ac->oc[1].m4ac.sbr > 0) { - ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret); + AAC_RENAME(ff_sbr_apply)(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret); } } if (type <= TYPE_CCE) @@ -3153,7 +3153,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx) for (i = 0; i < MAX_ELEM_ID; i++) { for (type = 0; type < 4; type++) { if (ac->che[type][i]) - ff_aac_sbr_ctx_close(&ac->che[type][i]->sbr); + AAC_RENAME(ff_aac_sbr_ctx_close)(&ac->che[type][i]->sbr); av_freep(&ac->che[type][i]); } } diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c index 766c47bc1c..81f1902822 100644 --- a/libavcodec/aacsbr.c +++ b/libavcodec/aacsbr.c @@ -25,6 +25,7 @@ * AAC Spectral Band Replication decoding functions * @author Robert Swain ( rob opendot cl ) */ +#define USE_FIXED 0 #include "aac.h" #include "sbr.h" diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h index 476bc65c54..ed1a7f9265 100644 --- a/libavcodec/aacsbr.h +++ b/libavcodec/aacsbr.h @@ -79,17 +79,17 @@ static const int8_t vlc_sbr_lav[10] = { name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) } /** Initialize SBR. */ -void ff_aac_sbr_init(void); +void AAC_RENAME(ff_aac_sbr_init)(void); /** Initialize one SBR context. */ -void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr); +void AAC_RENAME(ff_aac_sbr_ctx_init)(AACContext *ac, SpectralBandReplication *sbr); /** Close one SBR context. */ -void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr); +void AAC_RENAME(ff_aac_sbr_ctx_close)(SpectralBandReplication *sbr); /** Decode one SBR element. */ -int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, +int AAC_RENAME(ff_decode_sbr_extension)(AACContext *ac, SpectralBandReplication *sbr, GetBitContext *gb, int crc, int cnt, int id_aac); /** Apply one SBR element to one AAC element. */ -void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, - float* L, float *R); +void AAC_RENAME(ff_sbr_apply)(AACContext *ac, SpectralBandReplication *sbr, int id_aac, + INTFLOAT* L, INTFLOAT *R); void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c); diff --git a/libavcodec/aacsbr_fixed.c b/libavcodec/aacsbr_fixed.c new file mode 100644 index 0000000000..5a5c9cc75b --- /dev/null +++ b/libavcodec/aacsbr_fixed.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2013 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * AAC Spectral Band Replication decoding functions (fixed-point) + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2009-2010 Alex Converse <alex.converse@gmail.com> + * + * 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 + */ + +/** + * @file + * AAC Spectral Band Replication decoding functions (fixed-point) + * Note: Rounding-to-nearest used unless otherwise stated + * @author Robert Swain ( rob opendot cl ) + * @author Stanislav Ocovaj ( stanislav.ocovaj imgtec com ) + */ +#define USE_FIXED 1 + +#include "aac.h" +#include "sbr.h" +#include "aacsbr.h" +#include "aacsbrdata.h" +#include "aacsbr_fixed_tablegen.h" +#include "fft.h" +#include "aacps.h" +#include "sbrdsp.h" +#include "libavutil/internal.h" +#include "libavutil/libm.h" +#include "libavutil/avassert.h" + +#include <stdint.h> +#include <float.h> +#include <math.h> + +static VLC vlc_sbr[10]; +static void aacsbr_func_ptr_init(AACSBRContext *c); +static const int CONST_LN2 = Q31(0.6931471806/256); // ln(2)/256 +static const int CONST_RECIP_LN2 = Q31(0.7213475204); // 0.5/ln(2) +static const int CONST_SQRT2 = Q30(0.7071067812); // sqrt(2)/2 +static const int CONST_076923 = Q31(0.76923076923076923077f); + +int fixed_log_table[10] = +{ + Q31(1.0/2), Q31(1.0/3), Q31(1.0/4), Q31(1.0/5), Q31(1.0/6), + Q31(1.0/7), Q31(1.0/8), Q31(1.0/9), Q31(1.0/10), Q31(1.0/11) +}; + +static int fixed_log(int x) +{ + int i, ret, xpow, tmp; + + ret = x; + xpow = x; + for (i=0; i<10; i+=2){ + xpow = (int)(((int64_t)xpow * x + 0x40000000) >> 31); + tmp = (int)(((int64_t)xpow * fixed_log_table[i] + 0x40000000) >> 31); + ret -= tmp; + + xpow = (int)(((int64_t)xpow * x + 0x40000000) >> 31); + tmp = (int)(((int64_t)xpow * fixed_log_table[i+1] + 0x40000000) >> 31); + ret += tmp; + } + + return ret; +} + +int fixed_exp_table[7] = +{ + Q31(1.0/2), Q31(1.0/6), Q31(1.0/24), Q31(1.0/120), + Q31(1.0/720), Q31(1.0/5040), Q31(1.0/40320) +}; + +static int fixed_exp(int x) +{ + int i, ret, xpow, tmp; + + ret = 0x800000 + x; + xpow = x; + for (i=0; i<7; i++){ + xpow = (int)(((int64_t)xpow * x + 0x400000) >> 23); + tmp = (int)(((int64_t)xpow * fixed_exp_table[i] + 0x40000000) >> 31); + ret += tmp; + } + + return ret; +} + +static void make_bands(int16_t* bands, int start, int stop, int num_bands) +{ + int k, previous, present; + int base, prod, nz = 0; + + base = (stop << 23) / start; + while (base < 0x40000000){ + base <<= 1; + nz++; + } + base = fixed_log(base - 0x80000000); + base = (((base + 0x80) >> 8) + (8-nz)*CONST_LN2) / num_bands; + base = fixed_exp(base); + + previous = start; + prod = start << 23; + + for (k = 0; k < num_bands-1; k++) { + prod = (int)(((int64_t)prod * base + 0x400000) >> 23); + present = (prod + 0x400000) >> 23; + bands[k] = present - previous; + previous = present; + } + bands[num_bands-1] = stop - previous; +} + +/// Dequantization and stereo decoding (14496-3 sp04 p203) +static void sbr_dequant(SpectralBandReplication *sbr, int id_aac) +{ + int k, e; + int ch; + + if (id_aac == TYPE_CPE && sbr->bs_coupling) { + int alpha = sbr->data[0].bs_amp_res ? 2 : 1; + int pan_offset = sbr->data[0].bs_amp_res ? 12 : 24; + for (e = 1; e <= sbr->data[0].bs_num_env; e++) { + for (k = 0; k < sbr->n[sbr->data[0].bs_freq_res[e]]; k++) { + SoftFloat temp1, temp2, fac; + + temp1.exp = sbr->data[0].env_facs[e][k].mant * alpha + 14; + if (temp1.exp & 1) + temp1.mant = 759250125; + else + temp1.mant = 0x20000000; + temp1.exp = (temp1.exp >> 1) + 1; + + temp2.exp = (pan_offset - sbr->data[1].env_facs[e][k].mant) * alpha; + if (temp2.exp & 1) + temp2.mant = 759250125; + else + temp2.mant = 0x20000000; + temp2.exp = (temp2.exp >> 1) + 1; + fac = av_div_sf(temp1, av_add_sf(FLOAT_1, temp2)); + sbr->data[0].env_facs[e][k] = fac; + sbr->data[1].env_facs[e][k] = av_mul_sf(fac, temp2); + } + } + for (e = 1; e <= sbr->data[0].bs_num_noise; e++) { + for (k = 0; k < sbr->n_q; k++) { + SoftFloat temp1, temp2, fac; + + temp1.exp = NOISE_FLOOR_OFFSET - \ + sbr->data[0].noise_facs[e][k].mant + 2; + temp1.mant = 0x20000000; + temp2.exp = 12 - sbr->data[1].noise_facs[e][k].mant + 1; + temp2.mant = 0x20000000; + fac = av_div_sf(temp1, av_add_sf(FLOAT_1, temp2)); + sbr->data[0].noise_facs[e][k] = fac; + sbr->data[1].noise_facs[e][k] = av_mul_sf(fac, temp2); + } + } + } else { // SCE or one non-coupled CPE + for (ch = 0; ch < (id_aac == TYPE_CPE) + 1; ch++) { + int alpha = sbr->data[ch].bs_amp_res ? 2 : 1; + for (e = 1; e <= sbr->data[ch].bs_num_env; e++) + for (k = 0; k < sbr->n[sbr->data[ch].bs_freq_res[e]]; k++){ + SoftFloat temp1; + + temp1.exp = alpha * sbr->data[ch].env_facs[e][k].mant + 12; + if (temp1.exp & 1) + temp1.mant = 759250125; + else + temp1.mant = 0x20000000; + temp1.exp = (temp1.exp >> 1) + 1; + + sbr->data[ch].env_facs[e][k] = temp1; + } + for (e = 1; e <= sbr->data[ch].bs_num_noise; e++) + for (k = 0; k < sbr->n_q; k++){ + sbr->data[ch].noise_facs[e][k].exp = NOISE_FLOOR_OFFSET - \ + sbr->data[ch].noise_facs[e][k].mant + 1; + sbr->data[ch].noise_facs[e][k].mant = 0x20000000; + } + } + } +} + +/** High Frequency Generation (14496-3 sp04 p214+) and Inverse Filtering + * (14496-3 sp04 p214) + * Warning: This routine does not seem numerically stable. + */ +static void sbr_hf_inverse_filter(SBRDSPContext *dsp, + int (*alpha0)[2], int (*alpha1)[2], + const int X_low[32][40][2], int k0) +{ + int k; + int shift, round; + + for (k = 0; k < k0; k++) { + SoftFloat phi[3][2][2]; + SoftFloat a00, a01, a10, a11; + SoftFloat dk; + + dsp->autocorrelate(X_low[k], phi); + + dk = av_sub_sf(av_mul_sf(phi[2][1][0], phi[1][0][0]), + av_mul_sf(av_add_sf(av_mul_sf(phi[1][1][0], phi[1][1][0]), + av_mul_sf(phi[1][1][1], phi[1][1][1])), FLOAT_0999999)); + + if (!dk.mant) { + a10 = FLOAT_0; + a11 = FLOAT_0; + } else { + SoftFloat temp_real, temp_im; + temp_real = av_sub_sf(av_sub_sf(av_mul_sf(phi[0][0][0], phi[1][1][0]), + av_mul_sf(phi[0][0][1], phi[1][1][1])), + av_mul_sf(phi[0][1][0], phi[1][0][0])); + temp_im = av_sub_sf(av_add_sf(av_mul_sf(phi[0][0][0], phi[1][1][1]), + av_mul_sf(phi[0][0][1], phi[1][1][0])), + av_mul_sf(phi[0][1][1], phi[1][0][0])); + + a10 = av_div_sf(temp_real, dk); + a11 = av_div_sf(temp_im, dk); + } + + if (!phi[1][0][0].mant) { + a00 = FLOAT_0; + a01 = FLOAT_0; + } else { + SoftFloat temp_real, temp_im; + temp_real = av_add_sf(phi[0][0][0], + av_add_sf(av_mul_sf(a10, phi[1][1][0]), + av_mul_sf(a11, phi[1][1][1]))); + temp_im = av_add_sf(phi[0][0][1], + av_sub_sf(av_mul_sf(a11, phi[1][1][0]), + av_mul_sf(a10, phi[1][1][1]))); + + temp_real.mant = -temp_real.mant; + temp_im.mant = -temp_im.mant; + a00 = av_div_sf(temp_real, phi[1][0][0]); + a01 = av_div_sf(temp_im, phi[1][0][0]); + } + + shift = a00.exp; + if (shift >= 3) + alpha0[k][0] = 0x7fffffff; + else { + a00.mant <<= 1; + shift = 2-shift; + if (shift == 0) + alpha0[k][0] = a00.mant; + else { + round = 1 << (shift-1); + alpha0[k][0] = (a00.mant + round) >> shift; + } + } + + shift = a01.exp; + if (shift >= 3) + alpha0[k][1] = 0x7fffffff; + else { + a01.mant <<= 1; + shift = 2-shift; + if (shift == 0) + alpha0[k][1] = a01.mant; + else { + round = 1 << (shift-1); + alpha0[k][1] = (a01.mant + round) >> shift; + } + } + shift = a10.exp; + if (shift >= 3) + alpha1[k][0] = 0x7fffffff; + else { + a10.mant <<= 1; + shift = 2-shift; + if (shift == 0) + alpha1[k][0] = a10.mant; + else { + round = 1 << (shift-1); + alpha1[k][0] = (a10.mant + round) >> shift; + } + } + + shift = a11.exp; + if (shift >= 3) + alpha1[k][1] = 0x7fffffff; + else { + a11.mant <<= 1; + shift = 2-shift; + if (shift == 0) + alpha1[k][1] = a11.mant; + else { + round = 1 << (shift-1); + alpha1[k][1] = (a11.mant + round) >> shift; + } + } + + shift = (int)(((int64_t)(alpha1[k][0]>>1) * (alpha1[k][0]>>1) + \ + (int64_t)(alpha1[k][1]>>1) * (alpha1[k][1]>>1) + \ + 0x40000000) >> 31); + if (shift >= 0x20000000){ + alpha1[k][0] = 0; + alpha1[k][1] = 0; + alpha0[k][0] = 0; + alpha0[k][1] = 0; + } + + shift = (int)(((int64_t)(alpha0[k][0]>>1) * (alpha0[k][0]>>1) + \ + (int64_t)(alpha0[k][1]>>1) * (alpha0[k][1]>>1) + \ + 0x40000000) >> 31); + if (shift >= 0x20000000){ + alpha1[k][0] = 0; + alpha1[k][1] = 0; + alpha0[k][0] = 0; + alpha0[k][1] = 0; + } + } +} + +/// Chirp Factors (14496-3 sp04 p214) +static void sbr_chirp(SpectralBandReplication *sbr, SBRData *ch_data) +{ + int i; + int new_bw; + static const int bw_tab[] = { 0, 1610612736, 1932735283, 2104533975 }; + int64_t accu; + + for (i = 0; i < sbr->n_q; i++) { + if (ch_data->bs_invf_mode[0][i] + ch_data->bs_invf_mode[1][i] == 1) + new_bw = 1288490189; + else + new_bw = bw_tab[ch_data->bs_invf_mode[0][i]]; + + if (new_bw < ch_data->bw_array[i]){ + accu = (int64_t)new_bw * 1610612736; + accu += (int64_t)ch_data->bw_array[i] * 0x20000000; + new_bw = (int)((accu + 0x40000000) >> 31); + } else { + accu = (int64_t)new_bw * 1946157056; + accu += (int64_t)ch_data->bw_array[i] * 201326592; + new_bw = (int)((accu + 0x40000000) >> 31); + } + ch_data->bw_array[i] = new_bw < 0x2000000 ? 0 : new_bw; + } +} + +/** + * Calculation of levels of additional HF signal components (14496-3 sp04 p219) + * and Calculation of gain (14496-3 sp04 p219) + */ +static void sbr_gain_calc(AACContext *ac, SpectralBandReplication *sbr, + SBRData *ch_data, const int e_a[2]) +{ + int e, k, m; + // max gain limits : -3dB, 0dB, 3dB, inf dB (limiter off) + static const SoftFloat limgain[4] = { { 760155524, 0 }, { 0x20000000, 1 }, + { 758351638, 1 }, { 625000000, 34 } }; + + for (e = 0; e < ch_data->bs_num_env; e++) { + int delta = !((e == e_a[1]) || (e == e_a[0])); + for (k = 0; k < sbr->n_lim; k++) { + SoftFloat gain_boost, gain_max; + SoftFloat sum[2] = { { 0, 0}, { 0, 0 } }; + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + const SoftFloat temp = av_div_sf(sbr->e_origmapped[e][m], + av_add_sf(FLOAT_1, sbr->q_mapped[e][m])); + sbr->q_m[e][m] = av_sqrt_sf(av_mul_sf(temp, sbr->q_mapped[e][m])); + sbr->s_m[e][m] = av_sqrt_sf(av_mul_sf(temp, av_int2sf(ch_data->s_indexmapped[e + 1][m], 0))); + if (!sbr->s_mapped[e][m]) { + if (delta) { + sbr->gain[e][m] = av_sqrt_sf(av_div_sf(sbr->e_origmapped[e][m], + av_mul_sf(av_add_sf(FLOAT_1, sbr->e_curr[e][m]), + av_add_sf(FLOAT_1, sbr->q_mapped[e][m])))); + } else { + sbr->gain[e][m] = av_sqrt_sf(av_div_sf(sbr->e_origmapped[e][m], + av_add_sf(FLOAT_1, sbr->e_curr[e][m]))); + } + } else { + sbr->gain[e][m] = av_sqrt_sf( + av_div_sf( + av_mul_sf(sbr->e_origmapped[e][m], sbr->q_mapped[e][m]), + av_mul_sf( + av_add_sf(FLOAT_1, sbr->e_curr[e][m]), + av_add_sf(FLOAT_1, sbr->q_mapped[e][m])))); + } + } + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sum[0] = av_add_sf(sum[0], sbr->e_origmapped[e][m]); + sum[1] = av_add_sf(sum[1], sbr->e_curr[e][m]); + } + gain_max = av_mul_sf(limgain[sbr->bs_limiter_gains], + av_sqrt_sf( + av_div_sf( + av_add_sf(FLOAT_EPSILON, sum[0]), + av_add_sf(FLOAT_EPSILON, sum[1])))); + if (av_gt_sf(gain_max, FLOAT_100000)) + gain_max = FLOAT_100000; + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + SoftFloat q_m_max = av_div_sf( + av_mul_sf(sbr->q_m[e][m], gain_max), + sbr->gain[e][m]); + if (av_gt_sf(sbr->q_m[e][m], q_m_max)) + sbr->q_m[e][m] = q_m_max; + if (av_gt_sf(sbr->gain[e][m], gain_max)) + sbr->gain[e][m] = gain_max; + } + sum[0] = sum[1] = FLOAT_0; + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sum[0] = av_add_sf(sum[0], sbr->e_origmapped[e][m]); + sum[1] = av_add_sf(sum[1], + av_mul_sf( + av_mul_sf(sbr->e_curr[e][m], + sbr->gain[e][m]), + sbr->gain[e][m])); + sum[1] = av_add_sf(sum[1], + av_mul_sf(sbr->s_m[e][m], sbr->s_m[e][m])); + if (delta && !sbr->s_m[e][m].mant) + sum[1] = av_add_sf(sum[1], + av_mul_sf(sbr->q_m[e][m], sbr->q_m[e][m])); + } + gain_boost = av_sqrt_sf( + av_div_sf( + av_add_sf(FLOAT_EPSILON, sum[0]), + av_add_sf(FLOAT_EPSILON, sum[1]))); + if (av_gt_sf(gain_boost, FLOAT_1584893192)) + gain_boost = FLOAT_1584893192; + + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sbr->gain[e][m] = av_mul_sf(sbr->gain[e][m], gain_boost); + sbr->q_m[e][m] = av_mul_sf(sbr->q_m[e][m], gain_boost); + sbr->s_m[e][m] = av_mul_sf(sbr->s_m[e][m], gain_boost); + } + } + } +} + +/// Assembling HF Signals (14496-3 sp04 p220) +static void sbr_hf_assemble(int Y1[38][64][2], + const int X_high[64][40][2], + SpectralBandReplication *sbr, SBRData *ch_data, + const int e_a[2]) +{ + int e, i, j, m; + const int h_SL = 4 * !sbr->bs_smoothing_mode; + const int kx = sbr->kx[1]; + const int m_max = sbr->m[1]; + static const SoftFloat h_smooth[5] = { + { 715827883, -1 }, + { 647472402, -1 }, + { 937030863, -2 }, + { 989249804, -3 }, + { 546843842, -4 }, + }; + SoftFloat (*g_temp)[48] = ch_data->g_temp, (*q_temp)[48] = ch_data->q_temp; + int indexnoise = ch_data->f_indexnoise; + int indexsine = ch_data->f_indexsine; + + if (sbr->reset) { + for (i = 0; i < h_SL; i++) { + memcpy(g_temp[i + 2*ch_data->t_env[0]], sbr->gain[0], m_max * sizeof(sbr->gain[0][0])); + memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0], m_max * sizeof(sbr->q_m[0][0])); + } + } else if (h_SL) { + for (i = 0; i < 4; i++) { + memcpy(g_temp[i + 2 * ch_data->t_env[0]], + g_temp[i + 2 * ch_data->t_env_num_env_old], + sizeof(g_temp[0])); + memcpy(q_temp[i + 2 * ch_data->t_env[0]], + q_temp[i + 2 * ch_data->t_env_num_env_old], + sizeof(q_temp[0])); + } + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + memcpy(g_temp[h_SL + i], sbr->gain[e], m_max * sizeof(sbr->gain[0][0])); + memcpy(q_temp[h_SL + i], sbr->q_m[e], m_max * sizeof(sbr->q_m[0][0])); + } + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + SoftFloat g_filt_tab[48]; + SoftFloat q_filt_tab[48]; + SoftFloat *g_filt, *q_filt; + + if (h_SL && e != e_a[0] && e != e_a[1]) { + g_filt = g_filt_tab; + q_filt = q_filt_tab; + for (m = 0; m < m_max; m++) { + const int idx1 = i + h_SL; + g_filt[m].mant = g_filt[m].exp = 0; + q_filt[m].mant = q_filt[m].exp = 0; + for (j = 0; j <= h_SL; j++) { + g_filt[m] = av_add_sf(g_filt[m], + av_mul_sf(g_temp[idx1 - j][m], + h_smooth[j])); + q_filt[m] = av_add_sf(q_filt[m], + av_mul_sf(q_temp[idx1 - j][m], + h_smooth[j])); + } + } + } else { + g_filt = g_temp[i + h_SL]; + q_filt = q_temp[i]; + } + + sbr->dsp.hf_g_filt(Y1[i] + kx, X_high + kx, g_filt, m_max, + i + ENVELOPE_ADJUSTMENT_OFFSET); + + if (e != e_a[0] && e != e_a[1]) { + sbr->dsp.hf_apply_noise[indexsine](Y1[i] + kx, sbr->s_m[e], + q_filt, indexnoise, + kx, m_max); + } else { + int idx = indexsine&1; + int A = (1-((indexsine+(kx & 1))&2)); + int B = (A^(-idx)) + idx; + int *out = &Y1[i][kx][idx]; + int shift, round; + + SoftFloat *in = sbr->s_m[e]; + for (m = 0; m+1 < m_max; m+=2) { + shift = 22 - in[m ].exp; + round = 1 << (shift-1); + out[2*m ] += (in[m ].mant * A + round) >> shift; + + shift = 22 - in[m+1].exp; + round = 1 << (shift-1); + out[2*m+2] += (in[m+1].mant * B + round) >> shift; + } + if(m_max&1) + { + shift = 22 - in[m ].exp; + round = 1 << (shift-1); + + out[2*m ] += (in[m ].mant * A + round) >> shift; + } + } + indexnoise = (indexnoise + m_max) & 0x1ff; + indexsine = (indexsine + 1) & 3; + } + } + ch_data->f_indexnoise = indexnoise; + ch_data->f_indexsine = indexsine; +} + +#include "aacsbr_template.c" diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c index a176078880..dd0ddcf7ee 100644 --- a/libavcodec/aacsbr_template.c +++ b/libavcodec/aacsbr_template.c @@ -3,6 +3,10 @@ * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) * Copyright (c) 2009-2010 Alex Converse <alex.converse@gmail.com> * + * Fixed point code + * Copyright (c) 2013 + * MIPS Technologies, Inc., California. + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -24,9 +28,11 @@ * @file * AAC Spectral Band Replication decoding functions * @author Robert Swain ( rob opendot cl ) + * @author Stanislav Ocovaj ( stanislav.ocovaj@imgtec.com ) + * @author Zoran Basaric ( zoran.basaric@imgtec.com ) */ -av_cold void ff_aac_sbr_init(void) +av_cold void AAC_RENAME(ff_aac_sbr_init)(void) { static const struct { const void *sbr_codes, *sbr_bits; @@ -72,7 +78,7 @@ static void sbr_turnoff(SpectralBandReplication *sbr) { memset(&sbr->spectrum_params, -1, sizeof(SpectrumParameters)); } -av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr) +av_cold void AAC_RENAME(ff_aac_sbr_ctx_init)(AACContext *ac, SpectralBandReplication *sbr) { if(sbr->mdct.mdct_bits) return; @@ -83,17 +89,17 @@ av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr) /* SBR requires samples to be scaled to +/-32768.0 to work correctly. * mdct scale factors are adjusted to scale up from +/-1.0 at analysis * and scale back down at synthesis. */ - ff_mdct_init(&sbr->mdct, 7, 1, 1.0 / (64 * 32768.0)); - ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0 * 32768.0); + AAC_RENAME_32(ff_mdct_init)(&sbr->mdct, 7, 1, 1.0 / (64 * 32768.0)); + AAC_RENAME_32(ff_mdct_init)(&sbr->mdct_ana, 7, 1, -2.0 * 32768.0); ff_ps_ctx_init(&sbr->ps); - ff_sbrdsp_init(&sbr->dsp); + AAC_RENAME(ff_sbrdsp_init)(&sbr->dsp); aacsbr_func_ptr_init(&sbr->c); } -av_cold void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr) +av_cold void AAC_RENAME(ff_aac_sbr_ctx_close)(SpectralBandReplication *sbr) { - ff_mdct_end(&sbr->mdct); - ff_mdct_end(&sbr->mdct_ana); + AAC_RENAME_32(ff_mdct_end)(&sbr->mdct); + AAC_RENAME_32(ff_mdct_end)(&sbr->mdct_ana); } static int qsort_comparison_function_int16(const void *a, const void *b) @@ -115,10 +121,10 @@ static void sbr_make_f_tablelim(SpectralBandReplication *sbr) { int k; if (sbr->bs_limiter_bands > 0) { - static const float bands_warped[3] = { 1.32715174233856803909f, //2^(0.49/1.2) - 1.18509277094158210129f, //2^(0.49/2) - 1.11987160404675912501f }; //2^(0.49/3) - const float lim_bands_per_octave_warped = bands_warped[sbr->bs_limiter_bands - 1]; + static const INTFLOAT bands_warped[3] = { Q23(1.32715174233856803909f), //2^(0.49/1.2) + Q23(1.18509277094158210129f), //2^(0.49/2) + Q23(1.11987160404675912501f) }; //2^(0.49/3) + const INTFLOAT lim_bands_per_octave_warped = bands_warped[sbr->bs_limiter_bands - 1]; int16_t patch_borders[7]; uint16_t *in = sbr->f_tablelim + 1, *out = sbr->f_tablelim; @@ -138,7 +144,11 @@ static void sbr_make_f_tablelim(SpectralBandReplication *sbr) sbr->n_lim = sbr->n[0] + sbr->num_patches - 1; while (out < sbr->f_tablelim + sbr->n_lim) { +#if USE_FIXED + if ((*in << 23) >= *out * lim_bands_per_octave_warped) { +#else if (*in >= *out * lim_bands_per_octave_warped) { +#endif /* USE_FIXED */ *++out = *in++; } else if (*in == *out || !in_table_int16(patch_borders, sbr->num_patches, *in)) { @@ -344,6 +354,9 @@ static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, int two_regions, num_bands_0; int vdk0_max, vdk1_min; int16_t vk0[49]; +#if USE_FIXED + int tmp, nz = 0; +#endif /* USE_FIXED */ if (49 * sbr->k[2] > 110 * sbr->k[0]) { two_regions = 1; @@ -353,7 +366,19 @@ static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, sbr->k[1] = sbr->k[2]; } +#if USE_FIXED + tmp = (sbr->k[1] << 23) / sbr->k[0]; + while (tmp < 0x40000000) { + tmp <<= 1; + nz++; + } + tmp = fixed_log(tmp - 0x80000000); + tmp = (int)(((int64_t)tmp * CONST_RECIP_LN2 + 0x20000000) >> 30); + tmp = (((tmp + 0x80) >> 8) + ((8 - nz) << 23)) * half_bands; + num_bands_0 = ((tmp + 0x400000) >> 23) * 2; +#else num_bands_0 = lrintf(half_bands * log2f(sbr->k[1] / (float)sbr->k[0])) * 2; +#endif /* USE_FIXED */ if (num_bands_0 <= 0) { // Requirements (14496-3 sp04 p205) av_log(ac->avctx, AV_LOG_ERROR, "Invalid num_bands_0: %d\n", num_bands_0); @@ -378,11 +403,27 @@ static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, if (two_regions) { int16_t vk1[49]; +#if USE_FIXED + int num_bands_1; + + tmp = (sbr->k[2] << 23) / sbr->k[1]; + nz = 0; + while (tmp < 0x40000000) { + tmp <<= 1; + nz++; + } + tmp = fixed_log(tmp - 0x80000000); + tmp = (int)(((int64_t)tmp * CONST_RECIP_LN2 + 0x20000000) >> 30); + tmp = (((tmp + 0x80) >> 8) + ((8 - nz) << 23)) * half_bands; + if (spectrum->bs_alter_scale) + tmp = (int)(((int64_t)tmp * CONST_076923 + 0x40000000) >> 31); + num_bands_1 = ((tmp + 0x400000) >> 23) * 2; +#else float invwarp = spectrum->bs_alter_scale ? 0.76923076923076923077f : 1.0f; // bs_alter_scale = {0,1} int num_bands_1 = lrintf(half_bands * invwarp * log2f(sbr->k[2] / (float)sbr->k[1])) * 2; - +#endif /* USE_FIXED */ make_bands(vk1+1, sbr->k[1], sbr->k[2], num_bands_1); vdk1_min = array_min_int16(vk1 + 1, num_bands_1); @@ -487,6 +528,9 @@ static int sbr_hf_calc_npatches(AACContext *ac, SpectralBandReplication *sbr) static int sbr_make_f_derived(AACContext *ac, SpectralBandReplication *sbr) { int k, temp; +#if USE_FIXED + int nz = 0; +#endif /* USE_FIXED */ sbr->n[1] = sbr->n_master - sbr->spectrum_params.bs_xover_band; sbr->n[0] = (sbr->n[1] + 1) >> 1; @@ -511,9 +555,24 @@ static int sbr_make_f_derived(AACContext *ac, SpectralBandReplication *sbr) temp = sbr->n[1] & 1; for (k = 1; k <= sbr->n[0]; k++) sbr->f_tablelow[k] = sbr->f_tablehigh[2 * k - temp]; +#if USE_FIXED + temp = (sbr->k[2] << 23) / sbr->kx[1]; + while (temp < 0x40000000) { + temp <<= 1; + nz++; + } + temp = fixed_log(temp - 0x80000000); + temp = (int)(((int64_t)temp * CONST_RECIP_LN2 + 0x20000000) >> 30); + temp = (((temp + 0x80) >> 8) + ((8 - nz) << 23)) * sbr->spectrum_params.bs_noise_bands; + sbr->n_q = (temp + 0x400000) >> 23; + if (sbr->n_q < 1) + sbr->n_q = 1; +#else sbr->n_q = FFMAX(1, lrintf(sbr->spectrum_params.bs_noise_bands * log2f(sbr->k[2] / (float)sbr->kx[1]))); // 0 <= bs_noise_bands <= 3 +#endif /* USE_FIXED */ + if (sbr->n_q > 5) { av_log(ac->avctx, AV_LOG_ERROR, "Too many noise floor scale factors: %d\n", sbr->n_q); return -1; @@ -770,6 +829,31 @@ static void read_sbr_envelope(SpectralBandReplication *sbr, GetBitContext *gb, } } +#if USE_FIXED + for (i = 0; i < ch_data->bs_num_env; i++) { + if (ch_data->bs_df_env[i]) { + // bs_freq_res[0] == bs_freq_res[bs_num_env] from prev frame + if (ch_data->bs_freq_res[i + 1] == ch_data->bs_freq_res[i]) { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) + ch_data->env_facs[i + 1][j].mant = ch_data->env_facs[i][j].mant + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } else if (ch_data->bs_freq_res[i + 1]) { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) { + k = (j + odd) >> 1; // find k such that f_tablelow[k] <= f_tablehigh[j] < f_tablelow[k + 1] + ch_data->env_facs[i + 1][j].mant = ch_data->env_facs[i][k].mant + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } + } else { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) { + k = j ? 2*j - odd : 0; // find k such that f_tablehigh[k] == f_tablelow[j] + ch_data->env_facs[i + 1][j].mant = ch_data->env_facs[i][k].mant + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } + } + } else { + ch_data->env_facs[i + 1][0].mant = delta * get_bits(gb, bits); // bs_env_start_value_balance + for (j = 1; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) + ch_data->env_facs[i + 1][j].mant = ch_data->env_facs[i + 1][j - 1].mant + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); + } + } +#else for (i = 0; i < ch_data->bs_num_env; i++) { if (ch_data->bs_df_env[i]) { // bs_freq_res[0] == bs_freq_res[bs_num_env] from prev frame @@ -793,6 +877,7 @@ static void read_sbr_envelope(SpectralBandReplication *sbr, GetBitContext *gb, ch_data->env_facs[i + 1][j] = ch_data->env_facs[i + 1][j - 1] + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); } } +#endif /* USE_FIXED */ //assign 0th elements of env_facs from last elements memcpy(ch_data->env_facs[0], ch_data->env_facs[ch_data->bs_num_env], @@ -819,6 +904,18 @@ static void read_sbr_noise(SpectralBandReplication *sbr, GetBitContext *gb, f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_3_0DB]; } +#if USE_FIXED + for (i = 0; i < ch_data->bs_num_noise; i++) { + if (ch_data->bs_df_noise[i]) { + for (j = 0; j < sbr->n_q; j++) + ch_data->noise_facs[i + 1][j].mant = ch_data->noise_facs[i][j].mant + delta * (get_vlc2(gb, t_huff, 9, 2) - t_lav); + } else { + ch_data->noise_facs[i + 1][0].mant = delta * get_bits(gb, 5); // bs_noise_start_value_balance or bs_noise_start_value_level + for (j = 1; j < sbr->n_q; j++) + ch_data->noise_facs[i + 1][j].mant = ch_data->noise_facs[i + 1][j - 1].mant + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); + } + } +#else for (i = 0; i < ch_data->bs_num_noise; i++) { if (ch_data->bs_df_noise[i]) { for (j = 0; j < sbr->n_q; j++) @@ -829,6 +926,7 @@ static void read_sbr_noise(SpectralBandReplication *sbr, GetBitContext *gb, ch_data->noise_facs[i + 1][j] = ch_data->noise_facs[i + 1][j - 1] + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); } } +#endif /* USE_FIXED */ //assign 0th elements of noise_facs from last elements memcpy(ch_data->noise_facs[0], ch_data->noise_facs[ch_data->bs_num_noise], @@ -992,7 +1090,7 @@ static void sbr_reset(AACContext *ac, SpectralBandReplication *sbr) * * @return Returns number of bytes consumed from the TYPE_FIL element. */ -int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, +int AAC_RENAME(ff_decode_sbr_extension)(AACContext *ac, SpectralBandReplication *sbr, GetBitContext *gb_host, int crc, int cnt, int id_aac) { unsigned int num_sbr_bits = 0, num_align_bits; @@ -1044,9 +1142,13 @@ int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, * @param W array of complex-valued samples split into subbands */ #ifndef sbr_qmf_analysis +#if USE_FIXED +static void sbr_qmf_analysis(AVFixedDSPContext *dsp, FFTContext *mdct, +#else static void sbr_qmf_analysis(AVFloatDSPContext *dsp, FFTContext *mdct, - SBRDSPContext *sbrdsp, const float *in, float *x, - float z[320], float W[2][32][32][2], int buf_idx) +#endif /* USE_FIXED */ + SBRDSPContext *sbrdsp, const INTFLOAT *in, INTFLOAT *x, + INTFLOAT z[320], INTFLOAT W[2][32][32][2], int buf_idx) { int i; memcpy(x , x+1024, (320-32)*sizeof(x[0])); @@ -1069,19 +1171,23 @@ static void sbr_qmf_analysis(AVFloatDSPContext *dsp, FFTContext *mdct, */ #ifndef sbr_qmf_synthesis static void sbr_qmf_synthesis(FFTContext *mdct, +#if USE_FIXED + SBRDSPContext *sbrdsp, AVFixedDSPContext *dsp, +#else SBRDSPContext *sbrdsp, AVFloatDSPContext *dsp, - float *out, float X[2][38][64], - float mdct_buf[2][64], - float *v0, int *v_off, const unsigned int div) +#endif /* USE_FIXED */ + INTFLOAT *out, INTFLOAT X[2][38][64], + INTFLOAT mdct_buf[2][64], + INTFLOAT *v0, int *v_off, const unsigned int div) { int i, n; - const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us; + const INTFLOAT *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us; const int step = 128 >> div; - float *v; + INTFLOAT *v; for (i = 0; i < 32; i++) { if (*v_off < step) { int saved_samples = (1280 - 128) >> div; - memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float)); + memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(INTFLOAT)); *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step; } else { *v_off -= step; @@ -1117,7 +1223,7 @@ static void sbr_qmf_synthesis(FFTContext *mdct, /// Generate the subband filtered lowband static int sbr_lf_gen(AACContext *ac, SpectralBandReplication *sbr, - float X_low[32][40][2], const float W[2][32][32][2], + INTFLOAT X_low[32][40][2], const INTFLOAT W[2][32][32][2], int buf_idx) { int i, k; @@ -1142,9 +1248,9 @@ static int sbr_lf_gen(AACContext *ac, SpectralBandReplication *sbr, /// High Frequency Generator (14496-3 sp04 p215) static int sbr_hf_gen(AACContext *ac, SpectralBandReplication *sbr, - float X_high[64][40][2], const float X_low[32][40][2], - const float (*alpha0)[2], const float (*alpha1)[2], - const float bw_array[5], const uint8_t *t_env, + INTFLOAT X_high[64][40][2], const INTFLOAT X_low[32][40][2], + const INTFLOAT (*alpha0)[2], const INTFLOAT (*alpha1)[2], + const INTFLOAT bw_array[5], const uint8_t *t_env, int bs_num_env) { int j, x; @@ -1176,9 +1282,9 @@ static int sbr_hf_gen(AACContext *ac, SpectralBandReplication *sbr, } /// Generate the subband filtered lowband -static int sbr_x_gen(SpectralBandReplication *sbr, float X[2][38][64], - const float Y0[38][64][2], const float Y1[38][64][2], - const float X_low[32][40][2], int ch) +static int sbr_x_gen(SpectralBandReplication *sbr, INTFLOAT X[2][38][64], + const INTFLOAT Y0[38][64][2], const INTFLOAT Y1[38][64][2], + const INTFLOAT X_low[32][40][2], int ch) { int k, i; const int i_f = 32; @@ -1270,7 +1376,7 @@ static int sbr_mapping(AACContext *ac, SpectralBandReplication *sbr, } /// Estimation of current envelope (14496-3 sp04 p218) -static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], +static void sbr_env_estimate(AAC_FLOAT (*e_curr)[48], INTFLOAT X_high[64][40][2], SpectralBandReplication *sbr, SBRData *ch_data) { int e, m; @@ -1278,13 +1384,21 @@ static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], if (sbr->bs_interpol_freq) { for (e = 0; e < ch_data->bs_num_env; e++) { +#if USE_FIXED + const SoftFloat recip_env_size = av_int2sf(0x20000000 / (ch_data->t_env[e + 1] - ch_data->t_env[e]), 30); +#else const float recip_env_size = 0.5f / (ch_data->t_env[e + 1] - ch_data->t_env[e]); +#endif /* USE_FIXED */ int ilb = ch_data->t_env[e] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; int iub = ch_data->t_env[e + 1] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; for (m = 0; m < sbr->m[1]; m++) { - float sum = sbr->dsp.sum_square(X_high[m+kx1] + ilb, iub - ilb); + AAC_FLOAT sum = sbr->dsp.sum_square(X_high[m+kx1] + ilb, iub - ilb); +#if USE_FIXED + e_curr[e][m] = av_mul_sf(sum, recip_env_size); +#else e_curr[e][m] = sum * recip_env_size; +#endif /* USE_FIXED */ } } } else { @@ -1297,6 +1411,14 @@ static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], const uint16_t *table = ch_data->bs_freq_res[e + 1] ? sbr->f_tablehigh : sbr->f_tablelow; for (p = 0; p < sbr->n[ch_data->bs_freq_res[e + 1]]; p++) { +#if USE_FIXED + SoftFloat sum = { 0, 0 }; + const SoftFloat den = av_int2sf(0x20000000 / (env_size * (table[p + 1] - table[p])), 29); + for (k = table[p]; k < table[p + 1]; k++) { + sum = av_add_sf(sum, sbr->dsp.sum_square(X_high[k] + ilb, iub - ilb)); + } + sum = av_mul_sf(sum, den); +#else float sum = 0.0f; const int den = env_size * (table[p + 1] - table[p]); @@ -1304,6 +1426,7 @@ static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], sum += sbr->dsp.sum_square(X_high[k] + ilb, iub - ilb); } sum /= den; +#endif /* USE_FIXED */ for (k = table[p]; k < table[p + 1]; k++) { e_curr[e][k - kx1] = sum; } @@ -1312,8 +1435,8 @@ static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], } } -void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, - float* L, float* R) +void AAC_RENAME(ff_sbr_apply)(AACContext *ac, SpectralBandReplication *sbr, int id_aac, + INTFLOAT* L, INTFLOAT* R) { int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate; int ch; @@ -1339,21 +1462,21 @@ void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, for (ch = 0; ch < nch; ch++) { /* decode channel */ sbr_qmf_analysis(ac->fdsp, &sbr->mdct_ana, &sbr->dsp, ch ? R : L, sbr->data[ch].analysis_filterbank_samples, - (float*)sbr->qmf_filter_scratch, + (INTFLOAT*)sbr->qmf_filter_scratch, sbr->data[ch].W, sbr->data[ch].Ypos); sbr->c.sbr_lf_gen(ac, sbr, sbr->X_low, - (const float (*)[32][32][2]) sbr->data[ch].W, + (const INTFLOAT (*)[32][32][2]) sbr->data[ch].W, sbr->data[ch].Ypos); sbr->data[ch].Ypos ^= 1; if (sbr->start) { sbr->c.sbr_hf_inverse_filter(&sbr->dsp, sbr->alpha0, sbr->alpha1, - (const float (*)[40][2]) sbr->X_low, sbr->k[0]); + (const INTFLOAT (*)[40][2]) sbr->X_low, sbr->k[0]); sbr_chirp(sbr, &sbr->data[ch]); av_assert0(sbr->data[ch].bs_num_env > 0); sbr_hf_gen(ac, sbr, sbr->X_high, - (const float (*)[40][2]) sbr->X_low, - (const float (*)[2]) sbr->alpha0, - (const float (*)[2]) sbr->alpha1, + (const INTFLOAT (*)[40][2]) sbr->X_low, + (const INTFLOAT (*)[2]) sbr->alpha0, + (const INTFLOAT (*)[2]) sbr->alpha1, sbr->data[ch].bw_array, sbr->data[ch].t_env, sbr->data[ch].bs_num_env); @@ -1363,7 +1486,7 @@ void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, sbr_env_estimate(sbr->e_curr, sbr->X_high, sbr, &sbr->data[ch]); sbr_gain_calc(ac, sbr, &sbr->data[ch], sbr->data[ch].e_a); sbr->c.sbr_hf_assemble(sbr->data[ch].Y[sbr->data[ch].Ypos], - (const float (*)[40][2]) sbr->X_high, + (const INTFLOAT (*)[40][2]) sbr->X_high, sbr, &sbr->data[ch], sbr->data[ch].e_a); } @@ -1371,9 +1494,9 @@ void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, /* synthesis */ sbr->c.sbr_x_gen(sbr, sbr->X[ch], - (const float (*)[64][2]) sbr->data[ch].Y[1-sbr->data[ch].Ypos], - (const float (*)[64][2]) sbr->data[ch].Y[ sbr->data[ch].Ypos], - (const float (*)[40][2]) sbr->X_low, ch); + (const INTFLOAT (*)[64][2]) sbr->data[ch].Y[1-sbr->data[ch].Ypos], + (const INTFLOAT (*)[64][2]) sbr->data[ch].Y[ sbr->data[ch].Ypos], + (const INTFLOAT (*)[40][2]) sbr->X_low, ch); } if (ac->oc[1].m4ac.ps == 1) { @@ -1405,6 +1528,8 @@ static void aacsbr_func_ptr_init(AACSBRContext *c) c->sbr_x_gen = sbr_x_gen; c->sbr_hf_inverse_filter = sbr_hf_inverse_filter; +#if !USE_FIXED if(ARCH_MIPS) ff_aacsbr_func_ptr_init_mips(c); +#endif } diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h index 96acb37146..9b76e2fb43 100644 --- a/libavcodec/lpc.h +++ b/libavcodec/lpc.h @@ -25,6 +25,7 @@ #include <stdint.h> #include "libavutil/avassert.h" #include "libavutil/lls.h" +#include "aac_defines.h" #define ORDER_METHOD_EST 0 #define ORDER_METHOD_2LEVEL 1 @@ -111,11 +112,15 @@ void ff_lpc_init_x86(LPCContext *s); */ void ff_lpc_end(LPCContext *s); +#if USE_FIXED +#define LPC_TYPE int +#else #ifdef LPC_USE_DOUBLE #define LPC_TYPE double #else #define LPC_TYPE float #endif +#endif // USE_FIXED /** * Schur recursion. @@ -152,7 +157,7 @@ static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order, * Levinson-Durbin recursion. * Produce LPC coefficients from autocorrelation data. */ -static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, +static inline int AAC_RENAME(compute_lpc_coefs)(const LPC_TYPE *autoc, int max_order, LPC_TYPE *lpc, int lpc_stride, int fail, int normalize) { @@ -169,14 +174,14 @@ static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, return -1; for(i=0; i<max_order; i++) { - LPC_TYPE r = -autoc[i]; + LPC_TYPE r = AAC_SRA_R(-autoc[i], 5); if (normalize) { for(j=0; j<i; j++) r -= lpc_last[j] * autoc[i-j-1]; r /= err; - err *= 1.0 - (r * r); + err *= FIXR(1.0) - (r * r); } lpc[i] = r; @@ -184,8 +189,8 @@ static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, for(j=0; j < (i+1)>>1; j++) { LPC_TYPE f = lpc_last[ j]; LPC_TYPE b = lpc_last[i-1-j]; - lpc[ j] = f + r * b; - lpc[i-1-j] = b + r * f; + lpc[ j] = f + AAC_MUL26(r, b); + lpc[i-1-j] = b + AAC_MUL26(r, f); } if (fail && err < 0) diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h index ff00acba0d..66a88a2898 100644 --- a/libavcodec/sbr.h +++ b/libavcodec/sbr.h @@ -66,9 +66,9 @@ typedef struct SBRData { */ unsigned bs_frame_class; unsigned bs_add_harmonic_flag; - unsigned bs_num_env; + AAC_SIGNE bs_num_env; uint8_t bs_freq_res[7]; - unsigned bs_num_noise; + AAC_SIGNE bs_num_noise; uint8_t bs_df_env[5]; uint8_t bs_df_noise[2]; uint8_t bs_invf_mode[2][5]; @@ -80,25 +80,25 @@ typedef struct SBRData { * @name State variables * @{ */ - DECLARE_ALIGNED(32, float, synthesis_filterbank_samples)[SBR_SYNTHESIS_BUF_SIZE]; - DECLARE_ALIGNED(32, float, analysis_filterbank_samples) [1312]; + DECLARE_ALIGNED(32, INTFLOAT, synthesis_filterbank_samples)[SBR_SYNTHESIS_BUF_SIZE]; + DECLARE_ALIGNED(32, INTFLOAT, analysis_filterbank_samples) [1312]; int synthesis_filterbank_samples_offset; ///l_APrev and l_A int e_a[2]; ///Chirp factors - float bw_array[5]; + INTFLOAT bw_array[5]; ///QMF values of the original signal - float W[2][32][32][2]; + INTFLOAT W[2][32][32][2]; ///QMF output of the HF adjustor int Ypos; - DECLARE_ALIGNED(16, float, Y)[2][38][64][2]; - DECLARE_ALIGNED(16, float, g_temp)[42][48]; - float q_temp[42][48]; + DECLARE_ALIGNED(16, INTFLOAT, Y)[2][38][64][2]; + DECLARE_ALIGNED(16, AAC_FLOAT, g_temp)[42][48]; + AAC_FLOAT q_temp[42][48]; uint8_t s_indexmapped[8][48]; ///Envelope scalefactors - float env_facs[6][48]; + AAC_FLOAT env_facs[6][48]; ///Noise scalefactors - float noise_facs[3][5]; + AAC_FLOAT noise_facs[3][5]; ///Envelope time borders uint8_t t_env[8]; ///Envelope time border of the last envelope of the previous frame @@ -117,18 +117,18 @@ typedef struct SpectralBandReplication SpectralBandReplication; */ typedef struct AACSBRContext { int (*sbr_lf_gen)(AACContext *ac, SpectralBandReplication *sbr, - float X_low[32][40][2], const float W[2][32][32][2], + INTFLOAT X_low[32][40][2], const INTFLOAT W[2][32][32][2], int buf_idx); - void (*sbr_hf_assemble)(float Y1[38][64][2], - const float X_high[64][40][2], + void (*sbr_hf_assemble)(INTFLOAT Y1[38][64][2], + const INTFLOAT X_high[64][40][2], SpectralBandReplication *sbr, SBRData *ch_data, const int e_a[2]); - int (*sbr_x_gen)(SpectralBandReplication *sbr, float X[2][38][64], - const float Y0[38][64][2], const float Y1[38][64][2], - const float X_low[32][40][2], int ch); + int (*sbr_x_gen)(SpectralBandReplication *sbr, INTFLOAT X[2][38][64], + const INTFLOAT Y0[38][64][2], const INTFLOAT Y1[38][64][2], + const INTFLOAT X_low[32][40][2], int ch); void (*sbr_hf_inverse_filter)(SBRDSPContext *dsp, - float (*alpha0)[2], float (*alpha1)[2], - const float X_low[32][40][2], int k0); + INTFLOAT (*alpha0)[2], INTFLOAT (*alpha1)[2], + const INTFLOAT X_low[32][40][2], int k0); } AACSBRContext; /** @@ -151,23 +151,23 @@ struct SpectralBandReplication { unsigned bs_smoothing_mode; /** @} */ unsigned bs_coupling; - unsigned k[5]; ///< k0, k1, k2 + AAC_SIGNE k[5]; ///< k0, k1, k2 ///kx', and kx respectively, kx is the first QMF subband where SBR is used. ///kx' is its value from the previous frame - unsigned kx[2]; + AAC_SIGNE kx[2]; ///M' and M respectively, M is the number of QMF subbands that use SBR. - unsigned m[2]; + AAC_SIGNE m[2]; unsigned kx_and_m_pushed; ///The number of frequency bands in f_master - unsigned n_master; + AAC_SIGNE n_master; SBRData data[2]; PSContext ps; ///N_Low and N_High respectively, the number of frequency bands for low and high resolution - unsigned n[2]; + AAC_SIGNE n[2]; ///Number of noise floor bands - unsigned n_q; + AAC_SIGNE n_q; ///Number of limiter bands - unsigned n_lim; + AAC_SIGNE n_lim; ///The master QMF frequency grouping uint16_t f_master[49]; ///Frequency borders for low resolution SBR @@ -178,33 +178,33 @@ struct SpectralBandReplication { uint16_t f_tablenoise[6]; ///Frequency borders for the limiter uint16_t f_tablelim[30]; - unsigned num_patches; + AAC_SIGNE num_patches; uint8_t patch_num_subbands[6]; uint8_t patch_start_subband[6]; ///QMF low frequency input to the HF generator - DECLARE_ALIGNED(16, float, X_low)[32][40][2]; + DECLARE_ALIGNED(16, INTFLOAT, X_low)[32][40][2]; ///QMF output of the HF generator - DECLARE_ALIGNED(16, float, X_high)[64][40][2]; + DECLARE_ALIGNED(16, INTFLOAT, X_high)[64][40][2]; ///QMF values of the reconstructed signal - DECLARE_ALIGNED(16, float, X)[2][2][38][64]; + DECLARE_ALIGNED(16, INTFLOAT, X)[2][2][38][64]; ///Zeroth coefficient used to filter the subband signals - DECLARE_ALIGNED(16, float, alpha0)[64][2]; + DECLARE_ALIGNED(16, INTFLOAT, alpha0)[64][2]; ///First coefficient used to filter the subband signals - DECLARE_ALIGNED(16, float, alpha1)[64][2]; + DECLARE_ALIGNED(16, INTFLOAT, alpha1)[64][2]; ///Dequantized envelope scalefactors, remapped - float e_origmapped[7][48]; + AAC_FLOAT e_origmapped[7][48]; ///Dequantized noise scalefactors, remapped - float q_mapped[7][48]; + AAC_FLOAT q_mapped[7][48]; ///Sinusoidal presence, remapped uint8_t s_mapped[7][48]; ///Estimated envelope - float e_curr[7][48]; + AAC_FLOAT e_curr[7][48]; ///Amplitude adjusted noise scalefactors - float q_m[7][48]; + AAC_FLOAT q_m[7][48]; ///Sinusoidal levels - float s_m[7][48]; - float gain[7][48]; - DECLARE_ALIGNED(32, float, qmf_filter_scratch)[5][64]; + AAC_FLOAT s_m[7][48]; + AAC_FLOAT gain[7][48]; + DECLARE_ALIGNED(32, INTFLOAT, qmf_filter_scratch)[5][64]; FFTContext mdct_ana; FFTContext mdct; SBRDSPContext dsp; diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c index aa60de4eda..cc432b6534 100644 --- a/libavcodec/sbrdsp.c +++ b/libavcodec/sbrdsp.c @@ -20,6 +20,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define USE_FIXED 0 + +#include "aac.h" #include "config.h" #include "libavutil/attributes.h" #include "libavutil/intfloat.h" diff --git a/libavcodec/sbrdsp.h b/libavcodec/sbrdsp.h index 1c1bcdfa90..66852de618 100644 --- a/libavcodec/sbrdsp.h +++ b/libavcodec/sbrdsp.h @@ -22,29 +22,31 @@ #define AVCODEC_SBRDSP_H #include <stdint.h> +#include "aac_defines.h" +#include "libavutil/softfloat.h" typedef struct SBRDSPContext { - void (*sum64x5)(float *z); - float (*sum_square)(float (*x)[2], int n); - void (*neg_odd_64)(float *x); - void (*qmf_pre_shuffle)(float *z); - void (*qmf_post_shuffle)(float W[32][2], const float *z); - void (*qmf_deint_neg)(float *v, const float *src); - void (*qmf_deint_bfly)(float *v, const float *src0, const float *src1); - void (*autocorrelate)(const float x[40][2], float phi[3][2][2]); - void (*hf_gen)(float (*X_high)[2], const float (*X_low)[2], - const float alpha0[2], const float alpha1[2], - float bw, int start, int end); - void (*hf_g_filt)(float (*Y)[2], const float (*X_high)[40][2], - const float *g_filt, int m_max, intptr_t ixh); - void (*hf_apply_noise[4])(float (*Y)[2], const float *s_m, - const float *q_filt, int noise, + void (*sum64x5)(INTFLOAT *z); + AAC_FLOAT (*sum_square)(INTFLOAT (*x)[2], int n); + void (*neg_odd_64)(INTFLOAT *x); + void (*qmf_pre_shuffle)(INTFLOAT *z); + void (*qmf_post_shuffle)(INTFLOAT W[32][2], const INTFLOAT *z); + void (*qmf_deint_neg)(INTFLOAT *v, const INTFLOAT *src); + void (*qmf_deint_bfly)(INTFLOAT *v, const INTFLOAT *src0, const INTFLOAT *src1); + void (*autocorrelate)(const INTFLOAT x[40][2], AAC_FLOAT phi[3][2][2]); + void (*hf_gen)(INTFLOAT (*X_high)[2], const INTFLOAT (*X_low)[2], + const INTFLOAT alpha0[2], const INTFLOAT alpha1[2], + INTFLOAT bw, int start, int end); + void (*hf_g_filt)(INTFLOAT (*Y)[2], const INTFLOAT (*X_high)[40][2], + const AAC_FLOAT *g_filt, int m_max, intptr_t ixh); + void (*hf_apply_noise[4])(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m, + const AAC_FLOAT *q_filt, int noise, int kx, int m_max); } SBRDSPContext; -extern const float ff_sbr_noise_table[][2]; +extern const INTFLOAT AAC_RENAME(ff_sbr_noise_table)[][2]; -void ff_sbrdsp_init(SBRDSPContext *s); +void AAC_RENAME(ff_sbrdsp_init)(SBRDSPContext *s); void ff_sbrdsp_init_arm(SBRDSPContext *s); void ff_sbrdsp_init_x86(SBRDSPContext *s); void ff_sbrdsp_init_mips(SBRDSPContext *s); diff --git a/libavcodec/sbrdsp_fixed.c b/libavcodec/sbrdsp_fixed.c new file mode 100644 index 0000000000..5b7b7a6f9b --- /dev/null +++ b/libavcodec/sbrdsp_fixed.c @@ -0,0 +1,286 @@ +/* + * AAC Spectral Band Replication decoding functions + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2009-2010 Alex Converse <alex.converse@gmail.com> + * + * 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 + * + * Note: Rounding-to-nearest used unless otherwise stated + * + */ + +#define USE_FIXED 1 + +#include "aac.h" +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/intfloat.h" +#include "sbrdsp.h" + +static SoftFloat sbr_sum_square_c(int (*x)[2], int n) +{ + SoftFloat ret; + int64_t accu = 0; + int i, nz, round; + + for (i = 0; i < n; i += 2) { + accu += (int64_t)x[i + 0][0] * x[i + 0][0]; + accu += (int64_t)x[i + 0][1] * x[i + 0][1]; + accu += (int64_t)x[i + 1][0] * x[i + 1][0]; + accu += (int64_t)x[i + 1][1] * x[i + 1][1]; + } + + i = (int)(accu >> 32); + if (i == 0) { + nz = 1; + } else { + nz = 0; + while (FFABS(i) < 0x40000000) { + i <<= 1; + nz++; + } + nz = 32 - nz; + } + + round = 1 << (nz-1); + i = (int)((accu + round) >> nz); + i >>= 1; + ret = av_int2sf(i, 15 - nz); + + return ret; +} + +static void sbr_neg_odd_64_c(int *x) +{ + int i; + for (i = 1; i < 64; i += 2) + x[i] = -x[i]; +} + +static void sbr_qmf_pre_shuffle_c(int *z) +{ + int k; + z[64] = z[0]; + z[65] = z[1]; + for (k = 1; k < 32; k++) { + z[64+2*k ] = -z[64 - k]; + z[64+2*k+1] = z[ k + 1]; + } +} + +static void sbr_qmf_post_shuffle_c(int W[32][2], const int *z) +{ + int k; + for (k = 0; k < 32; k++) { + W[k][0] = -z[63-k]; + W[k][1] = z[k]; + } +} + +static void sbr_qmf_deint_neg_c(int *v, const int *src) +{ + int i; + for (i = 0; i < 32; i++) { + v[ i] = ( src[63 - 2*i ] + 0x10) >> 5; + v[63 - i] = (-src[63 - 2*i - 1] + 0x10) >> 5; + } +} + +static av_always_inline SoftFloat autocorr_calc(int64_t accu) +{ + int nz, mant, expo, round; + int i = (int)(accu >> 32); + if (i == 0) { + nz = 1; + } else { + nz = 0; + while (FFABS(i) < 0x40000000) { + i <<= 1; + nz++; + } + nz = 32-nz; + } + + round = 1 << (nz-1); + mant = (int)((accu + round) >> nz); + mant = (mant + 0x40)>>7; + mant <<= 6; + expo = nz + 15; + return av_int2sf(mant, 30 - expo); +} + +static av_always_inline void autocorrelate(const int x[40][2], SoftFloat phi[3][2][2], int lag) +{ + int i; + int64_t real_sum, imag_sum; + int64_t accu_re = 0, accu_im = 0; + + if (lag) { + for (i = 1; i < 38; i++) { + accu_re += (int64_t)x[i][0] * x[i+lag][0]; + accu_re += (int64_t)x[i][1] * x[i+lag][1]; + accu_im += (int64_t)x[i][0] * x[i+lag][1]; + accu_im -= (int64_t)x[i][1] * x[i+lag][0]; + } + + real_sum = accu_re; + imag_sum = accu_im; + + accu_re += (int64_t)x[ 0][0] * x[lag][0]; + accu_re += (int64_t)x[ 0][1] * x[lag][1]; + accu_im += (int64_t)x[ 0][0] * x[lag][1]; + accu_im -= (int64_t)x[ 0][1] * x[lag][0]; + + phi[2-lag][1][0] = autocorr_calc(accu_re); + phi[2-lag][1][1] = autocorr_calc(accu_im); + + if (lag == 1) { + accu_re = real_sum; + accu_im = imag_sum; + accu_re += (int64_t)x[38][0] * x[39][0]; + accu_re += (int64_t)x[38][1] * x[39][1]; + accu_im += (int64_t)x[38][0] * x[39][1]; + accu_im -= (int64_t)x[38][1] * x[39][0]; + + phi[0][0][0] = autocorr_calc(accu_re); + phi[0][0][1] = autocorr_calc(accu_im); + } + } else { + for (i = 1; i < 38; i++) { + accu_re += (int64_t)x[i][0] * x[i][0]; + accu_re += (int64_t)x[i][1] * x[i][1]; + } + real_sum = accu_re; + accu_re += (int64_t)x[ 0][0] * x[ 0][0]; + accu_re += (int64_t)x[ 0][1] * x[ 0][1]; + + phi[2][1][0] = autocorr_calc(accu_re); + + accu_re = real_sum; + accu_re += (int64_t)x[38][0] * x[38][0]; + accu_re += (int64_t)x[38][1] * x[38][1]; + + phi[1][0][0] = autocorr_calc(accu_re); + } +} + +static void sbr_autocorrelate_c(const int x[40][2], SoftFloat phi[3][2][2]) +{ + autocorrelate(x, phi, 0); + autocorrelate(x, phi, 1); + autocorrelate(x, phi, 2); +} + +static void sbr_hf_gen_c(int (*X_high)[2], const int (*X_low)[2], + const int alpha0[2], const int alpha1[2], + int bw, int start, int end) +{ + int alpha[4]; + int i; + int64_t accu; + + accu = (int64_t)alpha0[0] * bw; + alpha[2] = (int)((accu + 0x40000000) >> 31); + accu = (int64_t)alpha0[1] * bw; + alpha[3] = (int)((accu + 0x40000000) >> 31); + accu = (int64_t)bw * bw; + bw = (int)((accu + 0x40000000) >> 31); + accu = (int64_t)alpha1[0] * bw; + alpha[0] = (int)((accu + 0x40000000) >> 31); + accu = (int64_t)alpha1[1] * bw; + alpha[1] = (int)((accu + 0x40000000) >> 31); + + for (i = start; i < end; i++) { + accu = (int64_t)X_low[i][0] * 0x20000000; + accu += (int64_t)X_low[i - 2][0] * alpha[0]; + accu -= (int64_t)X_low[i - 2][1] * alpha[1]; + accu += (int64_t)X_low[i - 1][0] * alpha[2]; + accu -= (int64_t)X_low[i - 1][1] * alpha[3]; + X_high[i][0] = (int)((accu + 0x10000000) >> 29); + + accu = (int64_t)X_low[i][1] * 0x20000000; + accu += (int64_t)X_low[i - 2][1] * alpha[0]; + accu += (int64_t)X_low[i - 2][0] * alpha[1]; + accu += (int64_t)X_low[i - 1][1] * alpha[2]; + accu += (int64_t)X_low[i - 1][0] * alpha[3]; + X_high[i][1] = (int)((accu + 0x10000000) >> 29); + } +} + +static void sbr_hf_g_filt_c(int (*Y)[2], const int (*X_high)[40][2], + const SoftFloat *g_filt, int m_max, intptr_t ixh) +{ + int m, r; + int64_t accu; + + for (m = 0; m < m_max; m++) { + r = 1 << (22-g_filt[m].exp); + accu = (int64_t)X_high[m][ixh][0] * ((g_filt[m].mant + 0x40)>>7); + Y[m][0] = (int)((accu + r) >> (23-g_filt[m].exp)); + + accu = (int64_t)X_high[m][ixh][1] * ((g_filt[m].mant + 0x40)>>7); + Y[m][1] = (int)((accu + r) >> (23-g_filt[m].exp)); + } +} + +static av_always_inline void sbr_hf_apply_noise(int (*Y)[2], + const SoftFloat *s_m, + const SoftFloat *q_filt, + int noise, + int phi_sign0, + int phi_sign1, + int m_max) +{ + int m; + + for (m = 0; m < m_max; m++) { + int y0 = Y[m][0]; + int y1 = Y[m][1]; + noise = (noise + 1) & 0x1ff; + if (s_m[m].mant) { + int shift, round; + + shift = 22 - s_m[m].exp; + if (shift < 30) { + round = 1 << (shift-1); + y0 += (s_m[m].mant * phi_sign0 + round) >> shift; + y1 += (s_m[m].mant * phi_sign1 + round) >> shift; + } + } else { + int shift, round, tmp; + int64_t accu; + + shift = 22 - q_filt[m].exp; + if (shift < 30) { + round = 1 << (shift-1); + + accu = (int64_t)q_filt[m].mant * ff_sbr_noise_table_fixed[noise][0]; + tmp = (int)((accu + 0x40000000) >> 31); + y0 += (tmp + round) >> shift; + + accu = (int64_t)q_filt[m].mant * ff_sbr_noise_table_fixed[noise][1]; + tmp = (int)((accu + 0x40000000) >> 31); + y1 += (tmp + round) >> shift; + } + } + Y[m][0] = y0; + Y[m][1] = y1; + phi_sign1 = -phi_sign1; + } +} + +#include "sbrdsp_template.c" diff --git a/libavcodec/sbrdsp_template.c b/libavcodec/sbrdsp_template.c index 410671e143..b649dfd7ee 100644 --- a/libavcodec/sbrdsp_template.c +++ b/libavcodec/sbrdsp_template.c @@ -20,55 +20,55 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -static void sbr_sum64x5_c(float *z) +static void sbr_sum64x5_c(INTFLOAT *z) { int k; for (k = 0; k < 64; k++) { - float f = z[k] + z[k + 64] + z[k + 128] + z[k + 192] + z[k + 256]; + INTFLOAT f = z[k] + z[k + 64] + z[k + 128] + z[k + 192] + z[k + 256]; z[k] = f; } } -static void sbr_qmf_deint_bfly_c(float *v, const float *src0, const float *src1) +static void sbr_qmf_deint_bfly_c(INTFLOAT *v, const INTFLOAT *src0, const INTFLOAT *src1) { int i; for (i = 0; i < 64; i++) { - v[ i] = src0[i] - src1[63 - i]; - v[127 - i] = src0[i] + src1[63 - i]; + v[ i] = AAC_SRA_R((src0[i] - src1[63 - i]), 5); + v[127 - i] = AAC_SRA_R((src0[i] + src1[63 - i]), 5); } } -static void sbr_hf_apply_noise_0(float (*Y)[2], const float *s_m, - const float *q_filt, int noise, +static void sbr_hf_apply_noise_0(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m, + const AAC_FLOAT *q_filt, int noise, int kx, int m_max) { - sbr_hf_apply_noise(Y, s_m, q_filt, noise, 1.0, 0.0, m_max); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, (INTFLOAT)1.0, (INTFLOAT)0.0, m_max); } -static void sbr_hf_apply_noise_1(float (*Y)[2], const float *s_m, - const float *q_filt, int noise, +static void sbr_hf_apply_noise_1(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m, + const AAC_FLOAT *q_filt, int noise, int kx, int m_max) { - float phi_sign = 1 - 2 * (kx & 1); - sbr_hf_apply_noise(Y, s_m, q_filt, noise, 0.0, phi_sign, m_max); + INTFLOAT phi_sign = 1 - 2 * (kx & 1); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, (INTFLOAT)0.0, phi_sign, m_max); } -static void sbr_hf_apply_noise_2(float (*Y)[2], const float *s_m, - const float *q_filt, int noise, +static void sbr_hf_apply_noise_2(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m, + const AAC_FLOAT *q_filt, int noise, int kx, int m_max) { - sbr_hf_apply_noise(Y, s_m, q_filt, noise, -1.0, 0.0, m_max); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, (INTFLOAT)-1.0, (INTFLOAT)0.0, m_max); } -static void sbr_hf_apply_noise_3(float (*Y)[2], const float *s_m, - const float *q_filt, int noise, +static void sbr_hf_apply_noise_3(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m, + const AAC_FLOAT *q_filt, int noise, int kx, int m_max) { - float phi_sign = 1 - 2 * (kx & 1); - sbr_hf_apply_noise(Y, s_m, q_filt, noise, 0.0, -phi_sign, m_max); + INTFLOAT phi_sign = 1 - 2 * (kx & 1); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, (INTFLOAT)0.0, -phi_sign, m_max); } -av_cold void ff_sbrdsp_init(SBRDSPContext *s) +av_cold void AAC_RENAME(ff_sbrdsp_init)(SBRDSPContext *s) { s->sum64x5 = sbr_sum64x5_c; s->sum_square = sbr_sum_square_c; @@ -86,10 +86,12 @@ av_cold void ff_sbrdsp_init(SBRDSPContext *s) s->hf_apply_noise[2] = sbr_hf_apply_noise_2; s->hf_apply_noise[3] = sbr_hf_apply_noise_3; +#if !USE_FIXED if (ARCH_ARM) ff_sbrdsp_init_arm(s); if (ARCH_X86) ff_sbrdsp_init_x86(s); if (ARCH_MIPS) ff_sbrdsp_init_mips(s); +#endif /* !USE_FIXED */ } diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h index 4272363489..642a675d67 100644 --- a/libavutil/softfloat.h +++ b/libavutil/softfloat.h @@ -36,6 +36,14 @@ typedef struct SoftFloat{ int32_t exp; }SoftFloat; +static const SoftFloat FLOAT_0 = { 0, 0}; +static const SoftFloat FLOAT_05 = { 0x20000000, 0}; +static const SoftFloat FLOAT_1 = { 0x20000000, 1}; +static const SoftFloat FLOAT_EPSILON = { 0x29F16B12, -16}; +static const SoftFloat FLOAT_1584893192 = { 0x32B771ED, 1}; +static const SoftFloat FLOAT_100000 = { 0x30D40000, 17}; +static const SoftFloat FLOAT_0999999 = { 0x3FFFFBCE, 0}; + static inline av_const double av_sf2double(SoftFloat v) { v.exp -= ONE_BITS +1; if(v.exp > 0) return (double)v.mant * (double)(1 << v.exp); |