Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.xiph.org/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2011-10-12 05:09:14 +0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2011-10-12 05:09:14 +0400
commitb24e57462724185f8922455a2196607f06b98e41 (patch)
tree5949b3c5f784d4ec8aba4f4c618d30c8537bc63e /silk/decoder_set_fs.c
parenta4885a5fd5165d4732929328de613a35a3d3b359 (diff)
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.c105
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;
}