Table Spectrum_downto_Table (Spectrum me, bool includeBinNumbers, bool includeFrequency, bool includeRealPart, bool includeImaginaryPart, bool includeEnergyDensity, bool includePowerDensity) { try { autoTable thee = Table_createWithoutColumnNames (my nx, includeBinNumbers + includeFrequency + includeRealPart + includeImaginaryPart + includeEnergyDensity + includePowerDensity); long icol = 0; if (includeBinNumbers) Table_setColumnLabel (thee.peek(), ++ icol, L"bin"); if (includeFrequency) Table_setColumnLabel (thee.peek(), ++ icol, L"freq(Hz)"); if (includeRealPart) Table_setColumnLabel (thee.peek(), ++ icol, L"re(Pa/Hz)"); if (includeImaginaryPart) Table_setColumnLabel (thee.peek(), ++ icol, L"im(Pa/Hz)"); if (includeEnergyDensity) Table_setColumnLabel (thee.peek(), ++ icol, L"energy(Pa^2/Hz^2)"); if (includePowerDensity) Table_setColumnLabel (thee.peek(), ++ icol, L"pow(dB/Hz)"); for (long ibin = 1; ibin <= my nx; ibin ++) { icol = 0; if (includeBinNumbers) Table_setNumericValue (thee.peek(), ibin, ++ icol, ibin); if (includeFrequency) Table_setNumericValue (thee.peek(), ibin, ++ icol, my x1 + (ibin - 1) * my dx); if (includeRealPart) Table_setNumericValue (thee.peek(), ibin, ++ icol, my z [1] [ibin]); if (includeImaginaryPart) Table_setNumericValue (thee.peek(), ibin, ++ icol, my z [2] [ibin]); if (includeEnergyDensity) Table_setNumericValue (thee.peek(), ibin, ++ icol, Sampled_getValueAtSample (me, ibin, 0, 1)); if (includePowerDensity) Table_setNumericValue (thee.peek(), ibin, ++ icol, Sampled_getValueAtSample (me, ibin, 0, 2)); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Table."); } }
autoPitch Pitch_subtractLinearFit (Pitch me, int unit) { try { autoPitch thee = Pitch_interpolate (me); /* * Find the first and last voiced frame. */ long imin = thy nx + 1, imax = 0; for (long i = 1; i <= my nx; i ++) if (Pitch_isVoiced_i (thee.peek(), i)) { imin = i; break; } for (long i = imin + 1; i <= my nx; i ++) if (! Pitch_isVoiced_i (thee.peek(), i)) { imax = i - 1; break; } long n = imax - imin + 1; if (n < 3) return thee; /* * Compute average pitch and time. */ double sum = 0.0; for (long i = imin; i <= imax; i ++) { sum += Sampled_getValueAtSample (thee.peek(), i, Pitch_LEVEL_FREQUENCY, unit); } double fmean = sum / n; double tmean = thy x1 + (0.5 * (imin + imax) - 1) * thy dx; /* * Compute slope. */ double numerator = 0.0, denominator = 0.0; for (long i = imin; i <= imax; i ++) { double t = thy x1 + (i - 1) * thy dx - tmean; double f = Sampled_getValueAtSample (thee.peek(), i, Pitch_LEVEL_FREQUENCY, unit) - fmean; numerator += f * t; denominator += t * t; } double slope = numerator / denominator; /* * Modify frequencies. */ for (long i = imin; i <= imax; i ++) { Pitch_Frame myFrame = & my frame [i], thyFrame = & thy frame [i]; double t = thy x1 + (i - 1) * thy dx - tmean, myFreq = FREQUENCY (myFrame); double f = Sampled_getValueAtSample (thee.peek(), i, Pitch_LEVEL_FREQUENCY, unit); f -= slope * t; if (NOT_VOICED (myFreq)) FREQUENCY (thyFrame) = 0.0; else FREQUENCY (thyFrame) = Function_convertSpecialToStandardUnit (me, f, Pitch_LEVEL_FREQUENCY, unit); } return thee; } catch (MelderError) { Melder_throw (me, U": linear fit not subtracted."); } }
Ltas Spectrum_to_Ltas_1to1 (Spectrum me) { long iband; Ltas thee = Thing_new (Ltas); cherror Matrix_init (thee, my xmin, my xmax, my nx, my dx, my x1, 1, 1, 1, 1, 1); cherror for (iband = 1; iband <= my nx; iband ++) { thy z [1] [iband] = Sampled_getValueAtSample (me, iband, 0, 2); } end: iferror forget (thee); return thee; }
Ltas Spectrum_to_Ltas_1to1 (Spectrum me) { try { autoLtas thee = Thing_new (Ltas); Matrix_init (thee.peek(), my xmin, my xmax, my nx, my dx, my x1, 1.0, 1.0, 1, 1.0, 1.0); for (long iband = 1; iband <= my nx; iband ++) { thy z [1] [iband] = Sampled_getValueAtSample (me, iband, 0, 2); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Ltas."); } }
static void Sampled_speckleInside (Sampled me, Graphics g, double xmin, double xmax, double ymin, double ymax, double speckle_mm, long ilevel, int unit) { Function_unidirectionalAutowindow (me, & xmin, & xmax); long ixmin, ixmax; Sampled_getWindowSamples (me, xmin, xmax, & ixmin, & ixmax); if (Function_isUnitLogarithmic (me, ilevel, unit)) { ymin = Function_convertStandardToSpecialUnit (me, ymin, ilevel, unit); ymax = Function_convertStandardToSpecialUnit (me, ymax, ilevel, unit); } if (ymax <= ymin) return; Graphics_setWindow (g, xmin, xmax, ymin, ymax); for (long ix = ixmin; ix <= ixmax; ix ++) { double value = Sampled_getValueAtSample (me, ix, ilevel, unit); if (NUMdefined (value)) { double x = Sampled_indexToX (me, ix); if (value >= ymin && value <= ymax) { Graphics_fillCircle_mm (g, x, value, speckle_mm); } } } }
double Sampled_getValueAtX (Sampled me, double x, long ilevel, int unit, int interpolate) { if (x < my xmin || x > my xmax) return NUMundefined; if (interpolate) { double ireal = Sampled_xToIndex (me, x); long ileft = floor (ireal), inear, ifar; double phase = ireal - ileft; if (phase < 0.5) { inear = ileft, ifar = ileft + 1; } else { ifar = ileft, inear = ileft + 1; phase = 1.0 - phase; } if (inear < 1 || inear > my nx) return NUMundefined; // x out of range? double fnear = my v_getValueAtSample (inear, ilevel, unit); if (fnear == NUMundefined) return NUMundefined; // function value not defined? if (ifar < 1 || ifar > my nx) return fnear; // at edge? Extrapolate double ffar = my v_getValueAtSample (ifar, ilevel, unit); if (ffar == NUMundefined) return fnear; // neighbour undefined? Extrapolate return fnear + phase * (ffar - fnear); // interpolate } return Sampled_getValueAtSample (me, Sampled_xToNearestIndex (me, x), ilevel, unit); }
double Sampled_getValueAtX (I, double x, long ilevel, int unit, int interpolate) { iam (Sampled); if (x < my xmin || x > my xmax) return NUMundefined; if (interpolate) { double ireal = Sampled_xToIndex (me, x), phase, fnear, ffar; long ileft = floor (ireal), inear, ifar; phase = ireal - ileft; if (phase < 0.5) { inear = ileft, ifar = ileft + 1; } else { ifar = ileft, inear = ileft + 1; phase = 1.0 - phase; } if (inear < 1 || inear > my nx) return NUMundefined; /* X out of range? */ fnear = our getValueAtSample (me, inear, ilevel, unit); if (fnear == NUMundefined) return NUMundefined; /* Function value not defined? */ if (ifar < 1 || ifar > my nx) return fnear; /* At edge? Extrapolate. */ ffar = our getValueAtSample (me, ifar, ilevel, unit); if (ffar == NUMundefined) return fnear; /* Neighbour undefined? Extrapolate. */ return fnear + phase * (ffar - fnear); /* Interpolate. */ } return Sampled_getValueAtSample (me, Sampled_xToNearestIndex (me, x), ilevel, unit); }
bool Pitch_isVoiced_i (Pitch me, long iframe) { return NUMdefined (Sampled_getValueAtSample (me, iframe, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ)); }
void Sampled_drawInside (Sampled me, Graphics g, double xmin, double xmax, double ymin, double ymax, double speckle_mm, long ilevel, int unit) { try { if (speckle_mm != 0.0) { Sampled_speckleInside (me, g, xmin, xmax, ymin, ymax, speckle_mm, ilevel, unit); return; } Function_unidirectionalAutowindow (me, & xmin, & xmax); long ixmin, ixmax, startOfDefinedStretch = -1; Sampled_getWindowSamples (me, xmin, xmax, & ixmin, & ixmax); if (Function_isUnitLogarithmic (me, ilevel, unit)) { ymin = Function_convertStandardToSpecialUnit (me, ymin, ilevel, unit); ymax = Function_convertStandardToSpecialUnit (me, ymax, ilevel, unit); } if (ymax <= ymin) return; Graphics_setWindow (g, xmin, xmax, ymin, ymax); autoNUMvector <double> xarray (ixmin - 1, ixmax + 1); autoNUMvector <double> yarray (ixmin - 1, ixmax + 1); double previousValue = Sampled_getValueAtSample (me, ixmin - 1, ilevel, unit); if (NUMdefined (previousValue)) { startOfDefinedStretch = ixmin - 1; xarray [ixmin - 1] = Sampled_indexToX (me, ixmin - 1); yarray [ixmin - 1] = previousValue; } for (long ix = ixmin; ix <= ixmax; ix ++) { double x = Sampled_indexToX (me, ix), value = Sampled_getValueAtSample (me, ix, ilevel, unit); if (NUMdefined (value)) { if (NUMdefined (previousValue)) { xarray [ix] = x; yarray [ix] = value; } else { startOfDefinedStretch = ix - 1; xarray [ix - 1] = x - 0.5 * my dx; yarray [ix - 1] = value; xarray [ix] = x; yarray [ix] = value; } } else if (NUMdefined (previousValue)) { Melder_assert (startOfDefinedStretch >= ixmin - 1); if (ix > ixmin) { xarray [ix] = x - 0.5 * my dx; yarray [ix] = previousValue; if (xarray [startOfDefinedStretch] < xmin) { double phase = (xmin - xarray [startOfDefinedStretch]) / my dx; xarray [startOfDefinedStretch] = xmin; yarray [startOfDefinedStretch] = phase * yarray [startOfDefinedStretch + 1] + (1.0 - phase) * yarray [startOfDefinedStretch]; } Graphics_polyline (g, ix + 1 - startOfDefinedStretch, & xarray [startOfDefinedStretch], & yarray [startOfDefinedStretch]); } startOfDefinedStretch = -1; } previousValue = value; } if (startOfDefinedStretch > -1) { double x = Sampled_indexToX (me, ixmax + 1), value = Sampled_getValueAtSample (me, ixmax + 1, ilevel, unit); Melder_assert (NUMdefined (previousValue)); if (NUMdefined (value)) { xarray [ixmax + 1] = x; yarray [ixmax + 1] = value; } else { xarray [ixmax + 1] = x - 0.5 * my dx; yarray [ixmax + 1] = previousValue; } if (xarray [startOfDefinedStretch] < xmin) { double phase = (xmin - xarray [startOfDefinedStretch]) / my dx; xarray [startOfDefinedStretch] = xmin; yarray [startOfDefinedStretch] = phase * yarray [startOfDefinedStretch + 1] + (1.0 - phase) * yarray [startOfDefinedStretch]; } if (xarray [ixmax + 1] > xmax) { double phase = (xarray [ixmax + 1] - xmax) / my dx; xarray [ixmax + 1] = xmax; yarray [ixmax + 1] = phase * yarray [ixmax] + (1.0 - phase) * yarray [ixmax + 1]; } Graphics_polyline (g, ixmax + 2 - startOfDefinedStretch, & xarray [startOfDefinedStretch], & yarray [startOfDefinedStretch]); } } catch (MelderError) { Melder_clearError (); } }
static void Sampled_getSum2AndDefinitionRange (Sampled me, double xmin, double xmax, long ilevel, int unit, double mean, int interpolate, double *return_sum2, double *return_definitionRange) { /* This function computes the area under the linearly interpolated squared difference curve between xmin and xmax. Outside [x1-dx/2, xN+dx/2], the curve is undefined and neither times nor values are counted. In [x1-dx/2,x1] and [xN,xN+dx/2], the curve is linearly extrapolated. */ long imin, imax, isamp; double sum2 = 0.0, definitionRange = 0.0; Function_unidirectionalAutowindow (me, & xmin, & xmax); if (Function_intersectRangeWithDomain (me, & xmin, & xmax)) { if (interpolate) { if (Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax)) { double leftEdge = my x1 - 0.5 * my dx, rightEdge = leftEdge + my nx * my dx; for (isamp = imin; isamp <= imax; isamp ++) { double value = my v_getValueAtSample (isamp, ilevel, unit); // a fast way to integrate a linearly interpolated curve; works everywhere except at the edges if (NUMdefined (value)) { value -= mean; value *= value; definitionRange += 1.0; sum2 += value; } } /* * Corrections within the first and last sampling intervals. */ if (xmin > leftEdge) { // otherwise, constant extrapolation over 0.5 sample is OK double phase = (my x1 + (imin - 1) * my dx - xmin) / my dx; // this fraction of sampling interval is still to be determined double rightValue = Sampled_getValueAtSample (me, imin, ilevel, unit); double leftValue = Sampled_getValueAtSample (me, imin - 1, ilevel, unit); if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange -= 0.5; // delete constant extrapolation over 0.5 sample sum2 -= 0.5 * rightValue; if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; definitionRange += phase; // add current fraction sum2 += phase * (rightValue + 0.5 * phase * (leftValue - rightValue)); // interpolate to outside sample } else { if (phase > 0.5) phase = 0.5; definitionRange += phase; // add current fraction, but never more than 0.5 sum2 += phase * rightValue; } } else if (NUMdefined (leftValue) && phase > 0.5) { leftValue -= mean; leftValue *= leftValue; definitionRange += phase - 0.5; sum2 += (phase - 0.5) * leftValue; } } if (xmax < rightEdge) { // otherwise, constant extrapolation is OK double phase = (xmax - (my x1 + (imax - 1) * my dx)) / my dx; // this fraction of sampling interval is still to be determined double leftValue = Sampled_getValueAtSample (me, imax, ilevel, unit); double rightValue = Sampled_getValueAtSample (me, imax + 1, ilevel, unit); if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; definitionRange -= 0.5; // delete constant extrapolation over 0.5 sample sum2 -= 0.5 * leftValue; if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase; // add current fraction sum2 += phase * (leftValue + 0.5 * phase * (rightValue - leftValue)); // interpolate to outside sample } else { if (phase > 0.5) phase = 0.5; definitionRange += phase; // add current fraction, but never more than 0.5 sum2 += phase * leftValue; } } else if (NUMdefined (rightValue) && phase > 0.5) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase - 0.5; sum2 += (phase - 0.5) * rightValue; } } } else { // no sample centres between xmin and xmax /* * Try to return the mean of the interpolated values at these two points. * Thus, a small (xmin, xmax) range gives the same value as the (xmin+xmax)/2 point. */ double leftValue = Sampled_getValueAtSample (me, imax, ilevel, unit); double rightValue = Sampled_getValueAtSample (me, imin, ilevel, unit); double phase1 = (xmin - (my x1 + (imax - 1) * my dx)) / my dx; double phase2 = (xmax - (my x1 + (imax - 1) * my dx)) / my dx; if (imin == imax + 1) { // not too far from sample definition region if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * (leftValue + 0.5 * (phase1 + phase2) * (rightValue - leftValue)); } else if (phase1 < 0.5) { if (phase2 > 0.5) phase2 = 0.5; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * leftValue; } } else if (NUMdefined (rightValue) && phase2 > 0.5) { rightValue -= mean; rightValue *= rightValue; if (phase1 < 0.5) phase1 = 0.5; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * rightValue; } } } } else { // no interpolation double rimin = Sampled_xToIndex (me, xmin), rimax = Sampled_xToIndex (me, xmax); if (rimax >= 0.5 && rimin < my nx + 0.5) { imin = rimin < 0.5 ? 0 : (long) floor (rimin + 0.5); imax = rimax >= my nx + 0.5 ? my nx + 1 : (long) floor (rimax + 0.5); for (isamp = imin + 1; isamp < imax; isamp ++) { double value = my v_getValueAtSample (isamp, ilevel, unit); if (NUMdefined (value)) { value -= mean; value *= value; definitionRange += 1.0; sum2 += value; } } if (imin == imax) { double value = my v_getValueAtSample (imin, ilevel, unit); if (NUMdefined (value)) { double phase = rimax - rimin; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } else { if (imin >= 1) { double value = my v_getValueAtSample (imin, ilevel, unit); if (NUMdefined (value)) { double phase = imin - rimin + 0.5; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } if (imax <= my nx) { double value = my v_getValueAtSample (imax, ilevel, unit); if (NUMdefined (value)) { double phase = rimax - imax + 0.5; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } } } } } if (return_sum2) *return_sum2 = sum2; if (return_definitionRange) *return_definitionRange = definitionRange; }
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; }