ref: 8d43b185b2bb44841cb9b13e6dc1f4f30da0db87
parent: 000af0340a6483edc76028e7fcd889b1270f5f80
author: Jean-Marc Valin <jmvalin@amazon.com>
date: Wed Oct 18 13:40:54 EDT 2023
Support OPUS_SET_COMPLEXITY() on decoder side Controls whether deep PLC is enabled
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -152,7 +152,7 @@
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet
#endif
);
--- a/celt/celt_decoder.c
+++ b/celt/celt_decoder.c
@@ -90,6 +90,7 @@
int start, end;
int signalling;
int disable_inv;
+ int complexity;
int arch;
/* Everything beyond this point gets cleared on a reset */
@@ -110,7 +111,7 @@
celt_sig preemph_memD[2];
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
opus_int16 plc_pcm[PLC_UPDATE_SAMPLES];
int plc_fill;
float plc_preemphasis_mem;
@@ -551,7 +552,7 @@
} while (++c<CC);
}
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
#define SINC_ORDER 48
/* h=cos(pi/2*abs(sin([-24:24]/48*pi*23./24)).^2);
@@ -603,7 +604,7 @@
#endif
static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet
#endif
)
@@ -641,7 +642,7 @@
loss_duration = st->loss_duration;
start = st->start;
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
noise_based = start != 0 || (lpcnet->fec_fill_pos == 0 && (st->skip_plc || loss_duration >= 80));
#else
noise_based = loss_duration >= 40 || start != 0 || st->skip_plc;
@@ -718,7 +719,7 @@
if (loss_duration == 0)
{-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
update_plc_state(lpcnet, decode_mem, C);
#endif
st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
@@ -911,8 +912,8 @@
} while (++c<C);
-#ifdef ENABLE_DRED
- {+#ifdef ENABLE_DEEP_PLC
+ if (st->complexity >= 5 || lpcnet->fec_fill_pos > 0) {float overlap_mem;
int samples_needed16k;
int ignored = 0;
@@ -982,7 +983,7 @@
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
,LPCNetPLCState *lpcnet
#endif
)
@@ -1103,7 +1104,7 @@
if (data == NULL || len<=1)
{celt_decode_lost(st, N, LM
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
, lpcnet
#endif
);
@@ -1111,7 +1112,7 @@
RESTORE_STACK;
return frame_size/st->downsample;
}
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
else {/* FIXME: This is a bit of a hack just to make sure opus_decode_native() knows we're no longer in PLC. */
if (lpcnet) lpcnet->blend = 0;
@@ -1365,7 +1366,7 @@
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
{return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
, NULL
#endif
);
@@ -1443,6 +1444,26 @@
va_start(ap, request);
switch (request)
{+ case OPUS_SET_COMPLEXITY_REQUEST:
+ {+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>10)
+ {+ goto bad_arg;
+ }
+ st->complexity = value;
+ }
+ break;
+ case OPUS_GET_COMPLEXITY_REQUEST:
+ {+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {+ goto bad_arg;
+ }
+ *value = st->complexity;
+ }
+ break;
case CELT_SET_START_BAND_REQUEST:
{opus_int32 value = va_arg(ap, opus_int32);
--- a/silk/PLC.c
+++ b/silk/PLC.c
@@ -398,12 +398,19 @@
}
#ifdef ENABLE_DEEP_PLC
if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) {- for( k = 0; k < psDec->nb_subfr; k += 2 ) {- lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
- }
- /* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
- for( i = 0; i < psDec->frame_length; i++ ) {- sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
+ int run_deep_plc = psDec->sPLC.enable_deep_plc || lpcnet->fec_fill_pos != 0;
+ if( run_deep_plc ) {+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {+ lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
+ }
+ /* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
+ for( i = 0; i < psDec->frame_length; i++ ) {+ sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
+ }
+ } else {+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {+ lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+ }
}
}
#endif
--- a/silk/control.h
+++ b/silk/control.h
@@ -144,6 +144,9 @@
/* O: Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz */
opus_int prevPitchLag;
+
+ /* I: Enable Deep PLC */
+ opus_int enable_deep_plc;
} silk_DecControlStruct;
#ifdef __cplusplus
--- a/silk/dec_API.c
+++ b/silk/dec_API.c
@@ -281,6 +281,7 @@
has_side = !psDec->prev_decode_only_middle
|| (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 );
}
+ channel_state[ 0 ].sPLC.enable_deep_plc = decControl->enable_deep_plc;
/* Call decoder for one frame */
for( n = 0; n < decControl->nChannelsInternal; n++ ) { if( n == 0 || has_side ) {--- a/silk/structs.h
+++ b/silk/structs.h
@@ -253,6 +253,7 @@
opus_int fs_kHz;
opus_int nb_subfr;
opus_int subfr_length;
+ opus_int enable_deep_plc;
} silk_PLC_struct;
/* Struct for CNG */
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -63,6 +63,7 @@
opus_int32 Fs; /** Sampling rate (at the API level) */
silk_DecControlStruct DecControl;
int decode_gain;
+ int complexity;
int arch;
#ifdef ENABLE_DEEP_PLC
LPCNetPLCState lpcnet;
@@ -142,6 +143,7 @@
silk_dec = (char*)st+st->silk_dec_offset;
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
st->stream_channels = st->channels = channels;
+ st->complexity = 0;
st->Fs = Fs;
st->DecControl.API_sampleRate = st->Fs;
@@ -404,6 +406,7 @@
st->DecControl.internalSampleRate = 16000;
}
}
+ st->DecControl.enable_deep_plc = st->complexity >= 5;
lost_flag = data == NULL ? 1 : 2 * !!decode_fec;
decoded_samples = 0;
@@ -537,7 +540,7 @@
/* Decode CELT */
celt_ret = celt_decode_with_ec_dred(celt_dec, decode_fec ? NULL : data,
len, pcm, celt_frame_size, &dec, celt_accum
-#ifdef ENABLE_DRED
+#ifdef ENABLE_DEEP_PLC
, &st->lpcnet
#endif
);
@@ -909,6 +912,27 @@
goto bad_arg;
}
*value = st->bandwidth;
+ }
+ break;
+ case OPUS_SET_COMPLEXITY_REQUEST:
+ {+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>10)
+ {+ goto bad_arg;
+ }
+ st->complexity = value;
+ celt_decoder_ctl(celt_dec, OPUS_SET_COMPLEXITY(value));
+ }
+ break;
+ case OPUS_GET_COMPLEXITY_REQUEST:
+ {+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {+ goto bad_arg;
+ }
+ *value = st->complexity;
}
break;
case OPUS_GET_FINAL_RANGE_REQUEST:
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -126,6 +126,7 @@
}
#define check_encoder_option(decode_only, opt) do {if (decode_only) {fprintf(stderr, "option %s is only for encoding\n", opt); goto failure;}} while(0)+#define check_decoder_option(encode_only, opt) do {if (encode_only) {fprintf(stderr, "option %s is only for decoding\n", opt); goto failure;}} while(0) static const int silk8_test[][4] = { {MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},@@ -273,6 +274,7 @@
int use_vbr;
int max_payload_bytes;
int complexity;
+ int dec_complexity;
int use_inbandfec;
int use_dtx;
int forcechannels;
@@ -391,6 +393,7 @@
use_vbr = 1;
max_payload_bytes = MAX_PACKET;
complexity = 10;
+ dec_complexity = 0;
use_inbandfec = 0;
forcechannels = OPUS_AUTO;
use_dtx = 0;
@@ -456,6 +459,10 @@
check_encoder_option(decode_only, "-complexity");
complexity = atoi( argv[ args + 1 ] );
args += 2;
+ } else if( strcmp( argv[ args ], "-dec_complexity" ) == 0 ) {+ check_decoder_option(encode_only, "-dec_complexity");
+ dec_complexity = atoi( argv[ args + 1 ] );
+ args += 2;
} else if( strcmp( argv[ args ], "-inbandfec" ) == 0 ) {use_inbandfec = 1;
args++;
@@ -616,6 +623,7 @@
fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
goto failure;
}
+ opus_decoder_ctl(dec, OPUS_SET_COMPLEXITY(dec_complexity));
}
switch(bandwidth)
{--
⑨