📄 pctolsp2.c
字号:
/*
CELP voice codec, part of the HawkVoice Direct Interface (HVDI)
cross platform network voice library
Copyright (C) 2001-2003 Phil Frisbie, Jr. (phil@hawksoft.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "celpint.h"
#include "ftol.h"
#define N 128
#define NB 15
#define EPS 1.e-6
/* PI/2 */
#define MYPI_S2 1.57079632679489661923
/* 2/PI */
#define MYIPI_S2 0.63661977236758134308
double mycos(double f)
{
double f2;
double co;
int i1;
/* bring the argument f to the [-PI/2, PI/2] interval */
i1=lrintf((float)(f*MYIPI_S2));
if(i1&1) i1++;
f-=i1*MYPI_S2;
/* the real cos routine */
f2=f*f;
co=1.0+f2*(-0.4999999963 + f2*(0.0416666418 + f2*(-0.0013888397 +
f2*(0.0000247609 - f2*0.0000002605))));
/* this handles the values with negative cosines */
return ((i1&2)?-co:co);
}
#define cos(x) mycos(x)
void pctolsp2(float *a, int m, float *freq, celp_encoder_state *st)
{
float p[MAXORD], q[MAXORD], ang, fm, tempfreq;
float fr, pxr, tpxr, tfr, pxm, pxl, fl, qxl, tqxr;
float qxm, qxr, tqxl;
int mp, mh, nf, mb, jc, i, j;
mp = m + 1;
mh = m / 2;
/* *generate p and q polynomials */
for (i = 0; i < mh; i++)
{
p[i] = a[i+1] + a[m-i];
q[i] = a[i+1] - a[m-i];
}
/* *compute p at f=0. */
fl = 0.;
for (pxl = 1.0, j = 0; j < mh; j++)
pxl += p[j];
/* *search for zeros of p */
nf = 0;
for (i = 1; i <= N; pxl = tpxr, fl = tfr, i++)
{
mb = 0;
fr = i * (0.5f / N);
pxr = (float)cos(mp * M_PI * fr);
for (j = 0; j < mh; j++)
{
jc = mp - (j+1)*2;
ang = jc * M_PI * fr;
pxr += (float)cos(ang) * p[j];
}
tpxr = pxr;
tfr = fr;
if (pxl * pxr > 0.0) continue;
do
{
mb++;
fm = fl + (fr-fl) / (pxl-pxr) * pxl;
pxm = (float)cos(mp * M_PI * fm);
for (j = 0; j < mh; j++)
{
jc = mp - (j+1) * 2;
ang = jc * M_PI * fm;
pxm += (float)cos(ang) * p[j];
}
(pxm*pxl > 0.0) ? (pxl = pxm, fl = fm) : (pxr = pxm, fr = fm);
} while ((fabs(pxm) > EPS) && (mb < 4));
if ((pxl-pxr) * pxl == 0)
{
for (j = 0; j < m; j++)
freq[j] = (j+1) * 0.04545f;
return;
}
freq[nf] = fl + (fr-fl) / (pxl-pxr) * pxl;
nf += 2;
if (nf > m-2) break;
}
/* *search for the zeros of q(z) */
freq[m] = 0.5;
fl = freq[0];
qxl = (float)sin(mp * M_PI * fl);
for (j = 0; j < mh; j++)
{
jc = mp - (j+1) * 2;
ang = jc * M_PI * fl;
qxl += (float)sin(ang) * q[j];
}
for (i = 2; i < mp; qxl = tqxr, fl = tfr, i += 2)
{
mb = 0;
fr = freq[i];
qxr = (float)sin(mp * M_PI * fr);
for (j = 0; j < mh; j++)
{
jc = mp - (j+1) * 2;
ang = jc * M_PI * fr;
qxr += (float)sin(ang) * q[j];
}
tqxl = qxl;
tfr = fr;
tqxr = qxr;
do
{
mb++;
fm = (fl+fr) * 0.5f;
qxm = (float)sin(mp * M_PI * fm);
for (j = 0; j < mh; j++)
{
jc = mp - (j+1) * 2;
ang = jc * M_PI * fm;
qxm += (float)sin(ang) * q[j];
}
(qxm*qxl > 0.0) ? (qxl = qxm, fl = fm) : (qxr = qxm, fr = fm);
} while ((fabs(qxm) > EPS*tqxl) && (mb < NB));
if ((qxl-qxr) * qxl == 0)
{
for (j = 0; j < m; j++)
freq[j] = st->lastfreq[j];
return;
}
freq[i-1] = fl + (fr-fl) / (qxl-qxr) * qxl;
}
for (i = 1; i < m; i++)
{
/* *reorder lsps if non-monotonic */
if (freq[i] < freq[i-1])
{
tempfreq = freq[i];
freq[i] = freq[i-1];
freq[i-1] = tempfreq;
}
}
/* *if non-monotonic after 1st pass, reset to last values */
for (i = 1; i < m; i++)
{
if (freq[i] < freq[i-1])
{
for (j = 0; j < m; j++)
freq[j] = st->lastfreq[j];
break;
}
}
for (i = 0; i < m; i++)
st->lastfreq[i] = freq[i];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -