/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ void SKP_Silk_LBRR_encode_FLP( SKP_Silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ SKP_Silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */ SKP_uint8 *pCode, /* O Payload */ SKP_int16 *pnBytesOut, /* I/O Payload bytes; in: max; out: used */ const SKP_float xfw[] /* I Input signal */ ) { SKP_int32 Gains_Q16[ NB_SUBFR ]; SKP_int k, TempGainsIndices[ NB_SUBFR ], frame_terminator; SKP_int nBytes, nFramesInPayloadBuf; SKP_float TempGains[ NB_SUBFR ]; SKP_int typeOffset, LTP_scaleIndex, Rate_only_parameters = 0; /* Control use of inband LBRR */ SKP_Silk_LBRR_ctrl_FLP( psEnc, &psEncCtrl->sCmn ); if( psEnc->sCmn.LBRR_enabled ) { /* Save original gains */ SKP_memcpy( TempGainsIndices, psEncCtrl->sCmn.GainsIndices, NB_SUBFR * sizeof( SKP_int ) ); SKP_memcpy( TempGains, psEncCtrl->Gains, NB_SUBFR * sizeof( SKP_float ) ); typeOffset = psEnc->sCmn.typeOffsetPrev; // Temp save as cannot be overwritten LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex; /* Set max rate where quant signal is encoded */ if( psEnc->sCmn.fs_kHz == 8 ) { Rate_only_parameters = 13500; } else if( psEnc->sCmn.fs_kHz == 12 ) { Rate_only_parameters = 15500; } else if( psEnc->sCmn.fs_kHz == 16 ) { Rate_only_parameters = 17500; } else if( psEnc->sCmn.fs_kHz == 24 ) { Rate_only_parameters = 19500; } else { SKP_assert( 0 ); } if( psEnc->sCmn.Complexity > 0 && psEnc->sCmn.TargetRate_bps > Rate_only_parameters ) { if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) { /* First frame in packet copy everything */ SKP_memcpy( &psEnc->sCmn.sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( SKP_Silk_nsq_state ) ); psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; /* Increase Gains to get target LBRR rate */ psEncCtrl->sCmn.GainsIndices[ 0 ] += psEnc->sCmn.LBRR_GainIncreases; psEncCtrl->sCmn.GainsIndices[ 0 ] = SKP_LIMIT_int( psEncCtrl->sCmn.GainsIndices[ 0 ], 0, N_LEVELS_QGAIN - 1 ); } /* Decode to get gains in sync with decoder */ SKP_Silk_gains_dequant( Gains_Q16, psEncCtrl->sCmn.GainsIndices, &psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf ); /* Overwrite unquantized gains with quantized gains and convert back to Q0 from Q16 */ for( k = 0; k < NB_SUBFR; k++ ) { psEncCtrl->Gains[ k ] = Gains_Q16[ k ] / 65536.0f; } /*****************************************/ /* Noise shaping quantization */ /*****************************************/ SKP_Silk_NSQ_wrapper_FLP( psEnc, psEncCtrl, xfw, psEnc->sCmn.q_LBRR, 1 ); } else { SKP_memset( psEnc->sCmn.q_LBRR, 0, psEnc->sCmn.frame_length * sizeof( SKP_int8 ) ); psEncCtrl->sCmn.LTP_scaleIndex = 0; } /****************************************/ /* Initialize arithmetic coder */ /****************************************/ if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) { SKP_Silk_range_enc_init( &psEnc->sCmn.sRC_LBRR ); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ SKP_Silk_encode_parameters( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR, psEnc->sCmn.q_LBRR ); if( psEnc->sCmn.sRC_LBRR.error ) { /* Encoder returned error: Clear payload buffer */ nFramesInPayloadBuf = 0; } else { nFramesInPayloadBuf = psEnc->sCmn.nFramesInPayloadBuf + 1; } /****************************************/ /* Finalize payload and copy to output */ /****************************************/ if( nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms ) { /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; /* Add the frame termination info to stream */ SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF ); /* Payload length so far */ SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC_LBRR, &nBytes ); /* Check that there is enough space in external output buffer and move data */ if( *pnBytesOut >= nBytes ) { SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC_LBRR ); SKP_memcpy( pCode, psEnc->sCmn.sRC_LBRR.buffer, nBytes * sizeof( SKP_uint8 ) ); *pnBytesOut = nBytes; } else { /* Not enough space: Payload will be discarded */ *pnBytesOut = 0; SKP_assert( 0 ); } } else { /* No payload this time */ *pnBytesOut = 0; /* Encode that more frames follows */ frame_terminator = SKP_SILK_MORE_FRAMES; SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF ); } /* Restore original Gains */ SKP_memcpy( psEncCtrl->sCmn.GainsIndices, TempGainsIndices, NB_SUBFR * sizeof( SKP_int ) ); SKP_memcpy( psEncCtrl->Gains, TempGains, NB_SUBFR * sizeof( SKP_float ) ); /* Restore LTP scale index and typeoffset */ psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex; psEnc->sCmn.typeOffsetPrev = typeOffset; } }
/* Low BitRate Redundancy encoding functionality. Reuse all parameters but encode residual with lower bitrate */ void SKP_Silk_LBRR_encode_FIX(SKP_Silk_encoder_state_FIX * psEnc, /* I/O Pointer to Silk encoder state */ SKP_Silk_encoder_control_FIX * psEncCtrl, /* I/O Pointer to Silk encoder control struct */ uint8_t * pCode, /* O Pointer to payload */ int16_t * pnBytesOut, /* I/O Pointer to number of payload bytes */ int16_t xfw[] /* I Input signal */ ) { int i, TempGainsIndices[NB_SUBFR], frame_terminator; int nBytes, nFramesInPayloadBuf; int32_t TempGains_Q16[NB_SUBFR]; int typeOffset, LTP_scaleIndex, Rate_only_parameters = 0; /*******************************************/ /* Control use of inband LBRR */ /*******************************************/ SKP_Silk_LBRR_ctrl_FIX(psEnc, psEncCtrl); if (psEnc->sCmn.LBRR_enabled) { /* Save original Gains */ SKP_memcpy(TempGainsIndices, psEncCtrl->sCmn.GainsIndices, NB_SUBFR * sizeof(int)); SKP_memcpy(TempGains_Q16, psEncCtrl->Gains_Q16, NB_SUBFR * sizeof(int32_t)); typeOffset = psEnc->sCmn.typeOffsetPrev; // Temp save as cannot be overwritten LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex; /* Set max rate where quant signal is encoded */ if (psEnc->sCmn.fs_kHz == 8) { Rate_only_parameters = 13500; } else if (psEnc->sCmn.fs_kHz == 12) { Rate_only_parameters = 15500; } else if (psEnc->sCmn.fs_kHz == 16) { Rate_only_parameters = 17500; } else if (psEnc->sCmn.fs_kHz == 24) { Rate_only_parameters = 19500; } else { assert(0); } if (psEnc->sCmn.Complexity > 0 && psEnc->sCmn.TargetRate_bps > Rate_only_parameters) { if (psEnc->sCmn.nFramesInPayloadBuf == 0) { /* First frame in packet copy Everything */ SKP_memcpy(&psEnc->sNSQ_LBRR, &psEnc->sNSQ, sizeof(SKP_Silk_nsq_state)); psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; /* Increase Gains to get target LBRR rate */ psEncCtrl->sCmn.GainsIndices[0] = psEncCtrl->sCmn.GainsIndices[0] + psEnc->sCmn.LBRR_GainIncreases; psEncCtrl->sCmn.GainsIndices[0] = SKP_LIMIT(psEncCtrl->sCmn.GainsIndices[0], 0, N_LEVELS_QGAIN - 1); } /* Decode to get Gains in sync with decoder */ /* Overwrite unquantized gains with quantized gains */ SKP_Silk_gains_dequant(psEncCtrl->Gains_Q16, psEncCtrl->sCmn.GainsIndices, &psEnc->sCmn. LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ psEnc->NoiseShapingQuantizer(&psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sNSQ_LBRR, xfw, &psEnc->sCmn.q_LBRR[psEnc-> sCmn. nFramesInPayloadBuf * psEnc-> sCmn. frame_length], psEncCtrl->sCmn. NLSFInterpCoef_Q2, psEncCtrl->PredCoef_Q12[0], psEncCtrl->LTPCoef_Q14, psEncCtrl->AR2_Q13, psEncCtrl-> HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, psEncCtrl->Gains_Q16, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14); } else { SKP_memset(&psEnc->sCmn. q_LBRR[psEnc->sCmn.nFramesInPayloadBuf * psEnc->sCmn.frame_length], 0, psEnc->sCmn.frame_length * sizeof(int)); psEncCtrl->sCmn.LTP_scaleIndex = 0; } /****************************************/ /* Initialize arithmetic coder */ /****************************************/ if (psEnc->sCmn.nFramesInPayloadBuf == 0) { SKP_Silk_range_enc_init(&psEnc->sCmn.sRC_LBRR); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { SKP_Silk_encode_parameters_v4(&psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR); } else { SKP_Silk_encode_parameters(&psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sRC_LBRR, &psEnc->sCmn.q_LBRR[psEnc-> sCmn. nFramesInPayloadBuf * psEnc-> sCmn. frame_length]); } if (psEnc->sCmn.sRC_LBRR.error) { /* encoder returned error: clear payload buffer */ nFramesInPayloadBuf = 0; } else { nFramesInPayloadBuf = psEnc->sCmn.nFramesInPayloadBuf + 1; } /****************************************/ /* finalize payload and copy to output */ /****************************************/ if (SKP_SMULBB(nFramesInPayloadBuf, FRAME_LENGTH_MS) >= psEnc->sCmn.PacketSize_ms) { /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; /* Add the frame termination info to stream */ SKP_Silk_range_encoder(&psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF); if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { /*********************************************/ /* Encode quantization indices of excitation */ /*********************************************/ for (i = 0; i < nFramesInPayloadBuf; i++) { SKP_Silk_encode_pulses(&psEnc->sCmn. sRC_LBRR, psEnc->sCmn. sigtype[i], psEnc->sCmn. QuantOffsetType [i], &psEnc->sCmn. q_LBRR[i * psEnc-> sCmn. frame_length], psEnc->sCmn. frame_length); } } /* payload length so far */ SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC_LBRR, &nBytes); /* check that there is enough space in external output buffer, and move data */ if (*pnBytesOut >= nBytes) { SKP_Silk_range_enc_wrap_up(&psEnc->sCmn. sRC_LBRR); SKP_memcpy(pCode, psEnc->sCmn.sRC_LBRR.buffer, nBytes * sizeof(uint8_t)); *pnBytesOut = nBytes; } else { /* not enough space: payload will be discarded */ *pnBytesOut = 0; assert(0); } } else { /* no payload for you this time */ *pnBytesOut = 0; /* Encode that more frames follows */ frame_terminator = SKP_SILK_MORE_FRAMES; SKP_Silk_range_encoder(&psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF); } /* Restore original Gains */ SKP_memcpy(psEncCtrl->sCmn.GainsIndices, TempGainsIndices, NB_SUBFR * sizeof(int)); SKP_memcpy(psEncCtrl->Gains_Q16, TempGains_Q16, NB_SUBFR * sizeof(int32_t)); /* Restore LTP scale index and typeoffset */ psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex; psEnc->sCmn.typeOffsetPrev = typeOffset; } }