API for checking whether the encoder is in DTX
authorGustaf Ullberg <gustaf.ullberg@gmail.com>
Thu, 20 Dec 2018 14:35:41 +0000 (15:35 +0100)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 10 Apr 2019 21:26:57 +0000 (17:26 -0400)
Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
include/opus_defines.h
src/opus_encoder.c

index fbf5d0e..d141418 100644 (file)
@@ -168,6 +168,7 @@ extern "C" {
 /* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
 #define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
 #define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+#define OPUS_GET_IN_DTX_REQUEST              4049
 
 /** Defines for the presence of extended APIs. */
 #define OPUS_HAVE_OPUS_PROJECTION_H
@@ -715,6 +716,16 @@ extern "C" {
   * </dl>
   * @hideinitializer */
 #define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+/** Gets the DTX state of the encoder.
+  * Returns whether the last encoded frame was either a comfort noise update
+  * during DTX or not encoded because of DTX.
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>The encoder is not in DTX.</dd>
+  * <dt>1</dt><dd>The encoder is in DTX.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
 
 /**@}*/
 
index 2768aa3..e98ac5b 100644 (file)
@@ -2727,6 +2727,33 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
             ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
         }
         break;
+        case OPUS_GET_IN_DTX_REQUEST:
+        {
+            opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value)
+            {
+                goto bad_arg;
+            }
+            if (st->silk_mode.useDTX && (st->prev_mode == MODE_SILK_ONLY || st->prev_mode == MODE_HYBRID)) {
+                /* DTX determined by Silk. */
+                int n;
+                void *silk_enc = (char*)st+st->silk_enc_offset;
+                *value = 1;
+                for (n=0;n<st->silk_mode.nChannelsInternal;n++) {
+                    *value = *value && ((silk_encoder*)silk_enc)->state_Fxx[n].sCmn.noSpeechCounter >= NB_SPEECH_FRAMES_BEFORE_DTX;
+                }
+            }
+#ifndef DISABLE_FLOAT_API
+            else if (st->use_dtx) {
+                /* DTX determined by Opus. */
+                *value = st->nb_no_activity_frames >= NB_SPEECH_FRAMES_BEFORE_DTX;
+            }
+#endif
+            else {
+                *value = 0;
+            }
+        }
+        break;
 
         case CELT_GET_MODE_REQUEST:
         {