Moves the main headers from src/ to include/
[opus.git] / src / opus_decoder.c
index 6b72efa..4f4d648 100644 (file)
@@ -245,9 +245,10 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
 
     ALLOC(pcm_transition, F5*st->channels, opus_val16);
 
-    if (data!=NULL && !st->prev_redundancy && mode != st->prev_mode && st->prev_mode > 0
-               && !(mode == MODE_SILK_ONLY && st->prev_mode == MODE_HYBRID)
-               && !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
+    if (data!=NULL && st->prev_mode > 0 && (
+            (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
+         || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
+         )
     {
        transition = 1;
        if (mode == MODE_CELT_ONLY)
@@ -321,7 +322,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     }
 
     start_band = 0;
-    if (mode != MODE_CELT_ONLY && data != NULL && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) < 8*len)
+    if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
     {
         /* Check if we have a redundant 0-8 kHz band */
         if (mode == MODE_HYBRID)
@@ -334,7 +335,9 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
             /* redundancy_bytes will be at least two, in the non-hybrid case due to the ec_tell() check above */
             redundancy_bytes = mode==MODE_HYBRID ? (opus_int32)ec_dec_uint(&dec, 256)+2 : len-((ec_tell(&dec)+7)>>3);
             len -= redundancy_bytes;
-            if (len<0)
+            /* This is a sanity check. It should never happen for a valid packet,
+               so the exact behaviour is not normative. */
+            if (len*8 < ec_tell(&dec))
             {
                len=0;
                redundancy_bytes=0;
@@ -382,21 +385,17 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
         celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL);
         celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
-        celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
     }
 
     /* MUST be after PLC */
     celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));
 
-    if (transition)
-       celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
-
     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);
+        int celt_frame_size = IMIN(F20, frame_size);
+        /* Make sure to discard any previous CELT state */
+        if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
+            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 {
@@ -418,7 +417,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
             pcm[i] = SAT16(pcm[i] + pcm_silk[i]);
 #else
         for (i=0;i<frame_size*st->channels;i++)
-            pcm[i] = pcm[i] + (1./32768.)*pcm_silk[i];
+            pcm[i] = pcm[i] + (opus_val16)((1./32768.)*pcm_silk[i]);
 #endif
     }
 
@@ -451,12 +450,23 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
     }
     if (transition)
     {
-       for (i=0;i<st->channels*F2_5;i++)
-               pcm[i] = pcm_transition[i];
-       if (audiosize >= F5)
-           smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
-                   pcm+st->channels*F2_5, F2_5,
-                   st->channels, window, st->Fs);
+       if (audiosize >= F5)
+       {
+          for (i=0;i<st->channels*F2_5;i++)
+             pcm[i] = pcm_transition[i];
+          smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
+                pcm+st->channels*F2_5, F2_5,
+                st->channels, window, st->Fs);
+       } else {
+          /* Not enough time to do a clean transition, but we do it anyway
+             This will not preserve amplitude perfectly and may introduce
+             a bit of temporal aliasing, but it shouldn't be too bad and
+             that's pretty much the best we can do. In any case, generating this
+             transition it pretty silly in the first place */
+          smooth_fade(pcm_transition, pcm,
+                pcm, F2_5,
+                st->channels, window, st->Fs);
+       }
     }
 
     if (len <= 1)
@@ -465,7 +475,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
        st->rangeFinal = dec.rng ^ redundant_rng;
 
     st->prev_mode = mode;
-    st->prev_redundancy = redundancy;
+    st->prev_redundancy = redundancy && !celt_to_silk;
     RESTORE_STACK;
        return celt_ret<0 ? celt_ret : audiosize;
 
@@ -716,7 +726,7 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
    if (ret > 0)
    {
       for (i=0;i<ret*st->channels;i++)
-         pcm[i] = (1./32768.)*(out[i]);
+         pcm[i] = (1.f/32768.f)*(out[i]);
    }
    RESTORE_STACK;
    return ret;
@@ -802,9 +812,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
       if (st->prev_mode == MODE_CELT_ONLY)
          celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
       else
-         *value = ((silk_decoder_state*)silk_dec)->indices.signalType == TYPE_VOICED
-         ? ((silk_decoder_state*)silk_dec)->lagPrev*48/((silk_decoder_state*)silk_dec)->fs_kHz
-         : 0;
+         *value = st->DecControl.prevPitchLag;
    }
    break;
    default: