| /* |
| * Copyright (c) 2011 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 "pitch_estimator.h" |
| #include "os_specific_inline.h" |
| |
| #include <stdlib.h> |
| #include <memory.h> |
| #include <math.h> |
| |
| static const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25, -0.07}; |
| |
| /* interpolation coefficients; generated by design_pitch_filter.m */ |
| static const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = { |
| {-0.02239172458614, 0.06653315052934, -0.16515880017569, 0.60701333734125, 0.64671399919202, -0.20249000396417, 0.09926548334755, -0.04765933793109, 0.01754159521746}, |
| {-0.01985640750434, 0.05816126837866, -0.13991265473714, 0.44560418147643, 0.79117042386876, -0.20266133815188, 0.09585268418555, -0.04533310458084, 0.01654127246314}, |
| {-0.01463300534216, 0.04229888475060, -0.09897034715253, 0.28284326017787, 0.90385267956632, -0.16976950138649, 0.07704272393639, -0.03584218578311, 0.01295781500709}, |
| {-0.00764851320885, 0.02184035544377, -0.04985561057281, 0.13083306574393, 0.97545011664662, -0.10177807997561, 0.04400901776474, -0.02010737175166, 0.00719783432422}, |
| {-0.00000000000000, 0.00000000000000, -0.00000000000001, 0.00000000000001, 0.99999999999999, 0.00000000000001, -0.00000000000001, 0.00000000000000, -0.00000000000000}, |
| { 0.00719783432422, -0.02010737175166, 0.04400901776474, -0.10177807997562, 0.97545011664663, 0.13083306574393, -0.04985561057280, 0.02184035544377, -0.00764851320885}, |
| { 0.01295781500710, -0.03584218578312, 0.07704272393640, -0.16976950138650, 0.90385267956634, 0.28284326017785, -0.09897034715252, 0.04229888475059, -0.01463300534216}, |
| { 0.01654127246315, -0.04533310458085, 0.09585268418557, -0.20266133815190, 0.79117042386878, 0.44560418147640, -0.13991265473712, 0.05816126837865, -0.01985640750433} |
| }; |
| |
| |
| void WebRtcIsac_PitchfilterPre(double *indat, |
| double *outdat, |
| PitchFiltstr *pfp, |
| double *lags, |
| double *gains) |
| { |
| |
| double ubuf[PITCH_INTBUFFSIZE]; |
| const double *fracoeff = NULL; |
| double curgain, curlag, gaindelta, lagdelta; |
| double sum, inystate[PITCH_DAMPORDER]; |
| double ftmp, oldlag, oldgain; |
| int k, n, m, pos, ind, pos2, Li, frc; |
| |
| Li = 0; |
| /* Set up buffer and states */ |
| memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| oldlag = *pfp->oldlagp; |
| oldgain = *pfp->oldgainp; |
| |
| /* No interpolation if pitch lag step is big */ |
| if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) { |
| oldlag = lags[0]; |
| oldgain = gains[0]; |
| } |
| |
| ind=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdelta=(lags[k]-oldlag) / PITCH_GRAN_PER_SUBFRAME; |
| curlag=oldlag ; |
| gaindelta=(gains[k]-oldgain) / PITCH_GRAN_PER_SUBFRAME; |
| curgain=oldgain ; |
| oldlag=lags[k]; |
| oldgain=gains[k]; |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| if ((ind % PITCH_UPDATE) == 0) { /* Update parameters */ |
| curgain += gaindelta; |
| curlag += lagdelta; |
| Li = WebRtcIsac_lrint(curlag+PITCH_FILTDELAY + 0.5); |
| ftmp = Li - (curlag+PITCH_FILTDELAY); |
| frc = WebRtcIsac_lrint(PITCH_FRACS * ftmp - 0.5); |
| fracoeff = kIntrpCoef[frc]; |
| } |
| |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystate[m] = inystate[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| sum=0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| sum=0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Subtract from input and update buffer */ |
| outdat[ind] = indat[ind] - sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| ind++; |
| } |
| } |
| |
| /* Export buffer and states */ |
| memcpy(pfp->ubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| *pfp->oldlagp = oldlag; |
| *pfp->oldgainp = oldgain; |
| |
| } |
| |
| |
| void WebRtcIsac_PitchfilterPre_la(double *indat, |
| double *outdat, |
| PitchFiltstr *pfp, |
| double *lags, |
| double *gains) |
| { |
| double ubuf[PITCH_INTBUFFSIZE+QLOOKAHEAD]; |
| const double *fracoeff = NULL; |
| double curgain, curlag, gaindelta, lagdelta; |
| double sum, inystate[PITCH_DAMPORDER]; |
| double ftmp; |
| double oldlag, oldgain; |
| int k, n, m, pos, ind, pos2, Li, frc; |
| |
| Li = 0; |
| /* Set up buffer and states */ |
| memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| oldlag = *pfp->oldlagp; |
| oldgain = *pfp->oldgainp; |
| |
| /* No interpolation if pitch lag step is big */ |
| if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) { |
| oldlag = lags[0]; |
| oldgain = gains[0]; |
| } |
| |
| |
| ind=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdelta=(lags[k]-oldlag) / PITCH_GRAN_PER_SUBFRAME; |
| curlag=oldlag ; |
| gaindelta=(gains[k]-oldgain) / PITCH_GRAN_PER_SUBFRAME; |
| curgain=oldgain ; |
| oldlag=lags[k]; |
| oldgain=gains[k]; |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| if ((ind % PITCH_UPDATE) == 0) { /* Update parameters */ |
| curgain += gaindelta; |
| curlag += lagdelta; |
| Li = WebRtcIsac_lrint(curlag+PITCH_FILTDELAY + 0.5); |
| ftmp = Li - (curlag+PITCH_FILTDELAY); |
| frc = WebRtcIsac_lrint(PITCH_FRACS * ftmp - 0.5); |
| fracoeff = kIntrpCoef[frc]; |
| } |
| |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystate[m] = inystate[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| sum=0.0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| sum=0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Subtract from input and update buffer */ |
| outdat[ind] = indat[ind] - sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| ind++; |
| } |
| } |
| |
| /* Export buffer and states */ |
| memcpy(pfp->ubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| *pfp->oldlagp = oldlag; |
| *pfp->oldgainp = oldgain; |
| |
| |
| /* Filter look-ahead segment */ |
| for (n=0;n<QLOOKAHEAD;n++) { |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystate[m] = inystate[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| sum=0.0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| sum=0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Subtract from input and update buffer */ |
| outdat[ind] = indat[ind] - sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| ind++; |
| } |
| } |
| |
| |
| void WebRtcIsac_PitchfilterPre_gains(double *indat, |
| double *outdat, |
| double out_dG[][PITCH_FRAME_LEN + QLOOKAHEAD], |
| PitchFiltstr *pfp, |
| double *lags, |
| double *gains) |
| { |
| double ubuf[PITCH_INTBUFFSIZE+QLOOKAHEAD]; |
| double inystate_dG[4][PITCH_DAMPORDER]; |
| double gain_mult[4]; |
| const double *fracoeff = NULL; |
| double curgain, curlag, gaindelta, lagdelta; |
| double sum, sum2, inystate[PITCH_DAMPORDER]; |
| double ftmp, oldlag, oldgain; |
| int k, n, m, m_tmp, j, pos, ind, pos2, Li, frc; |
| |
| Li = 0; |
| |
| /* Set up buffer and states */ |
| memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| /* clear some buffers */ |
| for (k = 0; k < 4; k++) { |
| gain_mult[k] = 0.0; |
| for (n = 0; n < PITCH_DAMPORDER; n++) |
| inystate_dG[k][n] = 0.0; |
| } |
| |
| oldlag = *pfp->oldlagp; |
| oldgain = *pfp->oldgainp; |
| |
| /* No interpolation if pitch lag step is big */ |
| if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) { |
| oldlag = lags[0]; |
| oldgain = gains[0]; |
| gain_mult[0] = 1.0; |
| } |
| |
| |
| ind=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdelta=(lags[k]-oldlag) / PITCH_GRAN_PER_SUBFRAME; |
| curlag=oldlag ; |
| gaindelta=(gains[k]-oldgain) / PITCH_GRAN_PER_SUBFRAME; |
| curgain=oldgain ; |
| oldlag=lags[k]; |
| oldgain=gains[k]; |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| if ((ind % PITCH_UPDATE) == 0) { /* Update parameters */ |
| curgain += gaindelta; |
| curlag += lagdelta; |
| Li = WebRtcIsac_lrint(curlag+PITCH_FILTDELAY + 0.5); |
| ftmp = Li - (curlag+PITCH_FILTDELAY); |
| frc = WebRtcIsac_lrint(PITCH_FRACS * ftmp - 0.5); |
| fracoeff = kIntrpCoef[frc]; |
| gain_mult[k] += 0.2; |
| if (gain_mult[k] > 1.0) gain_mult[k] = 1.0; |
| if (k > 0) gain_mult[k-1] -= 0.2; |
| } |
| |
| /* shift low pass filter states */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) { |
| inystate[m] = inystate[m-1]; |
| for (j = 0; j < 4; j++) |
| inystate_dG[j][m] = inystate_dG[j][m-1]; |
| } |
| |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| |
| /* Filter to get fractional pitch */ |
| sum=0.0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| m_tmp = (Li-ind > 0) ? Li-ind : 0; |
| for (j = 0; j < k+1; j++) { |
| /* filter */ |
| sum2 = 0.0; |
| for (m = PITCH_FRACORDER-1; m >= m_tmp; m--) |
| sum2 += out_dG[j][ind-Li + m] * fracoeff[m]; |
| inystate_dG[j][0] = gain_mult[j] * sum + curgain * sum2; |
| } |
| |
| /* Low pass filter */ |
| sum=0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Subtract from input and update buffer */ |
| outdat[ind] = indat[ind] - sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| |
| for (j = 0; j < k+1; j++) { |
| sum = 0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum -= inystate_dG[j][m] * kDampFilter[m]; |
| out_dG[j][ind] = sum; |
| } |
| for (j = k+1; j < 4; j++) |
| out_dG[j][ind] = 0.0; |
| |
| |
| ind++; |
| } |
| } |
| |
| /* Filter look-ahead segment */ |
| for (n=0;n<QLOOKAHEAD;n++) { |
| /* shift low pass filter states */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) { |
| inystate[m] = inystate[m-1]; |
| for (j = 0; j < 4; j++) |
| inystate_dG[j][m] = inystate_dG[j][m-1]; |
| } |
| |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| |
| /* Filter to get fractional pitch */ |
| sum=0.0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| m_tmp = (Li-ind > 0) ? Li-ind : 0; |
| for (j = 0; (j<k+1)&&(j<4); j++) { |
| /* filter */ |
| sum2 = 0.0; |
| for (m = PITCH_FRACORDER-1; m >= m_tmp; m--) |
| sum2 += out_dG[j][ind-Li + m] * fracoeff[m]; |
| inystate_dG[j][0] = gain_mult[j] * sum + curgain * sum2; |
| } |
| |
| /* Low pass filter */ |
| sum=0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Subtract from input and update buffer */ |
| outdat[ind] = indat[ind] - sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| |
| for (j = 0; (j<k+1)&&(j<4); j++) { |
| sum = 0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum -= inystate_dG[j][m] * kDampFilter[m]; |
| out_dG[j][ind] = sum; |
| } |
| |
| ind++; |
| } |
| } |
| |
| |
| void WebRtcIsac_PitchfilterPost(double *indat, |
| double *outdat, |
| PitchFiltstr *pfp, |
| double *lags, |
| double *gains) |
| { |
| |
| double ubuf[PITCH_INTBUFFSIZE]; |
| const double *fracoeff = NULL; |
| double curgain, curlag, gaindelta, lagdelta; |
| double sum, inystate[PITCH_DAMPORDER]; |
| double ftmp, oldlag, oldgain; |
| int k, n, m, pos, ind, pos2, Li, frc; |
| |
| Li = 0; |
| |
| /* Set up buffer and states */ |
| memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| oldlag = *pfp->oldlagp; |
| oldgain = *pfp->oldgainp; |
| |
| /* make output more periodic */ |
| for (k=0;k<PITCH_SUBFRAMES;k++) |
| gains[k] *= 1.3; |
| |
| /* No interpolation if pitch lag step is big */ |
| if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) { |
| oldlag = lags[0]; |
| oldgain = gains[0]; |
| } |
| |
| |
| ind=0; |
| for (k=0;k<PITCH_SUBFRAMES;k++) { |
| |
| /* Calculate interpolation steps */ |
| lagdelta=(lags[k]-oldlag) / PITCH_GRAN_PER_SUBFRAME; |
| curlag=oldlag ; |
| gaindelta=(gains[k]-oldgain) / PITCH_GRAN_PER_SUBFRAME; |
| curgain=oldgain ; |
| oldlag=lags[k]; |
| oldgain=gains[k]; |
| |
| for (n=0;n<PITCH_SUBFRAME_LEN;n++) { |
| if ((ind % PITCH_UPDATE) == 0) { /* Update parameters */ |
| curgain += gaindelta; |
| curlag += lagdelta; |
| Li = WebRtcIsac_lrint(curlag+PITCH_FILTDELAY + 0.5); |
| ftmp = Li - (curlag+PITCH_FILTDELAY); |
| frc = WebRtcIsac_lrint(PITCH_FRACS * ftmp - 0.5); |
| fracoeff = kIntrpCoef[frc]; |
| } |
| |
| /* shift low pass filter state */ |
| for (m=PITCH_DAMPORDER-1;m>0;m--) |
| inystate[m] = inystate[m-1]; |
| |
| /* Filter to get fractional pitch */ |
| pos = ind + PITCH_BUFFSIZE; |
| pos2 = pos - Li; |
| sum=0.0; |
| for (m=0;m<PITCH_FRACORDER;m++) |
| sum += ubuf[pos2+m] * fracoeff[m]; |
| inystate[0] = curgain * sum; /* Multiply with gain */ |
| |
| /* Low pass filter */ |
| sum=0.0; |
| for (m=0;m<PITCH_DAMPORDER;m++) |
| sum += inystate[m] * kDampFilter[m]; |
| |
| /* Add to input and update buffer */ |
| outdat[ind] = indat[ind] + sum; |
| ubuf[pos] = indat[ind] + outdat[ind]; |
| ind++; |
| } |
| } |
| |
| /* Export buffer and states */ |
| memcpy(pfp->ubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE); |
| memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER); |
| |
| *pfp->oldlagp = oldlag; |
| *pfp->oldgainp = oldgain; |
| |
| } |