shithub: opus

Download patch

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:
--