ref: 82485dd2c4f4dfe8ed0d89eebd4e4f6c0a091532
parent: a4854afac86a3481374e5956813e2cdd797649d4
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Mon Jun 10 20:55:15 EDT 2024
Preserving 24-bit accuracy for fixed-point encoder
--- a/celt/arch.h
+++ b/celt/arch.h
@@ -144,6 +144,9 @@
#define RES2FLOAT(a) ((1.f/32768.f/256.)*(a))
#define INT16TORES(a) SHL32(EXTEND32(a), RES_SHIFT)
#define ADD_RES(a, b) ADD32(a, b)
+#define FLOAT2RES(a) float2int(32768.f*256.f*(a))
+#define RES2SIG(a) SHL32((a), SIG_SHIFT-RES_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_32_Q15(a,b)
#else
typedef opus_val16 opus_res;
#define RES_SHIFT 0
@@ -153,8 +156,13 @@
#define RES2FLOAT(a) ((1.f/32768.f)*(a))
#define INT16TORES(a) (a)
#define ADD_RES(a, b) SAT16(ADD32((a), (b)));
+#define FLOAT2RES(a) FLOAT2INT16(a)
+#define RES2SIG(a) SHL32(EXTEND32(a), SIG_SHIFT)
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
#endif
+#define RES2VAL16(a) RES2INT16(a)
+
#define celt_isnan(x) 0
#define Q15ONE 32767
@@ -313,6 +321,12 @@
#define RES2FLOAT(a) (a)
#define INT16TORES(a) ((a)*(1/CELT_SIG_SCALE))
#define ADD_RES(a, b) ADD32(a, b)
+#define FLOAT2RES(a) (a)
+#define RES2SIG(a) (CELT_SIG_SCALE*(a))
+#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b)
+
+#define RES2VAL16(a) (a)
+
#endif /* !FIXED_POINT */
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -139,7 +139,7 @@
int celt_encoder_get_size(int channels);
-int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
+int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
int arch);
@@ -229,7 +229,7 @@
int resampling_factor(opus_int32 rate);
-void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
+void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -513,7 +513,7 @@
}
-void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
+void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip)
{
int i;
@@ -529,11 +529,11 @@
{
for (i=0;i<N;i++)
{
- opus_val16 x;
- x = SCALEIN(pcmp[CC*i]);
+ celt_sig x;
+ x = RES2SIG(pcmp[CC*i]);
/* Apply pre-emphasis */
- inp[i] = SHL32(x, SIG_SHIFT) - m;
- m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT);
+ inp[i] = x - m;
+ m = MULT16_32_Q15(coef0, x);
}
*mem = m;
return;
@@ -545,7 +545,7 @@
OPUS_CLEAR(inp, N);
}
for (i=0;i<Nu;i++)
- inp[i*upsample] = SCALEIN(pcmp[CC*i]);
+ inp[i*upsample] = RES2SIG(pcmp[CC*i]);
#ifndef FIXED_POINT
if (clip)
@@ -567,7 +567,7 @@
celt_sig x, tmp;
x = inp[i];
/* Apply pre-emphasis */
- tmp = MULT16_16(coef2, x);
+ tmp = SHL32(MULT16_32_Q15(coef2, x), 15-SIG_SHIFT);
inp[i] = tmp + m;
m = MULT16_32_Q15(coef1, inp[i]) - MULT16_32_Q15(coef0, tmp);
}
@@ -576,11 +576,11 @@
{
for (i=0;i<N;i++)
{
- opus_val16 x;
+ celt_sig x;
x = inp[i];
/* Apply pre-emphasis */
- inp[i] = SHL32(x, SIG_SHIFT) - m;
- m = SHR32(MULT16_16(coef0, x), 15-SIG_SHIFT);
+ inp[i] = x - m;
+ m = MULT16_32_Q15(coef0, x);
}
}
*mem = m;
@@ -1597,7 +1597,7 @@
return target;
}
-int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
+int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
{
int i, c, N;
opus_int32 bits;
@@ -1813,8 +1813,8 @@
ALLOC(in, CC*(N+overlap), celt_sig);
- sample_max=MAX32(st->overlap_max, celt_maxabs16(pcm, C*(N-overlap)/st->upsample));
- st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample);
+ sample_max=MAX32(st->overlap_max, celt_maxabs_res(pcm, C*(N-overlap)/st->upsample));
+ st->overlap_max=celt_maxabs_res(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample);
sample_max=MAX32(sample_max, st->overlap_max);
#ifdef FIXED_POINT
silence = (sample_max==0);
@@ -2473,7 +2473,7 @@
} while (++c<CC);
/* We reuse freq[] as scratch space for the de-emphasis */
- deemphasis(out_mem, (opus_val16*)pcm, N, CC, st->upsample, mode->preemph, st->preemph_memD, 0);
+ deemphasis(out_mem, (opus_res*)pcm, N, CC, st->upsample, mode->preemph, st->preemph_memD, 0);
st->prefilter_period_old = st->prefilter_period;
st->prefilter_gain_old = st->prefilter_gain;
st->prefilter_tapset_old = st->prefilter_tapset;
@@ -2545,16 +2545,43 @@
#ifdef CUSTOM_MODES
#ifdef FIXED_POINT
+#ifdef ENABLE_RES24
int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
+ int j, ret, C, N;
+ VARDECL(opus_res, in);
+ ALLOC_STACK;
+
+ if (pcm==NULL)
+ return OPUS_BAD_ARG;
+
+ C = st->channels;
+ N = frame_size;
+ ALLOC(in, C*N, opus_res);
+
+ for (j=0;j<C*N;j++)
+ in[j] = INT16TORES(pcm[j]);
+
+ ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
+#ifdef RESYNTH
+ for (j=0;j<C*N;j++)
+ ((opus_int16*)pcm)[j]=RES2INT16(in[j]);
+#endif
+ RESTORE_STACK;
+ return ret;
+}
+#else
+int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
+{
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
}
+#endif
#ifndef DISABLE_FLOAT_API
int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{
int j, ret, C, N;
- VARDECL(opus_int16, in);
+ VARDECL(opus_res, in);
ALLOC_STACK;
if (pcm==NULL)
@@ -2562,15 +2589,15 @@
C = st->channels;
N = frame_size;
- ALLOC(in, C*N, opus_int16);
+ ALLOC(in, C*N, opus_res);
for (j=0;j<C*N;j++)
- in[j] = FLOAT2INT16(pcm[j]);
+ in[j] = FLOAT2RES(pcm[j]);
ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
#ifdef RESYNTH
for (j=0;j<C*N;j++)
- ((float*)pcm)[j]=in[j]*(1.f/32768.f);
+ ((float*)pcm)[j]=RES2FLOAT(in[j]);
#endif
RESTORE_STACK;
return ret;
--- a/celt/mathops.h
+++ b/celt/mathops.h
@@ -91,6 +91,26 @@
}
#endif
+#ifdef ENABLE_RES24
+static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len)
+{
+ int i;
+ opus_res maxval = 0;
+ opus_res minval = 0;
+ for (i=0;i<len;i++)
+ {
+ maxval = MAX32(maxval, x[i]);
+ minval = MIN32(minval, x[i]);
+ }
+ /* opus_res should never reach such amplitude, so we should be safe. */
+ celt_sig_assert(minval != -2147483648);
+ return MAX32(maxval,-minval);
+}
+#else
+#define celt_maxabs_res celt_maxabs16
+#endif
+
+
#ifndef OVERRIDE_CELT_MAXABS32
#ifdef FIXED_POINT
static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
--- a/silk/API.h
+++ b/silk/API.h
@@ -80,7 +80,7 @@
opus_int silk_Encode( /* O Returns error code */
void *encState, /* I/O State */
silk_EncControlStruct *encControl, /* I Control status */
- const opus_int16 *samplesIn, /* I Speech sample input vector */
+ const opus_res *samplesIn, /* I Speech sample input vector */
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
--- a/silk/enc_API.c
+++ b/silk/enc_API.c
@@ -144,7 +144,7 @@
opus_int silk_Encode( /* O Returns error code */
void *encState, /* I/O State */
silk_EncControlStruct *encControl, /* I Control status */
- const opus_int16 *samplesIn, /* I Speech sample input vector */
+ const opus_res *samplesIn, /* I Speech sample input vector */
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
@@ -282,7 +282,7 @@
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
for( n = 0; n < nSamplesFromInput; n++ ) {
- buf[ n ] = samplesIn[ 2 * n ];
+ buf[ n ] = RES2INT16(samplesIn[ 2 * n ]);
}
/* Making sure to start both resamplers from the same state when switching from mono to stereo */
if( psEnc->nPrevChannelsInternal == 1 && id==0 ) {
@@ -296,7 +296,7 @@
nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx;
nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
for( n = 0; n < nSamplesFromInput; n++ ) {
- buf[ n ] = samplesIn[ 2 * n + 1 ];
+ buf[ n ] = RES2INT16(samplesIn[ 2 * n + 1 ]);
}
ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@@ -305,7 +305,7 @@
} else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) {
/* Combine left and right channels before resampling */
for( n = 0; n < nSamplesFromInput; n++ ) {
- sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ];
+ sum = RES2INT16(samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]);
buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 );
}
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
@@ -323,7 +323,9 @@
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else {
celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
- silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
+ for( n = 0; n < nSamplesFromInput; n++ ) {
+ buf[n] = RES2INT16(samplesIn[n]);
+ }
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
--- a/src/mapping_matrix.c
+++ b/src/mapping_matrix.c
@@ -86,7 +86,7 @@
const MappingMatrix *matrix,
const float *input,
int input_rows,
- opus_val16 *output,
+ opus_res *output,
int output_row,
int output_rows,
int frame_size)
@@ -108,11 +108,7 @@
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
}
-#if defined(FIXED_POINT)
- output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
-#else
- output[output_rows * i] = (1/32768.f)*tmp;
-#endif
+ output[output_rows * i] = FLOAT2RES((1/32768.f)*tmp);
}
}
@@ -153,7 +149,7 @@
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
- opus_val16 *output,
+ opus_res *output,
int output_row,
int output_rows,
int frame_size)
@@ -182,7 +178,7 @@
#endif
}
#if defined(FIXED_POINT)
- output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
+ output[output_rows * i] = INT16TORES((tmp + 64) >> 7);
#else
output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
#endif
--- a/src/mapping_matrix.h
+++ b/src/mapping_matrix.h
@@ -66,7 +66,7 @@
const MappingMatrix *matrix,
const float *input,
int input_rows,
- opus_val16 *output,
+ opus_res *output,
int output_row,
int output_rows,
int frame_size
@@ -87,7 +87,7 @@
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
- opus_val16 *output,
+ opus_res *output,
int output_row,
int output_rows,
int frame_size
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -121,7 +121,7 @@
int first;
opus_val16 * energy_masking;
StereoWidthState width_mem;
- opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
+ opus_res delay_buffer[MAX_ENCODER_BUFFER*2];
#ifndef DISABLE_FLOAT_API
int detected_bandwidth;
int nb_no_activity_ms_Q1;
@@ -328,13 +328,52 @@
return toc;
}
-#ifndef FIXED_POINT
-static void silk_biquad_float(
- const opus_val16 *in, /* I: Input signal */
+#ifdef FIXED_POINT
+/* Second order ARMA filter, alternative implementation */
+void silk_biquad_res(
+ const opus_res *in, /* I input signal */
+ const opus_int32 *B_Q28, /* I MA coefficients [3] */
+ const opus_int32 *A_Q28, /* I AR coefficients [2] */
+ opus_int32 *S, /* I/O State vector [2] */
+ opus_res *out, /* O output signal */
+ const opus_int32 len, /* I signal length (must be even) */
+ int stride
+)
+{
+ /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+ opus_int k;
+ opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
+
+ /* Negate A_Q28 values and split in two parts */
+ A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
+ A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
+ A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
+ A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
+
+ for( k = 0; k < len; k++ ) {
+ /* S[ 0 ], S[ 1 ]: Q12 */
+ inval = RES2INT16(in[ k*stride ]);
+ out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
+
+ S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
+ S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
+
+ S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
+ S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
+
+ /* Scale back to Q0 and saturate */
+ out[ k*stride ] = INT16TORES( silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ) );
+ }
+}
+#else
+static void silk_biquad_res(
+ const opus_res *in, /* I: Input signal */
const opus_int32 *B_Q28, /* I: MA coefficients [3] */
const opus_int32 *A_Q28, /* I: AR coefficients [2] */
opus_val32 *S, /* I/O: State vector [2] */
- opus_val16 *out, /* O: Output signal */
+ opus_res *out, /* O: Output signal */
const opus_int32 len, /* I: Signal length (must be even) */
int stride
)
@@ -368,7 +407,7 @@
}
#endif
-static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch)
+static void hp_cutoff(const opus_res *in, opus_int32 cutoff_Hz, opus_res *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch)
{
opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
opus_int32 Fc_Q19, r_Q28, r_Q22;
@@ -391,7 +430,7 @@
A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) );
A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
-#ifdef FIXED_POINT
+#if defined(FIXED_POINT) && !defined(ENABLE_RES24)
if( channels == 1 ) {
silk_biquad_alt_stride1( in, B_Q28, A_Q28, hp_mem, out, len );
} else {
@@ -398,15 +437,15 @@
silk_biquad_alt_stride2( in, B_Q28, A_Q28, hp_mem, out, len, arch );
}
#else
- silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels );
+ silk_biquad_res( in, B_Q28, A_Q28, hp_mem, out, len, channels );
if( channels == 2 ) {
- silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
+ silk_biquad_res( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
}
#endif
}
#ifdef FIXED_POINT
-static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
+static void dc_reject(const opus_res *in, opus_int32 cutoff_Hz, opus_res *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
{
int c, i;
int shift;
@@ -418,10 +457,15 @@
for (i=0;i<len;i++)
{
opus_val32 x, y;
- x = SHL32(EXTEND32(in[channels*i+c]), 14);
+ x = SHL32((opus_val32)in[channels*i+c], 14-RES_SHIFT);
y = x-hp_mem[2*c];
hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
- out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
+#ifdef ENABLE_RES24
+ /* Don't saturate if we have the headroom to avoid it. */
+ out[channels*i+c] = PSHR32(y, 14-RES_SHIFT);
+#else
+ out[channels*i+c] = SATURATE(PSHR32(y, 14-RES_SHIFT), 32767);
+#endif
}
}
}
@@ -468,7 +512,7 @@
}
#endif
-static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
+static void stereo_fade(const opus_res *in, opus_res *out, opus_val16 g1, opus_val16 g2,
int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
{
int i;
@@ -485,8 +529,8 @@
w = MULT16_16_Q15(window[i*inc], window[i*inc]);
g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15);
- diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
- diff = MULT16_16_Q15(g, diff);
+ diff = HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]);
+ diff = MULT16_RES_Q15(g, diff);
out[i*channels] = out[i*channels] - diff;
out[i*channels+1] = out[i*channels+1] + diff;
}
@@ -493,14 +537,14 @@
for (;i<frame_size;i++)
{
opus_val32 diff;
- diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
- diff = MULT16_16_Q15(g2, diff);
+ diff = HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]);
+ diff = MULT16_RES_Q15(g2, diff);
out[i*channels] = out[i*channels] - diff;
out[i*channels+1] = out[i*channels+1] + diff;
}
}
-static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
+static void gain_fade(const opus_res *in, opus_res *out, opus_val16 g1, opus_val16 g2,
int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
{
int i;
@@ -517,7 +561,7 @@
w = MULT16_16_Q15(window[i*inc], window[i*inc]);
g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15);
- out[i] = MULT16_16_Q15(g, in[i]);
+ out[i] = MULT16_RES_Q15(g, in[i]);
}
} else {
for (i=0;i<overlap;i++)
@@ -526,14 +570,14 @@
w = MULT16_16_Q15(window[i*inc], window[i*inc]);
g = SHR32(MAC16_16(MULT16_16(w,g2),
Q15ONE-w, g1), 15);
- out[i*2] = MULT16_16_Q15(g, in[i*2]);
- out[i*2+1] = MULT16_16_Q15(g, in[i*2+1]);
+ out[i*2] = MULT16_RES_Q15(g, in[i*2]);
+ out[i*2+1] = MULT16_RES_Q15(g, in[i*2+1]);
}
}
c=0;do {
for (i=overlap;i<frame_size;i++)
{
- out[i*channels+c] = MULT16_16_Q15(g2, in[i*channels+c]);
+ out[i*channels+c] = MULT16_RES_Q15(g2, in[i*channels+c]);
}
}
while (++c<channels);
@@ -726,7 +770,7 @@
return new_size;
}
-opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
+opus_val16 compute_stereo_width(const opus_res *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
{
opus_val32 xx, xy, yy;
opus_val16 sqrt_xx, sqrt_yy;
@@ -747,23 +791,23 @@
opus_val32 pxy=0;
opus_val32 pyy=0;
opus_val16 x, y;
- x = pcm[2*i];
- y = pcm[2*i+1];
+ x = RES2VAL16(pcm[2*i]);
+ y = RES2VAL16(pcm[2*i+1]);
pxx = SHR32(MULT16_16(x,x),2);
pxy = SHR32(MULT16_16(x,y),2);
pyy = SHR32(MULT16_16(y,y),2);
- x = pcm[2*i+2];
- y = pcm[2*i+3];
+ x = RES2VAL16(pcm[2*i+2]);
+ y = RES2VAL16(pcm[2*i+3]);
pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2);
- x = pcm[2*i+4];
- y = pcm[2*i+5];
+ x = RES2VAL16(pcm[2*i+4]);
+ y = RES2VAL16(pcm[2*i+5]);
pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2);
- x = pcm[2*i+6];
- y = pcm[2*i+7];
+ x = RES2VAL16(pcm[2*i+6]);
+ y = RES2VAL16(pcm[2*i+7]);
pxx += SHR32(MULT16_16(x,x),2);
pxy += SHR32(MULT16_16(x,y),2);
pyy += SHR32(MULT16_16(y,y),2);
@@ -930,7 +974,7 @@
#ifndef DISABLE_FLOAT_API
-int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth)
+int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth)
{
int silence = 0;
opus_val32 sample_max = 0;
@@ -937,7 +981,7 @@
#ifdef MLP_TRAINING
return 0;
#endif
- sample_max = celt_maxabs16(pcm, frame_size*channels);
+ sample_max = celt_maxabs_res(pcm, frame_size*channels);
#ifdef FIXED_POINT
silence = (sample_max == 0);
@@ -950,7 +994,7 @@
}
#ifdef FIXED_POINT
-static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
+static opus_val32 compute_frame_energy(const opus_res *pcm, int frame_size, int channels, int arch)
{
int i;
opus_val32 sample_max;
@@ -960,7 +1004,7 @@
int len = frame_size*channels;
(void)arch;
/* Max amplitude in the signal */
- sample_max = celt_maxabs16(pcm, len);
+ sample_max = RES2INT16(celt_maxabs_res(pcm, len));
/* Compute the right shift required in the MAC to avoid an overflow */
max_shift = celt_ilog2(len);
@@ -968,7 +1012,7 @@
/* Compute the energy */
for (i=0; i<len; i++)
- energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift);
+ energy += SHR32(MULT16_16(RES2INT16(pcm[i]), RES2INT16(pcm[i])), shift);
/* Normalize energy by the frame size and left-shift back to the original position */
energy /= len;
@@ -1042,7 +1086,7 @@
return redundancy_bytes;
}
-static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
+static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 max_data_bytes,
int float_api, int first_frame,
#ifdef ENABLE_DRED
@@ -1054,7 +1098,7 @@
int redundancy, int celt_to_silk, int prefill,
opus_int32 equiv_rate, int to_celt);
-opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
+opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api)
@@ -1696,7 +1740,7 @@
}
}
-static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
+static opus_int32 opus_encode_frame_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 max_data_bytes,
int float_api, int first_frame,
#ifdef ENABLE_DRED
@@ -1729,8 +1773,8 @@
int delay_compensation;
int total_buffer;
opus_int activity = VAD_NO_DECISION;
- VARDECL(opus_val16, pcm_buf);
- VARDECL(opus_val16, tmp_prefill);
+ VARDECL(opus_res, pcm_buf);
+ VARDECL(opus_res, tmp_prefill);
SAVE_STACK;
st->rangeFinal = 0;
@@ -1791,7 +1835,7 @@
ec_enc_init(&enc, data, max_data_bytes-1);
- ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16);
+ ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_res);
OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels);
if (st->mode == MODE_CELT_ONLY)
@@ -1867,12 +1911,7 @@
if (st->mode != MODE_CELT_ONLY)
{
opus_int32 total_bitRate, celt_rate;
-#ifdef FIXED_POINT
- const opus_int16 *pcm_silk;
-#else
- VARDECL(opus_int16, pcm_silk);
- ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
-#endif
+ const opus_res *pcm_silk;
/* Distribute bits between SILK and CELT */
total_bitRate = 8 * bytes_target * frame_rate;
@@ -2025,23 +2064,13 @@
gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset,
0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs);
OPUS_CLEAR(st->delay_buffer, prefill_offset);
-#ifdef FIXED_POINT
pcm_silk = st->delay_buffer;
-#else
- for (i=0;i<st->encoder_buffer*st->channels;i++)
- pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
-#endif
silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, prefill, activity );
/* Prevent a second switch in the real encode call. */
st->silk_mode.opusCanSwitch = 0;
}
-#ifdef FIXED_POINT
pcm_silk = pcm_buf+total_buffer*st->channels;
-#else
- for (i=0;i<frame_size*st->channels;i++)
- pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]);
-#endif
ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0, activity );
if( ret ) {
/*fprintf (stderr, "SILK encode error: %d\n", ret);*/
@@ -2116,7 +2145,7 @@
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred));
}
- ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16);
+ ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_res);
if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0)
{
OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400);
@@ -2467,7 +2496,7 @@
{
int i, ret;
int frame_size;
- VARDECL(opus_int16, in);
+ VARDECL(opus_res, in);
ALLOC_STACK;
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
@@ -2476,10 +2505,10 @@
RESTORE_STACK;
return OPUS_BAD_ARG;
}
- ALLOC(in, frame_size*st->channels, opus_int16);
+ ALLOC(in, frame_size*st->channels, opus_res);
for (i=0;i<frame_size*st->channels;i++)
- in[i] = FLOAT2INT16(pcm[i]);
+ in[i] = FLOAT2RES(pcm[i]);
ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
RESTORE_STACK;
@@ -2487,14 +2516,40 @@
}
#endif
+#ifdef ENABLE_RES24
opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
- unsigned char *data, opus_int32 out_data_bytes)
+ unsigned char *data, opus_int32 max_data_bytes)
{
+ int i, ret;
int frame_size;
+ VARDECL(opus_res, in);
+ ALLOC_STACK;
+
frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
- return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16,
+ if (frame_size <= 0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+ ALLOC(in, frame_size*st->channels, opus_res);
+
+ for (i=0;i<frame_size*st->channels;i++)
+ in[i] = INT16TORES(pcm[i]);
+ ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 1);
+ RESTORE_STACK;
+ return ret;
+}
+#else
+opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
+ unsigned char *data, opus_int32 max_data_bytes)
+{
+ int frame_size;
+ frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+ return opus_encode_native(st, pcm, frame_size, data, max_data_bytes, 16,
pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
}
+#endif /* ENABLE_RES24 */
#else
opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -236,7 +236,7 @@
opus_val32 bandE[21];
opus_val16 maskLogE[3][21];
VARDECL(opus_val32, in);
- VARDECL(opus_val16, x);
+ VARDECL(opus_res, x);
VARDECL(opus_val32, freq);
SAVE_STACK;
@@ -250,7 +250,7 @@
break;
ALLOC(in, frame_size+overlap, opus_val32);
- ALLOC(x, len, opus_val16);
+ ALLOC(x, len, opus_res);
ALLOC(freq, freq_size, opus_val32);
channel_pos(channels, pos);
@@ -819,7 +819,7 @@
int s;
char *ptr;
int tot_size;
- VARDECL(opus_val16, buf);
+ VARDECL(opus_res, buf);
VARDECL(opus_val16, bandSMR);
unsigned char tmp_data[MS_FRAME_TMP];
OpusRepacketizer rp;
@@ -862,7 +862,7 @@
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
- ALLOC(buf, 2*frame_size, opus_val16);
+ ALLOC(buf, 2*frame_size, opus_res);
coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1);
@@ -1014,7 +1014,7 @@
#if !defined(DISABLE_FLOAT_API)
static void opus_copy_channel_in_float(
- opus_val16 *dst,
+ opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
@@ -1028,16 +1028,12 @@
(void)user_data;
float_src = (const float *)src;
for (i=0;i<frame_size;i++)
-#if defined(FIXED_POINT)
- dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
-#else
- dst[i*dst_stride] = float_src[i*src_stride+src_channel];
-#endif
+ dst[i*dst_stride] = FLOAT2RES(float_src[i*src_stride+src_channel]);
}
#endif
static void opus_copy_channel_in_short(
- opus_val16 *dst,
+ opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
@@ -1051,11 +1047,7 @@
(void)user_data;
short_src = (const opus_int16 *)src;
for (i=0;i<frame_size;i++)
-#if defined(FIXED_POINT)
- dst[i*dst_stride] = short_src[i*src_stride+src_channel];
-#else
- dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
-#endif
+ dst[i*dst_stride] = INT16TORES(short_src[i*src_stride+src_channel]);
}
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -125,7 +125,7 @@
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
typedef void (*opus_copy_channel_in_func)(
- opus_val16 *dst,
+ opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
@@ -174,13 +174,13 @@
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
-int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth);
+int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
-opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
+opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api);
--- a/src/opus_projection_encoder.c
+++ b/src/opus_projection_encoder.c
@@ -47,7 +47,7 @@
#if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_in_float(
- opus_val16 *dst,
+ opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
@@ -62,7 +62,7 @@
#endif
static void opus_projection_copy_channel_in_short(
- opus_val16 *dst,
+ opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
--- a/tests/test_opus_projection.c
+++ b/tests/test_opus_projection.c
@@ -52,17 +52,12 @@
#define SIMPLE_MATRIX_OUTPUT_SIZE 40
int assert_is_equal(
- const opus_val16 *a, const opus_int16 *b, int size, opus_int16 tolerance)
+ const opus_res *a, const opus_int16 *b, int size, opus_int16 tolerance)
{
int i;
for (i = 0; i < size; i++)
{
-#ifdef FIXED_POINT
- opus_int16 val = a[i];
-#else
- opus_int16 val = FLOAT2INT16(a[i]);
-#endif
- if (abs(val - b[i]) > tolerance)
+ if (abs(RES2INT16(a[i]) - b[i]) > tolerance)
return 1;
}
return 0;
@@ -95,7 +90,7 @@
int i, ret;
opus_int32 simple_matrix_size;
opus_res *input_pcm;
- opus_val16 *output_val16;
+ opus_res *output_pcm;
opus_int16 *output_int16;
MappingMatrix *simple_matrix;
@@ -102,7 +97,7 @@
/* Allocate input/output buffers. */
input_pcm = (opus_res *)opus_alloc(sizeof(opus_res) * SIMPLE_MATRIX_INPUT_SIZE);
output_int16 = (opus_int16 *)opus_alloc(sizeof(opus_int16) * SIMPLE_MATRIX_OUTPUT_SIZE);
- output_val16 = (opus_val16 *)opus_alloc(sizeof(opus_val16) * SIMPLE_MATRIX_OUTPUT_SIZE);
+ output_pcm = (opus_res *)opus_alloc(sizeof(opus_res) * SIMPLE_MATRIX_OUTPUT_SIZE);
/* Initialize matrix */
simple_matrix_size = mapping_matrix_get_size(simple_matrix_params.rows,
@@ -123,14 +118,14 @@
/* _in_short */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
- output_val16[i] = 0;
+ output_pcm[i] = 0;
for (i = 0; i < simple_matrix->rows; i++)
{
mapping_matrix_multiply_channel_in_short(simple_matrix,
- input_int16, simple_matrix->cols, &output_val16[i], i,
+ input_int16, simple_matrix->cols, &output_pcm[i], i,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
- ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
+ ret = assert_is_equal(output_pcm, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
@@ -150,27 +145,27 @@
#if !defined(DISABLE_FLOAT_API) && !defined(FIXED_POINT)
/* _in_float */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
- output_val16[i] = 0;
+ output_pcm[i] = 0;
for (i = 0; i < simple_matrix->rows; i++)
{
mapping_matrix_multiply_channel_in_float(simple_matrix,
- input_pcm, simple_matrix->cols, &output_val16[i], i,
+ input_pcm, simple_matrix->cols, &output_pcm[i], i,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
- ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
+ ret = assert_is_equal(output_pcm, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
/* _out_float */
for (i = 0; i < SIMPLE_MATRIX_OUTPUT_SIZE; i++)
- output_val16[i] = 0;
+ output_pcm[i] = 0;
for (i = 0; i < simple_matrix->cols; i++)
{
mapping_matrix_multiply_channel_out_float(simple_matrix,
- &input_pcm[i], i, simple_matrix->cols, output_val16,
+ &input_pcm[i], i, simple_matrix->cols, output_pcm,
simple_matrix->rows, SIMPLE_MATRIX_FRAME_SIZE);
}
- ret = assert_is_equal(output_val16, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
+ ret = assert_is_equal(output_pcm, expected_output_int16, SIMPLE_MATRIX_OUTPUT_SIZE, ERROR_TOLERANCE);
if (ret)
test_failed();
#endif
@@ -177,7 +172,7 @@
opus_free(input_pcm);
opus_free(output_int16);
- opus_free(output_val16);
+ opus_free(output_pcm);
opus_free(simple_matrix);
}
--
⑨