Formant Formant_tracker (Formant me, int ntrack, double refF1, double refF2, double refF3, double refF4, double refF5, double dfCost, /* Per kHz. */ double bfCost, double octaveJumpCost) { try { long nformmin = Formant_getMinNumFormants (me); struct fparm parm; if (ntrack > nformmin) Melder_throw (U"Number of tracks (", ntrack, U") should not exceed minimum number of formants (", nformmin, U")."); autoFormant thee = Formant_create (my xmin, my xmax, my nx, my dx, my x1, ntrack); for (long iframe = 1; iframe <= thy nx; iframe ++) { thy d_frames [iframe]. formant = NUMvector <structFormant_Formant> (1, ntrack); thy d_frames [iframe]. nFormants = ntrack; thy d_frames [iframe]. intensity = my d_frames [iframe]. intensity; } /* BUG: limit costs to 1e10 or so */ parm.me = me; parm.thee = thee.peek(); parm.dfCost = dfCost / 1000.0; // per Hz parm.bfCost = bfCost; parm.octaveJumpCost = octaveJumpCost; parm.refF [1] = refF1; parm.refF [2] = refF2; parm.refF [3] = refF3; parm.refF [4] = refF4; parm.refF [5] = refF5; NUM_viterbi_multi (my nx, my maxnFormants, ntrack, getLocalCost, getTransitionCost, putResult, & parm); return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": not tracked."); } }
Formant Excitation_to_Formant (Excitation me, int maxnFormants) { Formant thee = NULL; long i, nfreq = my nx, nform = 0; double *p = my z [1]; thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); if (! thee) return NULL; thy frame [1]. formant = NUMstructvector (Formant_Formant, 1, maxnFormants); for (i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double min3phon, left, right; double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; long j; Formant_Formant formant = & thy frame [1]. formant [++ nform]; formant -> frequency = Excitation_barkToHertz ( my x1 + my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative)); min3phon = p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative - 3.0; /* Search left. */ j = i - 1; while (p [j] > min3phon && j > 1) j --; left = Excitation_barkToHertz ( p [j] > min3phon ? my xmin : my x1 + my dx * (j - 1 + (min3phon - p [j]) / (p [j + 1] - p [j]))); /* Search right. */ j = i + 1; while (p [j] > min3phon && j < nfreq) j ++; right = Excitation_barkToHertz ( p [j] > min3phon ? my xmax : my x1 + my dx * (j - 1 - (min3phon - p [j]) / (p [j - 1] - p [j]))); formant -> bandwidth = right - left; if (nform == thy maxnFormants) break; } thy frame [1]. nFormants = nform; return thee; }
autoFormant Spectrum_to_Formant (Spectrum me, int maxnFormants) { try { long nfreq = my nx, nform = 0; autoNUMvector <double> p (1, nfreq); // power autoFormant thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); thy d_frames [1]. formant = NUMvector <structFormant_Formant> (1, maxnFormants); for (long i = 1; i <= nfreq; i ++) p [i] = my z [1] [i] * my z [1] [i] + my z [2] [i] * my z [2] [i]; for (long i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; Formant_Formant formant = & thy d_frames [1]. formant [++ nform]; formant -> frequency = my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative); double min3dB = 0.5 * (p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative); /* Search left. */ long j = i - 1; while (p [j] > min3dB && j > 1) j --; if (p [j] > min3dB) formant -> bandwidth = formant -> frequency; else formant -> bandwidth = formant -> frequency - my dx * (j - 1 + (min3dB - p [j]) / (p [j + 1] - p [j])); /* Search right. */ j = i + 1; while (p [j] > min3dB && j < nfreq) j ++; if (p [j] > min3dB) formant -> bandwidth += my xmax - formant -> frequency; else formant -> bandwidth += my dx * (j - 1 - (min3dB - p [j]) / (p [j - 1] - p [j])) - formant -> frequency; if (nform == maxnFormants) break; } thy d_frames [1]. nFormants = nform; return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Formant."); } }
autoFormant Excitation_to_Formant (Excitation me, int maxnFormants) { try { long nfreq = my nx, nform = 0; double *p = my z [1]; autoFormant thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); thy d_frames [1]. formant = NUMvector <structFormant_Formant> (1, maxnFormants); for (long i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double min3phon, left, right; double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; long j; Formant_Formant formant = & thy d_frames [1]. formant [++ nform]; formant -> frequency = Excitation_barkToHertz ( my x1 + my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative)); min3phon = p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative - 3.0; /* Search left. */ j = i - 1; while (p [j] > min3phon && j > 1) j --; left = Excitation_barkToHertz ( p [j] > min3phon ? my xmin : my x1 + my dx * (j - 1 + (min3phon - p [j]) / (p [j + 1] - p [j]))); /* Search right. */ j = i + 1; while (p [j] > min3phon && j < nfreq) j ++; right = Excitation_barkToHertz ( p [j] > min3phon ? my xmax : my x1 + my dx * (j - 1 - (min3phon - p [j]) / (p [j - 1] - p [j]))); formant -> bandwidth = right - left; if (nform == thy maxnFormants) break; } thy d_frames [1]. nFormants = nform; return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Formant."); } }
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."); } }
Formant Spectrum_to_Formant (Spectrum me, int maxnFormants) { Formant thee = NULL; long i, nfreq = my nx, nform = 0; double *p = NUMdvector (1, nfreq); if (! p) goto end; /* power */ thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); if (! thee) goto end; thy frame [1]. formant = NUMstructvector (Formant_Formant, 1, maxnFormants); if (! thy frame [1]. formant) goto end; for (i = 1; i <= nfreq; i ++) p [i] = my z [1] [i] * my z [1] [i] + my z [2] [i] * my z [2] [i]; for (i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double min3dB; double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; long j; Formant_Formant formant = & thy frame [1]. formant [++ nform]; formant -> frequency = my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative); min3dB = 0.5 * (p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative); /* Search left. */ j = i - 1; while (p [j] > min3dB && j > 1) j --; if (p [j] > min3dB) formant -> bandwidth = formant -> frequency; else formant -> bandwidth = formant -> frequency - my dx * (j - 1 + (min3dB - p [j]) / (p [j + 1] - p [j])); /* Search right. */ j = i + 1; while (p [j] > min3dB && j < nfreq) j ++; if (p [j] > min3dB) formant -> bandwidth += my xmax - formant -> frequency; else formant -> bandwidth += my dx * (j - 1 - (min3dB - p [j]) / (p [j - 1] - p [j])) - formant -> frequency; if (nform == maxnFormants) break; } thy frame [1]. nFormants = nform; end: NUMdvector_free (p, 1); return thee; }
Formant FormantGrid_to_Formant (FormantGrid me, double dt, double intensity) { Melder_assert (dt > 0.0); Melder_assert (intensity >= 0.0); long nt = (long) floor ((my xmax - my xmin) / dt) + 1; double t1 = 0.5 * (my xmin + my xmax - (nt - 1) * dt); Formant thee = Formant_create (my xmin, my xmax, nt, dt, t1, my formants -> size); for (long iframe = 1; iframe <= nt; iframe ++) { Formant_Frame frame = & thy frame [iframe]; frame -> intensity = intensity; frame -> nFormants = my formants -> size; frame -> formant = NUMstructvector (Formant_Formant, 1, my formants -> size); double t = t1 + (iframe - 1) * dt; for (long iformant = 1; iformant <= my formants -> size; iformant ++) { Formant_Formant formant = & frame -> formant [iformant]; formant -> frequency = RealTier_getValueAtTime (my formants -> item [iformant], t); formant -> bandwidth = RealTier_getValueAtTime (my bandwidths -> item [iformant], t); } } end: iferror forget (thee); return thee; }
Formant FormantGrid_to_Formant (FormantGrid me, double dt, double intensity) { try { Melder_assert (dt > 0.0); Melder_assert (intensity >= 0.0); long nt = (long) floor ((my xmax - my xmin) / dt) + 1; double t1 = 0.5 * (my xmin + my xmax - (nt - 1) * dt); autoFormant thee = Formant_create (my xmin, my xmax, nt, dt, t1, my formants -> size); for (long iframe = 1; iframe <= nt; iframe ++) { Formant_Frame frame = & thy d_frames [iframe]; frame -> intensity = intensity; frame -> nFormants = my formants -> size; frame -> formant = NUMvector <structFormant_Formant> (1, my formants -> size); double t = t1 + (iframe - 1) * dt; for (long iformant = 1; iformant <= my formants -> size; iformant ++) { Formant_Formant formant = & frame -> formant [iformant]; formant -> frequency = RealTier_getValueAtTime ((RealTier) my formants -> item [iformant], t); formant -> bandwidth = RealTier_getValueAtTime ((RealTier) my bandwidths -> item [iformant], t); } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Formant."); } }
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; }