diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-10-07 08:38:27 -0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-10-07 11:46:01 -0400 |
commit | b5972388d7c9b0d5f5a780da23ba00dce6a2628d (patch) | |
tree | 674e0a7515fa77ae620d4cb7028f34d769e25c54 /silk/enc_API.c | |
parent | a5e96b84302f2008ec32e8664356dc83efd72c17 (diff) | |
download | opus-b5972388d7c9b0d5f5a780da23ba00dce6a2628d.tar.gz |
Proper SILK delay compensation for resampling
Adds SILK delay compensation that depends on encode and decode sampling
rate, as well as SILK internal coding rate. This ensures that the SILK
part of Opus is always in sync with the CELT part no matter what the
sampling rates are. It also increases the resampling delay to 1.15 ms
(was previously 0.48 ms).
Diffstat (limited to 'silk/enc_API.c')
-rw-r--r-- | silk/enc_API.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/silk/enc_API.c b/silk/enc_API.c index 0fe945b6..403aecce 100644 --- a/silk/enc_API.c +++ b/silk/enc_API.c @@ -138,8 +138,8 @@ opus_int silk_Encode( opus_int speech_act_thr_for_switch_Q8; opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol; silk_encoder *psEnc = ( silk_encoder * )encState; - opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; - opus_int transition; + opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY]; + opus_int transition, delay; psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; @@ -222,6 +222,7 @@ opus_int silk_Encode( } silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + delay = psEnc->state_Fxx[ 0 ].sCmn.delay; /* Input buffering/resampling and encoding */ while( 1 ) { nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; @@ -231,12 +232,15 @@ opus_int silk_Encode( if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n ]; + buf[ n+delay ] = samplesIn[ 2 * n ]; } + silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[MAX_ENCODER_DELAY-delay], delay*sizeof(opus_int16)); /* Making sure to start both resamplers from the same state when switching from mono to stereo */ if(psEnc->nPrevChannelsInternal == 1 && id==0) { - silk_memcpy(&psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.delayBuf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf, MAX_ENCODER_DELAY*sizeof(opus_int16)); } + silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf+nSamplesFromInput+delay-MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); @@ -245,23 +249,31 @@ opus_int silk_Encode( nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = samplesIn[ 2 * n + 1 ]; + buf[ n+delay ] = samplesIn[ 2 * n + 1 ]; } + silk_memcpy(buf, &psEnc->state_Fxx[ 1 ].sCmn.delayBuf[MAX_ENCODER_DELAY-delay], delay*sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + silk_memcpy(psEnc->state_Fxx[ 1 ].sCmn.delayBuf, buf+nSamplesFromInput+delay-MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); + psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { /* Combine left and right channels before resampling */ for( n = 0; n < nSamplesFromInput; n++ ) { - buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ], 1 ); + buf[ n+delay ] = (opus_int16)silk_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ], 1 ); } + silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[MAX_ENCODER_DELAY-delay], delay*sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf+nSamplesFromInput+delay-MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } else { silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); + silk_memcpy(buf+delay, samplesIn, nSamplesFromInput*sizeof(opus_int16)); + silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[MAX_ENCODER_DELAY-delay], delay*sizeof(opus_int16)); ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, - &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], samplesIn, nSamplesFromInput ); + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf+nSamplesFromInput+delay-MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16)); psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; } |