opus_int silk_setup_resamplers( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz /* I */ ) { opus_int ret = SILK_NO_ERROR; opus_int32 nSamples_temp; if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) { if( psEnc->sCmn.fs_kHz == 0 ) { /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); } else { /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ]; silk_resampler_state_struct temp_resampler_state; #ifdef FIXED_POINT opus_int16 *x_bufFIX = psEnc->x_buf; #else opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ]; #endif nSamples_temp = silk_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz; #ifndef FIXED_POINT silk_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp ); #endif /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); /* Temporary resampling of x_buf data to API_fs_Hz */ ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp ); /* Calculate number of samples that has been temporarily upsampled */ nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) ); /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp ); #ifndef FIXED_POINT silk_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz ); #endif } } psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; return ret; }
opus_int silk_encode_frame_FLP( silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ opus_int32 *pnBytesOut, /* O Number of payload bytes; */ ec_enc *psRangeEnc, /* I/O compressor data structure */ opus_int condCoding, /* I The type of conditional coding to use */ opus_int maxBits, /* I If > 0: maximum number of output bits */ opus_int useCBR /* I Flag to force constant-bitrate operation */ ) { silk_encoder_control_FLP sEncCtrl; opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; silk_float *x_frame, *res_pitch_frame; silk_float xfw[ MAX_FRAME_LENGTH ]; silk_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; ec_enc sRangeEnc_copy, sRangeEnc_copy2; silk_nsq_state sNSQ_copy, sNSQ_copy2; opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper; opus_int32 gainsID, gainsID_lower, gainsID_upper; opus_int16 gainMult_Q8; opus_int16 ec_prevLagIndex_copy; opus_int ec_prevSignalType_copy; opus_int8 LastGainIndex_copy2; opus_int32 pGains_Q16[ MAX_NB_SUBFR ]; opus_uint8 ec_buf_copy[ 1275 ]; /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */ LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0; psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Set up Input Pointers, and insert frame in input buffer */ /**************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; /* start of frame to encode */ res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; /* start of pitch LPC residual frame */ /***************************************/ /* Ensure smooth bandwidth transitions */ /***************************************/ silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); /*******************************************/ /* Copy new frame to front of input buffer */ /*******************************************/ silk_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ for( i = 0; i < 8; i++ ) { x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + i * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( i & 2 ) ) * 1e-6f; } if( !psEnc->sCmn.prefillFlag ) { /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); /************************/ /* Noise shape analysis */ /************************/ silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding ); /****************************************/ /* Process gains */ /****************************************/ silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding ); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding ); /* Loop over quantizer and entroy coding to control bitrate */ maxIter = 6; gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); found_lower = 0; found_upper = 0; gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); gainsID_lower = -1; gainsID_upper = -1; /* Copy part of the input state */ silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) ); silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); seed_copy = psEnc->sCmn.indices.Seed; ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex; ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType; for( iter = 0; ; iter++ ) { if( gainsID == gainsID_lower ) { nBits = nBits_lower; } else if( gainsID == gainsID_upper ) { nBits = nBits_upper; } else { /* Restore part of the input state */ if( iter > 0 ) { silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) ); silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) ); psEnc->sCmn.indices.Seed = seed_copy; psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; } /*****************************************/ /* Noise shaping quantization */ /*****************************************/ silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw ); /****************************************/ /* Encode Parameters */ /****************************************/ silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding ); /****************************************/ /* Encode Excitation Signal */ /****************************************/ silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); nBits = ec_tell( psRangeEnc ); if( useCBR == 0 && iter == 0 && nBits <= maxBits ) { break; } } if( iter == maxIter ) { if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) { /* Restore output state from earlier iteration that did meet the bitrate budget */ silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) ); silk_assert( sRangeEnc_copy2.offs <= 1275 ); silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) ); psEnc->sShape.LastGainIndex = LastGainIndex_copy2; } break; } if( nBits > maxBits ) { if( found_lower == 0 && iter >= 2 ) { /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */ sEncCtrl.Lambda *= 1.5f; found_upper = 0; gainsID_upper = -1; } else { found_upper = 1; nBits_upper = nBits; gainMult_upper = gainMult_Q8; gainsID_upper = gainsID; } } else if( nBits < maxBits - 5 ) { found_lower = 1; nBits_lower = nBits; gainMult_lower = gainMult_Q8; if( gainsID != gainsID_lower ) { gainsID_lower = gainsID; /* Copy part of the output state */ silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) ); silk_assert( psRangeEnc->offs <= 1275 ); silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; } } else { /* Within 5 bits of budget: close enough */ break; } if( ( found_lower & found_upper ) == 0 ) { /* Adjust gain according to high-rate rate/distortion curve */ opus_int32 gain_factor_Q16; gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); if( nBits > maxBits ) { gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); } gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); } else { /* Adjust gain by interpolating */ gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower ); /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */ if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) { gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ); } else if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) { gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ); } } for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 ); } /* Quantize gains */ psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16, &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); /* Unique identifier of gains vector */ gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { sEncCtrl.Gains[ i ] = pGains_Q16[ i ] / 65536.0f; } } } /* Update input buffer */ silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( silk_float ) ); /* Parameters needed for next frame */ psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; /* Exit without entropy coding */ if( psEnc->sCmn.prefillFlag ) { /* No payload */ *pnBytesOut = 0; return ret; } /****************************************/ /* Finalize payload */ /****************************************/ psEnc->sCmn.first_frame_after_reset = 0; /* Payload size */ *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); return ret; }
static opus_int silk_setup_resamplers( silk_encoder_state_Fxx *psEnc, /* I/O */ opus_int fs_kHz /* I */ ) { opus_int ret = SILK_NO_ERROR; SAVE_STACK; if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) { if( psEnc->sCmn.fs_kHz == 0 ) { /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); } else { VARDECL( opus_int16, x_buf_API_fs_Hz ); VARDECL( silk_resampler_state_struct, temp_resampler_state ); #ifdef OPUS_FIXED_POINT opus_int16 *x_bufFIX = psEnc->x_buf; #else VARDECL( opus_int16, x_bufFIX ); opus_int32 new_buf_samples; #endif opus_int32 api_buf_samples; opus_int32 old_buf_samples; opus_int32 buf_length_ms; buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS; old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz; #ifndef OPUS_FIXED_POINT new_buf_samples = buf_length_ms * fs_kHz; ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ), opus_int16 ); silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples ); #endif /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ ALLOC( temp_resampler_state, 1, silk_resampler_state_struct ); ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); /* Calculate number of samples to temporarily upsample */ api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 ); /* Temporary resampling of x_buf data to API_fs_Hz */ ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 ); ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples ); /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples ); #ifndef OPUS_FIXED_POINT silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples); #endif } } psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; RESTORE_STACK; return ret; }