1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <memory.h> 12 #include <string.h> 13 #ifdef WEBRTC_ANDROID 14 #include <stdlib.h> 15 #endif 16 #include "pitch_estimator.h" 17 #include "lpc_analysis.h" 18 #include "codec.h" 19 20 21 22 void WebRtcIsac_AllPoleFilter(double* InOut, 23 double* Coef, 24 size_t lengthInOut, 25 int orderCoef) { 26 /* the state of filter is assumed to be in InOut[-1] to InOut[-orderCoef] */ 27 double scal; 28 double sum; 29 size_t n; 30 int k; 31 32 //if (fabs(Coef[0]-1.0)<0.001) { 33 if ( (Coef[0] > 0.9999) && (Coef[0] < 1.0001) ) 34 { 35 for(n = 0; n < lengthInOut; n++) 36 { 37 sum = Coef[1] * InOut[-1]; 38 for(k = 2; k <= orderCoef; k++){ 39 sum += Coef[k] * InOut[-k]; 40 } 41 *InOut++ -= sum; 42 } 43 } 44 else 45 { 46 scal = 1.0 / Coef[0]; 47 for(n=0;n<lengthInOut;n++) 48 { 49 *InOut *= scal; 50 for(k=1;k<=orderCoef;k++){ 51 *InOut -= scal*Coef[k]*InOut[-k]; 52 } 53 InOut++; 54 } 55 } 56 } 57 58 59 void WebRtcIsac_AllZeroFilter(double* In, 60 double* Coef, 61 size_t lengthInOut, 62 int orderCoef, 63 double* Out) { 64 /* the state of filter is assumed to be in In[-1] to In[-orderCoef] */ 65 66 size_t n; 67 int k; 68 double tmp; 69 70 for(n = 0; n < lengthInOut; n++) 71 { 72 tmp = In[0] * Coef[0]; 73 74 for(k = 1; k <= orderCoef; k++){ 75 tmp += Coef[k] * In[-k]; 76 } 77 78 *Out++ = tmp; 79 In++; 80 } 81 } 82 83 84 void WebRtcIsac_ZeroPoleFilter(double* In, 85 double* ZeroCoef, 86 double* PoleCoef, 87 size_t lengthInOut, 88 int orderCoef, 89 double* Out) { 90 /* the state of the zero section is assumed to be in In[-1] to In[-orderCoef] */ 91 /* the state of the pole section is assumed to be in Out[-1] to Out[-orderCoef] */ 92 93 WebRtcIsac_AllZeroFilter(In,ZeroCoef,lengthInOut,orderCoef,Out); 94 WebRtcIsac_AllPoleFilter(Out,PoleCoef,lengthInOut,orderCoef); 95 } 96 97 98 void WebRtcIsac_AutoCorr(double* r, const double* x, size_t N, size_t order) { 99 size_t lag, n; 100 double sum, prod; 101 const double *x_lag; 102 103 for (lag = 0; lag <= order; lag++) 104 { 105 sum = 0.0f; 106 x_lag = &x[lag]; 107 prod = x[0] * x_lag[0]; 108 for (n = 1; n < N - lag; n++) { 109 sum += prod; 110 prod = x[n] * x_lag[n]; 111 } 112 sum += prod; 113 r[lag] = sum; 114 } 115 116 } 117 118 119 void WebRtcIsac_BwExpand(double* out, double* in, double coef, size_t length) { 120 size_t i; 121 double chirp; 122 123 chirp = coef; 124 125 out[0] = in[0]; 126 for (i = 1; i < length; i++) { 127 out[i] = chirp * in[i]; 128 chirp *= coef; 129 } 130 } 131 132 void WebRtcIsac_WeightingFilter(const double* in, 133 double* weiout, 134 double* whiout, 135 WeightFiltstr* wfdata) { 136 double tmpbuffer[PITCH_FRAME_LEN + PITCH_WLPCBUFLEN]; 137 double corr[PITCH_WLPCORDER+1], rc[PITCH_WLPCORDER+1]; 138 double apol[PITCH_WLPCORDER+1], apolr[PITCH_WLPCORDER+1]; 139 double rho=0.9, *inp, *dp, *dp2; 140 double whoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER]; 141 double weoutbuf[PITCH_WLPCBUFLEN + PITCH_WLPCORDER]; 142 double *weo, *who, opol[PITCH_WLPCORDER+1], ext[PITCH_WLPCWINLEN]; 143 int k, n, endpos, start; 144 145 /* Set up buffer and states */ 146 memcpy(tmpbuffer, wfdata->buffer, sizeof(double) * PITCH_WLPCBUFLEN); 147 memcpy(tmpbuffer+PITCH_WLPCBUFLEN, in, sizeof(double) * PITCH_FRAME_LEN); 148 memcpy(wfdata->buffer, tmpbuffer+PITCH_FRAME_LEN, sizeof(double) * PITCH_WLPCBUFLEN); 149 150 dp=weoutbuf; 151 dp2=whoutbuf; 152 for (k=0;k<PITCH_WLPCORDER;k++) { 153 *dp++ = wfdata->weostate[k]; 154 *dp2++ = wfdata->whostate[k]; 155 opol[k]=0.0; 156 } 157 opol[0]=1.0; 158 opol[PITCH_WLPCORDER]=0.0; 159 weo=dp; 160 who=dp2; 161 162 endpos=PITCH_WLPCBUFLEN + PITCH_SUBFRAME_LEN; 163 inp=tmpbuffer + PITCH_WLPCBUFLEN; 164 165 for (n=0; n<PITCH_SUBFRAMES; n++) { 166 /* Windowing */ 167 start=endpos-PITCH_WLPCWINLEN; 168 for (k=0; k<PITCH_WLPCWINLEN; k++) { 169 ext[k]=wfdata->window[k]*tmpbuffer[start+k]; 170 } 171 172 /* Get LPC polynomial */ 173 WebRtcIsac_AutoCorr(corr, ext, PITCH_WLPCWINLEN, PITCH_WLPCORDER); 174 corr[0]=1.01*corr[0]+1.0; /* White noise correction */ 175 WebRtcIsac_LevDurb(apol, rc, corr, PITCH_WLPCORDER); 176 WebRtcIsac_BwExpand(apolr, apol, rho, PITCH_WLPCORDER+1); 177 178 /* Filtering */ 179 WebRtcIsac_ZeroPoleFilter(inp, apol, apolr, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, weo); 180 WebRtcIsac_ZeroPoleFilter(inp, apolr, opol, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, who); 181 182 inp+=PITCH_SUBFRAME_LEN; 183 endpos+=PITCH_SUBFRAME_LEN; 184 weo+=PITCH_SUBFRAME_LEN; 185 who+=PITCH_SUBFRAME_LEN; 186 } 187 188 /* Export filter states */ 189 for (k=0;k<PITCH_WLPCORDER;k++) { 190 wfdata->weostate[k]=weoutbuf[PITCH_FRAME_LEN+k]; 191 wfdata->whostate[k]=whoutbuf[PITCH_FRAME_LEN+k]; 192 } 193 194 /* Export output data */ 195 memcpy(weiout, weoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN); 196 memcpy(whiout, whoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN); 197 } 198 199 200 static const double APupper[ALLPASSSECTIONS] = {0.0347, 0.3826}; 201 static const double APlower[ALLPASSSECTIONS] = {0.1544, 0.744}; 202 203 204 void WebRtcIsac_AllpassFilterForDec(double* InOut, 205 const double* APSectionFactors, 206 size_t lengthInOut, 207 double* FilterState) { 208 //This performs all-pass filtering--a series of first order all-pass sections are used 209 //to filter the input in a cascade manner. 210 size_t n,j; 211 double temp; 212 for (j=0; j<ALLPASSSECTIONS; j++){ 213 for (n=0;n<lengthInOut;n+=2){ 214 temp = InOut[n]; //store input 215 InOut[n] = FilterState[j] + APSectionFactors[j]*temp; 216 FilterState[j] = -APSectionFactors[j]*InOut[n] + temp; 217 } 218 } 219 } 220 221 void WebRtcIsac_DecimateAllpass(const double* in, 222 double* state_in, 223 size_t N, 224 double* out) { 225 size_t n; 226 double data_vec[PITCH_FRAME_LEN]; 227 228 /* copy input */ 229 memcpy(data_vec+1, in, sizeof(double) * (N-1)); 230 231 data_vec[0] = state_in[2*ALLPASSSECTIONS]; //the z^(-1) state 232 state_in[2*ALLPASSSECTIONS] = in[N-1]; 233 234 WebRtcIsac_AllpassFilterForDec(data_vec+1, APupper, N, state_in); 235 WebRtcIsac_AllpassFilterForDec(data_vec, APlower, N, state_in+ALLPASSSECTIONS); 236 237 for (n=0;n<N/2;n++) 238 out[n] = data_vec[2*n] + data_vec[2*n+1]; 239 240 } 241 242 243 /* create high-pass filter ocefficients 244 * z = 0.998 * exp(j*2*pi*35/8000); 245 * p = 0.94 * exp(j*2*pi*140/8000); 246 * HP_b = [1, -2*real(z), abs(z)^2]; 247 * HP_a = [1, -2*real(p), abs(p)^2]; */ 248 static const double a_coef[2] = { 1.86864659625574, -0.88360000000000}; 249 static const double b_coef[2] = {-1.99524591718270, 0.99600400000000}; 250 251 /* second order high-pass filter */ 252 void WebRtcIsac_Highpass(const double* in, 253 double* out, 254 double* state, 255 size_t N) { 256 size_t k; 257 258 for (k=0; k<N; k++) { 259 *out = *in + state[1]; 260 state[1] = state[0] + b_coef[0] * *in + a_coef[0] * *out; 261 state[0] = b_coef[1] * *in++ + a_coef[1] * *out++; 262 } 263 } 264