static void kf_bfly2( kiss_fft_cpx * Fout, int m, int N ) { kiss_fft_cpx * Fout2; int i; (void)m; #ifdef CUSTOM_MODES if (m==1) { celt_assert(m==1); for (i=0;i<N;i++) { kiss_fft_cpx t; Fout2 = Fout + 1; t = *Fout2; C_SUB( *Fout2 , *Fout , t ); C_ADDTO( *Fout , t ); Fout += 2; } } else #endif { opus_val16 tw; tw = QCONST16(0.7071067812f, 15); /* We know that m==4 here because the radix-2 is just after a radix-4 */ celt_assert(m==4); for (i=0;i<N;i++) { kiss_fft_cpx t; Fout2 = Fout + 4; t = Fout2[0]; C_SUB( Fout2[0] , Fout[0] , t ); C_ADDTO( Fout[0] , t ); t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw); t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw); C_SUB( Fout2[1] , Fout[1] , t ); C_ADDTO( Fout[1] , t ); t.r = Fout2[2].i; t.i = -Fout2[2].r; C_SUB( Fout2[2] , Fout[2] , t ); C_ADDTO( Fout[2] , t ); t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw); t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw); C_SUB( Fout2[3] , Fout[3] , t ); C_ADDTO( Fout[3] , t ); Fout += 8; } } }
/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness with this approximation is important because it has an impact on the bit allocation */ static opus_int16 bitexact_cos(opus_int16 x) { opus_int32 tmp; opus_int16 x2; tmp = (4096+((opus_int32)(x)*(x)))>>13; celt_assert(tmp<=32767); x2 = tmp; x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); celt_assert(x2<=32766); return 1+x2; }
void _celt_autocorr( const opus_val16 *x, /* in: [0...n-1] samples x */ opus_val32 *ac, /* out: [0...lag-1] ac values */ const opus_val16 *window, int overlap, int lag, int n ) { opus_val32 d; int i; VARDECL(opus_val16, xx); SAVE_STACK; ALLOC(xx, n, opus_val16); celt_assert(n>0); celt_assert(overlap>=0); for (i=0;i<n;i++) xx[i] = x[i]; for (i=0;i<overlap;i++) { xx[i] = MULT16_16_Q15(x[i],window[i]); xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); } #ifdef FIXED_POINT { opus_val32 ac0=0; int shift; for(i=0;i<n;i++) ac0 += SHR32(MULT16_16(xx[i],xx[i]),9); ac0 += 1+n; shift = celt_ilog2(ac0)-30+10; shift = (shift+1)/2; for(i=0;i<n;i++) xx[i] = VSHR32(xx[i], shift); } #endif while (lag>=0) { for (i = lag, d = 0; i < n; i++) d += xx[i] * xx[i-lag]; ac[lag] = d; /*printf ("%f ", ac[lag]);*/ lag--; } /*printf ("\n");*/ ac[0] += 10; RESTORE_STACK; }
void mapping_matrix_multiply_channel_out_short( const MappingMatrix *matrix, const opus_val16 *input, int input_row, int input_rows, opus_int16 *output, int output_rows, int frame_size) { /* Matrix data is ordered col-wise. */ opus_int16* matrix_data; int i, row; opus_int32 input_sample; celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); matrix_data = mapping_matrix_get_data(matrix); for (i = 0; i < frame_size; i++) { #if defined(FIXED_POINT) input_sample = (opus_int32)input[input_rows * i]; #else input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]); #endif for (row = 0; row < output_rows; row++) { opus_int32 tmp = (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] * input_sample; output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15; } } }
void mapping_matrix_multiply_channel_out_float( const MappingMatrix *matrix, const opus_val16 *input, int input_row, int input_rows, float *output, int output_rows, int frame_size ) { /* Matrix data is ordered col-wise. */ opus_int16* matrix_data; int i, row; float input_sample; celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); matrix_data = mapping_matrix_get_data(matrix); for (i = 0; i < frame_size; i++) { #if defined(FIXED_POINT) input_sample = (1/32768.f)*input[input_rows * i]; #else input_sample = input[input_rows * i]; #endif for (row = 0; row < output_rows; row++) { float tmp = (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] * input_sample; output[MATRIX_INDEX(output_rows, row, i)] += tmp; } } }
void mapping_matrix_multiply_channel_in_float( const MappingMatrix *matrix, const float *input, int input_rows, opus_val16 *output, int output_row, int output_rows, int frame_size) { /* Matrix data is ordered col-wise. */ opus_int16* matrix_data; int i, col; celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); matrix_data = mapping_matrix_get_data(matrix); for (i = 0; i < frame_size; i++) { float tmp = 0; for (col = 0; col < input_rows; col++) { tmp += 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 } }
/* Entropy code the mid/side quantization indices */ void silk_stereo_encode_pred( ec_enc *psRangeEnc, /* I/O Compressor data structure */ opus_int8 ix[ 2 ][ 3 ] /* I Quantization indices */ ) { opus_int n; /* Entropy coding */ n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; celt_assert( n < 25 ); ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); for( n = 0; n < 2; n++ ) { celt_assert( ix[ n ][ 0 ] < 3 ); celt_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); } }
/* 2 -> sine window from pi/2 to pi */ void silk_apply_sine_window_FLP( silk_float px_win[], /* O Pointer to windowed signal */ const silk_float px[], /* I Pointer to input signal */ const opus_int win_type, /* I Selects a window type */ const opus_int length /* I Window length, multiple of 4 */ ) { opus_int k; silk_float freq, c, S0, S1; celt_assert( win_type == 1 || win_type == 2 ); /* Length must be multiple of 4 */ celt_assert( ( length & 3 ) == 0 ); freq = PI / ( length + 1 ); /* Approximation of 2 * cos(f) */ c = 2.0f - freq * freq; /* Initialize state */ if( win_type < 2 ) { /* Start from 0 */ S0 = 0.0f; /* Approximation of sin(f) */ S1 = freq; } else { /* Start from 1 */ S0 = 1.0f; /* Approximation of cos(f) */ S1 = 0.5f * c; } /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ /* 4 samples at a time */ for( k = 0; k < length; k += 4 ) { px_win[ k + 0 ] = px[ k + 0 ] * 0.5f * ( S0 + S1 ); px_win[ k + 1 ] = px[ k + 1 ] * S1; S0 = c * S1 - S0; px_win[ k + 2 ] = px[ k + 2 ] * 0.5f * ( S1 + S0 ); px_win[ k + 3 ] = px[ k + 3 ] * S0; S1 = c * S0 - S1; } }
/* Autocorrelations for a warped frequency axis */ void silk_warped_autocorrelation_FIX_c( opus_int32 *corr, /* O Result [order + 1] */ opus_int *scale, /* O Scaling of the correlation vector */ const opus_int16 *input, /* I Input data to correlate */ const opus_int warping_Q16, /* I Warping coefficient */ const opus_int length, /* I Length of input */ const opus_int order /* I Correlation order (even) */ ) { opus_int n, i, lsh; opus_int32 tmp1_QS, tmp2_QS; opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* Order must be even */ celt_assert( ( order & 1 ) == 0 ); silk_assert( 2 * QS - QC >= 0 ); /* Loop over samples */ for( n = 0; n < length; n++ ) { tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); /* Loop over allpass sections */ for( i = 0; i < order; i += 2 ) { /* Output of allpass section */ tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); state_QS[ i ] = tmp1_QS; corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); /* Output of allpass section */ tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); state_QS[ i + 1 ] = tmp2_QS; corr_QC[ i + 1 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); } state_QS[ order ] = tmp1_QS; corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); } lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); *scale = -( QC + lsh ); silk_assert( *scale >= -30 && *scale <= 12 ); if( lsh >= 0 ) { for( i = 0; i < order + 1; i++ ) { corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); } } else { for( i = 0; i < order + 1; i++ ) { corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); } } silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ }
opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len) { OpusRepacketizer rp; opus_int32 ret; if (len < 1) return OPUS_BAD_ARG; opus_repacketizer_init(&rp); ret = opus_repacketizer_cat(&rp, data, len); if (ret < 0) return ret; ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0); celt_assert(ret > 0 && ret <= len); return ret; }
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){ unsigned ft; unsigned s; int ftb; /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/ celt_assert(_ft>1); _ft--; ftb=EC_ILOG(_ft); if(ftb>EC_UINT_BITS){ opus_uint32 t; ftb-=EC_UINT_BITS; ft=(unsigned)(_ft>>ftb)+1; s=ec_decode(_this,ft); ec_dec_update(_this,s,s+1,ft); t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb); if(t<=_ft)return t; _this->error=1; return _ft; }
void mapping_matrix_init(MappingMatrix * const matrix, int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size) { int i; opus_int16 *ptr; #if !defined(ENABLE_ASSERTIONS) (void)data_size; #endif celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16))); matrix->rows = rows; matrix->cols = cols; matrix->gain = gain; ptr = mapping_matrix_get_data(matrix); for (i = 0; i < rows * cols; i++) { ptr[i] = data[i]; } }
void mapping_matrix_multiply_channel_in_short( const MappingMatrix *matrix, const opus_int16 *input, int input_rows, opus_val16 *output, int output_row, int output_rows, int frame_size) { /* Matrix data is ordered col-wise. */ opus_int16* matrix_data; int i, col; celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows); matrix_data = mapping_matrix_get_data(matrix); for (i = 0; i < frame_size; i++) { opus_val32 tmp = 0; for (col = 0; col < input_rows; col++) { #if defined(FIXED_POINT) tmp += ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8; #else tmp += matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] * input[MATRIX_INDEX(input_rows, col, i)]; #endif } #if defined(FIXED_POINT) output[output_rows * i] = (opus_int16)((tmp + 64) >> 7); #else output[output_rows * i] = (1/(32768.f*32768.f))*tmp; #endif } }
silk_float silk_schur_FLP( /* O returns residual energy */ silk_float refl_coef[], /* O reflection coefficients (length order) */ const silk_float auto_corr[], /* I autocorrelation sequence (length order+1) */ opus_int order /* I order */ ) { opus_int k, n; double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; double Ctmp1, Ctmp2, rc_tmp; celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC ); /* Copy correlations */ k = 0; do { C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ]; } while( ++k <= order ); for( k = 0; k < order; k++ ) { /* Get reflection coefficient */ rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f ); /* Save the output */ refl_coef[ k ] = (silk_float)rc_tmp; /* Update correlations */ for( n = 0; n < order - k; n++ ) { Ctmp1 = C[ n + k + 1 ][ 0 ]; Ctmp2 = C[ n ][ 1 ]; C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp; C[ n ][ 1 ] = Ctmp2 + Ctmp1 * rc_tmp; } } /* Return residual energy */ return (silk_float)C[ 0 ][ 1 ]; }
ec_uint32 ec_dec_uint(ec_dec *_this,ec_uint32 _ft){ ec_uint32 t; unsigned ft; unsigned s; int ftb; t=0; /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/ celt_assert(_ft>1); _ft--; ftb=EC_ILOG(_ft); if(ftb>EC_UNIT_BITS){ ftb-=EC_UNIT_BITS; ft=(unsigned)(_ft>>ftb)+1; s=ec_decode(_this,ft); ec_dec_update(_this,s,s+1,ft); t=t<<EC_UNIT_BITS|s; t = t<<ftb|ec_dec_bits(_this,ftb); if (t>_ft) { celt_notify("uint decode error"); t = _ft; } return t; } else {
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, opus_int32 *packet_offset, int soft_clip) { int i, nb_samples; int count, offset; unsigned char toc; int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; /* 48 x 2.5 ms = 120 ms */ opus_int16 size[48]; if (decode_fec<0 || decode_fec>1) return OPUS_BAD_ARG; /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) return OPUS_BAD_ARG; if (len==0 || data==NULL) { int pcm_count=0; do { int ret; ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); if (ret<0) return ret; pcm_count += ret; } while (pcm_count < frame_size); celt_assert(pcm_count == frame_size); if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) OPUS_PRINT_INT(pcm_count); st->last_packet_duration = pcm_count; return pcm_count; } else if (len<0) return OPUS_BAD_ARG; packet_mode = opus_packet_get_mode(data); packet_bandwidth = opus_packet_get_bandwidth(data); packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); packet_stream_channels = opus_packet_get_nb_channels(data); count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, size, &offset, packet_offset); if (count<0) return count; data += offset; if (decode_fec) { int duration_copy; int ret; /* If no FEC can be present, run the PLC (recursive call) */ if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); /* Otherwise, run the PLC on everything except the size for which we might have FEC */ duration_copy = st->last_packet_duration; if (frame_size-packet_frame_size!=0) { ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); if (ret<0) { st->last_packet_duration = duration_copy; return ret; } celt_assert(ret==frame_size-packet_frame_size); } /* Complete with FEC */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), packet_frame_size, 1); if (ret<0) return ret; else { if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) OPUS_PRINT_INT(frame_size); st->last_packet_duration = frame_size; return frame_size; } } if (count*packet_frame_size > frame_size) return OPUS_BUFFER_TOO_SMALL; /* Update the state as the last step to avoid updating it on an invalid packet */ st->mode = packet_mode; st->bandwidth = packet_bandwidth; st->frame_size = packet_frame_size; st->stream_channels = packet_stream_channels; nb_samples=0; for (i=0; i<count; i++) { int ret; ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); if (ret<0) return ret; celt_assert(ret==packet_frame_size); data += size[i]; nb_samples += ret; } st->last_packet_duration = nb_samples; if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) OPUS_PRINT_INT(nb_samples); #ifndef FIXED_POINT if (soft_clip) opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); else st->softclip_mem[0]=st->softclip_mem[1]=0; #endif return nb_samples; }
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen, int self_delimited, int pad) { int i, count; opus_int32 tot_size; opus_int16 *len; const unsigned char **frames; unsigned char * ptr; if (begin<0 || begin>=end || end>rp->nb_frames) { /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ return OPUS_BAD_ARG; } count = end-begin; len = rp->len+begin; frames = rp->frames+begin; if (self_delimited) tot_size = 1 + (len[count-1]>=252); else tot_size = 0; ptr = data; if (count==1) { /* Code 0 */ tot_size += len[0]+1; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *ptr++ = rp->toc&0xFC; } else if (count==2) { if (len[1] == len[0]) { /* Code 1 */ tot_size += 2*len[0]+1; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *ptr++ = (rp->toc&0xFC) | 0x1; } else { /* Code 2 */ tot_size += len[0]+len[1]+2+(len[0]>=252); if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *ptr++ = (rp->toc&0xFC) | 0x2; ptr += encode_size(len[0], ptr); } } if (count > 2 || (pad && tot_size < maxlen)) { /* Code 3 */ int vbr; int pad_amount=0; /* Restart the process for the padding case */ ptr = data; if (self_delimited) tot_size = 1 + (len[count-1]>=252); else tot_size = 0; vbr = 0; for (i=1;i<count;i++) { if (len[i] != len[0]) { vbr=1; break; } } if (vbr) { tot_size += 2; for (i=0;i<count-1;i++) tot_size += 1 + (len[i]>=252) + len[i]; tot_size += len[count-1]; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *ptr++ = (rp->toc&0xFC) | 0x3; *ptr++ = count | 0x80; } else { tot_size += count*len[0]+2; if (tot_size > maxlen) return OPUS_BUFFER_TOO_SMALL; *ptr++ = (rp->toc&0xFC) | 0x3; *ptr++ = count; } pad_amount = pad ? (maxlen-tot_size) : 0; if (pad_amount != 0) { int nb_255s; data[1] |= 0x40; nb_255s = (pad_amount-1)/255; for (i=0;i<nb_255s;i++) *ptr++ = 255; *ptr++ = pad_amount-255*nb_255s-1; tot_size += pad_amount; } if (vbr) { for (i=0;i<count-1;i++) ptr += encode_size(len[i], ptr); } } if (self_delimited) { int sdlen = encode_size(len[count-1], ptr); ptr += sdlen; } /* Copy the actual data */ for (i=0;i<count;i++) { /* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place padding from opus_packet_pad or opus_packet_unpad(). */ celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); OPUS_MOVE(ptr, frames[i], len[i]); ptr += len[i]; } if (pad) { /* Fill padding with zeros. */ while (ptr<data+maxlen) *ptr++=0; } return tot_size; }
static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix) { int i, b; const kiss_fft_state *kfft; VARDECL(kiss_fft_cpx, in); VARDECL(kiss_fft_cpx, out); int N = 480, N2=240; float * OPUS_RESTRICT A = tonal->angle; float * OPUS_RESTRICT dA = tonal->d_angle; float * OPUS_RESTRICT d2A = tonal->d2_angle; VARDECL(float, tonality); VARDECL(float, noisiness); float band_tonality[NB_TBANDS]; float logE[NB_TBANDS]; float BFCC[8]; float features[25]; float frame_tonality; float max_frame_tonality; /*float tw_sum=0;*/ float frame_noisiness; const float pi4 = (float)(M_PI*M_PI*M_PI*M_PI); float slope=0; float frame_stationarity; float relativeE; float frame_probs[2]; float alpha, alphaE, alphaE2; float frame_loudness; float bandwidth_mask; int bandwidth=0; float maxE = 0; float noise_floor; int remaining; AnalysisInfo *info; float hp_ener; float tonality2[240]; float midE[8]; float spec_variability=0; float band_log2[NB_TBANDS+1]; float leakage_from[NB_TBANDS+1]; float leakage_to[NB_TBANDS+1]; SAVE_STACK; alpha = 1.f/IMIN(10, 1+tonal->count); alphaE = 1.f/IMIN(25, 1+tonal->count); alphaE2 = 1.f/IMIN(500, 1+tonal->count); if (tonal->Fs == 48000) { /* len and offset are now at 24 kHz. */ len/= 2; offset /= 2; } else if (tonal->Fs == 16000) { len = 3*len/2; offset = 3*offset/2; } if (tonal->count<4) { if (tonal->application == OPUS_APPLICATION_VOIP) tonal->music_prob = .1f; else tonal->music_prob = .625f; } kfft = celt_mode->mdct.kfft[0]; if (tonal->count==0) tonal->mem_fill = 240; tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x, &tonal->inmem[tonal->mem_fill], tonal->downmix_state, IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs); if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE) { tonal->mem_fill += len; /* Don't have enough to update the analysis */ RESTORE_STACK; return; } hp_ener = tonal->hp_ener_accum; info = &tonal->info[tonal->write_pos++]; if (tonal->write_pos>=DETECT_SIZE) tonal->write_pos-=DETECT_SIZE; ALLOC(in, 480, kiss_fft_cpx); ALLOC(out, 480, kiss_fft_cpx); ALLOC(tonality, 240, float); ALLOC(noisiness, 240, float); for (i=0;i<N2;i++) { float w = analysis_window[i]; in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]); in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]); in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]); in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]); } OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240); remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill); tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x, &tonal->inmem[240], tonal->downmix_state, remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs); tonal->mem_fill = 240 + remaining; opus_fft(kfft, in, out, tonal->arch); #ifndef FIXED_POINT /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */ if (celt_isnan(out[0].r)) { info->valid = 0; RESTORE_STACK; return; } #endif for (i=1;i<N2;i++) { float X1r, X2r, X1i, X2i; float angle, d_angle, d2_angle; float angle2, d_angle2, d2_angle2; float mod1, mod2, avg_mod; X1r = (float)out[i].r+out[N-i].r; X1i = (float)out[i].i-out[N-i].i; X2r = (float)out[i].i+out[N-i].i; X2i = (float)out[N-i].r-out[i].r; angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r); d_angle = angle - A[i]; d2_angle = d_angle - dA[i]; angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r); d_angle2 = angle2 - angle; d2_angle2 = d_angle2 - d_angle; mod1 = d2_angle - (float)float2int(d2_angle); noisiness[i] = ABS16(mod1); mod1 *= mod1; mod1 *= mod1; mod2 = d2_angle2 - (float)float2int(d2_angle2); noisiness[i] += ABS16(mod2); mod2 *= mod2; mod2 *= mod2; avg_mod = .25f*(d2A[i]+mod1+2*mod2); /* This introduces an extra delay of 2 frames in the detection. */ tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f; /* No delay on this detection, but it's less reliable. */ tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f; A[i] = angle2; dA[i] = d_angle2; d2A[i] = mod2; } for (i=2;i<N2-1;i++) { float tt = MIN32(tonality2[i], MAX32(tonality2[i-1], tonality2[i+1])); tonality[i] = .9f*MAX32(tonality[i], tt-.1f); } frame_tonality = 0; max_frame_tonality = 0; /*tw_sum = 0;*/ info->activity = 0; frame_noisiness = 0; frame_stationarity = 0; if (!tonal->count) { for (b=0;b<NB_TBANDS;b++) { tonal->lowE[b] = 1e10; tonal->highE[b] = -1e10; } } relativeE = 0; frame_loudness = 0; /* The energy of the very first band is special because of DC. */ { float E = 0; float X1r, X2r; X1r = 2*(float)out[0].r; X2r = 2*(float)out[0].i; E = X1r*X1r + X2r*X2r; for (i=1;i<4;i++) { float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; E += binE; } E = SCALE_ENER(E); band_log2[0] = .5f*1.442695f*(float)log(E+1e-10f); } for (b=0;b<NB_TBANDS;b++) { float E=0, tE=0, nE=0; float L1, L2; float stationarity; for (i=tbands[b];i<tbands[b+1];i++) { float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; binE = SCALE_ENER(binE); E += binE; tE += binE*MAX32(0, tonality[i]); nE += binE*2.f*(.5f-noisiness[i]); } #ifndef FIXED_POINT /* Check for extreme band energies that could cause NaNs later. */ if (!(E<1e9f) || celt_isnan(E)) { info->valid = 0; RESTORE_STACK; return; } #endif tonal->E[tonal->E_count][b] = E; frame_noisiness += nE/(1e-15f+E); frame_loudness += (float)sqrt(E+1e-10f); logE[b] = (float)log(E+1e-10f); band_log2[b+1] = .5f*1.442695f*(float)log(E+1e-10f); tonal->logE[tonal->E_count][b] = logE[b]; if (tonal->count==0) tonal->highE[b] = tonal->lowE[b] = logE[b]; if (tonal->highE[b] > tonal->lowE[b] + 7.5) { if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b]) tonal->highE[b] -= .01f; else tonal->lowE[b] += .01f; } if (logE[b] > tonal->highE[b]) { tonal->highE[b] = logE[b]; tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]); } else if (logE[b] < tonal->lowE[b]) { tonal->lowE[b] = logE[b]; tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]); } relativeE += (logE[b]-tonal->lowE[b])/(1e-15f + (tonal->highE[b]-tonal->lowE[b])); L1=L2=0; for (i=0;i<NB_FRAMES;i++) { L1 += (float)sqrt(tonal->E[i][b]); L2 += tonal->E[i][b]; } stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2)); stationarity *= stationarity; stationarity *= stationarity; frame_stationarity += stationarity; /*band_tonality[b] = tE/(1e-15+E)*/; band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]); #if 0 if (b>=NB_TONAL_SKIP_BANDS) { frame_tonality += tweight[b]*band_tonality[b]; tw_sum += tweight[b]; } #else frame_tonality += band_tonality[b]; if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS) frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS]; #endif max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality); slope += band_tonality[b]*(b-8); /*printf("%f %f ", band_tonality[b], stationarity);*/ tonal->prev_band_tonality[b] = band_tonality[b]; } leakage_from[0] = band_log2[0]; leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET; for (b=1;b<NB_TBANDS+1;b++) { float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4; leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]); leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET); } for (b=NB_TBANDS-2;b>=0;b--) { float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4; leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]); leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]); } celt_assert(NB_TBANDS+1 <= LEAK_BANDS); for (b=0;b<NB_TBANDS+1;b++) { /* leak_boost[] is made up of two terms. The first, based on leakage_to[], represents the boost needed to overcome the amount of analysis leakage cause in a weaker band b by louder neighbouring bands. The second, based on leakage_from[], applies to a loud band b for which the quantization noise causes synthesis leakage to the weaker neighbouring bands. */ float boost = MAX16(0, leakage_to[b] - band_log2[b]) + MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET)); info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost)); } for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0; for (i=0;i<NB_FRAMES;i++) { int j; float mindist = 1e15f; for (j=0;j<NB_FRAMES;j++) { int k; float dist=0; for (k=0;k<NB_TBANDS;k++) { float tmp; tmp = tonal->logE[i][k] - tonal->logE[j][k]; dist += tmp*tmp; } if (j!=i) mindist = MIN32(mindist, dist); } spec_variability += mindist; } spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS); bandwidth_mask = 0; bandwidth = 0; maxE = 0; noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8))); noise_floor *= noise_floor; for (b=0;b<NB_TBANDS;b++) { float E=0; int band_start, band_end; /* Keep a margin of 300 Hz for aliasing */ band_start = tbands[b]; band_end = tbands[b+1]; for (i=band_start;i<band_end;i++) { float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i; E += binE; } E = SCALE_ENER(E); maxE = MAX32(maxE, E); tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); E = MAX32(E, tonal->meanE[b]); /* Use a simple follower with 13 dB/Bark slope for spreading function */ bandwidth_mask = MAX32(.05f*bandwidth_mask, E); /* Consider the band "active" only if all these conditions are met: 1) less than 10 dB below the simple follower 2) less than 90 dB below the peak band (maximal masking possible considering both the ATH and the loudness-dependent slope of the spreading function) 3) above the PCM quantization noise floor We use b+1 because the first CELT band isn't included in tbands[] */ if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start)) bandwidth = b+1; } /* Special case for the last two bands, for which we don't have spectrum but only the energy above 12 kHz. */ if (tonal->Fs == 48000) { float ratio; float E = hp_ener*(1.f/(240*240)); ratio = tonal->prev_bandwidth==20 ? 0.03f : 0.07f; #ifdef FIXED_POINT /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */ E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE); #endif maxE = MAX32(maxE, E); tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); E = MAX32(E, tonal->meanE[b]); /* Use a simple follower with 13 dB/Bark slope for spreading function */ bandwidth_mask = MAX32(.05f*bandwidth_mask, E); if (E>ratio*bandwidth_mask && E*1e9f > maxE && E > noise_floor*160) bandwidth = 20; /* This detector is unreliable, so if the bandwidth is close to SWB, assume it's FB. */ if (bandwidth >= 17) bandwidth = 20; } if (tonal->count<=2) bandwidth = 20; frame_loudness = 20*(float)log10(frame_loudness); tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness); tonal->lowECount *= (1-alphaE); if (frame_loudness < tonal->Etracker-30) tonal->lowECount += alphaE; for (i=0;i<8;i++) { float sum=0; for (b=0;b<16;b++) sum += dct_table[i*16+b]*logE[b]; BFCC[i] = sum; } for (i=0;i<8;i++) { float sum=0; for (b=0;b<16;b++) sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]); midE[i] = sum; } frame_stationarity /= NB_TBANDS; relativeE /= NB_TBANDS; if (tonal->count<10) relativeE = .5f; frame_noisiness /= NB_TBANDS; #if 1 info->activity = frame_noisiness + (1-frame_noisiness)*relativeE; #else info->activity = .5*(1+frame_noisiness-frame_stationarity); #endif frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS)); frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f); tonal->prev_tonality = frame_tonality; slope /= 8*8; info->tonality_slope = slope; tonal->E_count = (tonal->E_count+1)%NB_FRAMES; tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX); info->tonality = frame_tonality; for (i=0;i<4;i++) features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i]; for (i=0;i<4;i++) tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i]; for (i=0;i<4;i++) features[4+i] = 0.63246f*(BFCC[i]-tonal->mem[i+24]) + 0.31623f*(tonal->mem[i]-tonal->mem[i+16]); for (i=0;i<3;i++) features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8]; if (tonal->count > 5) { for (i=0;i<9;i++) tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i]; } for (i=0;i<4;i++) features[i] = BFCC[i]-midE[i]; for (i=0;i<8;i++) { tonal->mem[i+24] = tonal->mem[i+16]; tonal->mem[i+16] = tonal->mem[i+8]; tonal->mem[i+8] = tonal->mem[i]; tonal->mem[i] = BFCC[i]; } for (i=0;i<9;i++) features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i]; features[18] = spec_variability - 0.78f; features[20] = info->tonality - 0.154723f; features[21] = info->activity - 0.724643f; features[22] = frame_stationarity - 0.743717f; features[23] = info->tonality_slope + 0.069216f; features[24] = tonal->lowECount - 0.067930f; mlp_process(&net, features, frame_probs); frame_probs[0] = .5f*(frame_probs[0]+1); /* Curve fitting between the MLP probability and the actual probability */ /*frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);*/ /* Probability of active audio (as opposed to silence) */ frame_probs[1] = .5f*frame_probs[1]+.5f; frame_probs[1] *= frame_probs[1]; /* Probability of speech or music vs noise */ info->activity_probability = frame_probs[1]; /*printf("%f %f\n", frame_probs[0], frame_probs[1]);*/ { /* Probability of state transition */ float tau; /* Represents independence of the MLP probabilities, where beta=1 means fully independent. */ float beta; /* Denormalized probability of speech (p0) and music (p1) after update */ float p0, p1; /* Probabilities for "all speech" and "all music" */ float s0, m0; /* Probability sum for renormalisation */ float psum; /* Instantaneous probability of speech and music, with beta pre-applied. */ float speech0; float music0; float p, q; /* More silence transitions for speech than for music. */ tau = .001f*tonal->music_prob + .01f*(1-tonal->music_prob); p = MAX16(.05f,MIN16(.95f,frame_probs[1])); q = MAX16(.05f,MIN16(.95f,tonal->vad_prob)); beta = .02f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); /* p0 and p1 are the probabilities of speech and music at this frame using only information from previous frame and applying the state transition model */ p0 = (1-tonal->vad_prob)*(1-tau) + tonal->vad_prob *tau; p1 = tonal->vad_prob *(1-tau) + (1-tonal->vad_prob)*tau; /* We apply the current probability with exponent beta to work around the fact that the probability estimates aren't independent. */ p0 *= (float)pow(1-frame_probs[1], beta); p1 *= (float)pow(frame_probs[1], beta); /* Normalise the probabilities to get the Marokv probability of music. */ tonal->vad_prob = p1/(p0+p1); info->vad_prob = tonal->vad_prob; /* Consider that silence has a 50-50 probability of being speech or music. */ frame_probs[0] = tonal->vad_prob*frame_probs[0] + (1-tonal->vad_prob)*.5f; /* One transition every 3 minutes of active audio */ tau = .0001f; /* Adapt beta based on how "unexpected" the new prob is */ p = MAX16(.05f,MIN16(.95f,frame_probs[0])); q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); beta = .02f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); /* p0 and p1 are the probabilities of speech and music at this frame using only information from previous frame and applying the state transition model */ p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau; p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau; /* We apply the current probability with exponent beta to work around the fact that the probability estimates aren't independent. */ p0 *= (float)pow(1-frame_probs[0], beta); p1 *= (float)pow(frame_probs[0], beta); /* Normalise the probabilities to get the Marokv probability of music. */ tonal->music_prob = p1/(p0+p1); info->music_prob = tonal->music_prob; /*printf("%f %f %f %f\n", frame_probs[0], frame_probs[1], tonal->music_prob, tonal->vad_prob);*/ /* This chunk of code deals with delayed decision. */ psum=1e-20f; /* Instantaneous probability of speech and music, with beta pre-applied. */ speech0 = (float)pow(1-frame_probs[0], beta); music0 = (float)pow(frame_probs[0], beta); if (tonal->count==1) { if (tonal->application == OPUS_APPLICATION_VOIP) tonal->pmusic[0] = .1f; else tonal->pmusic[0] = .625f; tonal->pspeech[0] = 1-tonal->pmusic[0]; } /* Updated probability of having only speech (s0) or only music (m0), before considering the new observation. */ s0 = tonal->pspeech[0] + tonal->pspeech[1]; m0 = tonal->pmusic [0] + tonal->pmusic [1]; /* Updates s0 and m0 with instantaneous probability. */ tonal->pspeech[0] = s0*(1-tau)*speech0; tonal->pmusic [0] = m0*(1-tau)*music0; /* Propagate the transition probabilities */ for (i=1;i<DETECT_SIZE-1;i++) { tonal->pspeech[i] = tonal->pspeech[i+1]*speech0; tonal->pmusic [i] = tonal->pmusic [i+1]*music0; } /* Probability that the latest frame is speech, when all the previous ones were music. */ tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0; /* Probability that the latest frame is music, when all the previous ones were speech. */ tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0; /* Renormalise probabilities to 1 */ for (i=0;i<DETECT_SIZE;i++) psum += tonal->pspeech[i] + tonal->pmusic[i]; psum = 1.f/psum; for (i=0;i<DETECT_SIZE;i++) { tonal->pspeech[i] *= psum; tonal->pmusic [i] *= psum; } psum = tonal->pmusic[0]; for (i=1;i<DETECT_SIZE;i++) psum += tonal->pspeech[i]; /* Estimate our confidence in the speech/music decisions */ if (frame_probs[1]>.75) { if (tonal->music_prob>.9) { float adapt; adapt = 1.f/(++tonal->music_confidence_count); tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500); tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence); } if (tonal->music_prob<.1) { float adapt; adapt = 1.f/(++tonal->speech_confidence_count); tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500); tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence); } } } tonal->last_music = tonal->music_prob>.5f; #ifdef MLP_TRAINING for (i=0;i<25;i++) printf("%f ", features[i]); printf("\n"); #endif info->bandwidth = bandwidth; tonal->prev_bandwidth = bandwidth; /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/ info->noisiness = frame_noisiness; info->valid = 1; RESTORE_STACK; }
void xcorr_kernel_sse4_1(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[ 4 ], int len) { int j; __m128i vecX, vecX0, vecX1, vecX2, vecX3; __m128i vecY0, vecY1, vecY2, vecY3; __m128i sum0, sum1, sum2, sum3, vecSum; __m128i initSum; celt_assert(len >= 3); sum0 = _mm_setzero_si128(); sum1 = _mm_setzero_si128(); sum2 = _mm_setzero_si128(); sum3 = _mm_setzero_si128(); for (j=0;j<(len-7);j+=8) { vecX = _mm_loadu_si128((__m128i *)(&x[j + 0])); vecY0 = _mm_loadu_si128((__m128i *)(&y[j + 0])); vecY1 = _mm_loadu_si128((__m128i *)(&y[j + 1])); vecY2 = _mm_loadu_si128((__m128i *)(&y[j + 2])); vecY3 = _mm_loadu_si128((__m128i *)(&y[j + 3])); sum0 = _mm_add_epi32(sum0, _mm_madd_epi16(vecX, vecY0)); sum1 = _mm_add_epi32(sum1, _mm_madd_epi16(vecX, vecY1)); sum2 = _mm_add_epi32(sum2, _mm_madd_epi16(vecX, vecY2)); sum3 = _mm_add_epi32(sum3, _mm_madd_epi16(vecX, vecY3)); } sum0 = _mm_add_epi32(sum0, _mm_unpackhi_epi64( sum0, sum0)); sum0 = _mm_add_epi32(sum0, _mm_shufflelo_epi16( sum0, 0x0E)); sum1 = _mm_add_epi32(sum1, _mm_unpackhi_epi64( sum1, sum1)); sum1 = _mm_add_epi32(sum1, _mm_shufflelo_epi16( sum1, 0x0E)); sum2 = _mm_add_epi32(sum2, _mm_unpackhi_epi64( sum2, sum2)); sum2 = _mm_add_epi32(sum2, _mm_shufflelo_epi16( sum2, 0x0E)); sum3 = _mm_add_epi32(sum3, _mm_unpackhi_epi64( sum3, sum3)); sum3 = _mm_add_epi32(sum3, _mm_shufflelo_epi16( sum3, 0x0E)); vecSum = _mm_unpacklo_epi64(_mm_unpacklo_epi32(sum0, sum1), _mm_unpacklo_epi32(sum2, sum3)); for (;j<(len-3);j+=4) { vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]); vecX0 = _mm_shuffle_epi32(vecX, 0x00); vecX1 = _mm_shuffle_epi32(vecX, 0x55); vecX2 = _mm_shuffle_epi32(vecX, 0xaa); vecX3 = _mm_shuffle_epi32(vecX, 0xff); vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]); vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]); vecY3 = OP_CVTEPI16_EPI32_M64(&y[j + 3]); sum0 = _mm_mullo_epi32(vecX0, vecY0); sum1 = _mm_mullo_epi32(vecX1, vecY1); sum2 = _mm_mullo_epi32(vecX2, vecY2); sum3 = _mm_mullo_epi32(vecX3, vecY3); sum0 = _mm_add_epi32(sum0, sum1); sum2 = _mm_add_epi32(sum2, sum3); vecSum = _mm_add_epi32(vecSum, sum0); vecSum = _mm_add_epi32(vecSum, sum2); } for (;j<len;j++) { vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]); vecX0 = _mm_shuffle_epi32(vecX, 0x00); vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); sum0 = _mm_mullo_epi32(vecX0, vecY0); vecSum = _mm_add_epi32(vecSum, sum0); } initSum = _mm_loadu_si128((__m128i *)(&sum[0])); initSum = _mm_add_epi32(initSum, vecSum); _mm_storeu_si128((__m128i *)sum, initSum); }
opus_int silk_decode_frame( silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ ec_dec *psRangeDec, /* I/O Compressor data structure */ opus_int16 pOut[], /* O Pointer to output speech frame */ opus_int32 *pN, /* O Pointer to size of output frame */ opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ opus_int condCoding, /* I The type of conditional coding to use */ int arch /* I Run-time architecture */ ) { VARDECL( silk_decoder_control, psDecCtrl ); opus_int L, mv_len, ret = 0; SAVE_STACK; L = psDec->frame_length; ALLOC( psDecCtrl, 1, silk_decoder_control ); psDecCtrl->LTP_scale_Q14 = 0; /* Safety checks */ celt_assert( L > 0 && L <= MAX_FRAME_LENGTH ); if( lostFlag == FLAG_DECODE_NORMAL || ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) ) { VARDECL( opus_int16, pulses ); ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) & ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int16 ); /*********************************************/ /* Decode quantization indices of side info */ /*********************************************/ silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding ); /*********************************************/ /* Decode quantization indices of excitation */ /*********************************************/ silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, psDec->indices.quantOffsetType, psDec->frame_length ); /********************************************/ /* Decode parameters and pulse signal */ /********************************************/ silk_decode_parameters( psDec, psDecCtrl, condCoding ); /********************************************************/ /* Run inverse NSQ */ /********************************************************/ silk_decode_core( psDec, psDecCtrl, pOut, pulses, arch ); /********************************************************/ /* Update PLC state */ /********************************************************/ silk_PLC( psDec, psDecCtrl, pOut, 0, arch ); psDec->lossCnt = 0; psDec->prevSignalType = psDec->indices.signalType; celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 ); /* A frame has been decoded without errors */ psDec->first_frame_after_reset = 0; } else { /* Handle packet loss by extrapolation */ psDec->indices.signalType = psDec->prevSignalType; silk_PLC( psDec, psDecCtrl, pOut, 1, arch ); } /*************************/ /* Update output buffer. */ /*************************/ celt_assert( psDec->ltp_mem_length >= psDec->frame_length ); mv_len = psDec->ltp_mem_length - psDec->frame_length; silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) ); silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) ); /************************************************/ /* Comfort noise generation / estimation */ /************************************************/ silk_CNG( psDec, psDecCtrl, pOut, L ); /****************************************************************/ /* Ensure smooth connection of extrapolated and good frames */ /****************************************************************/ silk_PLC_glue_frames( psDec, pOut, L ); /* Update some decoder state variables */ psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; /* Set output frame length */ *pN = L; RESTORE_STACK; return ret; }
void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in, int arch ) { int c; int i; int LM; int pos[8] = {0}; int upsample; int frame_size; int freq_size; opus_val16 channel_offset; opus_val32 bandE[21]; opus_val16 maskLogE[3][21]; VARDECL(opus_val32, in); VARDECL(opus_val16, x); VARDECL(opus_val32, freq); SAVE_STACK; upsample = resampling_factor(rate); frame_size = len*upsample; freq_size = IMIN(960, frame_size); /* LM = log2(frame_size / 120) */ for (LM=0;LM<celt_mode->maxLM;LM++) if (celt_mode->shortMdctSize<<LM==frame_size) break; ALLOC(in, frame_size+overlap, opus_val32); ALLOC(x, len, opus_val16); ALLOC(freq, freq_size, opus_val32); channel_pos(channels, pos); for (c=0;c<3;c++) for (i=0;i<21;i++) maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT); for (c=0;c<channels;c++) { int frame; int nb_frames = frame_size/freq_size; celt_assert(nb_frames*freq_size == frame_size); OPUS_COPY(in, mem+c*overlap, overlap); (*copy_channel_in)(x, 1, pcm, channels, c, len); celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0); #ifndef FIXED_POINT { opus_val32 sum; sum = celt_inner_prod(in, in, frame_size+overlap, 0); /* This should filter out both NaNs and ridiculous signals that could cause NaNs further down. */ if (!(sum < 1e9f) || celt_isnan(sum)) { OPUS_CLEAR(in, frame_size+overlap); preemph_mem[c] = 0; } } #endif OPUS_CLEAR(bandE, 21); for (frame=0;frame<nb_frames;frame++) { opus_val32 tmpE[21]; clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1, arch); if (upsample != 1) { int bound = freq_size/upsample; for (i=0;i<bound;i++) freq[i] *= upsample; for (;i<freq_size;i++) freq[i] = 0; } compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM); /* If we have multiple frames, take the max energy. */ for (i=0;i<21;i++) bandE[i] = MAX32(bandE[i], tmpE[i]); } amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1); /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */ for (i=1;i<21;i++) bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT)); for (i=19;i>=0;i--) bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); if (pos[c]==1) { for (i=0;i<21;i++) maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]); } else if (pos[c]==3) { for (i=0;i<21;i++) maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]); } else if (pos[c]==2) { for (i=0;i<21;i++) { maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); } } #if 0 for (i=0;i<21;i++) printf("%f ", bandLogE[21*c+i]); float sum=0; for (i=0;i<21;i++) sum += bandLogE[21*c+i]; printf("%f ", sum/21); #endif OPUS_COPY(mem+c*overlap, in+frame_size, overlap); } for (i=0;i<21;i++) maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]); channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1))); for (c=0;c<3;c++) for (i=0;i<21;i++) maskLogE[c][i] += channel_offset; #if 0 for (c=0;c<3;c++) { for (i=0;i<21;i++) printf("%f ", maskLogE[c][i]); } #endif for (c=0;c<channels;c++) { opus_val16 *mask; if (pos[c]!=0) { mask = &maskLogE[pos[c]-1][0]; for (i=0;i<21;i++) bandLogE[21*c+i] = bandLogE[21*c+i] - mask[i]; } else { for (i=0;i<21;i++) bandLogE[21*c+i] = 0; } #if 0 for (i=0;i<21;i++) printf("%f ", bandLogE[21*c+i]); printf("\n"); #endif #if 0 float sum=0; for (i=0;i<21;i++) sum += bandLogE[21*c+i]; printf("%f ", sum/(float)QCONST32(21.f, DB_SHIFT)); printf("\n"); #endif } RESTORE_STACK; }
void celt_iir(const opus_val32 *_x, const opus_val16 *den, opus_val32 *_y, int N, int ord, opus_val16 *mem, int arch) { #ifdef SMALL_FOOTPRINT int i,j; (void)arch; for (i=0;i<N;i++) { opus_val32 sum = _x[i]; for (j=0;j<ord;j++) { sum -= MULT16_16(den[j],mem[j]); } for (j=ord-1;j>=1;j--) { mem[j]=mem[j-1]; } mem[0] = ROUND16(sum,SIG_SHIFT); _y[i] = sum; } #else int i,j; VARDECL(opus_val16, rden); VARDECL(opus_val16, y); SAVE_STACK; celt_assert((ord&3)==0); ALLOC(rden, ord, opus_val16); ALLOC(y, N+ord, opus_val16); for(i=0;i<ord;i++) rden[i] = den[ord-i-1]; for(i=0;i<ord;i++) y[i] = -mem[ord-i-1]; for(;i<N+ord;i++) y[i]=0; for (i=0;i<N-3;i+=4) { /* Unroll by 4 as if it were an FIR filter */ opus_val32 sum[4]; sum[0]=_x[i]; sum[1]=_x[i+1]; sum[2]=_x[i+2]; sum[3]=_x[i+3]; xcorr_kernel(rden, y+i, sum, ord, arch); /* Patch up the result to compensate for the fact that this is an IIR */ y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT); _y[i ] = sum[0]; sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]); y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT); _y[i+1] = sum[1]; sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]); sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]); y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT); _y[i+2] = sum[2]; sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]); sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]); sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]); y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT); _y[i+3] = sum[3]; } for (;i<N;i++) { opus_val32 sum = _x[i]; for (j=0;j<ord;j++) sum -= MULT16_16(rden[j],y[i+j]); y[i+ord] = ROUND16(sum,SIG_SHIFT); _y[i] = sum; } for(i=0;i<ord;i++) mem[i] = _y[N-i-1]; RESTORE_STACK; #endif }
static #endif void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum) { int c; int Nd; int apply_downsampling=0; opus_val16 coef0; VARDECL(celt_sig, scratch); SAVE_STACK; #ifndef FIXED_POINT (void)accum; celt_assert(accum==0); #endif ALLOC(scratch, N, celt_sig); coef0 = coef[0]; Nd = N/downsample; c=0; do { int j; celt_sig * OPUS_RESTRICT x; opus_val16 * OPUS_RESTRICT y; celt_sig m = mem[c]; x =in[c]; y = pcm+c; #ifdef CUSTOM_MODES if (coef[1] != 0) { opus_val16 coef1 = coef[1]; opus_val16 coef3 = coef[3]; for (j=0;j<N;j++) { celt_sig tmp = x[j] + m + VERY_SMALL; m = MULT16_32_Q15(coef0, tmp) - MULT16_32_Q15(coef1, x[j]); tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2); scratch[j] = tmp; } apply_downsampling=1; } else #endif if (downsample>1) { /* Shortcut for the standard (non-custom modes) case */ for (j=0;j<N;j++) { celt_sig tmp = x[j] + m + VERY_SMALL; m = MULT16_32_Q15(coef0, tmp); scratch[j] = tmp; } apply_downsampling=1; } else { /* Shortcut for the standard (non-custom modes) case */ #ifdef FIXED_POINT if (accum) { for (j=0;j<N;j++) { celt_sig tmp = x[j] + m + VERY_SMALL; m = MULT16_32_Q15(coef0, tmp); y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp)))); } } else #endif { for (j=0;j<N;j++) { celt_sig tmp = x[j] + m + VERY_SMALL; m = MULT16_32_Q15(coef0, tmp); y[j*C] = SCALEOUT(SIG2WORD16(tmp)); } } } mem[c] = m; if (apply_downsampling) { /* Perform down-sampling */ #ifdef FIXED_POINT if (accum) { for (j=0;j<Nd;j++) y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample])))); } else #endif { for (j=0;j<Nd;j++) y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample])); } } } while (++c<C); RESTORE_STACK; }
/* Make basic checks on the CELT state to ensure we don't end up writing all over memory. */ void validate_celt_decoder(CELTDecoder *st) { #ifndef CUSTOM_MODES celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL)); celt_assert(st->overlap == 120); #endif celt_assert(st->channels == 1 || st->channels == 2); celt_assert(st->stream_channels == 1 || st->stream_channels == 2); celt_assert(st->downsample > 0); celt_assert(st->start == 0 || st->start == 17); celt_assert(st->start < st->end); celt_assert(st->end <= 21); #ifdef OPUS_ARCHMASK celt_assert(st->arch >= 0); celt_assert(st->arch <= OPUS_ARCHMASK); #endif celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX); celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0); celt_assert(st->postfilter_period < MAX_PERIOD); celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0); celt_assert(st->postfilter_period_old < MAX_PERIOD); celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0); celt_assert(st->postfilter_tapset <= 2); celt_assert(st->postfilter_tapset >= 0); celt_assert(st->postfilter_tapset_old <= 2); celt_assert(st->postfilter_tapset_old >= 0); }
int _celt_autocorr( const opus_val16 *x, /* in: [0...n-1] samples x */ opus_val32 *ac, /* out: [0...lag-1] ac values */ const opus_val16 *window, int overlap, int lag, int n, int arch ) { opus_val32 d; int i, k; int fastN=n-lag; int shift; const opus_val16 *xptr; VARDECL(opus_val16, xx); SAVE_STACK; ALLOC(xx, n, opus_val16); celt_assert(n>0); celt_assert(overlap>=0); if (overlap == 0) { xptr = x; } else { for (i=0;i<n;i++) xx[i] = x[i]; for (i=0;i<overlap;i++) { xx[i] = MULT16_16_Q15(x[i],window[i]); xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); } xptr = xx; } shift=0; #ifdef OPUS_FIXED_POINT { opus_val32 ac0; ac0 = 1+(n<<7); if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9); for(i=(n&1);i<n;i+=2) { ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9); ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9); } shift = celt_ilog2(ac0)-30+10; shift = (shift)/2; if (shift>0) { for(i=0;i<n;i++) xx[i] = PSHR32(xptr[i], shift); xptr = xx; } else shift = 0; } #endif celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch); for (k=0;k<=lag;k++) { for (i = k+fastN, d = 0; i < n; i++) d = MAC16_16(d, xptr[i], xptr[i-k]); ac[k] += d; } #ifdef OPUS_FIXED_POINT shift = 2*shift; if (shift<=0) ac[0] += SHL32((opus_int32)1, -shift); if (ac[0] < 268435456) { int shift2 = 29 - EC_ILOG(ac[0]); for (i=0;i<=lag;i++) ac[i] = SHL32(ac[i], shift2); shift -= shift2; } else if (ac[0] >= 536870912) { int shift2=1; if (ac[0] >= 1073741824) shift2++; for (i=0;i<=lag;i++) ac[i] = SHR32(ac[i], shift2); shift += shift2; } #endif RESTORE_STACK; return shift; }
/* Encode quantization indices of excitation */ void silk_encode_pulses( ec_enc *psRangeEnc, /* I/O compressor data structure */ const opus_int signalType, /* I Signal type */ const opus_int quantOffsetType, /* I quantOffsetType */ opus_int8 pulses[], /* I quantization indices */ const opus_int frame_length /* I Frame length */ ) { opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; VARDECL( opus_int, abs_pulses ); VARDECL( opus_int, sum_pulses ); VARDECL( opus_int, nRshifts ); opus_int pulses_comb[ 8 ]; opus_int *abs_pulses_ptr; const opus_int8 *pulses_ptr; const opus_uint8 *cdf_ptr; const opus_uint8 *nBits_ptr; SAVE_STACK; silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/ /****************************/ /* Prepare for shell coding */ /****************************/ /* Calculate number of shell blocks */ silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) { celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ iter++; silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); } /* Take the absolute value of the pulses */ ALLOC( abs_pulses, iter * SHELL_CODEC_FRAME_LENGTH, opus_int ); silk_assert( !( SHELL_CODEC_FRAME_LENGTH & 3 ) ); for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] ); abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] ); abs_pulses[i+2] = ( opus_int )silk_abs( pulses[ i + 2 ] ); abs_pulses[i+3] = ( opus_int )silk_abs( pulses[ i + 3 ] ); } /* Calc sum pulses per shell code frame */ ALLOC( sum_pulses, iter, opus_int ); ALLOC( nRshifts, iter, opus_int ); abs_pulses_ptr = abs_pulses; for( i = 0; i < iter; i++ ) { nRshifts[ i ] = 0; while( 1 ) { /* 1+1 -> 2 */ scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); /* 2+2 -> 4 */ scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); /* 4+4 -> 8 */ scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); /* 8+8 -> 16 */ scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); if( scale_down ) { /* We need to downscale the quantization signal */ nRshifts[ i ]++; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_pulses_ptr[ k ] = silk_RSHIFT( abs_pulses_ptr[ k ], 1 ); } } else { /* Jump out of while(1) loop and go to next shell coding frame */ break; } } abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; } /**************/ /* Rate level */ /**************/ /* find rate level that leads to fewest bits for coding of pulses per block info */ minSumBits_Q5 = silk_int32_MAX; for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { sumBits_Q5 += nBits_ptr[ SILK_MAX_PULSES + 1 ]; } else { sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; } } if( sumBits_Q5 < minSumBits_Q5 ) { minSumBits_Q5 = sumBits_Q5; RateLevelIndex = k; } } ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); /***************************************************/ /* Sum-Weighted-Pulses Encoding */ /***************************************************/ cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] == 0 ) { ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); } else { ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, cdf_ptr, 8 ); for( k = 0; k < nRshifts[ i ] - 1; k++ ) { ec_enc_icdf( psRangeEnc, SILK_MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); } ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); } } /******************/ /* Shell Encoding */ /******************/ for( i = 0; i < iter; i++ ) { if( sum_pulses[ i ] > 0 ) { silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); } } /****************/ /* LSB Encoding */ /****************/ for( i = 0; i < iter; i++ ) { if( nRshifts[ i ] > 0 ) { pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; nLS = nRshifts[ i ] - 1; for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { abs_q = (opus_int8)silk_abs( pulses_ptr[ k ] ); for( j = nLS; j > 0; j-- ) { bit = silk_RSHIFT( abs_q, j ) & 1; ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); } bit = abs_q & 1; ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); } } } /****************/ /* Encode signs */ /****************/ silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); RESTORE_STACK; }