Skip to content

Commit 8d43b18

Browse files
committed
Support OPUS_SET_COMPLEXITY() on decoder side
Controls whether deep PLC is enabled
1 parent 000af03 commit 8d43b18

File tree

8 files changed

+84
-19
lines changed

8 files changed

+84
-19
lines changed

celt/celt.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
152152

153153
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
154154
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
155-
#ifdef ENABLE_DRED
155+
#ifdef ENABLE_DEEP_PLC
156156
,LPCNetPLCState *lpcnet
157157
#endif
158158
);

celt/celt_decoder.c

+32-11
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct OpusCustomDecoder {
9090
int start, end;
9191
int signalling;
9292
int disable_inv;
93+
int complexity;
9394
int arch;
9495

9596
/* Everything beyond this point gets cleared on a reset */
@@ -110,7 +111,7 @@ struct OpusCustomDecoder {
110111

111112
celt_sig preemph_memD[2];
112113

113-
#ifdef ENABLE_DRED
114+
#ifdef ENABLE_DEEP_PLC
114115
opus_int16 plc_pcm[PLC_UPDATE_SAMPLES];
115116
int plc_fill;
116117
float plc_preemphasis_mem;
@@ -551,7 +552,7 @@ static void prefilter_and_fold(CELTDecoder * OPUS_RESTRICT st, int N)
551552
} while (++c<CC);
552553
}
553554

554-
#ifdef ENABLE_DRED
555+
#ifdef ENABLE_DEEP_PLC
555556

