shithub: opus

Download patch

ref: 4958751ef4eaccf2624368a50cccd76acf0a6186
parent: 2f7a315101754f1becca9c7b253711222af4407a
author: Jean-Marc Valin <[email protected]>
date: Sat Jul 6 22:50:18 EDT 2013

Better handling of centre for surround masking, bitrate tuning

Centre channel now contributes sqrt(.5) to both channels
Reduces the stream offset at low bitrate

--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -37,6 +37,7 @@
 #include "float_cast.h"
 #include "os_support.h"
 #include "analysis.h"
+#include "mathops.h"
 
 typedef struct {
    int nb_streams;
@@ -372,9 +373,12 @@
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
 
+   if (st->bitrate_bps > st->layout.nb_channels*40000)
+      stream_offset = 20000;
+   else
+      stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
    /* We start by giving each stream (coupled or uncoupled) the same bitrate.
       This models the main saving of coupled channels over uncoupled. */
-   stream_offset = 20000;
    /* The LFE stream is an exception to the above and gets fewer bits. */
    lfe_offset = 3500;
    /* Coupled streams get twice the mono rate after the first 20 kb/s. */
@@ -524,8 +528,16 @@
             , &analysis_info
 #endif
             );
+      /* Combines the left and right mask into a centre mask. We
+         use an approximation for the log of the sum of the energies. */
       for(i=0;i<21;i++)
-         bandLogE_mono[i] = MAX16(bandLogE[i], bandLogE[21+i]);
+      {
+         opus_val16 diff;
+         diff = ABS16(SUB16(bandLogE[i], bandLogE[21+i]));
+         diff = diff + HALF16(diff);
+         diff = SHR32(HALF32(celt_exp2(-diff)), 16-DB_SHIFT);
+         bandLogE_mono[i] = MAX16(bandLogE[i], bandLogE[21+i]) + diff;
+      }
    }
 
    if (max_data_bytes < 4*st->layout.nb_streams-1)
@@ -696,7 +708,7 @@
 
    for (c=0;c<channels;c++)
    {
-      if (pos[c]==1||pos[c]==2)
+      if (pos[c]==1)
       {
          for (i=0;i<frame_size;i++)
 #if defined(FIXED_POINT)
@@ -704,8 +716,7 @@
 #else
             dst[2*i] += float_src[i*channels+c];
 #endif
-      }
-      if (pos[c]==2||pos[c]==3)
+      } else if (pos[c]==3)
       {
          for (i=0;i<frame_size;i++)
 #if defined(FIXED_POINT)
@@ -713,6 +724,18 @@
 #else
             dst[2*i+1] += float_src[i*channels+c];
 #endif
+      } else if (pos[c]==2)
+      {
+         for (i=0;i<frame_size;i++)
+         {
+#if defined(FIXED_POINT)
+            dst[2*i] += SHR32(MULT16_16(QCONST16(.70711f,15), FLOAT2INT16(float_src[i*channels+c])),3+15);
+            dst[2*i+1] += SHR32(MULT16_16(QCONST16(.70711f,15), FLOAT2INT16(float_src[i*channels+c])),3+15);
+#else
+            dst[2*i] += .707*float_src[i*channels+c];
+            dst[2*i+1] += .707*float_src[i*channels+c];
+#endif
+         }
       }
    }
 }
@@ -757,7 +780,7 @@
 
    for (c=0;c<channels;c++)
    {
-      if (pos[c]==1||pos[c]==2)
+      if (pos[c]==1)
       {
          for (i=0;i<frame_size;i++)
 #if defined(FIXED_POINT)
@@ -765,8 +788,7 @@
 #else
             dst[2*i] += (1/32768.f)*short_src[i*channels+c];
 #endif
-      }
-      if (pos[c]==2||pos[c]==3)
+      } else if (pos[c]==3)
       {
          for (i=0;i<frame_size;i++)
 #if defined(FIXED_POINT)
@@ -774,6 +796,18 @@
 #else
             dst[2*i+1] += (1/32768.f)*short_src[i*channels+c];
 #endif
+      } else if (pos[c]==2)
+      {
+         for (i=0;i<frame_size;i++)
+         {
+#if defined(FIXED_POINT)
+            dst[2*i] += SHR32(MULT16_16(QCONST16(.70711f,15), short_src[i*channels+c]),3+15);
+            dst[2*i+1] += SHR32(MULT16_16(QCONST16(.70711f,15), short_src[i*channels+c]),3+15);
+#else
+            dst[2*i] += (.707f/32768.f)*short_src[i*channels+c];
+            dst[2*i+1] += (.707f/32768.f)*short_src[i*channels+c];
+#endif
+         }
       }
    }
 }