/* Write shortest uniquely decodable stream to buffer, and determine its length */ void SKP_Silk_range_enc_wrap_up( SKP_Silk_range_coder_state *psRC /* I/O compressed data structure */ ) { SKP_int bufferIx_tmp, bits_to_store, bits_in_stream, nBytes, mask; SKP_uint32 base_Q24; /* Lower limit of interval, shifted 8 bits to the right */ base_Q24 = SKP_RSHIFT_uint( psRC->base_Q32, 8 ); bits_in_stream = SKP_Silk_range_coder_get_length( psRC, &nBytes ); /* Number of additional bits (1..9) required to be stored to stream */ bits_to_store = bits_in_stream - SKP_LSHIFT( psRC->bufferIx, 3 ); /* Round up to required resolution */ base_Q24 += SKP_RSHIFT_uint( 0x00800000, bits_to_store - 1 ); base_Q24 &= SKP_LSHIFT_ovflw( 0xFFFFFFFF, 24 - bits_to_store ); /* Check for carry */ if( base_Q24 & 0x01000000 ) { /* Propagate carry in buffer */ bufferIx_tmp = psRC->bufferIx; while( ( ++( psRC->buffer[ --bufferIx_tmp ] ) ) == 0 ); } /* Store to stream, making sure not to write beyond buffer */ if( psRC->bufferIx < psRC->bufferLength ) { psRC->buffer[ psRC->bufferIx++ ] = (SKP_uint8)SKP_RSHIFT_uint( base_Q24, 16 ); if( bits_to_store > 8 ) { if( psRC->bufferIx < psRC->bufferLength ) { psRC->buffer[ psRC->bufferIx++ ] = (SKP_uint8)SKP_RSHIFT_uint( base_Q24, 8 ); } } } /* Fill up any remaining bits in the last byte with 1s */ if( bits_in_stream & 7 ) { mask = SKP_RSHIFT( 0xFF, bits_in_stream & 7 ); if( nBytes - 1 < psRC->bufferLength ) { psRC->buffer[ nBytes - 1 ] |= mask; } } }
/* Check that any remaining bits in the last byte are set to 1 */ void SKP_Silk_range_coder_check_after_decoding( SKP_Silk_range_coder_state *psRC /* I/O compressed data structure */ ) { SKP_int bits_in_stream, nBytes, mask; bits_in_stream = SKP_Silk_range_coder_get_length( psRC, &nBytes ); /* Make sure not to read beyond buffer */ if( nBytes - 1 >= psRC->bufferLength ) { psRC->error = RANGE_CODER_DECODER_CHECK_FAILED; return; } /* Test any remaining bits in last byte */ if( bits_in_stream & 7 ) { mask = SKP_RSHIFT( 0xFF, bits_in_stream & 7 ); if( ( psRC->buffer[ nBytes - 1 ] & mask ) != mask ) { psRC->error = RANGE_CODER_DECODER_CHECK_FAILED; return; } } }
SKP_int SKP_Silk_encode_frame_FLP( SKP_Silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */ SKP_uint8 *pCode, /* O Payload */ SKP_int16 *pnBytesOut, /* I/O Number of payload bytes; */ /* input: max length; output: used */ const SKP_int16 *pIn /* I Input speech frame */ ) { SKP_Silk_encoder_control_FLP sEncCtrl; SKP_int k, nBytes, ret = 0; SKP_float *x_frame, *res_pitch_frame; SKP_int16 pIn_HP[ MAX_FRAME_LENGTH ]; SKP_int16 pIn_HP_LP[ MAX_FRAME_LENGTH ]; SKP_float xfw[ MAX_FRAME_LENGTH ]; SKP_float res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ]; SKP_int LBRR_idx, frame_terminator; /* Low bitrate redundancy parameters */ SKP_uint8 LBRRpayload[ MAX_ARITHM_BYTES ]; SKP_int16 nBytesLBRR; const SKP_uint16 *FrameTermination_CDF; sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Setup Input Pointers, and insert frame in input buffer */ /*************************************************************/ /* pointers aligned with start of frame to encode */ x_frame = psEnc->x_buf + psEnc->sCmn.frame_length; // start of frame to encode res_pitch_frame = res_pitch + psEnc->sCmn.frame_length; // start of pitch LPC residual frame /****************************/ /* Voice Activity Detection */ /****************************/ SKP_Silk_VAD_FLP( psEnc, &sEncCtrl, pIn ); /*******************************************/ /* High-pass filtering of the input signal */ /*******************************************/ #if HIGH_PASS_INPUT /* Variable high-pass filter */ SKP_Silk_HP_variable_cutoff_FLP( psEnc, &sEncCtrl, pIn_HP, pIn ); #else SKP_memcpy( pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) ); #endif #if SWITCH_TRANSITION_FILTERING /* Ensure smooth bandwidth transitions */ SKP_Silk_LP_variable_cutoff( &psEnc->sCmn.sLP, pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length ); #else SKP_memcpy( pIn_HP_LP, pIn_HP, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) ); #endif /*******************************************/ /* Copy new frame to front of input buffer */ /*******************************************/ SKP_short2float_array( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP_LP, psEnc->sCmn.frame_length ); /* Add tiny signal to avoid high CPU load from denormalized floating point numbers */ for( k = 0; k < 8; k++ ) { x_frame[ LA_SHAPE_MS * psEnc->sCmn.fs_kHz + k * ( psEnc->sCmn.frame_length >> 3 ) ] += ( 1 - ( k & 2 ) ) * 1e-6f; } /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ SKP_Silk_find_pitch_lags_FLP( psEnc, &sEncCtrl, res_pitch, x_frame ); /************************/ /* Noise shape analysis */ /************************/ SKP_Silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame ); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ SKP_Silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame ); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ SKP_Silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch ); /****************************************/ /* Process gains */ /****************************************/ SKP_Silk_process_gains_FLP( psEnc, &sEncCtrl ); /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ nBytesLBRR = MAX_ARITHM_BYTES; SKP_Silk_LBRR_encode_FLP( psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw ); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ SKP_Silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, xfw, psEnc->sCmn.q, 0 ); /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if( psEnc->speech_activity < SPEECH_ACTIVITY_DTX_THRES ) { psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if( psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.inDTX = 1; } if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NO_SPEECH_FRAMES_BEFORE_DTX ) { psEnc->sCmn.noSpeechCounter = NO_SPEECH_FRAMES_BEFORE_DTX; psEnc->sCmn.inDTX = 0; } } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.vadFlag = VOICE_ACTIVITY; } /****************************************/ /* Initialize range coder */ /****************************************/ if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) { SKP_Silk_range_enc_init( &psEnc->sCmn.sRC ); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ SKP_Silk_encode_parameters( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, psEnc->sCmn.q ); FrameTermination_CDF = SKP_Silk_FrameTermination_CDF; /****************************************/ /* Update Buffers and State */ /****************************************/ /* Update input buffer */ SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], ( psEnc->sCmn.frame_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_float ) ); /* Parameters needed for next frame */ psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype; psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[ NB_SUBFR - 1]; psEnc->sCmn.first_frame_after_reset = 0; if( psEnc->sCmn.sRC.error ) { /* Encoder returned error: Clear payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { psEnc->sCmn.nFramesInPayloadBuf++; } /****************************************/ /* Finalize payload and copy to output */ /****************************************/ if( psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms ) { LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK; /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; if( psEnc->sCmn.LBRR_buffer[ LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS1 ) { frame_terminator = SKP_SILK_LBRR_VER1; } if( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS2 ) { frame_terminator = SKP_SILK_LBRR_VER2; LBRR_idx = psEnc->sCmn.oldest_LBRR_idx; } /* Add the frame termination info to stream */ SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF ); /* Payload length so far */ SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &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 ); SKP_memcpy( pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof( SKP_uint8 ) ); if( frame_terminator > SKP_SILK_MORE_FRAMES && *pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes ) { /* Get old packet and add to payload. */ SKP_memcpy( &pCode[ nBytes ], psEnc->sCmn.LBRR_buffer[ LBRR_idx ].payload, psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes * sizeof( SKP_uint8 ) ); nBytes += psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes; } *pnBytesOut = nBytes; /* Update FEC buffer */ SKP_memcpy( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].payload, LBRRpayload, nBytesLBRR * sizeof( SKP_uint8 ) ); psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].nBytes = nBytesLBRR; /* The line below describes how FEC should be used */ psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage = sEncCtrl.sCmn.LBRR_usage; psEnc->sCmn.oldest_LBRR_idx = ( ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK ); } else { /* Not enough space: Payload will be discarded */ *pnBytesOut = 0; nBytes = 0; ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT; } /* Reset the number of frames in payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 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, frame_terminator, FrameTermination_CDF ); /* Payload length so far */ SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes ); } /* Check for arithmetic coder errors */ if( psEnc->sCmn.sRC.error ) { ret = SKP_SILK_ENC_INTERNAL_ERROR; } /* Simulate number of ms buffered in channel because of exceeding TargetRate */ psEnc->BufferedInChannel_ms += ( 8.0f * 1000.0f * ( nBytes - psEnc->sCmn.nBytesInPayloadBuf ) ) / psEnc->sCmn.TargetRate_bps; psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS; psEnc->BufferedInChannel_ms = SKP_LIMIT_float( psEnc->BufferedInChannel_ms, 0.0f, 100.0f ); psEnc->sCmn.nBytesInPayloadBuf = nBytes; if( psEnc->speech_activity > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES ) { psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32( psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS ); } return( ret ); }
/* 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; } }
int SKP_Silk_encode_frame_FIX(SKP_Silk_encoder_state_FIX * psEnc, /* I/O Pointer to Silk FIX encoder state */ uint8_t * pCode, /* O Pointer to payload */ int16_t * pnBytesOut, /* I/O Pointer to number of payload bytes */ /* input: max length; output: used */ const int16_t * pIn /* I Pointer to input speech frame */ ) { SKP_Silk_encoder_control_FIX sEncCtrl; int i, nBytes, ret = 0; int16_t *x_frame, *res_pitch_frame; int16_t xfw[MAX_FRAME_LENGTH]; int16_t pIn_HP[MAX_FRAME_LENGTH]; int16_t res_pitch[2 * MAX_FRAME_LENGTH + LA_PITCH_MAX]; int LBRR_idx, frame_terminator, SNR_dB_Q7; const uint16_t *FrameTermination_CDF; /* Low bitrate redundancy parameters */ uint8_t LBRRpayload[MAX_ARITHM_BYTES]; int16_t nBytesLBRR; //int32_t Seed[ MAX_LAYERS ]; sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3; /**************************************************************/ /* Setup Input Pointers, and insert frame in input buffer */ /*************************************************************/ x_frame = psEnc->x_buf + psEnc->sCmn.frame_length; /* start of frame to encode */ res_pitch_frame = res_pitch + psEnc->sCmn.frame_length; /* start of pitch LPC residual frame */ /****************************/ /* Voice Activity Detection */ /****************************/ ret = SKP_Silk_VAD_GetSA_Q8(&psEnc->sCmn.sVAD, &psEnc->speech_activity_Q8, &SNR_dB_Q7, sEncCtrl.input_quality_bands_Q15, &sEncCtrl.input_tilt_Q15, pIn, psEnc->sCmn.frame_length); /*******************************************/ /* High-pass filtering of the input signal */ /*******************************************/ #if HIGH_PASS_INPUT /* Variable high-pass filter */ SKP_Silk_HP_variable_cutoff_FIX(psEnc, &sEncCtrl, pIn_HP, pIn); #else SKP_memcpy(pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof(int16_t)); #endif #if SWITCH_TRANSITION_FILTERING /* Ensure smooth bandwidth transitions */ SKP_Silk_LP_variable_cutoff(&psEnc->sCmn.sLP, x_frame + psEnc->sCmn.la_shape, pIn_HP, psEnc->sCmn.frame_length); #else SKP_memcpy(x_frame + psEnc->sCmn.la_shape, pIn_HP, psEnc->sCmn.frame_length * sizeof(int16_t)); #endif /*****************************************/ /* Find pitch lags, initial LPC analysis */ /*****************************************/ SKP_Silk_find_pitch_lags_FIX(psEnc, &sEncCtrl, res_pitch, x_frame); /************************/ /* Noise shape analysis */ /************************/ SKP_Silk_noise_shape_analysis_FIX(psEnc, &sEncCtrl, res_pitch_frame, x_frame); /*****************************************/ /* Prefiltering for noise shaper */ /*****************************************/ SKP_Silk_prefilter_FIX(psEnc, &sEncCtrl, xfw, x_frame); /***************************************************/ /* Find linear prediction coefficients (LPC + LTP) */ /***************************************************/ SKP_Silk_find_pred_coefs_FIX(psEnc, &sEncCtrl, res_pitch); /****************************************/ /* Process gains */ /****************************************/ SKP_Silk_process_gains_FIX(psEnc, &sEncCtrl); psEnc->sCmn.sigtype[psEnc->sCmn.nFramesInPayloadBuf] = sEncCtrl.sCmn.sigtype; psEnc->sCmn.QuantOffsetType[psEnc->sCmn.nFramesInPayloadBuf] = sEncCtrl.sCmn.QuantOffsetType; /****************************************/ /* Low Bitrate Redundant Encoding */ /****************************************/ nBytesLBRR = MAX_ARITHM_BYTES; SKP_Silk_LBRR_encode_FIX(psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw); /*****************************************/ /* Noise shaping quantization */ /*****************************************/ psEnc->NoiseShapingQuantizer(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sNSQ, xfw, &psEnc->sCmn.q[psEnc->sCmn. nFramesInPayloadBuf * psEnc->sCmn.frame_length], sEncCtrl.sCmn.NLSFInterpCoef_Q2, sEncCtrl.PredCoef_Q12[0], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14); /**************************************************/ /* Convert speech activity into VAD and DTX flags */ /**************************************************/ if (psEnc->speech_activity_Q8 < SPEECH_ACTIVITY_DTX_THRES_Q8) { psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY; psEnc->sCmn.noSpeechCounter++; if (psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX) { psEnc->sCmn.inDTX = 1; } if (psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX) { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; } } else { psEnc->sCmn.noSpeechCounter = 0; psEnc->sCmn.inDTX = 0; psEnc->sCmn.vadFlag = VOICE_ACTIVITY; } /****************************************/ /* Initialize arithmetic coder */ /****************************************/ if (psEnc->sCmn.nFramesInPayloadBuf == 0) { SKP_Silk_range_enc_init(&psEnc->sCmn.sRC); psEnc->sCmn.nBytesInPayloadBuf = 0; } /****************************************/ /* Encode Parameters */ /****************************************/ if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { SKP_Silk_encode_parameters_v4(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC); FrameTermination_CDF = SKP_Silk_FrameTermination_v4_CDF; } else { SKP_Silk_encode_parameters(&psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, &psEnc->sCmn.q[psEnc->sCmn. nFramesInPayloadBuf * psEnc->sCmn. frame_length]); FrameTermination_CDF = SKP_Silk_FrameTermination_CDF; } /****************************************/ /* Update Buffers and State */ /****************************************/ /* Update Input buffer */ SKP_memmove(psEnc->x_buf, &psEnc->x_buf[psEnc->sCmn.frame_length], (psEnc->sCmn.frame_length + psEnc->sCmn.la_shape) * sizeof(int16_t)); /* parameters needed for next frame */ psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype; psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[NB_SUBFR - 1]; psEnc->sCmn.first_frame_after_reset = 0; if (psEnc->sCmn.sRC.error) { /* encoder returned error: clear payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { psEnc->sCmn.nFramesInPayloadBuf++; } /****************************************/ /* finalize payload and copy to output */ /****************************************/ if (psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms) { LBRR_idx = (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK; /* Check if FEC information should be added */ frame_terminator = SKP_SILK_LAST_FRAME; if (psEnc->sCmn.LBRR_buffer[LBRR_idx].usage == SKP_SILK_ADD_LBRR_TO_PLUS1) { frame_terminator = SKP_SILK_LBRR_VER1; } if (psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. usage == SKP_SILK_ADD_LBRR_TO_PLUS2) { frame_terminator = SKP_SILK_LBRR_VER2; LBRR_idx = psEnc->sCmn.oldest_LBRR_idx; } /* Add the frame termination info to stream */ SKP_Silk_range_encoder(&psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF); if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { /* Code excitation signal */ for (i = 0; i < psEnc->sCmn.nFramesInPayloadBuf; i++) { SKP_Silk_encode_pulses(&psEnc->sCmn.sRC, psEnc->sCmn.sigtype[i], psEnc->sCmn. QuantOffsetType[i], &psEnc->sCmn.q[i * psEnc-> sCmn. frame_length], psEnc->sCmn. frame_length); } } /* payload length so far */ SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &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); SKP_memcpy(pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof(uint8_t)); if (frame_terminator > SKP_SILK_MORE_FRAMES && *pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes) { /* Get old packet and add to payload. */ SKP_memcpy(&pCode[nBytes], psEnc->sCmn.LBRR_buffer[LBRR_idx]. payload, psEnc->sCmn.LBRR_buffer[LBRR_idx]. nBytes * sizeof(uint8_t)); nBytes += psEnc->sCmn.LBRR_buffer[LBRR_idx].nBytes; } *pnBytesOut = nBytes; /* Update FEC buffer */ SKP_memcpy(psEnc->sCmn. LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. payload, LBRRpayload, nBytesLBRR * sizeof(uint8_t)); psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. nBytes = nBytesLBRR; /* This line tells describes how FEC should be used */ psEnc->sCmn.LBRR_buffer[psEnc->sCmn.oldest_LBRR_idx]. usage = sEncCtrl.sCmn.LBRR_usage; psEnc->sCmn.oldest_LBRR_idx = (psEnc->sCmn.oldest_LBRR_idx + 1) & LBRR_IDX_MASK; /* Reset number of frames in payload buffer */ psEnc->sCmn.nFramesInPayloadBuf = 0; } else { /* Not enough space: Payload will be discarded */ *pnBytesOut = 0; nBytes = 0; psEnc->sCmn.nFramesInPayloadBuf = 0; ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT; } } 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, frame_terminator, FrameTermination_CDF); /* payload length so far */ SKP_Silk_range_coder_get_length(&psEnc->sCmn.sRC, &nBytes); if (psEnc->sCmn.bitstream_v == BIT_STREAM_V4) { /* Take into account the q signal that isnt in the bitstream yet */ nBytes += SKP_Silk_pulses_to_bytes(&psEnc->sCmn, &psEnc->sCmn. q[(psEnc->sCmn. nFramesInPayloadBuf - 1) * psEnc->sCmn. frame_length]); } } /* Check for arithmetic coder errors */ if (psEnc->sCmn.sRC.error) { ret = SKP_SILK_ENC_INTERNAL_ERROR; } /* simulate number of ms buffered in channel because of exceeding TargetRate */ assert((8 * 1000 * ((int64_t) nBytes - (int64_t) psEnc->sCmn.nBytesInPayloadBuf)) == SKP_SAT32(8 * 1000 * ((int64_t) nBytes - (int64_t) psEnc->sCmn.nBytesInPayloadBuf))); assert(psEnc->sCmn.TargetRate_bps > 0); psEnc->BufferedInChannel_ms += SKP_DIV32(8 * 1000 * (nBytes - psEnc->sCmn.nBytesInPayloadBuf), psEnc->sCmn.TargetRate_bps); psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS; psEnc->BufferedInChannel_ms = SKP_LIMIT(psEnc->BufferedInChannel_ms, 0, 100); psEnc->sCmn.nBytesInPayloadBuf = nBytes; if (psEnc->speech_activity_Q8 > WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES_Q8) { psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32(psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS); } return (ret); }