Commit c152d602 authored by Timothy B. Terriberry's avatar Timothy B. Terriberry
Browse files

Use dynamic stack allocation in the SILK encoder.

This makes all remaining large stack allocations use the vararray
 macros.
This continues the work of 6f2d9f50 to allow compiling with
 NONTHREADSAFE_PSEUDOSTACK to move the memory for large buffers
 off the stack for devices where it is very limited.

It also does this for some additional large buffers used by the
 PLC in the decoder.
parent dc58579c
......@@ -424,10 +424,12 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R
opus_val16 fade = Q15ONE;
int pitch_index;
VARDECL(opus_val32, etmp);
VARDECL(opus_val16, exc);
if (loss_count == 0)
{
opus_val16 lp_pitch_buf[DECODE_BUFFER_SIZE>>1];
VARDECL( opus_val16, lp_pitch_buf );
ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
pitch_downsample(decode_mem, lp_pitch_buf, DECODE_BUFFER_SIZE, C);
pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
......@@ -440,14 +442,12 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R
}
ALLOC(etmp, overlap, opus_val32);
ALLOC(exc, MAX_PERIOD, opus_val16);
window = mode->window;
c=0; do {
opus_val16 exc[MAX_PERIOD];
opus_val32 ac[LPC_ORDER+1];
opus_val16 decay;
opus_val16 attenuation;
opus_val32 S1=0;
opus_val16 lpc_mem[LPC_ORDER];
celt_sig *buf;
int extrapolation_offset;
int extrapolation_len;
......@@ -461,6 +461,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R
if (loss_count == 0)
{
opus_val32 ac[LPC_ORDER+1];
/* Compute LPC coefficients for the last MAX_PERIOD samples before
the first loss so we can work in the excitation-filter domain. */
_celt_autocorr(exc, ac, window, overlap, LPC_ORDER, MAX_PERIOD);
......@@ -487,14 +488,17 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R
exc_length = IMIN(2*pitch_index, MAX_PERIOD);
/* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */
for (i=0;i<LPC_ORDER;i++)
{
lpc_mem[i] =
ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
opus_val16 lpc_mem[LPC_ORDER];
for (i=0;i<LPC_ORDER;i++)
{
lpc_mem[i] =
ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
}
/* Compute the excitation for exc_length samples before the loss. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem);
}
/* Compute the excitation for exc_length samples before the loss. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem);
/* Check if the waveform is decaying, and if so how fast.
We do this to avoid adding energy when concealing in a segment
......@@ -547,14 +551,18 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, opus_val16 * OPUS_R
S1 += SHR32(MULT16_16(tmp, tmp), 8);
}
/* Copy the last decoded samples (prior to the overlap region) to
synthesis filter memory so we can have a continuous signal. */
for (i=0;i<LPC_ORDER;i++)
lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
/* Apply the synthesis filter to convert the excitation back into the
signal domain. */
celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER, lpc_mem);
{
opus_val16 lpc_mem[LPC_ORDER];
/* Copy the last decoded samples (prior to the overlap region) to
synthesis filter memory so we can have a continuous signal. */
for (i=0;i<LPC_ORDER;i++)
lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
/* Apply the synthesis filter to convert the excitation back into
the signal domain. */
celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
lpc_mem);
}
/* Check if the synthesis energy is higher than expected, which can
happen with the signal changes during our window. If so,
......
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
/* Generates excitation for CNG LPC synthesis */
static inline void silk_CNG_exc(
......@@ -86,8 +87,8 @@ void silk_CNG(
opus_int i, subfr;
opus_int32 sum_Q6, max_Gain_Q16;
opus_int16 A_Q12[ MAX_LPC_ORDER ];
opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ];
silk_CNG_struct *psCNG = &psDec->sCNG;
SAVE_STACK;
if( psDec->fs_kHz != psCNG->fs_kHz ) {
/* Reset state */
......@@ -123,6 +124,9 @@ void silk_CNG(
/* Add CNG when packet is lost or during DTX */
if( psDec->lossCnt ) {
VARDECL( opus_int32, CNG_sig_Q10 );
ALLOC( CNG_sig_Q10, length + MAX_LPC_ORDER, opus_int32 );
/* Generate CNG excitation */
silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
......@@ -164,4 +168,5 @@ void silk_CNG(
} else {
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
}
RESTORE_STACK;
}
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
/***********************/
/* NLSF vector encoder */
......@@ -46,10 +47,10 @@ opus_int32 silk_NLSF_encode( /* O Returns
{
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
opus_int32 W_tmp_Q9;
opus_int32 err_Q26[ NLSF_VQ_MAX_VECTORS ];
opus_int32 RD_Q25[ NLSF_VQ_MAX_SURVIVORS ];
opus_int tempIndices1[ NLSF_VQ_MAX_SURVIVORS ];
opus_int8 tempIndices2[ NLSF_VQ_MAX_SURVIVORS * MAX_LPC_ORDER ];
VARDECL( opus_int32, err_Q26 );
VARDECL( opus_int32, RD_Q25 );
VARDECL( opus_int, tempIndices1 );
VARDECL( opus_int8, tempIndices2 );
opus_int16 res_Q15[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
......@@ -58,6 +59,7 @@ opus_int32 silk_NLSF_encode( /* O Returns
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
const opus_uint8 *pCB_element, *iCDF_ptr;
SAVE_STACK;
silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
silk_assert( signalType >= 0 && signalType <= 2 );
......@@ -67,11 +69,16 @@ opus_int32 silk_NLSF_encode( /* O Returns
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
/* First stage: VQ */
ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 );
silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
/* Sort the quantization errors */
ALLOC( tempIndices1, nSurvivors, opus_int );
silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
ALLOC( RD_Q25, nSurvivors, opus_int32 );
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
/* Loop over survivors */
for( s = 0; s < nSurvivors; s++ ) {
ind1 = tempIndices1[ s ];
......@@ -125,4 +132,5 @@ opus_int32 silk_NLSF_encode( /* O Returns
silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
return RD_Q25[ 0 ];
RESTORE_STACK;
}
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
static inline void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
......@@ -88,11 +89,12 @@ void silk_NSQ(
opus_int k, lag, start_idx, LSF_interpolation_flag;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
VARDECL( opus_int32, x_sc_Q10 );
SAVE_STACK;
NSQ->rand_seed = psIndices->Seed;
......@@ -109,6 +111,10 @@ void silk_NSQ(
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15,
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
......@@ -160,6 +166,7 @@ void silk_NSQ(
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/***********************************/
......
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
......@@ -54,6 +55,8 @@ typedef struct {
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
typedef NSQ_sample_struct NSQ_sample_pair[ 2 ];
static inline void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
......@@ -123,17 +126,18 @@ void silk_NSQ_del_dec(
{
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
opus_int last_smple_idx, smpl_buf_idx, decisionDelay;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
opus_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
opus_int32 RDmin_Q10, Gain_Q10;
opus_int32 x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
opus_int32 delayedGain_Q10[ DECISION_DELAY ];
NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ];
VARDECL( opus_int32, x_sc_Q10 );
VARDECL( opus_int32, delayedGain_Q10 );
VARDECL( NSQ_del_dec_struct, psDelDec );
NSQ_del_dec_struct *psDD;
SAVE_STACK;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
......@@ -141,6 +145,7 @@ void silk_NSQ_del_dec(
silk_assert( NSQ->prev_gain_Q16 != 0 );
/* Initialize delayed decision states */
ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct );
silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
......@@ -175,6 +180,11 @@ void silk_NSQ_del_dec(
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15,
psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
/* Set up pointers to start of sub frame */
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
......@@ -287,6 +297,7 @@ void silk_NSQ_del_dec(
/* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/******************************************/
......@@ -328,11 +339,13 @@ static inline void silk_noise_shape_quantizer_del_dec(
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
VARDECL( NSQ_sample_pair, psSampleState );
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
SAVE_STACK;
silk_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
......@@ -614,6 +627,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
psDD = &psDelDec[ k ];
silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
RESTORE_STACK;
}
static inline void silk_nsq_del_dec_scale_states(
......
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
/* Silk VAD noise level estimation */
static inline void silk_VAD_GetNoiseLevels(
......@@ -82,15 +83,19 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
)
{
opus_int SA_Q15, pSNR_dB_Q7, input_tilt;
opus_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
opus_int decimated_framelength1, decimated_framelength2;
opus_int decimated_framelength;
opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
opus_int32 sumSquared, smooth_coef_Q16;
opus_int16 HPstateTmp;
opus_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ];
VARDECL( opus_int16, X );
opus_int32 Xnrg[ VAD_N_BANDS ];
opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
opus_int32 speech_nrg, x_tmp;
opus_int X_offset[ VAD_N_BANDS ];
opus_int ret = 0;
silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
SAVE_STACK;
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
......@@ -101,26 +106,46 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
/***********************/
/* Filter and Decimate */
/***********************/
decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
/* Decimate into 4 bands:
0 L 3L L 3L 5L
- -- - -- --
8 8 2 4 4
[0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz |
They're arranged to allow the minimal ( frame_length / 4 ) extra
scratch space during the downsampling process */
X_offset[ 0 ] = 0;
X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length );
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ],
X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */
silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 1 ) );
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */
silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 2 ) );
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
/*********************************************/
/* HP filter on lowest band (differentiator) */
/*********************************************/
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
X[ 0 ][ decimated_framelength - 1 ] = silk_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 );
HPstateTmp = X[ 0 ][ decimated_framelength - 1 ];
X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
HPstateTmp = X[ decimated_framelength - 1 ];
for( i = decimated_framelength - 1; i > 0; i-- ) {
X[ 0 ][ i - 1 ] = silk_RSHIFT( X[ 0 ][ i - 1 ], 1 );
X[ 0 ][ i ] -= X[ 0 ][ i - 1 ];
X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 );
X[ i ] -= X[ i - 1 ];
}
X[ 0 ][ 0 ] -= psSilk_VAD->HPstate;
X[ 0 ] -= psSilk_VAD->HPstate;
psSilk_VAD->HPstate = HPstateTmp;
/*************************************/
......@@ -142,7 +167,8 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
for( i = 0; i < dec_subframe_length; i++ ) {
/* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
x_tmp = silk_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 );
x_tmp = silk_RSHIFT(
X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
/* Safety check */
......@@ -264,6 +290,7 @@ opus_int silk_VAD_GetSA_Q8( /* O Return v
}
return( ret );
RESTORE_STACK;
}
/**************************/
......
......@@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "main_FLP.h"
#define silk_encoder_state_Fxx silk_encoder_state_FLP
#endif
#include "stack_alloc.h"
#include "tuning_parameters.h"
#include "pitch_est_defines.h"
......@@ -138,6 +139,7 @@ static opus_int silk_setup_resamplers(
{
opus_int ret = SILK_NO_ERROR;
opus_int32 nSamples_temp;
SAVE_STACK;
if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz )
{
......@@ -145,35 +147,38 @@ static opus_int silk_setup_resamplers(
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 );
} else {
/* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */
opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ];
silk_resampler_state_struct temp_resampler_state;
VARDECL( opus_int16, x_buf_API_fs_Hz );
VARDECL( silk_resampler_state_struct, temp_resampler_state );
#ifdef FIXED_POINT
opus_int16 *x_bufFIX = psEnc->x_buf;
#else
opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];
VARDECL( opus_int16, x_bufFIX );
#endif
opus_int32 nAPI_Samples_temp;
nSamples_temp = silk_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;
#ifndef FIXED_POINT
ALLOC( x_bufFIX, nSamples_temp, opus_int16 );
silk_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp );
#endif
/* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 );
ALLOC( temp_resampler_state, 1, silk_resampler_state_struct );
ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 );
/* Temporary resampling of x_buf data to API_fs_Hz */
ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
/* Calculate number of samples to temporarily upsample */
nAPI_Samples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
/* Calculate number of samples that has been temporarily upsampled */
nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
/* Temporary resampling of x_buf data to API_fs_Hz */
ALLOC( x_buf_API_fs_Hz, nAPI_Samples_temp, opus_int16 );
ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 );
/* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */
ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp );
ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nAPI_Samples_temp );
#ifndef FIXED_POINT
silk_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz );
......@@ -183,6 +188,7 @@ static opus_int silk_setup_resamplers(
psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
RESTORE_STACK;
return ret;
}
......
......@@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "API.h"
#include "control.h"
#include "typedef.h"
#include "stack_alloc.h"
#include "structs.h"
#include "tuning_parameters.h"
#ifdef FIXED_POINT
......@@ -146,18 +147,21 @@ opus_int silk_Encode( /* O Returns error co
)
{
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
opus_int nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;
opus_int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms;
opus_int nSamplesFromInput = 0, nSamplesFromInputMax;
opus_int speech_act_thr_for_switch_Q8;
opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum;
silk_encoder *psEnc = ( silk_encoder * )encState;
opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
VARDECL( opus_int16, buf );
opus_int transition, curr_block, tot_blocks;
SAVE_STACK;
psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
/* Check values in encoder control structure */
if( ( ret = check_control_input( encControl ) != 0 ) ) {
silk_assert( 0 );
RESTORE_STACK;
return ret;
}
......@@ -192,6 +196,7 @@ opus_int silk_Encode( /* O Returns error co
/* Only accept input length of 10 ms */
if( nBlocksOf10ms != 1 ) {
silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
/* Reset Encoder */
......@@ -212,11 +217,13 @@ opus_int silk_Encode( /* O Returns error co
/* Only accept input lengths that are a multiple of 10 ms */
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
/* Make sure no more than one packet can be produced */
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
silk_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
}
......@@ -227,6 +234,7 @@ opus_int silk_Encode( /* O Returns error co
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
silk_assert( 0 );
RESTORE_STACK;
return ret;
}
if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) {
......@@ -239,9 +247,16 @@ opus_int silk_Encode( /* O Returns error co
silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
/* Input buffering/resampling and encoding */
nSamplesToBufferMax =
10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz;
nSamplesFromInputMax =
silk_DIV32_16( nSamplesToBufferMax *
psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz,
psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 );
ALLOC( buf, nSamplesFromInputMax, opus_int16 );
while( 1 ) {
nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx;
nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz );
nSamplesToBuffer = silk_min( nSamplesToBuffer, nSamplesToBufferMax );
nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 );
/* Resample and write to buffer */
if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
......@@ -530,6 +545,7 @@ opus_int silk_Encode( /* O Returns error co
}
}
RESTORE_STACK;
return ret;
}
......@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
#include "main.h"
#include "stack_alloc.h"
/*********************************************/
/* Encode quantization indices of excitation */
......@@ -66,14 +67,15 @@ void silk_encode_pulses(
{
opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
opus_int32 abs_q, minSumBits_Q5, sumBits_Q5;
opus_int abs_pulses[ MAX_FRAME_LENGTH ];
opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ];
opus_int nRshifts[ MAX_NB_SHELL_BLOCKS ];
VARDECL( opus_int, abs_pulses );
VARDECL( opus_int, sum_pulses );
VARDECL( opus_int, nRshifts );
opus_int pulses_comb[ 8 ];
opus_int *abs_pulses_ptr;
const opus_int8 *pulses_ptr;
const opus_uint8 *cdf_ptr;
const opus_uint8 *nBits_ptr;
SAVE_STACK;
silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/
......@@ -90,6 +92,8 @@ void silk_encode_pulses(
}
/* Take the absolute value of the pulses */
ALLOC( abs_pulses, iter * SHELL_CODEC_FRAME_LENGTH, opus_int );
silk_assert( !( SHELL_CODEC_FRAME_LENGTH & 3 ) );
for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) {
abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] );
abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] );
......@@ -98,6 +102,8 @@ void silk_encode_pulses(
}
/* Calc sum pulses per shell code frame */
ALLOC( sum_pulses, iter, opus_int );
ALLOC( nRshifts, iter, opus_int );
abs_pulses_ptr = abs_pulses;
for( i = 0; i < iter; i++ ) {