/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include #include "stat_dec.h" #include "prot.h" #include "rom_com.h" #include "string.h" #include #if defined __ICL #define restrict __restrict #else #define restrict #endif #ifdef _MSC_VER #pragma warning(disable : 4305) /* disable truncation from double to float warning (VC++)*/ #endif /*-------------------------------------------------------------------* * local prototypes *--------------------------------------------------------------------*/ static void cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs); static float GetEnergyCldfb( float *energyValuesSum, float *energyLookahead, float **realValues, float **imagValues, int numberBands, int numberCols, HANDLE_TEC_ENC hTecEnc ); /*-------------------------------------------------------------------* * cplxMult() * * Conduct complex multiplication *--------------------------------------------------------------------*/ static void cplxMult( float *yr, /* o : real output */ float *yi, /* o : imag output */ float xr, /* i : real input 1*/ float xi, /* i : imag input 1*/ float cr, /* i : real input 1*/ float ci /* i : imag input 1*/ ) { *yr = xr*cr - xi*ci; *yi = xr*ci + xi*cr; return; } /*-------------------------------------------------------------------* * cldfbAnalysis() * * Conduct multple overlap cmplex low delay MDCT *--------------------------------------------------------------------*/ void cldfbAnalysis( const float *timeIn, /* i : time buffer */ float **realBuffer, /* o : real value buffer */ float **imagBuffer, /* o : imag value buffer */ int samplesToProcess, /* i : samples to process */ HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */ ) { short i, k; short L2, M1, M2, M4; short no_col = h_cldfb->no_col; float r1, r2, rr12, ir12; float i1, i2, ri12, ii12; float rBuffer[2*CLDFB_NO_CHANNELS_MAX]; float iBuffer[2*CLDFB_NO_CHANNELS_MAX]; const float *rot_vctr_re; const float *rot_vctr_im; const float *ptr_pf; float *timeBuffer = h_cldfb->cldfb_state; int offset = h_cldfb->p_filter_length - h_cldfb->no_channels; int frameSize = h_cldfb->no_channels * h_cldfb->no_col; /* prepare input buffer */ mvr2r( timeBuffer + frameSize, timeBuffer, offset ); if( samplesToProcess > -1 ) { mvr2r( timeIn, timeBuffer + offset, samplesToProcess ); set_f( timeBuffer+offset+samplesToProcess, 0.0f, (frameSize-samplesToProcess) ); } else { mvr2r( timeIn, timeBuffer + offset, frameSize ); } /* only process needed cols */ if( samplesToProcess > -1 ) { no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels); } M1 = h_cldfb->no_channels; M2 = M1 >> 1; M4 = M1 >> 2; L2 = M1 << 1; if( M2 & 1 ) { M4 += 1; } rot_vctr_re = h_cldfb->rot_vec_ana_re; rot_vctr_im = h_cldfb->rot_vec_ana_im; ptr_pf = h_cldfb->p_filter; for( i = 0; i < no_col; i++ ) { for (k=0; k < M4; k++ ) { /* prototype filter */ r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2]; r2 = 0 - ptr_pf[(L2-M2+(2*k) + 0 * L2)] * timeBuffer[L2-M2+(2*k) + 0 * L2]; r2 = r2 - ptr_pf[(L2-M2+(2*k) + 1 * L2)] * timeBuffer[L2-M2+(2*k) + 1 * L2]; r2 = r2 - ptr_pf[(L2-M2+(2*k) + 2 * L2)] * timeBuffer[L2-M2+(2*k) + 2 * L2]; r2 = r2 - ptr_pf[(L2-M2+(2*k) + 3 * L2)] * timeBuffer[L2-M2+(2*k) + 3 * L2]; r2 = r2 - ptr_pf[(L2-M2+(2*k) + 4 * L2)] * timeBuffer[L2-M2+(2*k) + 4 * L2]; i1 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2]; i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2]; i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2]; i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2]; i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2]; i2 = 0 - ptr_pf[(L2-3*M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 0 * L2]; i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 1 * L2]; i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 2 * L2]; i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 3 * L2]; i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 4 * L2]; /* folding + pre modulation of DST IV */ rr12 = r1 - r2; ri12 = -i1 - i2; cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]); /* folding + pre modulation of DCT IV */ ir12 = r1 + r2; ii12 = i1 - i2; cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]); } for (k=M4; k < M2; k++) { /* prototype filter */ r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2]; r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2]; r2 = 0 - ptr_pf[(L2-5*M2+(2*k) + 0 * L2)] * timeBuffer[L2-5*M2+(2*k) + 0 * L2]; r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 1 * L2)] * timeBuffer[L2-5*M2+(2*k) + 1 * L2]; r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 2 * L2)] * timeBuffer[L2-5*M2+(2*k) + 2 * L2]; r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 3 * L2)] * timeBuffer[L2-5*M2+(2*k) + 3 * L2]; r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 4 * L2)] * timeBuffer[L2-5*M2+(2*k) + 4 * L2]; i1 = 0 - ptr_pf[(L2+M2-1-(2*k) + 0 * L2)] * timeBuffer[L2+M2-1-(2*k) + 0 * L2]; i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 1 * L2)] * timeBuffer[L2+M2-1-(2*k) + 1 * L2]; i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 2 * L2)] * timeBuffer[L2+M2-1-(2*k) + 2 * L2]; i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 3 * L2)] * timeBuffer[L2+M2-1-(2*k) + 3 * L2]; i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 4 * L2)] * timeBuffer[L2+M2-1-(2*k) + 4 * L2]; i2 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2]; i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2]; i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2]; i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2]; i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2]; /* folding + pre modulation of DST IV */ rr12 = r1 + r2; ri12 = i1 - i2; cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]); /* folding + pre modulation of DCT IV */ ir12 = r1 - r2; ii12 = i1 + i2; cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]); } /* FFT of DST IV */ fft_cldfb(rBuffer, M2); /* post modulation of DST IV */ for (k=0; k < M2; k++) { cplxMult(&realBuffer[i][M1-1-(2*k)],&realBuffer[i][2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]); } /* FFT of DCT IV */ fft_cldfb(iBuffer, M2); /* post modulation of DCT IV */ for (k=0; k < M2; k++) { /* do it inplace */ cplxMult(&imagBuffer[i][2*k],&imagBuffer[i][M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]); } timeBuffer += L2 * 5; timeBuffer += h_cldfb->no_channels - h_cldfb->p_filter_length; } return; } /*-------------------------------------------------------------------* * cldfbSynthesis() * * Conduct inverse multple overlap cmplex low delay MDCT *--------------------------------------------------------------------*/ void cldfbSynthesis( float **realBuffer, /* i : real values */ float **imagBuffer, /* i : imag values */ float *timeOut, /* o : output time domain samples */ int samplesToProcess, /* i : number of processed samples */ HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */ ) { int i; int k; int L2; int M1; int M2; int M41; int M42; int Mz; float rBuffer[2*CLDFB_NO_CHANNELS_MAX]; float iBuffer[2*CLDFB_NO_CHANNELS_MAX]; const float *rot_vctr_re; const float *rot_vctr_im; float rr12, ir12; float ri12, ii12; float *synthesisBuffer; float new_samples[2*CLDFB_NO_CHANNELS_MAX]; float *ptr_time_out; const float *p_filter; float accu0, accu1, accu2, accu3, accu4; int no_col = h_cldfb->no_col; M1 = h_cldfb->no_channels; L2 = M1 << 1; M2 = M1 >> 1; M41 = M2>>1; M42 = M2-M41; Mz = M1 - h_cldfb->bandsToZero; /* only process needed cols */ if(samplesToProcess > -1) { no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels); } rot_vctr_re = h_cldfb->rot_vec_syn_re; rot_vctr_im = h_cldfb->rot_vec_syn_im; synthesisBuffer = h_cldfb->cldfb_state; p_filter = h_cldfb->p_filter; ptr_time_out = timeOut; mvr2r( synthesisBuffer, synthesisBuffer + M1 * h_cldfb->no_col, h_cldfb->p_filter_length ); synthesisBuffer += M1 * h_cldfb->no_col; for (k=0; k < no_col; k++) { for (i=Mz; i < M1; i++) { realBuffer[k][i] = 0.0f; imagBuffer[k][i] = 0.0f; } for (i=0; i < M2; i++) { /* pre modulation of DST IV */ cplxMult(&rBuffer[2*i], &rBuffer[2*i+1], realBuffer[k][2*i], realBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]); /* pre modulation of DCT IV */ cplxMult(&iBuffer[2*i], &iBuffer[2*i+1],-imagBuffer[k][2*i], imagBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]); } /* FFT of DST IV */ fft_cldfb(rBuffer, M2); /* FFT of DCT IV */ fft_cldfb(iBuffer, M2); /* folding */ for (i=0; ino_col = CLDFB_NO_COL_MAX; h_cldfb->bandsToZero = 0; h_cldfb->nab = 0; h_cldfb->no_channels = samplerate * INV_CLDFB_BANDWIDTH + 0.5f; h_cldfb->p_filter_length = 10*h_cldfb->no_channels; cldfb_init_proto_and_twiddles (h_cldfb); h_cldfb->scale = 0.f; for ( k=0; kp_filter_length; k++ ) { h_cldfb->scale += h_cldfb->p_filter[k] * h_cldfb->p_filter[k]; } h_cldfb->scale *= (float)(6400/h_cldfb->no_channels); h_cldfb->scale = (float)sqrt( h_cldfb->scale ); return; } /*-------------------------------------------------------------------* * openClfdb() * * open and configures a CLDFB handle *--------------------------------------------------------------------*/ int openCldfb( HANDLE_CLDFB_FILTER_BANK *h_cldfb, /* i/o : filter bank handle */ CLDFB_TYPE type, /* i : analysis or synthesis */ int samplerate /* i : max samplerate to oeprate */ ) { HANDLE_CLDFB_FILTER_BANK hs; short buf_len; hs = (HANDLE_CLDFB_FILTER_BANK) calloc(1, sizeof (CLDFB_FILTER_BANK)); if( hs == NULL ) { return (1); } hs->type = type; configureCldfb (hs, samplerate); hs->memory = NULL; hs->memory_length = 0; if (type == CLDFB_ANALYSIS) { short timeOffset = hs->p_filter_length - hs->no_channels; buf_len = (hs->no_channels*hs->no_col+timeOffset); } else { buf_len = (hs->p_filter_length + hs->no_channels*hs->no_col); } hs->cldfb_state = (float *) calloc( buf_len, sizeof (float)); if (hs->cldfb_state == NULL) { return (1); } set_f(hs->cldfb_state, 0.0f, buf_len); *h_cldfb = hs; return (0); } /*-------------------------------------------------------------------* * resampleCldfb() * * Change sample rate of filter bank *--------------------------------------------------------------------*/ void resampleCldfb( HANDLE_CLDFB_FILTER_BANK hs, int newSamplerate ) { short timeOffset, newframeSize; /* keep old parameters before switching*/ int timeOffsetold = hs->p_filter_length - hs->no_channels; int old_no_channels = hs->no_channels; /* new settings */ configureCldfb (hs, newSamplerate); timeOffset = hs->p_filter_length - hs->no_channels; newframeSize = hs->no_channels * hs->no_col; /*low complexity-resampling only stored previous samples that are needed for next frame modulation */ lerp(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+(old_no_channels*hs->no_col),timeOffset, timeOffsetold); mvr2r(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+newframeSize,timeOffset); return; } /*-------------------------------------------------------------------* * analysisCLDFBEncoder() * * Encoder CLDFB analysis + energy stage *--------------------------------------------------------------------*/ void analysisCldfbEncoder( Encoder_State *st, /* i/o: encoder state structure */ const float *timeIn, int samplesToProcess, float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float *ppBuf_Ener ) { short i; float *ppBuf_Real[CLDFB_NO_COL_MAX]; float *ppBuf_Imag[CLDFB_NO_COL_MAX]; for( i=0; icldfbAnaEnc ); st->currEnergyHF = GetEnergyCldfb( ppBuf_Ener, &st->currEnergyLookAhead, ppBuf_Real, ppBuf_Imag, st->cldfbAnaEnc->no_channels, st->cldfbAnaEnc->no_col, &(st->tecEnc) ); return; } /*-------------------------------------------------------------------* * GetEnergyCldfb() * * Conduct energy from complex data *--------------------------------------------------------------------*/ static float GetEnergyCldfb( float *energyValuesSum,/*!< the result of the operation */ float *energyLookahead, /*!< the result in the core look-ahead slot */ float **realValues, /*!< the real part of the subsamples */ float **imagValues, /*!< the imaginary part of the subsamples */ int numberBands, /*!< number of bands */ int numberCols, /*!< number of subsamples */ HANDLE_TEC_ENC hTecEnc ) { short j, k; float energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; short numLookahead = 1; for (k = 0; k < numberCols; k++) { for (j = 0; j < numberBands; j++) { energyValues[k][j] = realValues[k][j] * realValues[k][j] + imagValues[k][j] * imagValues[k][j]; } } if(numberBands >= freqTable[1]) { float *tempEnergyValuesArry[CLDFB_NO_COL_MAX]; assert(numberCols == CLDFB_NO_COL_MAX); for (j=0; jloBuffer, hTecEnc->hiTempEnv ); } for (j = 0; j < numberBands; j++) { energyValuesSum[j]=0; for (k = 0; k < CLDFB_NO_COL_MAX; k++) { energyValuesSum[j] += energyValues[k][j]; } } if (numberBands > 20) { float energyHF = *energyLookahead; /* energy above 8 kHz */ numberCols -= numLookahead; *energyLookahead = 6.1e-5f; /* process look-ahead region */ for (j = 20; j < min(40, numberBands); j++) { energyHF += energyValuesSum[j]; for (k = numberCols; k < CLDFB_NO_COL_MAX; k++) { energyHF -= energyValues[k][j]; *energyLookahead += energyValues[k][j]; } } return energyHF * OUTMAX_SQ_INV; } return 65535.0f; } /*-------------------------------------------------------------------* * GetEnergyCldfb() * * Remove handle *--------------------------------------------------------------------*/ void deleteCldfb( HANDLE_CLDFB_FILTER_BANK * h_cldfb ) { HANDLE_CLDFB_FILTER_BANK hs = *h_cldfb; if (hs) { if (hs->cldfb_state) { free(hs->cldfb_state); } free(hs); *h_cldfb = NULL; } return; } /*-------------------------------------------------------------------* * cldfb_init_proto_and_twiddles() * * Initializes rom pointer *--------------------------------------------------------------------*/ static void cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs ) { /*find appropriate set of rotVecs*/ switch(hs->no_channels) { case 10: hs->rot_vec_ana_re = rot_vec_ana_re_L10; hs->rot_vec_ana_im = rot_vec_ana_im_L10; hs->rot_vec_syn_re = rot_vec_syn_re_L10; hs->rot_vec_syn_im = rot_vec_syn_im_L10; hs->p_filter = CLDFB80_10; break; case 16: hs->rot_vec_ana_re = rot_vec_ana_re_L16; hs->rot_vec_ana_im = rot_vec_ana_im_L16; hs->rot_vec_syn_re = rot_vec_syn_re_L16; hs->rot_vec_syn_im = rot_vec_syn_im_L16; hs->p_filter = CLDFB80_16; break; case 20: hs->rot_vec_ana_re = rot_vec_ana_re_L20; hs->rot_vec_ana_im = rot_vec_ana_im_L20; hs->rot_vec_syn_re = rot_vec_syn_re_L20; hs->rot_vec_syn_im = rot_vec_syn_im_L20; hs->p_filter = CLDFB80_20; break; case 30: hs->rot_vec_ana_re = rot_vec_ana_re_L30; hs->rot_vec_ana_im = rot_vec_ana_im_L30; hs->rot_vec_syn_re = rot_vec_syn_re_L30; hs->rot_vec_syn_im = rot_vec_syn_im_L30; hs->p_filter = CLDFB80_30; break; case 32: hs->rot_vec_ana_re = rot_vec_ana_re_L32; hs->rot_vec_ana_im = rot_vec_ana_im_L32; hs->rot_vec_syn_re = rot_vec_syn_re_L32; hs->rot_vec_syn_im = rot_vec_syn_im_L32; hs->p_filter = CLDFB80_32; break; case 40: hs->rot_vec_ana_re = rot_vec_ana_re_L40; hs->rot_vec_ana_im = rot_vec_ana_im_L40; hs->rot_vec_syn_re = rot_vec_syn_re_L40; hs->rot_vec_syn_im = rot_vec_syn_im_L40; hs->p_filter = CLDFB80_40; break; case 60: hs->rot_vec_ana_re = rot_vec_ana_re_L60; hs->rot_vec_ana_im = rot_vec_ana_im_L60; hs->rot_vec_syn_re = rot_vec_syn_re_L60; hs->rot_vec_syn_im = rot_vec_syn_im_L60; hs->p_filter = CLDFB80_60; break; } return; } /*-------------------------------------------------------------------* * cldfb_save_memory() * * Save the memory of filter; to be restored with cldfb_restore_memory() *--------------------------------------------------------------------*/ int cldfb_save_memory( HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ ) { unsigned int offset = hs->p_filter_length - hs->no_channels; unsigned int frameSize = hs->no_channels * hs->no_col; if (hs->memory != NULL || hs->memory_length!=0) { /* memory already stored; Free memory first */ return 1; } if (hs->type == CLDFB_ANALYSIS) { hs->memory_length = offset + frameSize; } else { hs->memory_length = hs->p_filter_length; } hs->memory = (float *) calloc( hs->memory_length, sizeof (float)); if (hs->memory == NULL) { /* memory cannot be allocated */ return (1); } /* save the memory */ mvr2r (hs->cldfb_state, hs->memory, hs->memory_length); return 0; } /*-------------------------------------------------------------------* * cldfb_restore_memory() * * Restores the memory of filter; memory to be save by cldfb_save_memory() *--------------------------------------------------------------------*/ int cldfb_restore_memory( HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ ) { unsigned int offset = hs->p_filter_length - hs->no_channels; unsigned int frameSize = hs->no_channels * hs->no_col; unsigned int size; if (hs->memory == NULL || hs->memory_length==0) { /* memory not allocated */ return 1; } if ( hs->type == CLDFB_ANALYSIS ) { size = offset + frameSize; } else { size = hs->p_filter_length; } /* read the memory */ mvr2r (hs->memory, hs->cldfb_state, hs->memory_length); /* adjust sample rate if it was changed in the meanwhile */ if (hs->memory_length != size) { lerp(hs->cldfb_state, hs->cldfb_state, size, hs->memory_length); } hs->memory_length = 0; free(hs->memory); hs->memory = NULL; return 0; } /*-------------------------------------------------------------------* * cldfb_reset_memory() * * Resets the memory of filter. *--------------------------------------------------------------------*/ int cldfb_reset_memory( HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */ ) { unsigned int offset = hs->p_filter_length - hs->no_channels; unsigned int frameSize = hs->no_channels * hs->no_col; int memory_length; if (hs->type == CLDFB_ANALYSIS) { memory_length = offset + frameSize; } else { memory_length = hs->p_filter_length; } /* save the memory */ set_f (hs->cldfb_state, 0, memory_length); return 0; }