Fixes some return without va_end in the api, adds tests.
authorGregory Maxwell <greg@xiph.org>
Sun, 30 Jun 2013 03:06:07 +0000 (20:06 -0700)
committerGregory Maxwell <greg@xiph.org>
Sun, 30 Jun 2013 03:06:07 +0000 (20:06 -0700)
Also makes the CTL bad argument handling more consistent to avoid mistakes
 like that in the future.  Also updates the variable duration docs.

include/opus_defines.h
src/opus_decoder.c
src/opus_demo.c
src/opus_encoder.c
src/opus_multistream_decoder.c
src/opus_multistream_encoder.c
tests/test_opus_api.c

index d101482..3474e84 100644 (file)
@@ -538,8 +538,9 @@ extern "C" {
 #define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
 
 /** Configures the encoder's use of variable duration frames.
-  * When enabled, the encoder is free to use a shorter frame size than the one
-  * requested in the opus_encode*() call. It is then the user's responsibility
+  * When variable duration is enabled, the encoder is free to use a shorter frame
+  * size than the one requested in the opus_encode*() call.
+  * It is then the user's responsibility
   * to verify how much audio was encoded by checking the ToC byte of the encoded
   * packet. The part of the audio that was not encoded needs to be resent to the
   * encoder for the next call. Do not use this option unless you <b>really</b>
@@ -547,8 +548,14 @@ extern "C" {
   * @see OPUS_GET_EXPERT_VARIABLE_DURATION
   * @param[in] x <tt>opus_int32</tt>: Allowed values:
   * <dl>
-  * <dt>0</dt><dd>Disable variable duration (default).</dd>
-  * <dt>1</dt><dd>Enable variable duration.</dd>
+  * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+  * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+  * <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_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
@@ -556,8 +563,14 @@ extern "C" {
   * @see OPUS_SET_EXPERT_VARIABLE_DURATION
   * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
   * <dl>
-  * <dt>0</dt><dd>variable duration disabled (default).</dd>
-  * <dt>1</dt><dd>variable duration enabled.</dd>
+  * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
+  * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 2.5 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
+  * <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_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
index 6bc7091..13a910f 100644 (file)
@@ -937,12 +937,14 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
    case OPUS_GET_BANDWIDTH_REQUEST:
    {
       opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value) goto bad_arg;
       *value = st->bandwidth;
    }
    break;
    case OPUS_GET_FINAL_RANGE_REQUEST:
    {
       opus_uint32 *value = va_arg(ap, opus_uint32*);
+      if (!value) goto bad_arg;
       *value = st->rangeFinal;
    }
    break;
@@ -961,22 +963,14 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
    case OPUS_GET_SAMPLE_RATE_REQUEST:
    {
       opus_int32 *value = va_arg(ap, opus_int32*);
-      if (value==NULL)
-      {
-         ret = OPUS_BAD_ARG;
-         break;
-      }
+      if (!value) goto bad_arg;
       *value = st->Fs;
    }
    break;
    case OPUS_GET_PITCH_REQUEST:
    {
       opus_int32 *value = va_arg(ap, opus_int32*);
-      if (value==NULL)
-      {
-         ret = OPUS_BAD_ARG;
-         break;
-      }
+      if (!value) goto bad_arg;
       if (st->prev_mode == MODE_CELT_ONLY)
          celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
       else
@@ -986,28 +980,21 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
    case OPUS_GET_GAIN_REQUEST:
    {
       opus_int32 *value = va_arg(ap, opus_int32*);
-      if (value==NULL)
-      {
-         ret = OPUS_BAD_ARG;
-         break;
-      }
+      if (!value) goto bad_arg;
       *value = st->decode_gain;
    }
    break;
    case OPUS_SET_GAIN_REQUEST:
    {
        opus_int32 value = va_arg(ap, opus_int32);
-       if (value<-32768 || value>32767)
-       {
-          ret = OPUS_BAD_ARG;
-          break;
-       }
+       if (value<-32768 || value>32767) goto bad_arg;
        st->decode_gain = value;
    }
    break;
    case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
    {
       opus_uint32 *value = va_arg(ap, opus_uint32*);
+      if (!value) goto bad_arg;
       *value = st->last_packet_duration;
    }
    break;
@@ -1019,6 +1006,9 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
 
    va_end(ap);
    return ret;
+bad_arg:
+   va_end(ap);
+   return OPUS_BAD_ARG;
 }
 
 void opus_decoder_destroy(OpusDecoder *st)
index 3709c3a..9771ed8 100644 (file)
@@ -272,7 +272,7 @@ int main(int argc, char *argv[])
     int curr_mode=0;
     int curr_mode_count=0;
     int mode_switch_time = 48000;
-    int nb_encoded;
+    int nb_encoded=0;
     int remaining=0;
     int variable_duration=OPUS_FRAMESIZE_ARG;
     int delayed_decision=0;
index cce7f27..c361d0b 100644 (file)
@@ -1966,6 +1966,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_APPLICATION_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->application;
         }
         break;
@@ -1987,28 +1988,28 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_BITRATE_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276);
         }
         break;
         case OPUS_SET_FORCE_CHANNELS_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if((value<1 || value>st->channels) && value != OPUS_AUTO)
-                return OPUS_BAD_ARG;
+            if((value<1 || value>st->channels) && value != OPUS_AUTO) goto bad_arg;
             st->force_channels = value;
         }
         break;
         case OPUS_GET_FORCE_CHANNELS_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->force_channels;
         }
         break;
         case OPUS_SET_MAX_BANDWIDTH_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND)
-                return OPUS_BAD_ARG;
+            if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) goto bad_arg;
             st->max_bandwidth = value;
             if (st->max_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
                 st->silk_mode.maxInternalSampleRate = 8000;
@@ -2022,14 +2023,14 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_MAX_BANDWIDTH_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->max_bandwidth;
         }
         break;
         case OPUS_SET_BANDWIDTH_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO)
-                return OPUS_BAD_ARG;
+            if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO) goto bad_arg;
             st->user_bandwidth = value;
             if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
                 st->silk_mode.maxInternalSampleRate = 8000;
@@ -2043,28 +2044,28 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_BANDWIDTH_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->bandwidth;
         }
         break;
         case OPUS_SET_DTX_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value<0 || value>1)
-                return OPUS_BAD_ARG;
+            if(value<0 || value>1) goto bad_arg;
             st->silk_mode.useDTX = value;
         }
         break;
         case OPUS_GET_DTX_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->silk_mode.useDTX;
         }
         break;
         case OPUS_SET_COMPLEXITY_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value<0 || value>10)
-                return OPUS_BAD_ARG;
+            if(value<0 || value>10) goto bad_arg;
             st->silk_mode.complexity = value;
             celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(value));
         }
@@ -2072,28 +2073,28 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_COMPLEXITY_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->silk_mode.complexity;
         }
         break;
         case OPUS_SET_INBAND_FEC_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value<0 || value>1)
-                return OPUS_BAD_ARG;
+            if(value<0 || value>1) goto bad_arg;
             st->silk_mode.useInBandFEC = value;
         }
         break;
         case OPUS_GET_INBAND_FEC_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->silk_mode.useInBandFEC;
         }
         break;
         case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value < 0 || value > 100)
-                return OPUS_BAD_ARG;
+            if (value < 0 || value > 100) goto bad_arg;
             st->silk_mode.packetLossPercentage = value;
             celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value));
         }
@@ -2101,14 +2102,14 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->silk_mode.packetLossPercentage;
         }
         break;
         case OPUS_SET_VBR_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value<0 || value>1)
-                return OPUS_BAD_ARG;
+            if(value<0 || value>1) goto bad_arg;
             st->use_vbr = value;
             st->silk_mode.useCBR = 1-value;
         }
@@ -2116,54 +2117,56 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_VBR_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->use_vbr;
         }
         break;
         case OPUS_SET_VOICE_RATIO_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value>100 || value<-1)
-                goto bad_arg;
+            if (value<-1 || value>100) goto bad_arg;
             st->voice_ratio = value;
         }
         break;
         case OPUS_GET_VOICE_RATIO_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->voice_ratio;
         }
         break;
         case OPUS_SET_VBR_CONSTRAINT_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value<0 || value>1)
-                return OPUS_BAD_ARG;
+            if(value<0 || value>1) goto bad_arg;
             st->vbr_constraint = value;
         }
         break;
         case OPUS_GET_VBR_CONSTRAINT_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->vbr_constraint;
         }
         break;
         case OPUS_SET_SIGNAL_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC)
-                return OPUS_BAD_ARG;
+            if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC) goto bad_arg;
             st->signal_type = value;
         }
         break;
         case OPUS_GET_SIGNAL_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->signal_type;
         }
         break;
         case OPUS_GET_LOOKAHEAD_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->Fs/400;
             if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
                 *value += st->delay_compensation;
@@ -2172,37 +2175,40 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_SAMPLE_RATE_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
-            if (value==NULL)
-            {
-                ret = OPUS_BAD_ARG;
-                break;
-            }
+            if (!value) goto bad_arg;
             *value = st->Fs;
         }
         break;
         case OPUS_GET_FINAL_RANGE_REQUEST:
         {
             opus_uint32 *value = va_arg(ap, opus_uint32*);
+            if (!value) goto bad_arg;
             *value = st->rangeFinal;
         }
         break;
         case OPUS_SET_LSB_DEPTH_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value<8 || value>24)
-               goto bad_arg;
+            if (value<8 || value>24) goto bad_arg;
             st->lsb_depth=value;
         }
         break;
         case OPUS_GET_LSB_DEPTH_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->lsb_depth;
         }
         break;
         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) {
+              goto bad_arg;
+            }
             st->variable_duration = value;
             celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value));
         }
@@ -2210,6 +2216,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value) goto bad_arg;
             *value = st->variable_duration;
         }
         break;
@@ -2237,8 +2244,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         case OPUS_SET_FORCE_MODE_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO)
-               goto bad_arg;
+            if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO) goto bad_arg;
             st->user_forced_mode = value;
         }
         break;
@@ -2246,29 +2252,29 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
         {
             opus_int32 value = va_arg(ap, opus_int32);
             st->lfe = value;
-            celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value));
+            ret = celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value));
         }
         break;
         case OPUS_SET_ENERGY_SAVE_REQUEST:
         {
             opus_val16 *value = va_arg(ap, opus_val16*);
-            celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_SAVE(value));
+            if (!value) goto bad_arg;
+            ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_SAVE(value));
         }
         break;
         case OPUS_SET_ENERGY_MASK_REQUEST:
         {
             opus_val16 *value = va_arg(ap, opus_val16*);
             st->energy_masking = (value!=NULL);
-            celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
+            ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
         }
         break;
 
         case CELT_GET_MODE_REQUEST:
         {
            const CELTMode ** value = va_arg(ap, const CELTMode**);
-           if (value==0)
-              goto bad_arg;
-           celt_encoder_ctl(celt_enc, CELT_GET_MODE(value));
+           if (!value) goto bad_arg;
+           ret = celt_encoder_ctl(celt_enc, CELT_GET_MODE(value));
         }
         break;
         default:
index 495fb07..51fe5ed 100644 (file)
@@ -400,6 +400,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           int s;
           opus_uint32 *value = va_arg(ap, opus_uint32*);
           opus_uint32 tmp;
+          if (!value) goto bad_arg;
           *value = 0;
           for (s=0;s<st->layout.nb_streams;s++)
           {
@@ -442,6 +443,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           if (stream_id<0 || stream_id >= st->layout.nb_streams)
              ret = OPUS_BAD_ARG;
           value = va_arg(ap, OpusDecoder**);
+          if (!value) goto bad_arg;
           for (s=0;s<stream_id;s++)
           {
              if (s < st->layout.nb_coupled_streams)
@@ -479,6 +481,9 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
 
    va_end(ap);
    return ret;
+bad_arg:
+   va_end(ap);
+   return OPUS_BAD_ARG;
 }
 
 
index d9380ec..30ece34 100644 (file)
@@ -861,6 +861,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    {
       int s;
       opus_int32 *value = va_arg(ap, opus_int32*);
+      if (!value) goto bad_arg;
       *value = 0;
       for (s=0;s<st->layout.nb_streams;s++)
       {
@@ -903,6 +904,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       int s;
       opus_uint32 *value = va_arg(ap, opus_uint32*);
       opus_uint32 tmp;
+      if (!value) goto bad_arg;
       *value=0;
       for (s=0;s<st->layout.nb_streams;s++)
       {
@@ -958,6 +960,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       if (stream_id<0 || stream_id >= st->layout.nb_streams)
          ret = OPUS_BAD_ARG;
       value = va_arg(ap, OpusEncoder**);
+      if (!value) goto bad_arg;
       for (s=0;s<stream_id;s++)
       {
          if (s < st->layout.nb_coupled_streams)
@@ -977,6 +980,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
    {
        opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value) goto bad_arg;
        *value = st->variable_duration;
    }
    break;
@@ -996,5 +1000,3 @@ void opus_multistream_encoder_destroy(OpusMSEncoder *st)
 {
     opus_free(st);
 }
-
-
index 0d20892..98dab2e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 Xiph.Org Foundation
+/* Copyright (c) 2011-2013 Xiph.Org Foundation
    Written by Gregory Maxwell */
 /*
    Redistribution and use in source and binary forms, with or without
@@ -1120,8 +1120,8 @@ opus_int32 test_enc_api(void)
    cfgs++;
    err=opus_encoder_ctl(enc,OPUS_GET_LOOKAHEAD(&i));
    if(err!=OPUS_OK || i<0 || i>32766)test_failed();
-   opus_encoder_destroy(enc);
    cfgs++;
+   opus_encoder_destroy(enc);
 
    VG_UNDEF(&err,sizeof(err));
    enc = opus_encoder_create(48000, 2, OPUS_APPLICATION_AUDIO, &err);
@@ -1145,17 +1145,34 @@ opus_int32 test_enc_api(void)
    err=opus_encoder_ctl(enc,OPUS_GET_LOOKAHEAD(&i));
    if(err!=OPUS_OK || i<0 || i>32766)test_failed();
    cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_GET_LOOKAHEAD((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    fprintf(stdout,"    OPUS_GET_LOOKAHEAD ........................... OK.\n");
 
+   err=opus_encoder_ctl(enc,OPUS_GET_SAMPLE_RATE(&i));
+   if(err!=OPUS_OK || i!=48000)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_GET_SAMPLE_RATE((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
+   fprintf(stdout,"    OPUS_GET_SAMPLE_RATE ......................... OK.\n");
+
    if(opus_encoder_ctl(enc,OPUS_UNIMPLEMENTED)!=OPUS_UNIMPLEMENTED)test_failed();
    fprintf(stdout,"    OPUS_UNIMPLEMENTED ........................... OK.\n");
    cfgs++;
 
+   err=opus_encoder_ctl(enc,OPUS_GET_APPLICATION((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_APPLICATION(i),OPUS_GET_APPLICATION(&i),-1,OPUS_AUTO,
      OPUS_APPLICATION_AUDIO,OPUS_APPLICATION_RESTRICTED_LOWDELAY,
      "    OPUS_SET_APPLICATION ......................... OK.\n",
      "    OPUS_GET_APPLICATION ......................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_BITRATE((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    if(opus_encoder_ctl(enc,OPUS_SET_BITRATE(1073741832))!=OPUS_OK)test_failed();
    cfgs++;
    VG_UNDEF(&i,sizeof(i));
@@ -1167,6 +1184,9 @@ opus_int32 test_enc_api(void)
      "    OPUS_SET_BITRATE ............................. OK.\n",
      "    OPUS_GET_BITRATE ............................. OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_FORCE_CHANNELS((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_FORCE_CHANNELS(i),OPUS_GET_FORCE_CHANNELS(&i),-1,3,
      1,OPUS_AUTO,
      "    OPUS_SET_FORCE_CHANNELS ...................... OK.\n",
@@ -1202,6 +1222,9 @@ opus_int32 test_enc_api(void)
    cfgs++;
    if(opus_encoder_ctl(enc,OPUS_SET_BANDWIDTH(OPUS_AUTO))!=OPUS_OK)test_failed();
    cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_GET_BANDWIDTH((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    fprintf(stdout,"    OPUS_GET_BANDWIDTH ........................... OK.\n");
 
    i=-2;
@@ -1232,55 +1255,113 @@ opus_int32 test_enc_api(void)
       i!=OPUS_BANDWIDTH_MEDIUMBAND&&i!=OPUS_BANDWIDTH_WIDEBAND&&
       i!=OPUS_BANDWIDTH_FULLBAND))test_failed();
    cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_GET_MAX_BANDWIDTH((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    fprintf(stdout,"    OPUS_GET_MAX_BANDWIDTH ....................... OK.\n");
 
+   err=opus_encoder_ctl(enc,OPUS_GET_DTX((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_DTX(i),OPUS_GET_DTX(&i),-1,2,
      1,0,
      "    OPUS_SET_DTX ................................. OK.\n",
      "    OPUS_GET_DTX ................................. OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_COMPLEXITY((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_COMPLEXITY(i),OPUS_GET_COMPLEXITY(&i),-1,11,
      0,10,
      "    OPUS_SET_COMPLEXITY .......................... OK.\n",
      "    OPUS_GET_COMPLEXITY .......................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_INBAND_FEC((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_INBAND_FEC(i),OPUS_GET_INBAND_FEC(&i),-1,2,
      1,0,
      "    OPUS_SET_INBAND_FEC .......................... OK.\n",
      "    OPUS_GET_INBAND_FEC .......................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_PACKET_LOSS_PERC((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_PACKET_LOSS_PERC(i),OPUS_GET_PACKET_LOSS_PERC(&i),-1,101,
      100,0,
      "    OPUS_SET_PACKET_LOSS_PERC .................... OK.\n",
      "    OPUS_GET_PACKET_LOSS_PERC .................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_VBR((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_VBR(i),OPUS_GET_VBR(&i),-1,2,
      1,0,
      "    OPUS_SET_VBR ................................. OK.\n",
      "    OPUS_GET_VBR ................................. OK.\n")
 
-   /*CHECK_SETGET(OPUS_SET_VOICE_RATIO(i),OPUS_GET_VOICE_RATIO(&i),-2,101,
+/*   err=opus_encoder_ctl(enc,OPUS_GET_VOICE_RATIO((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
+   CHECK_SETGET(OPUS_SET_VOICE_RATIO(i),OPUS_GET_VOICE_RATIO(&i),-2,101,
      0,50,
      "    OPUS_SET_VOICE_RATIO ......................... OK.\n",
-     "    OPUS_GET_VOICE_RATIO ......................... OK.\n")
-   */
+     "    OPUS_GET_VOICE_RATIO ......................... OK.\n")*/
 
