diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-10-11 21:09:14 -0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2011-10-11 21:09:14 -0400 |
commit | b24e57462724185f8922455a2196607f06b98e41 (patch) | |
tree | 5949b3c5f784d4ec8aba4f4c618d30c8537bc63e /silk/decoder_set_fs.c | |
parent | a4885a5fd5165d4732929328de613a35a3d3b359 (diff) | |
download | opus-b24e57462724185f8922455a2196607f06b98e41.tar.gz |
Misc bug fixes
- There was a bug where the decoder resampler was not properly initialized
when fs_kHz == API_fs_kHz. In that case the resampler would continue to
upsample, and the output was corrupt.
- The delay value in the decoder was taken from the state before it was
potentially updated. This caused the decoder to apply the new dalay value one
frame late
- The encoder and decoder states are now updated more consistently, when
the sampling rate changes (pesq liked these changes)
- Properly resetting the side channel encoder and decoder for the first
frame with side coding active again
- Faster updating the "ratio" value in the LR_to_MS() code for large
prediction values means that for certain extreme/artificial input
signals the output looks better
Diffstat (limited to 'silk/decoder_set_fs.c')
-rw-r--r-- | silk/decoder_set_fs.c | 105 |
1 files changed, 69 insertions, 36 deletions
diff --git a/silk/decoder_set_fs.c b/silk/decoder_set_fs.c index c2430f8c..f80470f3 100644 --- a/silk/decoder_set_fs.c +++ b/silk/decoder_set_fs.c @@ -31,24 +31,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "main.h" +static const int dec_delay_matrix[3][5] = { +/*SILK API 8 12 16 24 48 */ +/* 8 */ {3, 0, 2, 0, 0}, +/*12 */ {0, 8, 5, 7, 5}, +/*16 */ {0, 0, 8, 5, 5} +}; + /* Set decoder sampling rate */ -void silk_decoder_set_fs( +opus_int silk_decoder_set_fs( silk_decoder_state *psDec, /* I/O Decoder state pointer */ - opus_int fs_kHz /* I Sampling frequency (kHz) */ + opus_int fs_kHz, /* I Sampling frequency (kHz) */ + opus_int fs_API_Hz /* I API Sampling frequency (Hz) */ ) { - opus_int frame_length; + opus_int frame_length, ret = 0; silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 ); + /* New (sub)frame length */ psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz ); frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length ); + + /* Initialize resampler when switching internal or external sampling frequency */ + if( psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz ) { + /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */ + opus_int16 temp_buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ]; + silk_resampler_state_struct temp_resampler_state; + + /* New delay value */ + psDec->delay = dec_delay_matrix[ rateID( silk_SMULBB( fs_kHz, 1000 ) ) ][ rateID( fs_API_Hz ) ]; + silk_assert( psDec->delay <= MAX_DECODER_DELAY ); + + if( psDec->fs_kHz != fs_kHz && psDec->fs_kHz > 0 ) { + /* Initialize resampler for temporary resampling of outBuf data to the new internal sampling rate */ + ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psDec->fs_kHz, 1000 ), silk_SMULBB( fs_kHz, 1000 ) ); + + /* Temporary resampling of outBuf data to the new internal sampling rate */ + silk_memcpy( temp_buf, psDec->outBuf, psDec->frame_length * sizeof( opus_int16 ) ); + ret += silk_resampler( &temp_resampler_state, psDec->outBuf, temp_buf, psDec->frame_length ); + } + + /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */ + ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz ); + + /* Correct resampler state by resampling buffered data from fs_kHz to API_fs_Hz */ + ret += silk_resampler( &psDec->resampler_state, temp_buf, psDec->outBuf, frame_length ); + + psDec->fs_API_hz = fs_API_Hz; + } + if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) { - psDec->fs_kHz = fs_kHz; - psDec->frame_length = frame_length; - psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); - if( psDec->fs_kHz == 8 ) { + if( fs_kHz == 8 ) { if( psDec->nb_subfr == MAX_NB_SUBFR ) { psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; } else { @@ -61,40 +96,38 @@ void silk_decoder_set_fs( psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; } } - if( psDec->fs_kHz == 8 || psDec->fs_kHz == 12 ) { - psDec->LPC_order = MIN_LPC_ORDER; - psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB; - } else { - psDec->LPC_order = MAX_LPC_ORDER; - psDec->psNLSF_CB = &silk_NLSF_CB_WB; + if( psDec->fs_kHz != fs_kHz ) { + psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + if( fs_kHz == 8 || fs_kHz == 12 ) { + psDec->LPC_order = MIN_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psDec->LPC_order = MAX_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_WB; + } + if( fs_kHz == 16 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( fs_kHz == 12 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else if( fs_kHz == 8 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } else { + /* unsupported sampling rate */ + silk_assert( 0 ); + } + psDec->first_frame_after_reset = 1; + psDec->lagPrev = 100; + psDec->LastGainIndex = 10; + psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY; } - if( psDec->fs_kHz != fs_kHz) - { - /* Reset part of the decoder state */ - silk_memset( psDec->sLPC_Q14_buf, 0, sizeof( psDec->sLPC_Q14_buf ) ); - silk_memset( psDec->outBuf, 0, MAX_FRAME_LENGTH * sizeof( opus_int16 ) ); - silk_memset( psDec->prevNLSF_Q15, 0, sizeof( psDec->prevNLSF_Q15 ) ); - } - psDec->lagPrev = 100; - psDec->LastGainIndex = 10; - psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY; - if( psDec->fs_kHz != fs_kHz) - psDec->first_frame_after_reset = 1; - - if( fs_kHz == 16 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; - } else if( fs_kHz == 12 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; - } else if( fs_kHz == 8 ) { - psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; - } else { - /* unsupported sampling rate */ - silk_assert( 0 ); - } + psDec->fs_kHz = fs_kHz; + psDec->frame_length = frame_length; } /* Check that settings are valid */ silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); + + return ret; } |