mirror of
https://github.com/xiph/opus.git
synced 2025-05-29 06:39:15 +00:00
Optimization of the CBR loop
Also some comment/warning fixes
This commit is contained in:
parent
3b2aee062d
commit
43a0de4af1
9 changed files with 152 additions and 99 deletions
|
@ -258,7 +258,7 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
|
|||
#endif
|
||||
if (pulsesLeft > N+3)
|
||||
{
|
||||
opus_val16 tmp = pulsesLeft;
|
||||
opus_val16 tmp = (opus_val16)pulsesLeft;
|
||||
yy = MAC16_16(yy, tmp, tmp);
|
||||
yy = MAC16_16(yy, tmp, y[0]);
|
||||
iy[0] += pulsesLeft;
|
||||
|
|
|
@ -214,7 +214,7 @@ opus_int silk_Encode(
|
|||
|
||||
TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
|
||||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
/* JMV: Force the side channel to the same rate as the mid. Is this the right way? */
|
||||
/* Force the side channel to the same rate as the mid */
|
||||
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
|
@ -426,9 +426,6 @@ opus_int silk_Encode(
|
|||
|
||||
/* Handling rate constraints */
|
||||
maxBits = encControl->maxBits;
|
||||
/*if( encControl->useCBR ) {
|
||||
maxBits = (encControl->bitRate * nBlocksOf10ms / 800) * 8;
|
||||
}*/
|
||||
if( tot_blocks == 2 && curr_block == 0 ) {
|
||||
maxBits = maxBits * 3 / 5;
|
||||
} else if( tot_blocks == 3 ) {
|
||||
|
|
|
@ -92,6 +92,7 @@ opus_int silk_encode_frame_FIX(
|
|||
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;
|
||||
|
@ -178,60 +179,68 @@ TIC(NSQ)
|
|||
}
|
||||
TOC(NSQ)
|
||||
} else {
|
||||
/* Loop over quantizer and entroy coding to control bitrate */
|
||||
/* Loop over quantizer and entropy coding to control bitrate */
|
||||
maxIter = 5;
|
||||
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++ ) {
|
||||
/* 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;
|
||||
|
||||
/*****************************************/
|
||||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
TIC(NSQ)
|
||||
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||
if( gainsID == gainsID_lower ) {
|
||||
nBits = nBits_lower;
|
||||
} else if( gainsID == gainsID_upper ) {
|
||||
nBits = nBits_upper;
|
||||
} else {
|
||||
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||
}
|
||||
/*****************************************/
|
||||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
TIC(NSQ)
|
||||
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
|
||||
silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||
} else {
|
||||
silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
|
||||
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
|
||||
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
|
||||
}
|
||||
TOC(NSQ)
|
||||
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
/****************************************/
|
||||
TIC(ENCODE_PARAMS)
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
TOC(ENCODE_PARAMS)
|
||||
|
||||
/****************************************/
|
||||
/* Encode Excitation Signal */
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
/* Encode Excitation Signal */
|
||||
/****************************************/
|
||||
TIC(ENCODE_PULSES)
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
TOC(ENCODE_PULSES)
|
||||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
|
||||
if( maxBits == 0 || ( useCBR == 0 && iter == 0 && nBits <= maxBits ) ) {
|
||||
break;
|
||||
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( iter == maxIter ) {
|
||||
if( nBits > maxBits && found_lower ) {
|
||||
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_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;
|
||||
|
@ -243,6 +252,7 @@ TOC(ENCODE_PULSES)
|
|||
found_upper = 1;
|
||||
nBits_upper = nBits;
|
||||
gainMult_upper = gainMult_Q8;
|
||||
gainsID_upper = gainsID;
|
||||
if( found_lower == 0 && iter >= 2 ) {
|
||||
/* Adjust the quantizer's rate/distortion tradeoff */
|
||||
sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
|
||||
|
@ -251,12 +261,15 @@ TOC(ENCODE_PULSES)
|
|||
found_lower = 1;
|
||||
nBits_lower = nBits;
|
||||
gainMult_lower = gainMult_Q8;
|
||||
/* 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;
|
||||
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;
|
||||
|
@ -266,6 +279,7 @@ TOC(ENCODE_PULSES)
|
|||
/* 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 ) );
|
||||
}
|
||||
|
@ -274,23 +288,26 @@ TOC(ENCODE_PULSES)
|
|||
/* Adjust gain by interpolating */
|
||||
gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( 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 > gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||
gainMult_Q8 = gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||
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 < gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||
gainMult_Q8 = gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||
}
|
||||
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++ ) {
|
||||
sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
|
||||
}
|
||||
|
||||
/* Quantize gains */
|
||||
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||
|
||||
/* Noise shaping quantization */
|
||||
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_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 );
|
||||
|
||||
/* Restore part of the input state */
|
||||
silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
|
||||
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) );
|
||||
|
|
|
@ -90,7 +90,7 @@ void silk_process_gains_FIX(
|
|||
silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
|
||||
psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
|
||||
|
||||
/* Noise shaping quantization */
|
||||
/* Quantize gains */
|
||||
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16,
|
||||
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ opus_int silk_encode_frame_FLP(
|
|||
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;
|
||||
|
@ -185,50 +186,58 @@ TOC(NSQ)
|
|||
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++ ) {
|
||||
/* 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;
|
||||
|
||||
/*****************************************/
|
||||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
if( gainsID == gainsID_lower ) {
|
||||
nBits = nBits_lower;
|
||||
} else if( gainsID == gainsID_upper ) {
|
||||
nBits = nBits_upper;
|
||||
} else {
|
||||
/*****************************************/
|
||||
/* Noise shaping quantization */
|
||||
/*****************************************/
|
||||
TIC(NSQ)
|
||||
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
||||
silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
|
||||
TOC(NSQ)
|
||||
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
/* Encode Parameters */
|
||||
/****************************************/
|
||||
TIC(ENCODE_PARAMS)
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
|
||||
TOC(ENCODE_PARAMS)
|
||||
|
||||
/****************************************/
|
||||
/* Encode Excitation Signal */
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
/* Encode Excitation Signal */
|
||||
/****************************************/
|
||||
TIC(ENCODE_PULSES)
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
|
||||
psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
|
||||
TOC(ENCODE_PULSES)
|
||||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
|
||||
nBits = ec_tell( psRangeEnc );
|
||||
|
||||
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||
break;
|
||||
if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( iter == maxIter ) {
|
||||
if( nBits > maxBits && found_lower ) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
@ -237,7 +246,8 @@ TOC(ENCODE_PULSES)
|
|||
found_upper = 1;
|
||||
nBits_upper = nBits;
|
||||
gainMult_upper = gainMult_Q8;
|
||||
if( found_lower == 0 && iter >= 3 ) {
|
||||
gainsID_upper = gainsID;
|
||||
if( found_lower == 0 && iter >= 2 ) {
|
||||
/* Adjust the quantizer's rate/distortion tradeoff */
|
||||
sEncCtrl.Lambda *= 1.5f;
|
||||
}
|
||||
|
@ -245,12 +255,15 @@ TOC(ENCODE_PULSES)
|
|||
found_lower = 1;
|
||||
nBits_lower = nBits;
|
||||
gainMult_lower = gainMult_Q8;
|
||||
/* 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;
|
||||
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;
|
||||
|
@ -269,23 +282,26 @@ TOC(ENCODE_PULSES)
|
|||
/* 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 > gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||
gainMult_Q8 = gainMult_lower + silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||
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 < gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 ) ) {
|
||||
gainMult_Q8 = gainMult_upper - silk_RSHIFT32( gainMult_upper - gainMult_lower, 2 );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
|
||||
|
||||
/* Noise shaping quantization */
|
||||
/* 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;
|
||||
|
|
|
@ -71,7 +71,7 @@ void silk_process_gains_FLP(
|
|||
silk_memcpy( psEncCtrl->GainsUnq_Q16, pGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
|
||||
psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex;
|
||||
|
||||
/* Noise shaping quantization */
|
||||
/* Quantize gains */
|
||||
silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
|
||||
&psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
|
||||
|
||||
|
|
|
@ -121,3 +121,20 @@ void silk_gains_dequant(
|
|||
gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute unique identifier of gain indices vector */
|
||||
opus_int32 silk_gains_ID( /* O returns unique identifier of gains */
|
||||
const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
|
||||
const opus_int nb_subfr /* I number of subframes */
|
||||
)
|
||||
{
|
||||
opus_int k;
|
||||
opus_int32 gainsID;
|
||||
|
||||
gainsID = 0;
|
||||
for( k = 0; k < nb_subfr; k++ ) {
|
||||
gainsID = silk_ADD_LSHIFT32( ind[ k ], gainsID, 8 );
|
||||
}
|
||||
|
||||
return gainsID;
|
||||
}
|
||||
|
|
|
@ -192,6 +192,12 @@ void silk_gains_dequant(
|
|||
const opus_int nb_subfr /* I number of subframes */
|
||||
);
|
||||
|
||||
/* Compute unique identifier of gain indices vector */
|
||||
opus_int32 silk_gains_ID( /* O returns unique identifier of gains */
|
||||
const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */
|
||||
const opus_int nb_subfr /* I number of subframes */
|
||||
);
|
||||
|
||||
/* Interpolate two vectors */
|
||||
void silk_interpolate(
|
||||
opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */
|
||||
|
|
|
@ -499,7 +499,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
|
|||
st->bitrate_bps = cbrBytes * (8*frame_rate);
|
||||
max_data_bytes = cbrBytes;
|
||||
}
|
||||
max_rate = frame_rate*max_data_bytes;
|
||||
max_rate = frame_rate*max_data_bytes*8;
|
||||
|
||||
/* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
|
||||
equiv_rate = st->bitrate_bps - 60*(st->Fs/frame_size - 50);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue