From 25f7f35555168f3426b9aad1efefab466f365af6 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jmvalin@jmvalin.ca> Date: Wed, 14 Sep 2011 09:50:06 -0700 Subject: [PATCH] Implements OPUS_GET_PITCH that queries the decoded pitch --- celt/celt.c | 12 ++++++++++-- celt/opus_defines.h | 13 ++++++++++++- src/opus_decoder.c | 30 ++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/celt/celt.c b/celt/celt.c index 50cc434fc..ad4873497 100644 --- a/celt/celt.c +++ b/celt/celt.c @@ -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: { diff --git a/celt/opus_defines.h b/celt/opus_defines.h index c72edcc30..361a58433 100644 --- a/celt/opus_defines.h +++ b/celt/opus_defines.h @@ -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 diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 55be0a76b..254548bed 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -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; -- GitLab