Make it possible to ignore inverted phase stereo for downmix purposes
[opus.git] / src / opus_encoder.c
index 93badd4..ef464fc 100644 (file)
@@ -86,9 +86,9 @@ struct OpusEncoder {
     int          encoder_buffer;
     int          lfe;
     int          arch;
+    int          use_dtx;                 /* general DTX for both SILK and CELT */
 #ifndef DISABLE_FLOAT_API
     TonalityAnalysisState analysis;
-    int          use_dtx;                 /* general DTX for both SILK and CELT */
 #endif
 
 #define OPUS_ENCODER_RESET_START stream_channels
@@ -388,14 +388,14 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
       for (i=0;i<len;i++)
       {
          opus_val32 x, tmp, y;
-         x = SHL32(EXTEND32(in[channels*i+c]), 15);
+         x = SHL32(EXTEND32(in[channels*i+c]), 14);
          /* First stage */
          tmp = x-hp_mem[2*c];
          hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
          /* Second stage */
          y = tmp - hp_mem[2*c+1];
          hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift);
-         out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 15), 32767));
+         out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
       }
    }
 }
@@ -403,24 +403,57 @@ static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *ou
 #else
 static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
 {
-   int c, i;
-   float coef;
-
+   int i;
+   float coef, coef2;
    coef = 4.0f*cutoff_Hz/Fs;
-   for (c=0;c<channels;c++)
+   coef2 = 1-coef;
+   if (channels==2)
    {
+      float m0, m1, m2, m3;
+      m0 = hp_mem[0];
+      m1 = hp_mem[1];
+      m2 = hp_mem[2];
+      m3 = hp_mem[3];
+      for (i=0;i<len;i++)
+      {
+         opus_val32 x0, x1, tmp0, tmp1, y0, y1;
+         x0 = in[2*i+0];
+         x1 = in[2*i+1];
+         /* First stage */
+         tmp0 = x0-m0;
+         tmp1 = x1-m2;
+         m0 = coef*x0 + VERY_SMALL + coef2*m0;
+         m2 = coef*x1 + VERY_SMALL + coef2*m2;
+         /* Second stage */
+         y0 = tmp0 - m1;
+         y1 = tmp1 - m3;
+         m1 = coef*tmp0 + VERY_SMALL + coef2*m1;
+         m3 = coef*tmp1 + VERY_SMALL + coef2*m3;
+         out[2*i+0] = y0;
+         out[2*i+1] = y1;
+      }
+      hp_mem[0] = m0;
+      hp_mem[1] = m1;
+      hp_mem[2] = m2;
+      hp_mem[3] = m3;
+   } else {
+      float m0, m1;
+      m0 = hp_mem[0];
+      m1 = hp_mem[1];
       for (i=0;i<len;i++)
       {
          opus_val32 x, tmp, y;
-         x = in[channels*i+c];
+         x = in[i];
          /* First stage */
-         tmp = x-hp_mem[2*c];
-         hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]) + VERY_SMALL;
+         tmp = x-m0;
+         m0 = coef*x + VERY_SMALL + coef2*m0;
          /* Second stage */
-         y = tmp - hp_mem[2*c+1];
-         hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]) + VERY_SMALL;
-         out[channels*i+c] = y;
+         y = tmp - m1;
+         m1 = coef*tmp + VERY_SMALL + coef2*m1;
+         out[i] = y;
       }
+      hp_mem[0] = m0;
+      hp_mem[1] = m1;
    }
 }
 #endif
@@ -778,9 +811,9 @@ void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, in
 #else
    scale = 1.f;
 #endif
-   if (C==-2)
+   if (c2==-2)
       scale /= C;
-   else
+   else if (c2>-1)
       scale /= 2;
    for (j=0;j<subframe;j++)
       sub[j] *= scale;
@@ -813,9 +846,9 @@ void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int
 #else
    scale = 1.f/32768;
 #endif
-   if (C==-2)
+   if (c2==-2)
       scale /= C;
-   else
+   else if (c2>-1)
       scale /= 2;
    for (j=0;j<subframe;j++)
       sub[j] *= scale;
@@ -984,23 +1017,24 @@ static int decide_fec(int useInBandFEC, int PacketLoss_perc, int last_fec, int m
    return 0;
 }
 