+   err=opus_encoder_ctl(enc,OPUS_GET_VBR_CONSTRAINT((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_VBR_CONSTRAINT(i),OPUS_GET_VBR_CONSTRAINT(&i),-1,2,
      1,0,
      "    OPUS_SET_VBR_CONSTRAINT ...................... OK.\n",
      "    OPUS_GET_VBR_CONSTRAINT ...................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_SIGNAL((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_SIGNAL(i),OPUS_GET_SIGNAL(&i),-12345,0x7FFFFFFF,
      OPUS_SIGNAL_MUSIC,OPUS_AUTO,
      "    OPUS_SET_SIGNAL .............................. OK.\n",
      "    OPUS_GET_SIGNAL .............................. OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_LSB_DEPTH((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    CHECK_SETGET(OPUS_SET_LSB_DEPTH(i),OPUS_GET_LSB_DEPTH(&i),7,25,16,24,
      "    OPUS_SET_LSB_DEPTH ........................... OK.\n",
      "    OPUS_GET_LSB_DEPTH ........................... OK.\n")
 
+   err=opus_encoder_ctl(enc,OPUS_GET_EXPERT_FRAME_DURATION((opus_int32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_2_5_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_5_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_10_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_40_MS));
+   if(err!=OPUS_OK)test_failed();
+   cfgs++;
+   err=opus_encoder_ctl(enc,OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_60_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_VARIABLE,OPUS_FRAMESIZE_ARG,
+     "    OPUS_SET_EXPERT_FRAME_DURATION ............... OK.\n",
+     "    OPUS_GET_EXPERT_FRAME_DURATION ............... OK.\n")
+
    /*OPUS_SET_FORCE_MODE is not tested here because it's not a public API, however the encoder tests use it*/
 
+   err=opus_encoder_ctl(enc,OPUS_GET_FINAL_RANGE((opus_uint32 *)NULL));
+   if(err!=OPUS_BAD_ARG)test_failed();
+   cfgs++;
    if(opus_encoder_ctl(enc,OPUS_GET_FINAL_RANGE(&enc_final_range))!=OPUS_OK)test_failed();
    cfgs++;
    fprintf(stdout,"    OPUS_GET_FINAL_RANGE ......................... OK.\n");