blob: ccc8d214da69e2ff6cf9ba534de15803f24659e4 [file] [log] [blame]
/*
* 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;
}