static int Sound_into_LPC_Frame_burg (Sound me, LPC_Frame thee) { int status = NUMburg (my z[1], my nx, thy a, thy nCoefficients, &thy gain); thy gain *= my nx; for (long i = 1; i <= thy nCoefficients; i++) { thy a[i] = -thy a[i]; } return status; }
static void burg (double sample [], long nsamp_window, double cof [], int nPoles, Formant_Frame frame, double nyquistFrequency, double safetyMargin) { double a0; NUMburg (sample, nsamp_window, cof, nPoles, & a0); /* * Convert LP coefficients to polynomial. */ autoPolynomial polynomial = Polynomial_create (-1, 1, nPoles); for (int i = 1; i <= nPoles; i ++) polynomial -> coefficients [i] = - cof [nPoles - i + 1]; polynomial -> coefficients [nPoles + 1] = 1.0; /* * Find the roots of the polynomial. */ autoRoots roots = Polynomial_to_Roots (polynomial.peek()); Roots_fixIntoUnitCircle (roots.peek()); Melder_assert (frame -> nFormants == 0 && ! frame -> formant); /* * First pass: count the formants. * The roots come in conjugate pairs, so we need only count those above the real axis. */ for (int i = roots -> min; i <= roots -> max; i ++) if (roots -> v [i]. im >= 0) { double f = fabs (atan2 (roots -> v [i].im, roots -> v [i].re)) * nyquistFrequency / NUMpi; if (f >= safetyMargin && f <= nyquistFrequency - safetyMargin) frame -> nFormants ++; } /* * Create space for formant data. */ if (frame -> nFormants > 0) frame -> formant = NUMvector <structFormant_Formant> (1, frame -> nFormants); /* * Second pass: fill in the formants. */ int iformant = 0; for (int i = roots -> min; i <= roots -> max; i ++) if (roots -> v [i]. im >= 0.0) { double f = fabs (atan2 (roots -> v [i].im, roots -> v [i].re)) * nyquistFrequency / NUMpi; if (f >= safetyMargin && f <= nyquistFrequency - safetyMargin) { Formant_Formant formant = & frame -> formant [++ iformant]; formant -> frequency = f; formant -> bandwidth = - log (roots -> v [i].re * roots -> v [i].re + roots -> v [i].im * roots -> v [i].im) * nyquistFrequency / NUMpi; } } Melder_assert (iformant == frame -> nFormants); // may fail if some frequency is NaN }
autoSpectrum Spectrum_lpcSmoothing (Spectrum me, int numberOfPeaks, double preemphasisFrequency) { try { double gain, a [100]; long numberOfCoefficients = 2 * numberOfPeaks; autoSound sound = Spectrum_to_Sound (me); NUMpreemphasize_f (sound -> z [1], sound -> nx, sound -> dx, preemphasisFrequency); NUMburg (sound -> z [1], sound -> nx, a, numberOfCoefficients, & gain); for (long i = 1; i <= numberOfCoefficients; i ++) a [i] = - a [i]; autoSpectrum thee = Data_copy (me); long nfft = 2 * (thy nx - 1); long ndata = numberOfCoefficients < nfft ? numberOfCoefficients : nfft - 1; double scale = 10 * (gain > 0 ? sqrt (gain) : 1) / numberOfCoefficients; autoNUMvector <double> data (1, nfft); data [1] = 1; for (long i = 1; i <= ndata; i ++) data [i + 1] = a [i]; NUMrealft (data.peek(), nfft, 1); double *re = thy z [1]; double *im = thy z [2]; re [1] = scale / data [1]; im [1] = 0.0; long halfnfft = nfft / 2; for (long i = 2; i <= halfnfft; i ++) { double real = data [i + i - 1], imag = data [i + i]; re [i] = scale / sqrt (real * real + imag * imag) / (1 + thy dx * (i - 1) / preemphasisFrequency); im [i] = 0; } re [halfnfft + 1] = scale / data [2] / (1 + thy dx * halfnfft / preemphasisFrequency); im [halfnfft + 1] = 0.0; return thee; } catch (MelderError) { Melder_throw (me, U": not smoothed."); } }