Formant LPC_to_Formant (LPC me, double margin) { try { double samplingFrequency = 1.0 / my samplingPeriod; long nmax = my maxnCoefficients, err = 0; long interval = nmax > 20 ? 1 : 10; if (nmax > 99) { Melder_throw ("We cannot find the roots of a polynomial of order > 99."); } if (margin >= samplingFrequency / 4) { Melder_throw ("Margin must be smaller than ", samplingFrequency / 4, "."); } autoFormant thee = Formant_create (my xmin, my xmax, my nx, my dx, my x1, (nmax + 1) / 2); autoMelderProgress progress (L"LPC to Formant"); for (long i = 1; i <= my nx; i++) { Formant_Frame formant = & thy d_frames[i]; LPC_Frame lpc = & my d_frames[i]; // Initialisation of Formant_Frame is taken care of in Roots_into_Formant_Frame! try { LPC_Frame_into_Formant_Frame (lpc, formant, my samplingPeriod, margin); } catch (MelderError) { Melder_clearError(); err++; } if ( (interval == 1 || (i % interval) == 1)) { Melder_progress ( (double) i / my nx, L"LPC to Formant: frame ", Melder_integer (i), L" out of ", Melder_integer (my nx), L"."); } } Formant_sort (thee.peek()); if (err > 0) { Melder_warning (Melder_integer (err), L" formant frames out of ", Melder_integer (my nx), L" suspect."); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Formant created."); } }
static autoFormant Sound_to_Formant_any_inline (Sound me, double dt_in, int numberOfPoles, double halfdt_window, int which, double preemphasisFrequency, double safetyMargin) { double dt = dt_in > 0.0 ? dt_in : halfdt_window / 4.0; double duration = my nx * my dx, t1; double dt_window = 2.0 * halfdt_window; long nFrames = 1 + (long) floor ((duration - dt_window) / dt); long nsamp_window = (long) floor (dt_window / my dx), halfnsamp_window = nsamp_window / 2; if (nsamp_window < numberOfPoles + 1) Melder_throw (U"Window too short."); t1 = my x1 + 0.5 * (duration - my dx - (nFrames - 1) * dt); // centre of first frame if (nFrames < 1) { nFrames = 1; t1 = my x1 + 0.5 * duration; dt_window = duration; nsamp_window = my nx; } autoFormant thee = Formant_create (my xmin, my xmax, nFrames, dt, t1, (numberOfPoles + 1) / 2); // e.g. 11 poles -> maximally 6 formants autoNUMvector <double> window (1, nsamp_window); autoNUMvector <double> frame (1, nsamp_window); autoNUMvector <double> cof (1, numberOfPoles); // superfluous if which==2, but nobody uses that anyway autoMelderProgress progress (U"Formant analysis..."); /* Pre-emphasis. */ Sound_preEmphasis (me, preemphasisFrequency); /* Gaussian window. */ for (long i = 1; i <= nsamp_window; i ++) { double imid = 0.5 * (nsamp_window + 1), edge = exp (-12.0); window [i] = (exp (-48.0 * (i - imid) * (i - imid) / (nsamp_window + 1) / (nsamp_window + 1)) - edge) / (1.0 - edge); } for (long iframe = 1; iframe <= nFrames; iframe ++) { double t = Sampled_indexToX (thee.peek(), iframe); long leftSample = Sampled_xToLowIndex (me, t); long rightSample = leftSample + 1; long startSample = rightSample - halfnsamp_window; long endSample = leftSample + halfnsamp_window; double maximumIntensity = 0.0; if (startSample < 1) startSample = 1; if (endSample > my nx) endSample = my nx; for (long i = startSample; i <= endSample; i ++) { double value = Sampled_getValueAtSample (me, i, Sound_LEVEL_MONO, 0); if (value * value > maximumIntensity) { maximumIntensity = value * value; } } if (maximumIntensity == HUGE_VAL) Melder_throw (U"Sound contains infinities."); thy d_frames [iframe]. intensity = maximumIntensity; if (maximumIntensity == 0.0) continue; // Burg cannot stand all zeroes /* Copy a pre-emphasized window to a frame. */ for (long j = 1, i = startSample; j <= nsamp_window; j ++) frame [j] = Sampled_getValueAtSample (me, i ++, Sound_LEVEL_MONO, 0) * window [j]; if (which == 1) { burg (frame.peek(), endSample - startSample + 1, cof.peek(), numberOfPoles, & thy d_frames [iframe], 0.5 / my dx, safetyMargin); } else if (which == 2) { if (! splitLevinson (frame.peek(), endSample - startSample + 1, numberOfPoles, & thy d_frames [iframe], 0.5 / my dx)) { Melder_clearError (); Melder_casual (U"(Sound_to_Formant:)" U" Analysis results of frame ", iframe, U" will be wrong." ); } } Melder_progress ((double) iframe / (double) nFrames, U"Formant analysis: frame ", iframe); } Formant_sort (thee.peek()); return thee; }