summaryrefslogtreecommitdiffstats
path: root/media/libopus/silk/PLC.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libopus/silk/PLC.c')
-rw-r--r--media/libopus/silk/PLC.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/media/libopus/silk/PLC.c b/media/libopus/silk/PLC.c
index 4667440db2..b35bf750a0 100644
--- a/media/libopus/silk/PLC.c
+++ b/media/libopus/silk/PLC.c
@@ -33,6 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "stack_alloc.h"
#include "PLC.h"
+#ifdef ENABLE_DEEP_PLC
+#include "lpcnet.h"
+#endif
+
#define NB_ATT 2
static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
@@ -47,6 +51,9 @@ static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
);
@@ -67,6 +74,9 @@ void silk_PLC(
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost, /* I Loss flag */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -80,7 +90,11 @@ void silk_PLC(
/****************************/
/* Generate Signal */
/****************************/
- silk_PLC_conceal( psDec, psDecCtrl, frame, arch );
+ silk_PLC_conceal( psDec, psDecCtrl, frame,
+#ifdef ENABLE_DEEP_PLC
+ lpcnet,
+#endif
+ arch );
psDec->lossCnt++;
} else {
@@ -88,6 +102,14 @@ void silk_PLC(
/* Update state */
/****************************/
silk_PLC_update( psDec, psDecCtrl );
+#ifdef ENABLE_DEEP_PLC
+ if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) {
+ int k;
+ for( k = 0; k < psDec->nb_subfr; k += 2 ) {
+ lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length );
+ }
+ }
+#endif
}
}
@@ -195,6 +217,9 @@ static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
+#ifdef ENABLE_DEEP_PLC
+ LPCNetPLCState *lpcnet,
+#endif
int arch /* I Run-time architecture */
)
{
@@ -371,6 +396,24 @@ static OPUS_INLINE void silk_PLC_conceal(
/* Scale with Gain */
frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
}
+#ifdef ENABLE_DEEP_PLC
+ if ( lpcnet != NULL && lpcnet->loaded && psDec->sPLC.fs_kHz == 16 ) {
+ 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
/* Save LPC state */
silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
@@ -431,12 +474,16 @@ void silk_PLC_glue_frames(
slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
/* Make slope 4x steeper to avoid missing onsets after DTX */
slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
-
- for( i = 0; i < length; i++ ) {
- frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
- gain_Q16 += slope_Q16;
- if( gain_Q16 > (opus_int32)1 << 16 ) {
- break;
+#ifdef ENABLE_DEEP_PLC
+ if ( psDec->sPLC.fs_kHz != 16 )
+#endif
+ {
+ for( i = 0; i < length; i++ ) {
+ frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
+ gain_Q16 += slope_Q16;
+ if( gain_Q16 > (opus_int32)1 << 16 ) {
+ break;
+ }
}
}
}