diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-11-23 03:38:24 +0300 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-11-23 21:30:22 +0300 |
commit | 107032fbdf8ea3d74367f80cc608eb96d4bcf53f (patch) | |
tree | 08439953e43b2725c9acc297975d583f7da7c256 | |
parent | 98007c05189ad1d3639674f427049d766a1e44c5 (diff) |
Makes the 24kHz analysis downsampling works for fixed-point
-rw-r--r-- | celt/arch.h | 2 | ||||
-rw-r--r-- | src/analysis.c | 4 | ||||
-rw-r--r-- | src/opus_encoder.c | 33 |
3 files changed, 24 insertions, 15 deletions
diff --git a/celt/arch.h b/celt/arch.h index 9eb37d8f..9eedf74d 100644 --- a/celt/arch.h +++ b/celt/arch.h @@ -101,6 +101,7 @@ static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line) typedef opus_int16 opus_val16; typedef opus_int32 opus_val32; +typedef opus_int64 opus_val64; typedef opus_val32 celt_sig; typedef opus_val16 celt_norm; @@ -158,6 +159,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { typedef float opus_val16; typedef float opus_val32; +typedef float opus_val64; typedef float celt_sig; typedef float celt_norm; diff --git a/src/analysis.c b/src/analysis.c index 3a9cc3ad..350b122f 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -484,6 +484,10 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt the energy above 12 kHz. */ { float E = hp_ener*(1./(240*240)); +#ifdef FIXED_POINT + /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */ + E *= ((opus_int32)1 << 2*SIG_SHIFT)*256.f; +#endif maxE = MAX32(maxE, E); tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); E = MAX32(E, tonal->meanE[b]); diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 09296d59..927eef36 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -578,17 +578,16 @@ static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int m #define PCM2VAL(x) SCALEIN(x) #endif -#ifndef FIXED_POINT -float silk_resampler_down2_float( +float silk_resampler_down2_hp( opus_val32 *S, /* I/O State vector [ 2 ] */ - opus_val16 *out, /* O Output signal [ floor(len/2) ] */ - const opus_val16 *in, /* I Input signal [ len ] */ + opus_val32 *out, /* O Output signal [ floor(len/2) ] */ + const opus_val32 *in, /* I Input signal [ len ] */ int inLen /* I Number of input samples */ ) { int k, len2 = inLen/2; opus_val32 in32, out32, out32_hp, Y, X; - float hp_ener = 0; + opus_val64 hp_ener = 0; /* Internal variables and state are in Q10 format */ for( k = 0; k < len2; k++ ) { /* Convert to Q10 */ @@ -596,7 +595,7 @@ float silk_resampler_down2_float( /* All-pass section for even input sample */ Y = SUB32( in32, S[ 0 ] ); - X = 0.6074371f*Y; + X = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y); out32 = ADD32( S[ 0 ], X ); S[ 0 ] = ADD32( in32, X ); out32_hp = out32; @@ -605,24 +604,27 @@ float silk_resampler_down2_float( /* All-pass section for odd input sample, and add to output of previous section */ Y = SUB32( in32, S[ 1 ] ); - X = 0.15063f*Y; + X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y); out32 = ADD32( out32, S[ 1 ] ); out32 = ADD32( out32, X ); S[ 1 ] = ADD32( in32, X ); Y = SUB32( -in32, S[ 2 ] ); - X = 0.15063f*Y; + X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y); out32_hp = ADD32( out32_hp, S[ 2 ] ); out32_hp = ADD32( out32_hp, X ); S[ 2 ] = ADD32( -in32, X ); - hp_ener += out32_hp*out32_hp; + hp_ener += out32_hp*(opus_val64)out32_hp; /* Add, convert back to int16 and store to output */ - out[ k ] = .5*out32; + out[ k ] = HALF32(out32); } +#ifdef FIXED_POINT + /* len2 can be up to 480, so we shift by 8 more to make it fit. */ + hp_ener = hp_ener >> (2*SIG_SHIFT + 8); +#endif return hp_ener; } -#endif opus_val32 downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) { @@ -660,18 +662,19 @@ opus_val32 downmix_float(const void *_x, opus_val32 *sub, int subframe, int offs } #endif -float S[3]; +opus_val32 S[3]; opus_val32 downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C) { - VARDECL(opus_val16, tmp); + VARDECL(opus_val32, tmp); const opus_int16 *x; opus_val32 scale; int j; ALLOC_STACK; + if (subframe==0) return 0; subframe *= 2; offset *= 2; - ALLOC(tmp, subframe, opus_val16); + ALLOC(tmp, subframe, opus_val32); x = (const opus_int16 *)_x; for (j=0;j<subframe;j++) @@ -700,7 +703,7 @@ opus_val32 downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset scale /= 2; for (j=0;j<subframe;j++) tmp[j] *= scale; - return silk_resampler_down2_float(S, sub, tmp, subframe); + return silk_resampler_down2_hp(S, sub, tmp, subframe); } opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs) |