/* Gain scalar quantization with hysteresis, uniform on log scale */ void SKP_Silk_gains_quant( SKP_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ SKP_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ SKP_int8 *prev_ind, /* I/O last index in previous frame */ const SKP_int conditional, /* I first gain is delta coded if 1 */ const SKP_int nb_subfr /* I number of subframes */ ) { SKP_int k, double_step_size_threshold; for( k = 0; k < nb_subfr; k++ ) { /* Add half of previous quantization error, convert to log scale, scale, floor() */ ind[ k ] = SKP_SMULWB( SCALE_Q16, SKP_Silk_lin2log( gain_Q16[ k ] ) - OFFSET ); /* Round towards previous quantized gain (hysteresis) */ if( ind[ k ] < *prev_ind ) { ind[ k ]++; } ind[ k ] = SKP_max_int( ind[ k ], 0 ); /* Compute delta indices and limit */ if( k == 0 && conditional == 0 ) { /* Full index */ ind[ k ] = SKP_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 ); *prev_ind = ind[ k ]; } else { /* Delta index */ ind[ k ] = ind[ k ] - *prev_ind; /* Double the quantization step size for large gain increases, so that the max gain level can be reached */ double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; if( ind[ k ] > double_step_size_threshold ) { ind[ k ] = double_step_size_threshold + SKP_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 ); } ind[ k ] = SKP_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT ); /* Accumulate deltas */ if( ind[ k ] > double_step_size_threshold ) { *prev_ind += SKP_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold; } else { *prev_ind += ind[ k ]; } /* Shift to make non-negative */ ind[ k ] -= MIN_DELTA_GAIN_QUANT; } /* Convert to linear scale and scale */ gain_Q16[ k ] = SKP_Silk_log2lin( SKP_min_32( SKP_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ } }
/* 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; } }