diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 336c7e0b..f56be9de 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -78,7 +78,10 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, SKP_SILK_SDK_DecControlStruct DecControl; SKP_int32 silk_frame_size; short pcm_celt[960*2]; + short pcm_transition[960*2]; int audiosize; + int mode; + int transition=0; /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */ if (len<=2) @@ -89,7 +92,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, /* Decoding mode/bandwidth/framesize from first byte */ if (data[0]&0x80) { - st->mode = MODE_CELT_ONLY; + mode = MODE_CELT_ONLY; st->bandwidth = BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3); if (st->bandwidth == BANDWIDTH_MEDIUMBAND) st->bandwidth = BANDWIDTH_NARROWBAND; @@ -97,12 +100,12 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, audiosize = (st->Fs<mode = MODE_HYBRID; + mode = MODE_HYBRID; st->bandwidth = (data[0]&0x10) ? BANDWIDTH_FULLBAND : BANDWIDTH_SUPERWIDEBAND; audiosize = (data[0]&0x08) ? st->Fs/50 : st->Fs/100; } else { - st->mode = MODE_SILK_ONLY; + mode = MODE_SILK_ONLY; st->bandwidth = BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3); audiosize = ((data[0]>>3)&0x3); if (audiosize == 3) @@ -118,8 +121,16 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, ec_dec_init(&dec,(unsigned char*)data,len); } else { audiosize = frame_size; + mode = st->prev_mode; } + if (mode != st->prev_mode + && !(mode == MODE_SILK_ONLY && st->prev_mode == MODE_HYBRID) + && !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY)) + { + transition = 1; + opus_decode(st, NULL, 0, pcm_transition, audiosize, 0); + } if (audiosize > frame_size) { fprintf(stderr, "PCM buffer too small"); @@ -129,13 +140,17 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, } /* SILK processing */ - if (st->mode != MODE_CELT_ONLY) + if (mode != MODE_CELT_ONLY) { int lost_flag, decoded_samples; SKP_int16 *pcm_ptr = pcm; + + if (st->prev_mode==MODE_CELT_ONLY) + SKP_Silk_SDK_InitDecoder( st->silk_dec ); + DecControl.API_sampleRate = st->Fs; DecControl.payloadSize_ms = 1000 * audiosize / st->Fs; - if( st->mode == MODE_SILK_ONLY ) { + if( mode == MODE_SILK_ONLY ) { if( st->bandwidth == BANDWIDTH_NARROWBAND ) { DecControl.internalSampleRate = 8000; } else if( st->bandwidth == BANDWIDTH_MEDIUMBAND ) { @@ -169,7 +184,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, pcm[i] = 0; } - if (st->mode == MODE_HYBRID) + if (mode == MODE_HYBRID) { /* This should be adjusted based on the SILK bandwidth */ celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(17)); @@ -177,7 +192,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0)); } - if (st->mode != MODE_SILK_ONLY) + if (mode != MODE_SILK_ONLY) { int endband; @@ -199,16 +214,31 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, celt_decoder_ctl(st->celt_dec, CELT_SET_END_BAND(endband)); celt_decoder_ctl(st->celt_dec, CELT_SET_CHANNELS(st->stream_channels)); + if (st->prev_mode == MODE_SILK_ONLY) + celt_decoder_ctl(st->celt_dec, CELT_RESET_STATE); /* Decode CELT */ celt_ret = celt_decode_with_ec(st->celt_dec, decode_fec?NULL:data, len, pcm_celt, frame_size, &dec); for (i=0;ichannels;i++) pcm[i] = ADD_SAT16(pcm[i], pcm_celt[i]); } + if (transition) + { + int tlength; + if (mode == MODE_CELT_ONLY) + tlength = IMIN(audiosize, 10+st->Fs/200); + else + tlength = IMIN(audiosize, 10+st->Fs/400); + for (i=0;irangeFinal = dec.rng; #endif + st->prev_mode = mode; return celt_ret<0 ? celt_ret : audiosize; } @@ -221,16 +251,10 @@ void opus_decoder_ctl(OpusDecoder *st, int request, ...) switch (request) { - case OPUS_SET_MODE_REQUEST: - { - int value = va_arg(ap, int); - st->mode = value; - } - break; case OPUS_GET_MODE_REQUEST: { int *value = va_arg(ap, int*); - *value = st->mode; + *value = st->prev_mode; } break; case OPUS_SET_BANDWIDTH_REQUEST: diff --git a/src/opus_decoder.h b/src/opus_decoder.h index 74777522..1b0569c2 100644 --- a/src/opus_decoder.h +++ b/src/opus_decoder.h @@ -37,10 +37,10 @@ struct OpusDecoder { int channels; int stream_channels; - int mode; int bandwidth; /* Sampling rate (at the API level) */ int Fs; + int prev_mode; #ifdef OPUS_TEST_RANGE_CODER_STATE int rangeFinal; diff --git a/src/opus_encoder.c b/src/opus_encoder.c index ca908916..c4d2aa1f 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -98,10 +98,17 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1; data += 1; + if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) + { + SKP_SILK_SDK_EncControlStruct dummy; + SKP_Silk_SDK_InitEncoder( st->silk_enc, &dummy); + } + ec_enc_init(&enc, data, max_data_bytes-1); /* SILK processing */ - if (st->mode != MODE_CELT_ONLY) { + if (st->mode != MODE_CELT_ONLY) + { st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size; if( st->mode == MODE_HYBRID ) { if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) { @@ -185,6 +192,13 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0)); celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000)); + if (st->prev_mode == MODE_SILK_ONLY) + { + celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE); + celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0)); + } else { + celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2)); + } if (st->mode == MODE_HYBRID) { int len; @@ -268,7 +282,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, #if OPUS_TEST_RANGE_CODER_STATE st->rangeFinal = enc.rng; #endif - + st->prev_mode = st->mode; return ret+1; } diff --git a/src/opus_encoder.h b/src/opus_encoder.h index ffaf2a3d..aec775b2 100644 --- a/src/opus_encoder.h +++ b/src/opus_encoder.h @@ -43,6 +43,7 @@ struct OpusEncoder { int stream_channels; int mode; + int prev_mode; int bandwidth; /* Sampling rate (at the API level) */ int Fs;