| /* | |
| * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "modules/audio_coding/codecs/isac/main/source/isac_vad.h" | |
| #include <math.h> | |
| void WebRtcIsac_InitPitchFilter(PitchFiltstr* pitchfiltdata) { | |
| int k; | |
| for (k = 0; k < PITCH_BUFFSIZE; k++) { | |
| pitchfiltdata->ubuf[k] = 0.0; | |
| } | |
| pitchfiltdata->ystate[0] = 0.0; | |
| for (k = 1; k < (PITCH_DAMPORDER); k++) { | |
| pitchfiltdata->ystate[k] = 0.0; | |
| } | |
| pitchfiltdata->oldlagp[0] = 50.0; | |
| pitchfiltdata->oldgainp[0] = 0.0; | |
| } | |
| static void WebRtcIsac_InitWeightingFilter(WeightFiltstr* wfdata) { | |
| int k; | |
| double t, dtmp, dtmp2, denum, denum2; | |
| for (k = 0; k < PITCH_WLPCBUFLEN; k++) | |
| wfdata->buffer[k] = 0.0; | |
| for (k = 0; k < PITCH_WLPCORDER; k++) { | |
| wfdata->istate[k] = 0.0; | |
| wfdata->weostate[k] = 0.0; | |
| wfdata->whostate[k] = 0.0; | |
| } | |
| /* next part should be in Matlab, writing to a global table */ | |
| t = 0.5; | |
| denum = 1.0 / ((double)PITCH_WLPCWINLEN); | |
| denum2 = denum * denum; | |
| for (k = 0; k < PITCH_WLPCWINLEN; k++) { | |
| dtmp = PITCH_WLPCASYM * t * denum + (1 - PITCH_WLPCASYM) * t * t * denum2; | |
| dtmp *= 3.14159265; | |
| dtmp2 = sin(dtmp); | |
| wfdata->window[k] = dtmp2 * dtmp2; | |
| t++; | |
| } | |
| } | |
| void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct* State) { | |
| int k; | |
| for (k = 0; k < PITCH_CORR_LEN2 + PITCH_CORR_STEP2 + PITCH_MAX_LAG / 2 - | |
| PITCH_FRAME_LEN / 2 + 2; | |
| k++) | |
| State->dec_buffer[k] = 0.0; | |
| for (k = 0; k < 2 * ALLPASSSECTIONS + 1; k++) | |
| State->decimator_state[k] = 0.0; | |
| for (k = 0; k < 2; k++) | |
| State->hp_state[k] = 0.0; | |
| for (k = 0; k < QLOOKAHEAD; k++) | |
| State->whitened_buf[k] = 0.0; | |
| for (k = 0; k < QLOOKAHEAD; k++) | |
| State->inbuf[k] = 0.0; | |
| WebRtcIsac_InitPitchFilter(&(State->PFstr_wght)); | |
| WebRtcIsac_InitPitchFilter(&(State->PFstr)); | |
| WebRtcIsac_InitWeightingFilter(&(State->Wghtstr)); | |
| } | |
| void WebRtcIsac_InitPreFilterbank(PreFiltBankstr* prefiltdata) { | |
| int k; | |
| for (k = 0; k < QLOOKAHEAD; k++) { | |
| prefiltdata->INLABUF1[k] = 0; | |
| prefiltdata->INLABUF2[k] = 0; | |
| prefiltdata->INLABUF1_float[k] = 0; | |
| prefiltdata->INLABUF2_float[k] = 0; | |
| } | |
| for (k = 0; k < 2 * (QORDER - 1); k++) { | |
| prefiltdata->INSTAT1[k] = 0; | |
| prefiltdata->INSTAT2[k] = 0; | |
| prefiltdata->INSTATLA1[k] = 0; | |
| prefiltdata->INSTATLA2[k] = 0; | |
| prefiltdata->INSTAT1_float[k] = 0; | |
| prefiltdata->INSTAT2_float[k] = 0; | |
| prefiltdata->INSTATLA1_float[k] = 0; | |
| prefiltdata->INSTATLA2_float[k] = 0; | |
| } | |
| /* High pass filter states */ | |
| prefiltdata->HPstates[0] = 0.0; | |
| prefiltdata->HPstates[1] = 0.0; | |
| prefiltdata->HPstates_float[0] = 0.0f; | |
| prefiltdata->HPstates_float[1] = 0.0f; | |
| return; | |
| } | |
| double WebRtcIsac_LevDurb(double* a, double* k, double* r, size_t order) { | |
| const double LEVINSON_EPS = 1.0e-10; | |
| double sum, alpha; | |
| size_t m, m_h, i; | |
| alpha = 0; // warning -DH | |
| a[0] = 1.0; | |
| if (r[0] < LEVINSON_EPS) { /* if r[0] <= 0, set LPC coeff. to zero */ | |
| for (i = 0; i < order; i++) { | |
| k[i] = 0; | |
| a[i + 1] = 0; | |
| } | |
| } else { | |
| a[1] = k[0] = -r[1] / r[0]; | |
| alpha = r[0] + r[1] * k[0]; | |
| for (m = 1; m < order; m++) { | |
| sum = r[m + 1]; | |
| for (i = 0; i < m; i++) { | |
| sum += a[i + 1] * r[m - i]; | |
| } | |
| k[m] = -sum / alpha; | |
| alpha += k[m] * sum; | |
| m_h = (m + 1) >> 1; | |
| for (i = 0; i < m_h; i++) { | |
| sum = a[i + 1] + k[m] * a[m - i]; | |
| a[m - i] += k[m] * a[i + 1]; | |
| a[i + 1] = sum; | |
| } | |
| a[m + 1] = k[m]; | |
| } | |
| } | |
| return alpha; | |
| } | |
| /* The upper channel all-pass filter factors */ | |
| const float WebRtcIsac_kUpperApFactorsFloat[2] = {0.03470000000000f, | |
| 0.38260000000000f}; | |
| /* The lower channel all-pass filter factors */ | |
| const float WebRtcIsac_kLowerApFactorsFloat[2] = {0.15440000000000f, | |
| 0.74400000000000f}; | |
| /* This function performs all-pass filtering--a series of first order all-pass | |
| * sections are used to filter the input in a cascade manner. | |
| * The input is overwritten!! | |
| */ | |
| void WebRtcIsac_AllPassFilter2Float(float* InOut, | |
| const float* APSectionFactors, | |
| int lengthInOut, | |
| int NumberOfSections, | |
| float* FilterState) { | |
| int n, j; | |
| float temp; | |
| for (j = 0; j < NumberOfSections; j++) { | |
| for (n = 0; n < lengthInOut; n++) { | |
| temp = FilterState[j] + APSectionFactors[j] * InOut[n]; | |
| FilterState[j] = -APSectionFactors[j] * temp + InOut[n]; | |
| InOut[n] = temp; | |
| } | |
| } | |
| } | |
| /* The number of composite all-pass filter factors */ | |
| #define NUMBEROFCOMPOSITEAPSECTIONS 4 | |
| /* Function WebRtcIsac_SplitAndFilter | |
| * This function creates low-pass and high-pass decimated versions of part of | |
| the input signal, and part of the signal in the input 'lookahead buffer'. | |
| INPUTS: | |
| in: a length FRAMESAMPLES array of input samples | |
| prefiltdata: input data structure containing the filterbank states | |
| and lookahead samples from the previous encoding | |
| iteration. | |
| OUTPUTS: | |
| LP: a FRAMESAMPLES_HALF array of low-pass filtered samples that | |
| have been phase equalized. The first QLOOKAHEAD samples are | |
| based on the samples in the two prefiltdata->INLABUFx arrays | |
| each of length QLOOKAHEAD. | |
| The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based | |
| on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input | |
| array in[]. | |
| HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that | |
| have been phase equalized. The first QLOOKAHEAD samples are | |
| based on the samples in the two prefiltdata->INLABUFx arrays | |
| each of length QLOOKAHEAD. | |
| The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based | |
| on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input | |
| array in[]. | |
| LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples. | |
| These samples are not phase equalized. They are computed | |
| from the samples in the in[] array. | |
| HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples | |
| that are not phase equalized. They are computed from | |
| the in[] vector. | |
| prefiltdata: this input data structure's filterbank state and | |
| lookahead sample buffers are updated for the next | |
| encoding iteration. | |
| */ | |
| void WebRtcIsac_SplitAndFilterFloat(float* pin, | |
| float* LP, | |
| float* HP, | |
| double* LP_la, | |
| double* HP_la, | |
| PreFiltBankstr* prefiltdata) { | |
| int k, n; | |
| float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS]; | |
| float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS]; | |
| float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS]; | |
| float tempinoutvec[FRAMESAMPLES + MAX_AR_MODEL_ORDER]; | |
| float tempin_ch1[FRAMESAMPLES + MAX_AR_MODEL_ORDER]; | |
| float tempin_ch2[FRAMESAMPLES + MAX_AR_MODEL_ORDER]; | |
| float in[FRAMESAMPLES]; | |
| float ftmp; | |
| /* HPstcoeff_in = {a1, a2, b1 - b0 * a1, b2 - b0 * a2}; */ | |
| static const float kHpStCoefInFloat[4] = { | |
| -1.94895953203325f, 0.94984516000000f, -0.05101826139794f, | |
| 0.05015484000000f}; | |
| /* The composite all-pass filter factors */ | |
| static const float WebRtcIsac_kCompositeApFactorsFloat[4] = { | |
| 0.03470000000000f, 0.15440000000000f, 0.38260000000000f, | |
| 0.74400000000000f}; | |
| // The matrix for transforming the backward composite state to upper channel | |
| // state. | |
| static const float WebRtcIsac_kTransform1Float[8] = { | |
| -0.00158678506084f, 0.00127157815343f, -0.00104805672709f, | |
| 0.00084837248079f, 0.00134467983258f, -0.00107756549387f, | |
| 0.00088814793277f, -0.00071893072525f}; | |
| // The matrix for transforming the backward composite state to lower channel | |
| // state. | |
| static const float WebRtcIsac_kTransform2Float[8] = { | |
| -0.00170686041697f, 0.00136780109829f, -0.00112736532350f, | |
| 0.00091257055385f, 0.00103094281812f, -0.00082615076557f, | |
| 0.00068092756088f, -0.00055119165484f}; | |
| /* High pass filter */ | |
| for (k = 0; k < FRAMESAMPLES; k++) { | |
| in[k] = pin[k] + kHpStCoefInFloat[2] * prefiltdata->HPstates_float[0] + | |
| kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1]; | |
| ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] - | |
| kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1]; | |
| prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0]; | |
| prefiltdata->HPstates_float[0] = ftmp; | |
| } | |
| /* First Channel */ | |
| /*initial state of composite filter is zero */ | |
| for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) { | |
| CompositeAPFilterState[k] = 0.0; | |
| } | |
| /* put every other sample of input into a temporary vector in reverse | |
| * (backward) order*/ | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| tempinoutvec[k] = in[FRAMESAMPLES - 1 - 2 * k]; | |
| } | |
| /* now all-pass filter the backwards vector. Output values overwrite the | |
| * input vector. */ | |
| WebRtcIsac_AllPassFilter2Float( | |
| tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, FRAMESAMPLES_HALF, | |
| NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | |
| /* save the backwards filtered output for later forward filtering, | |
| but write it in forward order*/ | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| tempin_ch1[FRAMESAMPLES_HALF + QLOOKAHEAD - 1 - k] = tempinoutvec[k]; | |
| } | |
| /* save the backwards filter state becaue it will be transformed | |
| later into a forward state */ | |
| for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) { | |
| ForTransform_CompositeAPFilterState[k] = CompositeAPFilterState[k]; | |
| } | |
| /* now backwards filter the samples in the lookahead buffer. The samples were | |
| placed there in the encoding of the previous frame. The output samples | |
| overwrite the input samples */ | |
| WebRtcIsac_AllPassFilter2Float( | |
| prefiltdata->INLABUF1_float, WebRtcIsac_kCompositeApFactorsFloat, | |
| QLOOKAHEAD, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | |
| /* save the output, but write it in forward order */ | |
| /* write the lookahead samples for the next encoding iteration. Every other | |
| sample at the end of the input frame is written in reverse order for the | |
| lookahead length. Exported in the prefiltdata structure. */ | |
| for (k = 0; k < QLOOKAHEAD; k++) { | |
| tempin_ch1[QLOOKAHEAD - 1 - k] = prefiltdata->INLABUF1_float[k]; | |
| prefiltdata->INLABUF1_float[k] = in[FRAMESAMPLES - 1 - 2 * k]; | |
| } | |
| /* Second Channel. This is exactly like the first channel, except that the | |
| even samples are now filtered instead (lower channel). */ | |
| for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) { | |
| CompositeAPFilterState[k] = 0.0; | |
| } | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| tempinoutvec[k] = in[FRAMESAMPLES - 2 - 2 * k]; | |
| } | |
| WebRtcIsac_AllPassFilter2Float( | |
| tempinoutvec, WebRtcIsac_kCompositeApFactorsFloat, FRAMESAMPLES_HALF, | |
| NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| tempin_ch2[FRAMESAMPLES_HALF + QLOOKAHEAD - 1 - k] = tempinoutvec[k]; | |
| } | |
| for (k = 0; k < NUMBEROFCOMPOSITEAPSECTIONS; k++) { | |
| ForTransform_CompositeAPFilterState2[k] = CompositeAPFilterState[k]; | |
| } | |
| WebRtcIsac_AllPassFilter2Float( | |
| prefiltdata->INLABUF2_float, WebRtcIsac_kCompositeApFactorsFloat, | |
| QLOOKAHEAD, NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState); | |
| for (k = 0; k < QLOOKAHEAD; k++) { | |
| tempin_ch2[QLOOKAHEAD - 1 - k] = prefiltdata->INLABUF2_float[k]; | |
| prefiltdata->INLABUF2_float[k] = in[FRAMESAMPLES - 2 - 2 * k]; | |
| } | |
| /* Transform filter states from backward to forward */ | |
| /*At this point, each of the states of the backwards composite filters for the | |
| two channels are transformed into forward filtering states for the | |
| corresponding forward channel filters. Each channel's forward filtering | |
| state from the previous | |
| encoding iteration is added to the transformed state to get a proper forward | |
| state */ | |
| /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is | |
| multiplied by a NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4) | |
| transform matrix to get the new state that is added to the previous 2x1 | |
| input state */ | |
| for (k = 0; k < NUMBEROFCHANNELAPSECTIONS; k++) { /* k is row variable */ | |
| for (n = 0; n < NUMBEROFCOMPOSITEAPSECTIONS; | |
| n++) { /* n is column variable */ | |
| prefiltdata->INSTAT1_float[k] += | |
| ForTransform_CompositeAPFilterState[n] * | |
| WebRtcIsac_kTransform1Float[k * NUMBEROFCHANNELAPSECTIONS + n]; | |
| prefiltdata->INSTAT2_float[k] += | |
| ForTransform_CompositeAPFilterState2[n] * | |
| WebRtcIsac_kTransform2Float[k * NUMBEROFCHANNELAPSECTIONS + n]; | |
| } | |
| } | |
| /*obtain polyphase components by forward all-pass filtering through each | |
| * channel */ | |
| /* the backward filtered samples are now forward filtered with the | |
| * corresponding channel filters */ | |
| /* The all pass filtering automatically updates the filter states which are | |
| exported in the prefiltdata structure */ | |
| WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kUpperApFactorsFloat, | |
| FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, | |
| prefiltdata->INSTAT1_float); | |
| WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kLowerApFactorsFloat, | |
| FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, | |
| prefiltdata->INSTAT2_float); | |
| /* Now Construct low-pass and high-pass signals as combinations of polyphase | |
| * components */ | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| LP[k] = 0.5f * (tempin_ch1[k] + tempin_ch2[k]); /* low pass signal*/ | |
| HP[k] = 0.5f * (tempin_ch1[k] - tempin_ch2[k]); /* high pass signal*/ | |
| } | |
| /* Lookahead LP and HP signals */ | |
| /* now create low pass and high pass signals of the input vector. However, no | |
| backwards filtering is performed, and hence no phase equalization is | |
| involved. Also, the input contains some samples that are lookahead samples. | |
| The high pass and low pass signals that are created are used outside this | |
| function for analysis (not encoding) purposes */ | |
| /* set up input */ | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| tempin_ch1[k] = in[2 * k + 1]; | |
| tempin_ch2[k] = in[2 * k]; | |
| } | |
| /* the input filter states are passed in and updated by the all-pass filtering | |
| routine and exported in the prefiltdata structure*/ | |
| WebRtcIsac_AllPassFilter2Float(tempin_ch1, WebRtcIsac_kUpperApFactorsFloat, | |
| FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, | |
| prefiltdata->INSTATLA1_float); | |
| WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kLowerApFactorsFloat, | |
| FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, | |
| prefiltdata->INSTATLA2_float); | |
| for (k = 0; k < FRAMESAMPLES_HALF; k++) { | |
| LP_la[k] = (float)(0.5f * (tempin_ch1[k] + tempin_ch2[k])); /*low pass */ | |
| HP_la[k] = (double)(0.5f * (tempin_ch1[k] - tempin_ch2[k])); /* high pass */ | |
| } | |
| } |