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."); } }
static void Pitch_line (Pitch me, Graphics g, double tmin, double fleft, double tmax, double fright, int nonPeriodicLineType) { /* * f = fleft + (t - tmin) * (fright - fleft) / (tmax - tmin); */ int lineType = Graphics_inqLineType (g); double lineWidth = Graphics_inqLineWidth (g); double slope = (fright - fleft) / (tmax - tmin); long imin = Sampled_xToNearestIndex (me, tmin); if (imin < 1) imin = 1; long imax = Sampled_xToNearestIndex (me, tmax); if (imax > my nx) imax = my nx; for (long i = imin; i <= imax; i ++) { double tleft, tright; if (! Pitch_isVoiced_i (me, i)) { if (nonPeriodicLineType == 2) continue; Graphics_setLineType (g, Graphics_DOTTED); Graphics_setLineWidth (g, 0.67 * lineWidth); } else if (nonPeriodicLineType != 2) { Graphics_setLineWidth (g, 2 * lineWidth); } tleft = Sampled_indexToX (me, i) - 0.5 * my dx, tright = tleft + my dx; if (tleft < tmin) tleft = tmin; if (tright > tmax) tright = tmax; Graphics_line (g, tleft, fleft + (tleft - tmin) * slope, tright, fleft + (tright - tmin) * slope); Graphics_setLineType (g, lineType); Graphics_setLineWidth (g, lineWidth); } }
static int Pitch_getVoicedIntervalAfter (Pitch me, double after, double *tleft, double *tright) { long ileft = Sampled_xToHighIndex (me, after), iright; if (ileft > my nx) return 0; /* Offright. */ if (ileft < 1) ileft = 1; /* Offleft. */ /* Search for first voiced frame. */ for (; ileft <= my nx; ileft ++) if (Pitch_isVoiced_i (me, ileft)) break; if (ileft > my nx) return 0; /* Offright. */ /* Search for last voiced frame. */ for (iright = ileft; iright <= my nx; iright ++) if (! Pitch_isVoiced_i (me, iright)) break; iright --; *tleft = Sampled_indexToX (me, ileft) - 0.5 * my dx; /* The whole frame is considered voiced. */ *tright = Sampled_indexToX (me, iright) + 0.5 * my dx; if (*tleft >= my xmax - 0.5 * my dx) return 0; if (*tleft < my xmin) *tleft = my xmin; if (*tright > my xmax) *tright = my xmax; return 1; }