Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.xiph.org/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2016-11-23 03:38:24 +0300
committerJean-Marc Valin <jmvalin@jmvalin.ca>2016-11-23 21:30:22 +0300
commit107032fbdf8ea3d74367f80cc608eb96d4bcf53f (patch)
tree08439953e43b2725c9acc297975d583f7da7c256
parent98007c05189ad1d3639674f427049d766a1e44c5 (diff)
Makes the 24kHz analysis downsampling works for fixed-point
-rw-r--r--celt/arch.h2
-rw-r--r--src/analysis.c4
-rw-r--r--src/opus_encoder.c33
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)