SILK bugfix
[opus.git] / src / opus_encoder.c
index b0e445f..4ac580e 100644 (file)
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -95,38 +91,51 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
        int ret=0;
        SKP_int32 nBytes;
        ec_enc enc;
-       ec_byte_buffer buf;
        int framerate, period;
     int silk_internal_bandwidth;
     int bytes_target;
+    int prefill=0;
+    int start_band;
+    int redundancy = 0;
 
        bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
 
        data += 1;
-       ec_byte_writeinit_buffer(&buf, data, max_data_bytes-1);
-       ec_enc_init(&enc,&buf);
+       if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
+       {
+               SKP_SILK_SDK_EncControlStruct dummy;
+               SKP_Silk_SDK_InitEncoder( st->silk_enc, &dummy);
+               prefill=1;
+       }
+
+       ec_enc_init(&enc, data, max_data_bytes-1);
 
        /* SILK processing */
-    if (st->mode != MODE_CELT_ONLY) {
+    if (st->mode != MODE_CELT_ONLY)
+    {
         st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size;
         if( st->mode == MODE_HYBRID ) {
             if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) {
                 if( st->Fs == 100 * frame_size ) {
                     /* 24 kHz, 10 ms */
-                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 8000 - ( 1 - st->use_vbr ) * 7000 ) * 2 ) / 3;
+                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
                 } else {
                     /* 24 kHz, 20 ms */
-                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 12000 - ( 1 - st->use_vbr ) * 10000 ) * 2 ) / 3;
+                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
                 }
             } else {
                 if( st->Fs == 100 * frame_size ) {
                     /* 48 kHz, 10 ms */
-                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 16000 - ( 1 - st->use_vbr ) * 8000 ) / 2;
+                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
                 } else {
                     /* 48 kHz, 20 ms */
-                       st->silk_mode.bitRate = ( st->silk_mode.bitRate + 14000 - ( 1 - st->use_vbr ) * 5000 ) / 2;
+                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
                 }
             }
+            /* don't let SILK use more than 80% */
+            if( st->silk_mode.bitRate > ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5 ) {
+                st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
+            }
         }
 
         st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
@@ -140,12 +149,20 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
         }
         if( st->mode == MODE_HYBRID ) {
             /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
-            st->silk_mode.minInternalSampleRate = st->silk_mode.maxInternalSampleRate ;
+            st->silk_mode.minInternalSampleRate = 16000;
+        } else {
+            st->silk_mode.minInternalSampleRate = 8000;
         }
 
         /* Call SILK encoder for the low band */
         nBytes = max_data_bytes-1;
-        ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes );
+        if (prefill)
+        {
+            int zero=0;
+               SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, st->delay_buffer, ENCODER_BUFFER, NULL, &zero, 1 );
+        }
+
+        ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 );
         if( ret ) {
             fprintf (stderr, "SILK encode error: %d\n", ret);
             /* Handle error */
@@ -159,13 +176,15 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
             } else if( st->silk_mode.internalSampleRate == 16000 ) {
                 silk_internal_bandwidth = BANDWIDTH_WIDEBAND;
             }
+        } else {
+            SKP_assert( st->silk_mode.internalSampleRate == 16000 );
         }
     }
 
     /* CELT processing */
        if (st->mode != MODE_SILK_ONLY)
        {
-               int endband;
+           int endband;
            short pcm_buf[960*2];
            int nb_compr_bytes;
 
@@ -189,20 +208,39 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
 
         celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
         celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000));
+        if (st->prev_mode == MODE_SILK_ONLY)
+        {
+               unsigned char dummy[2];
+               celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
+               celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));
+               /* FIXME: This wastes CPU a bit compared to just prefilling the buffer */
+               celt_encode(st->celt_enc, &st->delay_buffer[(ENCODER_BUFFER-ENCODER_DELAY_COMPENSATION-120)*st->channels], 120, dummy, 10);
+        } else {
+               celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2));
+        }
+
+        start_band = 0;
+        if (st->mode == MODE_HYBRID)
+        {
+            /* Check if we have a redundant 0-8 kHz band */
+            ec_enc_bit_logp(&enc, redundancy, 12);
+            if (!redundancy)
+                start_band = 17;
+        }
+        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(start_band));
+
         if (st->mode == MODE_HYBRID)
         {
             int len;
-            celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(17));
 
-            len = (ec_enc_tell(&enc, 0)+7)>>3;
+            len = (ec_tell(&enc)+7)>>3;
             if( st->use_vbr ) {
-                nb_compr_bytes = len + (st->bitrate_bps - 12000) * frame_size / (2 * 8 * st->Fs);
+                nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
             } else {
                 /* check if SILK used up too much */
                 nb_compr_bytes = len > bytes_target ? len : bytes_target;
             }
         } else {
-            celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
             if (st->use_vbr)
             {
                 celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(1));
@@ -213,19 +251,29 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
             }
         }
 
-           for (i=0;i<ENCODER_DELAY_COMPENSATION*st->channels;i++)
-               pcm_buf[i] = st->delay_buffer[i];
+        for (i=0;i<IMIN(frame_size, ENCODER_DELAY_COMPENSATION)*st->channels;i++)
+            pcm_buf[i] = st->delay_buffer[(ENCODER_BUFFER-ENCODER_DELAY_COMPENSATION)*st->channels+i];
         for (;i<frame_size*st->channels;i++)
             pcm_buf[i] = pcm[i-ENCODER_DELAY_COMPENSATION*st->channels];
 
-        ec_byte_shrink(&buf, nb_compr_bytes);
+        ec_enc_shrink(&enc, nb_compr_bytes);
 
            /* Encode high band with CELT */
            ret = celt_encode_with_ec(st->celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
-           for (i=0;i<ENCODER_DELAY_COMPENSATION*st->channels;i++)
-               st->delay_buffer[i] = pcm[frame_size*st->channels-ENCODER_DELAY_COMPENSATION*st->channels+i];
+
+           if (frame_size>ENCODER_BUFFER)
+           {
+               for (i=0;i<ENCODER_BUFFER*st->channels;i++)
+                   st->delay_buffer[i] = pcm[(frame_size-ENCODER_BUFFER)*st->channels+i];
+           } else {
+               int tmp = ENCODER_BUFFER-frame_size;
+               for (i=0;i<tmp*st->channels;i++)
+                   st->delay_buffer[i] = st->delay_buffer[i+frame_size*st->channels];
+               for (i=0;i<frame_size*st->channels;i++)
+                   st->delay_buffer[tmp*st->channels+i] = pcm[i];
+           }
        } else {
-           ret = (ec_enc_tell(&enc, 0)+7)>>3;
+           ret = (ec_tell(&enc)+7)>>3;
            ec_enc_done(&enc);
        }
 
@@ -262,7 +310,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
 #if OPUS_TEST_RANGE_CODER_STATE
     st->rangeFinal = enc.rng;
 #endif
-
+    st->prev_mode = st->mode;
     return ret+1;
 }
 
@@ -333,6 +381,7 @@ void opus_encoder_ctl(OpusEncoder *st, int request, ...)
         {
             int value = va_arg(ap, int);
             st->silk_mode.complexity = value;
+            celt_encoder_ctl(st->celt_enc, CELT_SET_COMPLEXITY(value));
         }
         break;
         case OPUS_GET_COMPLEXITY_REQUEST: