ref: e57dfb824c223c607d576cf7374a2ee339064634
parent: ef4f459ec3e0ce2e0587009ef71dfd9dd8cf3f93
author: Jean-Marc Valin <jmvalin@amazon.com>
date: Wed May 31 00:01:52 EDT 2023
Move LPCNet PLC state to top-level decoder So it can be used outside of the SILK PLC
--- a/silk/API.h
+++ b/silk/API.h
@@ -33,6 +33,7 @@
#include "errors.h"
#include "entenc.h"
#include "entdec.h"
+#include "lpcnet/src/lpcnet_private.h"
#ifdef __cplusplus
extern "C"
@@ -113,6 +114,9 @@
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut, /* O Number of samples decoded */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
);
--- a/silk/PLC.c
+++ b/silk/PLC.c
@@ -51,6 +51,9 @@
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
);
@@ -64,9 +67,6 @@
psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
psDec->sPLC.subfr_length = 20;
psDec->sPLC.nb_subfr = 2;
-#ifdef NEURAL_PLC
- lpcnet_plc_init( &psDec->sPLC.lpcnet, LPCNET_PLC_CODEC );
-#endif
}
void silk_PLC(
@@ -74,6 +74,9 @@
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost, /* I Loss flag */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -87,7 +90,11 @@
/****************************/
/* Generate Signal */
/****************************/
- silk_PLC_conceal( psDec, psDecCtrl, frame, arch );
+ silk_PLC_conceal( psDec, psDecCtrl, frame,
+#ifdef NEURAL_PLC
+ lpcnet,
+#endif
+ arch );
psDec->lossCnt++;
} else {
@@ -99,7 +106,7 @@
if ( psDec->sPLC.fs_kHz == 16 ) {
int k;
for( k = 0; k < psDec->nb_subfr; k += 2 ) {
- lpcnet_plc_update( &psDec->sPLC.lpcnet, frame + k * psDec->subfr_length );
+ lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
}
}
#endif
@@ -210,6 +217,9 @@
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -389,7 +399,7 @@
#ifdef NEURAL_PLC
if ( psDec->sPLC.fs_kHz == 16 ) {
for( k = 0; k < psDec->nb_subfr; k += 2 ) {
- lpcnet_plc_conceal( &psDec->sPLC.lpcnet, frame + k * psDec->subfr_length );
+ 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. */
--- a/silk/PLC.h
+++ b/silk/PLC.h
@@ -49,6 +49,9 @@
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost, /* I Loss flag */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
);
--- a/silk/dec_API.c
+++ b/silk/dec_API.c
@@ -86,6 +86,9 @@
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut, /* O Number of samples decoded */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -297,7 +300,11 @@
} else {
condCoding = CODE_CONDITIONALLY;
}
- ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding, arch);
+ ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding,
+#ifdef NEURAL_PLC
+ lpcnet,
+#endif
+ arch);
} else {
silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
}
--- a/silk/decode_frame.c
+++ b/silk/decode_frame.c
@@ -43,6 +43,9 @@
opus_int32 *pN, /* O Pointer to size of output frame */
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int condCoding, /* I The type of conditional coding to use */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -87,7 +90,11 @@
/********************************************************/
/* Update PLC state */
/********************************************************/
- silk_PLC( psDec, psDecCtrl, pOut, 0, arch );
+ silk_PLC( psDec, psDecCtrl, pOut, 0,
+#ifdef NEURAL_PLC
+ lpcnet,
+#endif
+ arch );
psDec->lossCnt = 0;
psDec->prevSignalType = psDec->indices.signalType;
@@ -97,7 +104,11 @@
psDec->first_frame_after_reset = 0;
} else {
/* Handle packet loss by extrapolation */
- silk_PLC( psDec, psDecCtrl, pOut, 1, arch );
+ silk_PLC( psDec, psDecCtrl, pOut, 1,
+#ifdef NEURAL_PLC
+ lpcnet,
+#endif
+ arch );
}
/*************************/
--- a/silk/main.h
+++ b/silk/main.h
@@ -410,6 +410,9 @@
opus_int32 *pN, /* O Pointer to size of output frame */
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int condCoding, /* I The type of conditional coding to use */
+#ifdef NEURAL_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
);
--- a/silk/structs.h
+++ b/silk/structs.h
@@ -256,9 +256,6 @@
opus_int fs_kHz;
opus_int nb_subfr;
opus_int subfr_length;
-#ifdef NEURAL_PLC
- LPCNetPLCState lpcnet;
-#endif
} silk_PLC_struct;
/* Struct for CNG */
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -60,6 +60,9 @@
silk_DecControlStruct DecControl;
int decode_gain;
int arch;
+#ifdef NEURAL_PLC
+ LPCNetPLCState lpcnet;
+#endif
/* Everything beyond this point gets cleared on a reset */
#define OPUS_DECODER_RESET_START stream_channels
@@ -152,6 +155,9 @@
st->prev_mode = 0;
st->frame_size = Fs/400;
+#ifdef NEURAL_PLC
+ lpcnet_plc_init( &st->lpcnet, LPCNET_PLC_CODEC );
+#endif
st->arch = opus_select_arch();
return OPUS_OK;
}
@@ -401,7 +407,11 @@
/* Call SILK decoder */
int first_frame = decoded_samples == 0;
silk_ret = silk_Decode( silk_dec, &st->DecControl,
- lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size, st->arch );
+ lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size,
+#ifdef NEURAL_PLC
+ &st->lpcnet,
+#endif
+ st->arch );
if( silk_ret ) {
if (lost_flag) {
/* PLC failure should not be fatal */
@@ -652,19 +662,17 @@
if (dred != NULL && dred->process_stage == 2) {
int features_per_frame;
int needed_feature_frames;
- silk_decoder_state *silk_dec;
- silk_dec = (silk_decoder_state*)((char*)st+st->silk_dec_offset);
- lpcnet_plc_fec_clear(&silk_dec->sPLC.lpcnet);
+ lpcnet_plc_fec_clear(&st->lpcnet);
features_per_frame = frame_size/(st->Fs/100);
needed_feature_frames = features_per_frame;
/* if blend==0, the last PLC call was "update" and we need to feed two extra 10-ms frames. */
- if (silk_dec->sPLC.lpcnet.blend == 0) needed_feature_frames+=2;
+ if (st->lpcnet.blend == 0) needed_feature_frames+=2;
for (i=0;i<needed_feature_frames;i++) {
int feature_offset = (needed_feature_frames-i-1 + (dred_offset/(st->Fs/100)-1)*features_per_frame);
if (feature_offset <= 4*dred->nb_latents-1) {
- lpcnet_plc_fec_add(&silk_dec->sPLC.lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
+ lpcnet_plc_fec_add(&st->lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
} else {
- lpcnet_plc_fec_add(&silk_dec->sPLC.lpcnet, NULL);
+ lpcnet_plc_fec_add(&st->lpcnet, NULL);
}
}
@@ -909,6 +917,9 @@
silk_InitDecoder( silk_dec );
st->stream_channels = st->channels;
st->frame_size = st->Fs/400;
+#ifdef NEURAL_PLC
+ lpcnet_plc_init( &st->lpcnet, LPCNET_PLC_CODEC );
+#endif
}
break;
case OPUS_GET_SAMPLE_RATE_REQUEST:
--
⑨