-static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr) {
+static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec) {
    int entry;
    int i;
    int N;
    int silk_rate;
    static int rate_table[][5] = {
   /*  |total| |-------- SILK------------|
-              SWB-10  FB-10 SWB-20  FB-20 */
+              |-- No FEC -| |--- FEC ---|
+               10ms   20ms   10ms   20ms */
       {    0,     0,     0,     0,     0},
-      {12000, 10000, 10000, 10000, 10000},
-      {16000, 14000, 14000, 14000, 13500},
-      {20000, 16000, 16000, 16000, 16000},
-      {24000, 18000, 18000, 18000, 18000},
-      {32000, 22000, 22000, 22000, 22000},
-      {64000, 38000, 38000, 38000, 38000}
+      {12000, 10000, 10000, 11000, 11000},
+      {16000, 13500, 13500, 15000, 15000},
+      {20000, 16000, 16000, 18000, 18000},
+      {24000, 18000, 18000, 21000, 21000},
+      {32000, 22000, 22000, 28000, 28000},
+      {64000, 38000, 38000, 50000, 50000}
    };
-   entry = 1 + 2*frame20ms + (bandwidth==OPUS_BANDWIDTH_FULLBAND);
+   entry = 1 + frame20ms + 2*fec;
    N = sizeof(rate_table)/sizeof(rate_table[0]);
    for (i=1;i<N;i++)
    {
@@ -1024,6 +1058,8 @@ static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms,
       /* Tiny boost to SILK for CBR. We should probably tune this better. */
       silk_rate += 100;
    }
+   if (bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND)
+      silk_rate += 300;
    return silk_rate;
 }
 
@@ -1063,15 +1099,16 @@ static opus_int32 compute_equiv_rate(opus_int32 bitrate, int channels,
 
 #ifndef DISABLE_FLOAT_API
 
-static int is_digital_silence(const opus_val16* pcm, int frame_size, int lsb_depth)
+static int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth)
 {
    int silence = 0;
    opus_val32 sample_max = 0;
 
-   sample_max = celt_maxabs16(pcm, frame_size);
+   sample_max = celt_maxabs16(pcm, frame_size*channels);
 
 #ifdef FIXED_POINT
    silence = (sample_max == 0);
+   (void)lsb_depth;
 #else
    silence = (sample_max <= (opus_val16) 1 / (1 << lsb_depth));
 #endif
@@ -1079,35 +1116,40 @@ static int is_digital_silence(const opus_val16* pcm, int frame_size, int lsb_dep
    return silence;
 }
 
-static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size)
+#ifdef FIXED_POINT
+static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
 {
    int i;
-#ifdef FIXED_POINT
    opus_val32 sample_max;
    int max_shift;
    int shift;
-#endif
    opus_val32 energy = 0;
-
-#ifdef FIXED_POINT
+   int len = frame_size*channels;
+   (void)arch;
    /* Max amplitude in the signal */
-   sample_max = celt_maxabs16(pcm, frame_size);
+   sample_max = celt_maxabs16(pcm, len);
 
    /* Compute the right shift required in the MAC to avoid an overflow */
-   max_shift = celt_ilog2(frame_size);
+   max_shift = celt_ilog2(len);
    shift = IMAX(0, (celt_ilog2(sample_max) << 1) + max_shift - 28);
-#endif
 
    /* Compute the energy */
-   for (i=0; i<frame_size; i++)
+   for (i=0; i<len; i++)
       energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift);
 
    /* Normalize energy by the frame size and left-shift back to the original position */
-   energy /= frame_size;
+   energy /= len;
    energy = SHL32(energy, shift);
 
    return energy;
 }
+#else
+static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
+{
+   int len = frame_size*channels;
+   return celt_inner_prod(pcm, pcm, len, arch)/len;
+}
+#endif
 
 /* Decides if DTX should be turned on (=1) or off (=0) */
 static int decide_dtx_mode(float activity_probability,    /* probability that current frame contains speech/music */
@@ -1115,7 +1157,9 @@ static int decide_dtx_mode(float activity_probability,    /* probability that cu
                            opus_val32 peak_signal_energy, /* peak energy of desired signal detected so far */
                            const opus_val16 *pcm,         /* input pcm signal */
                            int frame_size,                /* frame size */
-                           int is_silence                 /* only digital silence detected in this frame */
+                           int channels,
+                           int is_silence,                 /* only digital silence detected in this frame */
+                           int arch
                           )
 {
    int is_noise;
@@ -1127,7 +1171,7 @@ static int decide_dtx_mode(float activity_probability,    /* probability that cu
       is_noise = activity_probability < DTX_ACTIVITY_THRESHOLD;
       if (is_noise)
       {
-         noise_energy = compute_frame_energy(pcm, frame_size);
+         noise_energy = compute_frame_energy(pcm, frame_size, channels, arch);
          is_sufficiently_quiet = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
       }
    }
@@ -1226,7 +1270,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     if (st->silk_mode.complexity >= 7 && st->Fs==48000)
 #endif
     {
-       if (is_digital_silence(pcm, frame_size, lsb_depth))
+       if (is_digital_silence(pcm, frame_size, st->channels, lsb_depth))
        {
           is_silence = 1;
        } else {
@@ -1239,7 +1283,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
 
        /* Track the peak signal energy */
        if (!is_silence && analysis_info.activity_probability > DTX_ACTIVITY_THRESHOLD)
-          st->peak_signal_energy = MAX32(MULT16_32_Q15(QCONST16(0.999, 15), st->peak_signal_energy), compute_frame_energy(pcm, frame_size));
+          st->peak_signal_energy = MAX32(MULT16_32_Q15(QCONST16(0.999, 15), st->peak_signal_energy),
+                compute_frame_energy(pcm, frame_size, st->channels, st->arch));
     }
 #else
     (void)analysis_pcm;
@@ -1419,9 +1464,13 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
        if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4)
           st->mode = MODE_SILK_ONLY;
        /* When encoding voice and DTX is enabled but the generalized DTX cannot be used,
-          because of complexity and sampling frequency settings,
-          set the encoder to SILK mode so that the SILK DTX can be used */
+          because of complexity and sampling frequency settings, switch to SILK DTX and
+          set the encoder to SILK mode */
+#ifndef DISABLE_FLOAT_API
        st->silk_mode.useDTX = st->use_dtx && !(analysis_info.valid || is_silence);
+#else
+       st->silk_mode.useDTX = st->use_dtx;
+#endif
        if (st->silk_mode.useDTX && voice_est > 100)
           st->mode = MODE_SILK_ONLY;
 #endif
@@ -1741,7 +1790,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
         if( st->mode == MODE_HYBRID ) {
             /* Base rate for SILK */
             st->silk_mode.bitRate = compute_silk_rate_for_hybrid(total_bitRate,
-                  curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr);
+                  curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
             if (!st->energy_masking)
             {
                /* Increasingly attenuate high band when it gets allocated fewer bits */
@@ -1850,7 +1899,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
            {
               /* Compute SILK bitrate corresponding to the max total bits available */
               opus_int32 maxBitRate = compute_silk_rate_for_hybrid(nBytes*8*st->Fs / frame_size,
-                    curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr);
+                    curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
               st->silk_mode.maxBits = maxBitRate * frame_size / st->Fs;
            }
         }
@@ -2197,7 +2246,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
 #ifndef DISABLE_FLOAT_API
     if (st->use_dtx && (analysis_info.valid || is_silence))
     {
-       if (decide_dtx_mode(analysis_info.activity_probability, &st->nb_no_activity_frames, st->peak_signal_energy, pcm, frame_size, is_silence))
+       if (decide_dtx_mode(analysis_info.activity_probability, &st->nb_no_activity_frames,
+             st->peak_signal_energy, pcm, frame_size, st->channels, is_silence, st->arch))
        {
           st->rangeFinal = 0;
           data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
@@ -2731,6 +2781,26 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
            *value = st->silk_mode.reducedDependency;
         }
         break;
+        case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+        {
+            opus_int32 value = va_arg(ap, opus_int32);
+            if(value<0 || value>1)
+            {
+               goto bad_arg;
+            }
+            celt_encoder_ctl(celt_enc, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+        }
+        break;
+        case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+        {
+            opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value)
+            {
+               goto bad_arg;
+            }
+            celt_encoder_ctl(celt_enc, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+        }
+        break;
         case OPUS_RESET_STATE:
         {
            void *silk_enc;