in nlsCppSdk/encoder/lpc.cpp [58:157]
float vorbis_lpc_from_data(float *data, float *lpci, int n, int m, int stride) {
double *aut = (double *)malloc(sizeof(*aut) * (m + 1));
if (NULL == aut) {
return 0;
} else {
memset(aut, 0, sizeof(*aut) * (m + 1));
}
double *lpc = (double *)malloc(sizeof(*lpc) * (m));
if (!lpc) {
free(aut);
aut = NULL;
return 0;
} else {
memset(lpc, 0, sizeof(*lpc) * m);
}
double error;
double epsilon;
int i, j;
if (!aut || !lpc) {
if (aut) {
free(aut);
aut = NULL;
}
if (lpc) {
free(lpc);
lpc = NULL;
}
return 0;
}
/* autocorrelation, p+1 lag coefficients */
j = m + 1;
while (j--) {
double d = 0; /* double needed for accumulator depth */
for (i = j; i < n; i++) {
d += (double)data[i * stride] * data[(i - j) * stride];
}
aut[j] = d;
}
/* Generate lpc coefficients from autocorr values */
/* set our noise floor to about -100dB */
error = aut[0] * (1. + 1e-10);
epsilon = 1e-9 * aut[0] + 1e-10;
for (i = 0; i < m; i++) {
double r = -aut[i + 1];
if (error < epsilon) {
memset(lpc + i, 0, (m - i) * sizeof(*lpc));
goto done;
}
/* Sum up this iteration's reflection coefficient; note that in
Vorbis we don't save it. If anyone wants to recycle this code
and needs reflection coefficients, save the results of 'r' from
each iteration. */
for (j = 0; j < i; j++) r -= lpc[j] * aut[i - j];
r /= error;
/* Update LPC coefficients and total error */
lpc[i] = r;
for (j = 0; j < i / 2; j++) {
double tmp = lpc[j];
lpc[j] += r * lpc[i - 1 - j];
lpc[i - 1 - j] += r * tmp;
}
if (i & 1) {
lpc[j] += lpc[j] * r;
}
error *= 1. - r * r;
}
done:
/* slightly damp the filter */
{
double g = .99;
double damp = g;
for (j = 0; j < m; j++) {
lpc[j] *= damp;
damp *= g;
}
}
for (j = 0; j < m; j++) {
lpci[j] = (float)lpc[j];
}
/* we need the error value to know how big an impulse to hit the
filter with later */
free(aut);
free(lpc);
return error;
}