Automatic bandwidth selection
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Wed, 9 Mar 2011 03:12:43 +0000 (22:12 -0500)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Wed, 9 Mar 2011 03:12:43 +0000 (22:12 -0500)
src/opus.h
src/opus_decoder.c
src/opus_encoder.c
src/opus_encoder.h
src/test_opus.c

index 36cf26a..d4d6258 100644 (file)
@@ -71,11 +71,12 @@ extern "C" {
 #define MODE_HYBRID    1001
 #define MODE_CELT_ONLY 1002
 
-#define BANDWIDTH_NARROWBAND    1100
-#define BANDWIDTH_MEDIUMBAND    1101
-#define BANDWIDTH_WIDEBAND      1102
-#define BANDWIDTH_SUPERWIDEBAND 1103
-#define BANDWIDTH_FULLBAND      1104
+#define BANDWIDTH_AUTO          1100
+#define BANDWIDTH_NARROWBAND    1101
+#define BANDWIDTH_MEDIUMBAND    1102
+#define BANDWIDTH_WIDEBAND      1103
+#define BANDWIDTH_SUPERWIDEBAND 1104
+#define BANDWIDTH_FULLBAND      1105
 
 
 
@@ -135,7 +136,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
 
 void opus_encoder_destroy(OpusEncoder *st);
 
-void opus_encoder_ctl(OpusEncoder *st, int request, ...);
+int opus_encoder_ctl(OpusEncoder *st, int request, ...);
 
 OpusDecoder *opus_decoder_create(int Fs, int channels);
 
@@ -143,7 +144,7 @@ OpusDecoder *opus_decoder_create(int Fs, int channels);
 int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
                short *pcm, int frame_size, int decode_fec);
 
-void opus_decoder_ctl(OpusDecoder *st, int request, ...);
+int opus_decoder_ctl(OpusDecoder *st, int request, ...);
 
 void opus_decoder_destroy(OpusDecoder *st);
 
index d1b784a..b06cbaf 100644 (file)
@@ -325,7 +325,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
 
 }
 
-void opus_decoder_ctl(OpusDecoder *st, int request, ...)
+int opus_decoder_ctl(OpusDecoder *st, int request, ...)
 {
     va_list ap;
 
index ecd291f..384922d 100644 (file)
@@ -82,6 +82,7 @@ OpusEncoder *opus_encoder_create(int Fs, int channels)
        st->use_vbr = 0;
        st->bitrate_bps = 32000;
        st->user_mode = OPUS_MODE_AUTO;
+       st->user_bandwidth = BANDWIDTH_AUTO;
        st->voice_ratio = 90;
 
        st->encoder_buffer = st->Fs/100;
@@ -178,6 +179,19 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
         else
             st->bandwidth = BANDWIDTH_NARROWBAND;
     }
+
+    if (st->Fs <= 24000 && st->bandwidth > BANDWIDTH_SUPERWIDEBAND)
+       st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
+    if (st->Fs <= 16000 && st->bandwidth > BANDWIDTH_WIDEBAND)
+       st->bandwidth = BANDWIDTH_WIDEBAND;
+    if (st->Fs <= 12000 && st->bandwidth > BANDWIDTH_MEDIUMBAND)
+       st->bandwidth = BANDWIDTH_MEDIUMBAND;
+    if (st->Fs <= 8000 && st->bandwidth > BANDWIDTH_NARROWBAND)
+       st->bandwidth = BANDWIDTH_NARROWBAND;
+
+    if (st->user_bandwidth != BANDWIDTH_AUTO)
+       st->bandwidth = st->user_bandwidth;
+
     /* Preventing non-sensical configurations */
     if (frame_size < st->Fs/100 && st->mode != MODE_CELT_ONLY)
         st->mode = MODE_CELT_ONLY;
@@ -471,7 +485,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
     return ret+1+redundancy_bytes;
 }
 
-void opus_encoder_ctl(OpusEncoder *st, int request, ...)
+int opus_encoder_ctl(OpusEncoder *st, int request, ...)
 {
     va_list ap;
 
@@ -488,7 +502,7 @@ void opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_MODE_REQUEST:
         {
             int *value = va_arg(ap, int*);
-            *value = st->user_mode;
+            *value = st->mode;
         }
         break;
         case OPUS_SET_BITRATE_REQUEST:
@@ -506,8 +520,10 @@ void opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_SET_BANDWIDTH_REQUEST:
         {
             int value = va_arg(ap, int);
-            st->bandwidth = value;
-            if (st->bandwidth == BANDWIDTH_NARROWBAND) {
+            if (value < BANDWIDTH_AUTO || value > BANDWIDTH_FULLBAND)
+               return OPUS_BAD_ARG;
+            st->user_bandwidth = value;
+            if (st->user_bandwidth == BANDWIDTH_NARROWBAND) {
                 st->silk_mode.maxInternalSampleRate = 8000;
             } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
                 st->silk_mode.maxInternalSampleRate = 12000;
index 45dbac8..ce721eb 100644 (file)
@@ -46,6 +46,7 @@ struct OpusEncoder {
     int          user_mode;
     int          prev_mode;
        int          bandwidth;
+       int          user_bandwidth;
        int          voice_ratio;
     /* Sampling rate (at the API level) */
     int          Fs;
index 565f40d..ccbe6fa 100644 (file)
@@ -112,7 +112,7 @@ int main(int argc, char *argv[])
 
    /* defaults: */
    use_vbr = 1;
-   bandwidth=-1;
+   bandwidth=BANDWIDTH_AUTO;
    internal_sampling_rate_Hz = sampling_rate;
    max_payload_bytes = MAX_PACKET;
    complexity = 10;
@@ -120,24 +120,6 @@ int main(int argc, char *argv[])
    use_dtx = 0;
    packet_loss_perc = 0;
 
-   switch(sampling_rate)
-   {
-   case 8000:
-          bandwidth = BANDWIDTH_NARROWBAND;
-          break;
-   case 12000:
-          bandwidth = BANDWIDTH_MEDIUMBAND;
-          break;
-   case 16000:
-          bandwidth = BANDWIDTH_WIDEBAND;
-          break;
-   case 24000:
-          bandwidth = BANDWIDTH_SUPERWIDEBAND;
-          break;
-   case 48000:
-          bandwidth = BANDWIDTH_FULLBAND;
-          break;
-   }
    args = 5;
    while( args < argc - 2 ) {
        /* process command line options */
@@ -236,11 +218,6 @@ int main(int argc, char *argv[])
    enc = opus_encoder_create(sampling_rate, channels);
    dec = opus_decoder_create(sampling_rate, channels);
 
-   if (bandwidth == -1)
-   {
-       fprintf (stderr, "Please specify a bandwidth when the sampling rate does not match one exactly\n");
-       return 1;
-   }
    opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
    opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
@@ -272,6 +249,9 @@ int main(int argc, char *argv[])
    case BANDWIDTH_FULLBAND:
           bandwidth_string = "fullband";
           break;
+   case BANDWIDTH_AUTO:
+          bandwidth_string = "auto";
+          break;
    default:
           bandwidth_string = "unknown";
    }