556557
#define SINC_ORDER 48
557558
/* h=cos(pi/2*abs(sin([-24:24]/48*pi*23./24)).^2);
@@ -603,7 +604,7 @@ void update_plc_state(LPCNetPLCState *lpcnet, celt_sig *decode_mem[2], int CC)
603604
#endif
604605

605606
static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
606-
#ifdef ENABLE_DRED
607+
#ifdef ENABLE_DEEP_PLC
607608
,LPCNetPLCState *lpcnet
608609
#endif
609610
)
@@ -641,7 +642,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
641642

642643
loss_duration = st->loss_duration;
643644
start = st->start;
644-
#ifdef ENABLE_DRED
645+
#ifdef ENABLE_DEEP_PLC
645646
noise_based = start != 0 || (lpcnet->fec_fill_pos == 0 && (st->skip_plc || loss_duration >= 80));
646647
#else
647648
noise_based = loss_duration >= 40 || start != 0 || st->skip_plc;
@@ -718,7 +719,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
718719

719720
if (loss_duration == 0)
720721
{
721-
#ifdef ENABLE_DRED
722+
#ifdef ENABLE_DEEP_PLC
722723
update_plc_state(lpcnet, decode_mem, C);
723724
#endif
724725
st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
@@ -911,8 +912,8 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
911912

912913
} while (++c<C);
913914

914-
#ifdef ENABLE_DRED
915-
{
915+
#ifdef ENABLE_DEEP_PLC
916+
if (st->complexity >= 5 || lpcnet->fec_fill_pos > 0) {
916917
float overlap_mem;
917918
int samples_needed16k;
918919
int ignored = 0;
@@ -982,7 +983,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM
982983

983984
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
984985
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
985-
#ifdef ENABLE_DRED
986+
#ifdef ENABLE_DEEP_PLC
986987
,LPCNetPLCState *lpcnet
987988
#endif
988989
)
@@ -1103,15 +1104,15 @@ int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char
11031104
if (data == NULL || len<=1)
11041105
{
11051106
celt_decode_lost(st, N, LM
1106-
#ifdef ENABLE_DRED
1107+
#ifdef ENABLE_DEEP_PLC
11071108
, lpcnet
11081109
#endif
11091110
);
11101111
deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
11111112
RESTORE_STACK;
11121113
return frame_size/st->downsample;
11131114
}
1114-
#ifdef ENABLE_DRED
1115+
#ifdef ENABLE_DEEP_PLC
11151116
else {
11161117
/* FIXME: This is a bit of a hack just to make sure opus_decode_native() knows we're no longer in PLC. */
11171118
if (lpcnet) lpcnet->blend = 0;
@@ -1365,7 +1366,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
13651366
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
13661367
{
13671368
return celt_decode_with_ec_dred(st, data, len, pcm, frame_size, dec, accum
1368-
#ifdef ENABLE_DRED
1369+
#ifdef ENABLE_DEEP_PLC
13691370
, NULL
13701371
#endif
13711372
);
@@ -1443,6 +1444,26 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
14431444
va_start(ap, request);
14441445
switch (request)
14451446
{
1447+
case OPUS_SET_COMPLEXITY_REQUEST:
1448+
{
1449+
opus_int32 value = va_arg(ap, opus_int32);
1450+
if(value<0 || value>10)
1451+
{
1452+
goto bad_arg;
1453+
}
1454+
st->complexity = value;
1455+
}
1456+
break;
1457+
case OPUS_GET_COMPLEXITY_REQUEST:
1458+
{
1459+
opus_int32 *value = va_arg(ap, opus_int32*);
1460+
if (!value)
1461+
{
1462+
goto bad_arg;
1463+
}
1464+
*value = st->complexity;
1465+
}
1466+
break;
14461467
case CELT_SET_START_BAND_REQUEST:
14471468
{
14481469
opus_int32 value = va_arg(ap, opus_int32);

silk/PLC.c

+13-6
Original file line numberDiff line numberDiff line change
@@ -398,12 +398,19 @@ static OPUS_INLINE void silk_PLC_conceal(
398398
}
399399
#ifdef ENABLE_DEEP_PLC
400400
if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) {
401-
for( k = 0; k < psDec->nb_subfr; k += 2 ) {
402-
lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
403-
}
404-
/* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
405-
for( i = 0; i < psDec->frame_length; i++ ) {
406-
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
401+
int run_deep_plc = psDec->sPLC.enable_deep_plc || lpcnet->fec_fill_pos != 0;
402+
if( run_deep_plc ) {
403+
for( k = 0; k < psDec->nb_subfr; k += 2 ) {
404+
lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length );
405+
}
406+
/* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */
407+
for( i = 0; i < psDec->frame_length; i++ ) {
408+
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] );
409+
}
410+
} else {
411+
for( k = 0; k < psDec->nb_subfr; k += 2 ) {
412+
lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
413+
}
407414
}
408415
}
409416
#endif

silk/control.h

+3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ typedef struct {
144144

145145
/* O: Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz */
146146
opus_int prevPitchLag;
147+
148+
/* I: Enable Deep PLC */
149+
opus_int enable_deep_plc;
147150
} silk_DecControlStruct;
148151

149152
#ifdef __cplusplus

silk/dec_API.c

+1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ opus_int silk_Decode( /* O Returns error co
281281
has_side = !psDec->prev_decode_only_middle
282282
|| (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 );
283283
}
284+
channel_state[ 0 ].sPLC.enable_deep_plc = decControl->enable_deep_plc;
284285
/* Call decoder for one frame */
285286
for( n = 0; n < decControl->nChannelsInternal; n++ ) {
286287
if( n == 0 || has_side ) {

silk/structs.h

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ typedef struct {
253253
opus_int fs_kHz;
254254
opus_int nb_subfr;
255255
opus_int subfr_length;
256+
opus_int enable_deep_plc;
256257
} silk_PLC_struct;
257258

258259
/* Struct for CNG */

src/opus_decoder.c

+25-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct OpusDecoder {
6363
opus_int32 Fs; /** Sampling rate (at the API level) */
6464
silk_DecControlStruct DecControl;
6565
int decode_gain;
66+
int complexity;
6667
int arch;
6768
#ifdef ENABLE_DEEP_PLC
6869
LPCNetPLCState lpcnet;
@@ -142,6 +143,7 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
142143
silk_dec = (char*)st+st->silk_dec_offset;
143144
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
144145
st->stream_channels = st->channels = channels;
146+
st->complexity = 0;
145147

146148
st->Fs = Fs;
147149
st->DecControl.API_sampleRate = st->Fs;
@@ -404,6 +406,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
404406
st->DecControl.internalSampleRate = 16000;
405407
}
406408
}
409+
st->DecControl.enable_deep_plc = st->complexity >= 5;
407410

408411
lost_flag = data == NULL ? 1 : 2 * !!decode_fec;
409412
decoded_samples = 0;
@@ -537,7 +540,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
537540
/* Decode CELT */
538541
celt_ret = celt_decode_with_ec_dred(celt_dec, decode_fec ? NULL : data,
539542
len, pcm, celt_frame_size, &dec, celt_accum
540-
#ifdef ENABLE_DRED
543+
#ifdef ENABLE_DEEP_PLC
541544
, &st->lpcnet
542545
#endif
543546
);
@@ -911,6 +914,27 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
911914
*value = st->bandwidth;
912915
}
913916
break;
917+
case OPUS_SET_COMPLEXITY_REQUEST:
918+
{
919+
opus_int32 value = va_arg(ap, opus_int32);
920+
if(value<0 || value>10)
921+
{
922+
goto bad_arg;
923+
}
924+
st->complexity = value;
925+
celt_decoder_ctl(celt_dec, OPUS_SET_COMPLEXITY(value));
926+
}
927+
break;
928+
case OPUS_GET_COMPLEXITY_REQUEST:
929+
{
930+
opus_int32 *value = va_arg(ap, opus_int32*);
931+
if (!value)
932+
{
933+
goto bad_arg;
934+
}
935+
*value = st->complexity;
936+
}
937+
break;
914938
case OPUS_GET_FINAL_RANGE_REQUEST:
915939
{
916940
opus_uint32 *value = va_arg(ap, opus_uint32*);

src/opus_demo.c

+8
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static opus_uint32 char_to_int(unsigned char ch[4])
126126
}
127127

128128
#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)
129+
#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)
129130

130131
static const int silk8_test[][4] = {
131132
{MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},
@@ -273,6 +274,7 @@ int main(int argc, char *argv[])
273274
int use_vbr;
274275
int max_payload_bytes;
275276
int complexity;
277+
int dec_complexity;
276278
int use_inbandfec;
277279
int use_dtx;
278280
int forcechannels;
@@ -391,6 +393,7 @@ int main(int argc, char *argv[])
391393
use_vbr = 1;
392394
max_payload_bytes = MAX_PACKET;
393395
complexity = 10;
396+
dec_complexity = 0;
394397
use_inbandfec = 0;
395398
forcechannels = OPUS_AUTO;
396399
use_dtx = 0;
@@ -456,6 +459,10 @@ int main(int argc, char *argv[])
456459
check_encoder_option(decode_only, "-complexity");
457460
complexity = atoi( argv[ args + 1 ] );
458461
args += 2;
462+
} else if( strcmp( argv[ args ], "-dec_complexity" ) == 0 ) {
463+
check_decoder_option(encode_only, "-dec_complexity");
464+
dec_complexity = atoi( argv[ args + 1 ] );
465+
args += 2;
459466
} else if( strcmp( argv[ args ], "-inbandfec" ) == 0 ) {
460467
use_inbandfec = 1;
461468
args++;
@@ -616,6 +623,7 @@ int main(int argc, char *argv[])
616623
fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
617624
goto failure;
618625
}
626+
opus_decoder_ctl(dec, OPUS_SET_COMPLEXITY(dec_complexity));
619627
}
620628
switch(bandwidth)
621629
{

0 commit comments

Comments
 (0)