Fixes glithes when switching between SILK-only and hybrid
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 4 Oct 2011 15:59:32 +0000 (11:59 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 4 Oct 2011 15:59:32 +0000 (11:59 -0400)
We now reset the CELT state when swithing to hybrid and we "drain"
the CELT MDCT overlap when switching away from hybrid.

src/opus_decoder.c
src/opus_encoder.c

index 8f8d108..9e8071a 100644 (file)
@@ -390,11 +390,21 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     if (mode != MODE_SILK_ONLY)
     {
        int celt_frame_size = IMIN(F20, frame_size);
+       /* Make sure to discard any previous CELT state */
+       if (st->prev_mode == MODE_SILK_ONLY)
+          celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
         /* Decode CELT */
         celt_ret = celt_decode_with_ec(celt_dec, decode_fec?NULL:data, len, pcm, celt_frame_size, &dec);
     } else {
+       unsigned char silence[2] = {0xFF, 0xFF};
        for (i=0;i<frame_size*st->channels;i++)
           pcm[i] = 0;
+       /* For hybrid -> SILK transitions, we let the CELT MDCT do a fade-out by decoding a silence frame */
+       if (st->prev_mode == MODE_HYBRID)
+       {
+          celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
+          celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL);
+       }
     }
 
     if (mode != MODE_CELT_ONLY)
index 327d3cf..d203bfd 100644 (file)
@@ -891,7 +891,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
 
 
     if (st->mode != MODE_HYBRID || st->stream_channels==1)
-       st->silk_mode.stereoWidth_Q14 = 1<<14;
+       st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14 = 1<<14;
     if( st->channels == 2 ) {
         /* Apply stereo width reduction (at low bitrates) */
         if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {