[opus] Patches for adding 120 ms encoding

Felicia Lim flim at google.com
Thu Jun 2 12:13:22 UTC 2016


OK, I've amended the second patch and also added 80 and 100 ms.

Thanks,
Felicia

On Thu, Jun 2, 2016 at 7:20 AM Jean-Marc Valin <jmvalin at jmvalin.ca> wrote:

> On 06/01/2016 02:06 PM, Felicia Lim wrote:
> > That was my intention with refactoring out the subframe encoding and
> > repacketizing bit. Or do you mean I should merge the explicit check for
> > 120 ms frame and the existing checks for 40/60 ms wideband?
>
> What I mean is that this line in opus_encoder.c:
>
> if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY ||
> st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
>
> can probably be extended to also cover 80/100/120 ms. One difference is
> that it would also need to trigger for SILK-only > 60 ms.
>
> Cheers,
>
>         Jean-Marc
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.xiph.org/pipermail/opus/attachments/20160602/ef64463a/attachment.html>
-------------- next part --------------
From f8f1010620fc9c4478a5ae9b0cb466d30bdf2193 Mon Sep 17 00:00:00 2001
From: Felicia Lim <flim at google.com>
Date: Thu, 2 Jun 2016 13:58:24 +0200
Subject: [PATCH 2/2] Extend support for 80, 100 and 120 ms

---
 include/opus_defines.h |  9 +++++++++
 src/opus_demo.c        | 18 +++++++++++++++---
 src/opus_encoder.c     | 39 ++++++++++++++++++++++++---------------
 tests/test_opus_api.c  |  9 +++++++++
 4 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/include/opus_defines.h b/include/opus_defines.h
index 315412d..bd4401d 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -208,6 +208,9 @@ extern "C" {
 #define OPUS_FRAMESIZE_20_MS                 5004 /**< Use 20 ms frames */
 #define OPUS_FRAMESIZE_40_MS                 5005 /**< Use 40 ms frames */
 #define OPUS_FRAMESIZE_60_MS                 5006 /**< Use 60 ms frames */
+#define OPUS_FRAMESIZE_80_MS                 5007 /**< Use 80 ms frames */
+#define OPUS_FRAMESIZE_100_MS                5008 /**< Use 100 ms frames */
+#define OPUS_FRAMESIZE_120_MS                5009 /**< Use 120 ms frames */
 
 /**@}*/
 
@@ -566,6 +569,9 @@ extern "C" {
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
   * </dl>
   * @hideinitializer */
@@ -581,6 +587,9 @@ extern "C" {
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
   * </dl>
   * @hideinitializer */
diff --git a/src/opus_demo.c b/src/opus_demo.c
index 9e99a3b..56b9895 100644
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -56,7 +56,7 @@ void print_usage( char* argv[] )
     fprintf(stderr, "-cvbr                : enable constrained variable bitrate; default: unconstrained\n" );
     fprintf(stderr, "-variable-duration   : enable frames of variable duration (experts only); default: disabled\n" );
     fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
-    fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
+    fprintf(stderr, "-framesize <2.5|5|10|20|40|60|80|100|120> : frame size in ms; default: 20 \n" );
     fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
     fprintf(stderr, "-complexity <comp>   : complexity, 0 (lowest) ... 10 (highest); default: 10\n" );
     fprintf(stderr, "-inbandfec           : enable SILK inband FEC\n" );
@@ -382,9 +382,15 @@ int main(int argc, char *argv[])
                 frame_size = sampling_rate/25;
             else if (strcmp(argv[ args + 1 ], "60")==0)
                 frame_size = 3*sampling_rate/50;
+            else if (strcmp(argv[ args + 1 ], "80")==0)
+                frame_size = 4*sampling_rate/50;
+            else if (strcmp(argv[ args + 1 ], "100")==0)
+                frame_size = 5*sampling_rate/50;
+            else if (strcmp(argv[ args + 1 ], "120")==0)
+                frame_size = 6*sampling_rate/50;
             else {
                 fprintf(stderr, "Unsupported frame size: %s ms. "
-                                "Supported are 2.5, 5, 10, 20, 40, 60.\n",
+                                "Supported are 2.5, 5, 10, 20, 40, 60, 80, 100, 120.\n",
                                 argv[ args + 1 ]);
                 return EXIT_FAILURE;
             }
@@ -610,8 +616,14 @@ int main(int argc, char *argv[])
              variable_duration = OPUS_FRAMESIZE_20_MS;
           else if (frame_size==sampling_rate/25)
              variable_duration = OPUS_FRAMESIZE_40_MS;
-          else
+          else if (frame_size==3*sampling_rate/50)
              variable_duration = OPUS_FRAMESIZE_60_MS;
+          else if (frame_size==4*sampling_rate/50)
+             variable_duration = OPUS_FRAMESIZE_80_MS;
+          else if (frame_size==5*sampling_rate/50)
+             variable_duration = OPUS_FRAMESIZE_100_MS;
+          else
+             variable_duration = OPUS_FRAMESIZE_120_MS;
           opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));
        }
        frame_size = 2*48000;
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 9305990..a0f9d51 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -813,14 +813,20 @@ opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_
       new_size = frame_size;
    else if (variable_duration == OPUS_FRAMESIZE_VARIABLE)
       new_size = Fs/50;
-   else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS)
-      new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS));
+   else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_120_MS)
+   {
+      if (variable_duration <= OPUS_FRAMESIZE_40_MS)
+         new_size = (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS);
+      else
+         new_size = (variable_duration-OPUS_FRAMESIZE_2_5_MS-2)*Fs/50;
+   }
    else
       return -1;
    if (new_size>frame_size)
       return -1;
-   if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&
-            50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs)
+   if (400*new_size!=Fs   && 200*new_size!=Fs   && 100*new_size!=Fs   &&
+        50*new_size!=Fs   &&  25*new_size!=Fs   &&  50*new_size!=3*Fs &&
+        50*new_size!=4*Fs &&  50*new_size!=5*Fs &&  50*new_size!=6*Fs)
       return -1;
    return new_size;
 }
@@ -973,8 +979,8 @@ static opus_int32 encode_subframes_and_repacketize(OpusEncoder *st,
    st->user_forced_mode = st->mode;
    st->user_bandwidth = st->bandwidth;
    st->force_channels = st->stream_channels;
-   bak_to_mono = st->silk_mode.toMono;
 
+   bak_to_mono = st->silk_mode.toMono;
    if (bak_to_mono)
       st->force_channels = 1;
    else
@@ -1010,7 +1016,7 @@ static opus_int32 encode_subframes_and_repacketize(OpusEncoder *st,
    if (st->use_vbr)
       repacketize_len = out_data_bytes;
    else {
-      cbr_bytes = st->bitrate_bps / (8 * st->Fs/frame_size);
+      cbr_bytes = st->bitrate_bps/(8*st->Fs/frame_size);
       repacketize_len = IMIN(cbr_bytes*nb_frames, out_data_bytes);
    }
 
@@ -1078,7 +1084,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
 
     st->rangeFinal = 0;
     if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
-         50*frame_size != st->Fs &&  25*frame_size != st->Fs &&  50*frame_size != 3*st->Fs)
+         50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs && 50*frame_size != 4*st->Fs &&
+         50*frame_size != 5*st->Fs && 50*frame_size != 6*st->Fs)
          || (400*frame_size < st->Fs)
          || max_data_bytes<=0
          )
@@ -1445,15 +1452,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     if (st->lfe)
        st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
 
-    /* Can't support higher than wideband for >20 ms frames */
-    if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
+    /* Can't support higher than wideband for >20 ms frames, CELT-only for >20 ms and SILK-only for >60 ms */
+    if ((frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)) ||
+        (frame_size > 3*st->Fs/50 && st->mode == MODE_SILK_ONLY))
     {
        int subframe_size;
        int nb_subframes;
 
-       /* CELT can only support up to 20 ms */
        subframe_size = st->Fs/50;
-       nb_subframes = frame_size > st->Fs/25 ? 3 : 2;
+       nb_subframes = frame_size/subframe_size;
 
 #ifndef DISABLE_FLOAT_API
        if (analysis_read_pos_bak!= -1)
@@ -2456,10 +2463,12 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value != OPUS_FRAMESIZE_ARG   && value != OPUS_FRAMESIZE_2_5_MS &&
-                value != OPUS_FRAMESIZE_5_MS  && value != OPUS_FRAMESIZE_10_MS  &&
-                value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS  &&
-                value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE)
+            if (value != OPUS_FRAMESIZE_ARG    && value != OPUS_FRAMESIZE_2_5_MS &&
+                value != OPUS_FRAMESIZE_5_MS   && value != OPUS_FRAMESIZE_10_MS  &&
+                value != OPUS_FRAMESIZE_20_MS  && value != OPUS_FRAMESIZE_40_MS  &&
+                value != OPUS_FRAMESIZE_60_MS  && value != OPUS_FRAMESIZE_80_MS  &&
+                value != OPUS_FRAMESIZE_100_MS && value != OPUS_FRAMESIZE_120_MS &&
+                value != OPUS_FRAMESIZE_VARIABLE)
             {
                goto bad_arg;
             }
diff --git a/tests/test_opus_api.c b/tests/test_opus_api.c
index 9bfa5cc..b04f746 100644
--- a/tests/test_opus_api.c
+++ b/tests/test_opus_api.c
@@ -1383,6 +1383,15 @@ opus_int32 test_enc_api(void)
    err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_60_MS));
    if(err!=OPUS_OK)test_failed();
    cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_80_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_100_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_120_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_EXPERT_FRAME_DURATION(i),OPUS_GET_EXPERT_FRAME_DURATION(&i),0,-1,
          OPUS_FRAMESIZE_60_MS,OPUS_FRAMESIZE_ARG,
      "    OPUS_SET_EXPERT_FRAME_DURATION ............... OK.\n",
-- 
2.8.0.rc3.226.g39d4020



More information about the opus mailing list