Implements OPUS_GET_PITCH that queries the decoded pitch
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 14 Sep 2011 16:50:06 +0000 (09:50 -0700)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 14 Sep 2011 16:50:06 +0000 (09:50 -0700)
celt/celt.c
celt/opus_defines.h
src/opus_decoder.c

index 50cc434..ad48734 100644 (file)
@@ -2695,7 +2695,7 @@ int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
       break;
       case CELT_GET_AND_CLEAR_ERROR_REQUEST:
       {
-         int *value = va_arg(ap, int*);
+         int *value = va_arg(ap, opus_int32*);
          if (value==NULL)
             goto bad_arg;
          *value=st->error;
@@ -2704,7 +2704,7 @@ int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
       break;
       case OPUS_GET_LOOKAHEAD_REQUEST:
       {
-         int *value = va_arg(ap, int*);
+         int *value = va_arg(ap, opus_int32*);
          if (value==NULL)
             goto bad_arg;
          *value = st->overlap/st->downsample;
@@ -2717,6 +2717,14 @@ int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
                ((char*)&st->DECODER_RESET_START - (char*)st));
       }
       break;
+      case OPUS_GET_PITCH_REQUEST:
+      {
+         int *value = va_arg(ap, opus_int32*);
+         if (value==NULL)
+            goto bad_arg;
+         *value = st->postfilter_period;
+      }
+      break;
 #ifdef OPUS_BUILD
       case CELT_GET_MODE_REQUEST:
       {
index c72edcc..361a584 100644 (file)
@@ -103,6 +103,7 @@ extern "C" {
 #define OPUS_SET_DTX_REQUEST                 4016
 #define OPUS_GET_DTX_REQUEST                 4017
 #define OPUS_GET_FINAL_RANGE_REQUEST         4031
+#define OPUS_GET_PITCH_REQUEST               4033
 
 /* Macros to trigger compilation errors when the wrong types are provided to a CTL */
 #define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
@@ -343,11 +344,21 @@ extern "C" {
   * The encoder and decoder state should be identical after coding a payload
   * (assuming no data corruption or software bugs)
   *
-  * @param[out] x <tt>opus_int32*</tt>: Entropy coder state
+  * @param[out] x <tt>opus_uint32*</tt>: Entropy coder state
   *
   * @hideinitializer */
 #define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
 
+/** Gets the pitch of the last decoded frame, if available.
+  * This can be used for any post-processing algorithm requiring the use of pitch,
+  * e.g. time stretching/shortening. If the last frame was not voiced, or if the
+  * pitch was not coded in the frame, then zero is returned.
+  *
+  * @param[out] x <tt>opus_int32*</tt>: pitch period at 48 kHz (or 0 if not available)
+  *
+  * @hideinitializer */
+#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
+
 /**@}*/
 
 /** @defgroup libinfo Opus library information functions
index 55be0a7..254548b 100644 (file)
@@ -39,6 +39,8 @@
 #include "float_cast.h"
 #include "opus_private.h"
 #include "os_support.h"
+#include "silk_structs.h"
+#include "silk_define.h"
 
 struct OpusDecoder {
    int          celt_dec_offset;
@@ -737,6 +739,12 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
 {
    int ret = OPUS_OK;
    va_list ap;
+   void *silk_dec;
+   CELTDecoder *celt_dec;
+
+   silk_dec = (char*)st+st->silk_dec_offset;
+   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
+
 
    va_start(ap, request);
 
@@ -756,12 +764,6 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
    break;
    case OPUS_RESET_STATE:
    {
-      void *silk_dec;
-      CELTDecoder *celt_dec;
-
-      silk_dec = (char*)st+st->silk_dec_offset;
-      celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
-
       OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
             sizeof(OpusDecoder)-
             ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
@@ -772,6 +774,22 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
       st->frame_size = st->Fs/400;
    }
    break;
+   case OPUS_GET_PITCH_REQUEST:
+   {
+      int *value = va_arg(ap, opus_int32*);
+      if (value==NULL)
+      {
+         ret = OPUS_BAD_ARG;
+         break;
+      }
+      if (st->prev_mode == MODE_CELT_ONLY)
+         celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
+      else
+         *value = ((silk_decoder_state*)silk_dec)->indices.signalType == TYPE_VOICED
+         ? ((silk_decoder_state*)silk_dec)->lagPrev*48/((silk_decoder_state*)silk_dec)->fs_kHz
+         : 0;
+   }
+   break;
    default:
       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
       ret = OPUS_UNIMPLEMENTED;