static void Sound_PointProcess_fillVoiceless (Sound me, PointProcess pulses) { long ipointleft, ipointright; double beginVoiceless = my xmin, endVoiceless; for (ipointleft = 1; ipointleft <= pulses -> nt; ipointleft = ipointright + 1) { long i1, i2, i; endVoiceless = pulses -> t [ipointleft] - 0.005; i1 = Sampled_xToHighIndex (me, beginVoiceless); if (i1 < 1) i1 = 1; if (i1 > my nx) i1 = my nx; i2 = Sampled_xToLowIndex (me, endVoiceless); if (i2 < 1) i2 = 1; if (i2 > my nx) i2 = my nx; if (i2 - i1 > 10) for (i = i1; i <= i2; i ++) my z [1] [i] = NUMrandomGauss (0.0, 0.3); for (ipointright = ipointleft + 1; ipointright <= pulses -> nt; ipointright ++) if (pulses -> t [ipointright] - pulses -> t [ipointright - 1] > MAX_T) break; ipointright --; beginVoiceless = pulses -> t [ipointright] + 0.005; } endVoiceless = my xmax; { long i1, i2, i; i1 = Sampled_xToHighIndex (me, beginVoiceless); if (i1 < 1) i1 = 1; if (i1 > my nx) i1 = my nx; i2 = Sampled_xToLowIndex (me, endVoiceless); if (i2 < 1) i2 = 1; if (i2 > my nx) i2 = my nx; if (i2 - i1 > 10) for (i = i1; i <= i2; i ++) my z [1] [i] = NUMrandomGauss (0.0, 0.3); } }
static void copyFlat (Sound me, double tmin, double tmax, Sound thee, double tminTarget) { long imin = Sampled_xToHighIndex (me, tmin); if (imin < 1) imin = 1; long imax = Sampled_xToHighIndex (me, tmax) - 1; // not xToLowIndex: ensure separation of subsequent calls if (imax > my nx) imax = my nx; if (imax < imin) return; long iminTarget = Sampled_xToHighIndex (thee, tminTarget); if (iminTarget < 1) iminTarget = 1; trace (tmin, U" ", tmax, U" ", tminTarget, U" ", imin, U" ", imax, U" ", iminTarget); Melder_assert (iminTarget + imax - imin <= thy nx); NUMvector_copyElements (my z [1] + imin, thy z [1] + iminTarget, 0, imax - imin); }
static void copyFall (Sound me, double tmin, double tmax, Sound thee, double tminTarget) { long imin = Sampled_xToHighIndex (me, tmin); if (imin < 1) imin = 1; long imax = Sampled_xToHighIndex (me, tmax) - 1; // not xToLowIndex: ensure separation of subsequent calls if (imax > my nx) imax = my nx; if (imax < imin) return; long iminTarget = Sampled_xToHighIndex (thee, tminTarget); long distance = iminTarget - imin; double dphase = NUMpi / (imax - imin + 1); for (long i = imin; i <= imax; i ++) { long iTarget = i + distance; if (iTarget >= 1 && iTarget <= thy nx) thy z [1] [iTarget] += my z [1] [i] * 0.5 * (1.0 + cos (dphase * (i - imin + 0.5))); } }
int Manipulation_playPart (Manipulation me, double tmin, double tmax, int method) { try { if (method == Manipulation_OVERLAPADD) { if (! my sound) Melder_throw (U"Cannot synthesize overlap-add without a sound."); autoSound part = Data_copy (my sound.get()); long imin = Sampled_xToLowIndex (part.get(), tmin), imax = Sampled_xToHighIndex (part.get(), tmax); double *amp = part -> z [1]; for (long i = 1; i <= imin; i ++) amp [i] = 0.0; for (long i = imax; i <= part -> nx; i ++) amp [i] = 0.0; autoSound saved = my sound.move(); my sound = part.move(); try { autoSound played = Manipulation_to_Sound (me, Manipulation_OVERLAPADD); my sound = saved.move(); amp = played -> z [1]; for (imin = 1; imin <= played -> nx; imin ++) if (amp [imin] != 0.0) break; for (imax = played -> nx; imax >= 1; imax --) if (amp [imax] != 0.0) break; Sound_playPart (played.get(), played -> x1 + (imin - 1.5) * played -> dx, played -> x1 + (imax - 0.5) * played -> dx, nullptr, nullptr); } catch (MelderError) { my sound = saved.move(); throw; } } else { autoSound sound = Manipulation_to_Sound (me, method); Sound_playPart (sound.get(), tmin, tmax, nullptr, nullptr); } return 1; } catch (MelderError) { Melder_throw (me, U": not played."); } }
Polygon Sound_to_Polygon (Sound me, int channel, double tmin, double tmax, double ymin, double ymax, double level) { try { bool clip = ymin < ymax; if (channel < 1 || channel > my ny) { Melder_throw ("Channel does not exist."); } if (tmin >= tmax) { tmin = my xmin; tmax = my xmax; } if (tmin < my xmin) { tmin = my xmin; } if (tmax > my xmax) { tmax = my xmax; } if (tmin >= my xmax || tmax < my xmin) { Melder_throw ("Invalid domain."); } long k = 1, i1 = Sampled_xToHighIndex (me, tmin); long i2 = Sampled_xToLowIndex (me, tmax); long numberOfPoints = i2 - i1 + 1 + 2 + 2; // begin + endpoint + level autoPolygon him = Polygon_create (numberOfPoints); /* In Vector_getValueAtX the interpolation only returns defined values between the left and right edges that are calculated as left = x1 - 0.5 * dx; right = left + my nx * dx. Given a sound, for example on the domain [0,...], the value of 'left' with the above formula might not return exactly xmin but instead a very small deviation (due to the imprecise representation of real numbers in a computer). Querying for the value at xmin which is outside the interpolation domain then produces an 'undefined'. We try to avoid this with the following workaround. */ double xmin = my x1 - 0.5 * my dx; double xmax = xmin + my nx * my dx; tmin = tmin < xmin ? xmin : tmin; tmax = tmax > xmax ? xmax : tmax; // End of workaround his x[k] = tmin; his y[k++] = CLIP_Y (level, ymin, ymax); his x[k] = tmin; double y = Vector_getValueAtX (me, tmin, channel, Vector_VALUE_INTERPOLATION_LINEAR); his y[k++] = CLIP_Y (y, ymin, ymax); for (long i = i1; i <= i2; i++) { y = my z[channel][i]; his x[k] = my x1 + (i - 1) * my dx; his y[k++] = CLIP_Y (y, ymin, ymax); } his x[k] = tmax; y = Vector_getValueAtX (me, tmax, channel, Vector_VALUE_INTERPOLATION_LINEAR); his y[k++] = CLIP_Y (y, ymin, ymax); his x[k] = tmax; his y[k++] = CLIP_Y (level, ymin, ymax); return him.transfer(); } catch (MelderError) { Melder_throw (me, ":no Polygon created."); } }
static Spectrum Spectrum_band (Spectrum me, double fmin, double fmax) { autoSpectrum band = Data_copy (me); double *re = band -> z [1], *im = band -> z [2]; long imin = Sampled_xToLowIndex (band.peek(), fmin), imax = Sampled_xToHighIndex (band.peek(), fmax); for (long i = 1; i <= imin; i ++) re [i] = 0.0, im [i] = 0.0; for (long i = imax; i <= band -> nx; i ++) re [i] = 0.0, im [i] = 0.0; return band.transfer(); }
static double Sound_findMaximumCorrelation (Sound me, double t1, double windowLength, double tmin2, double tmax2, double *tout, double *peak) { double maximumCorrelation = -1.0, r1 = 0.0, r2 = 0.0, r3 = 0.0, r1_best, r3_best, ir; double halfWindowLength = 0.5 * windowLength; long i1, i2, ileft2; long ileft1 = Sampled_xToNearestIndex ((Sampled) me, t1 - halfWindowLength); long iright1 = Sampled_xToNearestIndex ((Sampled) me, t1 + halfWindowLength); long ileft2min = Sampled_xToLowIndex ((Sampled) me, tmin2 - halfWindowLength); long ileft2max = Sampled_xToHighIndex ((Sampled) me, tmax2 - halfWindowLength); *peak = 0.0; /* Default. */ for (ileft2 = ileft2min; ileft2 <= ileft2max; ileft2 ++) { double norm1 = 0.0, norm2 = 0.0, product = 0.0, localPeak = 0.0; if (my ny == 1) { for (i1 = ileft1, i2 = ileft2; i1 <= iright1; i1 ++, i2 ++) { if (i1 < 1 || i1 > my nx || i2 < 1 || i2 > my nx) continue; double amp1 = my z [1] [i1], amp2 = my z [1] [i2]; norm1 += amp1 * amp1; norm2 += amp2 * amp2; product += amp1 * amp2; if (fabs (amp2) > localPeak) localPeak = fabs (amp2); } } else { for (i1 = ileft1, i2 = ileft2; i1 <= iright1; i1 ++, i2 ++) { if (i1 < 1 || i1 > my nx || i2 < 1 || i2 > my nx) continue; double amp1 = 0.5 * (my z [1] [i1] + my z [2] [i1]), amp2 = 0.5 * (my z [1] [i2] + my z [2] [i2]); norm1 += amp1 * amp1; norm2 += amp2 * amp2; product += amp1 * amp2; if (fabs (amp2) > localPeak) localPeak = fabs (amp2); } } r1 = r2; r2 = r3; r3 = product ? product / (sqrt (norm1 * norm2)) : 0.0; if (r2 > maximumCorrelation && r2 >= r1 && r2 >= r3) { r1_best = r1; maximumCorrelation = r2; r3_best = r3; ir = ileft2 - 1; *peak = localPeak; } } /* * Improve the result by means of parabolic interpolation. */ if (maximumCorrelation > -1.0) { double d2r = 2 * maximumCorrelation - r1_best - r3_best; if (d2r != 0.0) { double dr = 0.5 * (r3_best - r1_best); maximumCorrelation += 0.5 * dr * dr / d2r; ir += dr / d2r; } *tout = t1 + (ir - ileft1) * my dx; } return maximumCorrelation; }
static double Sound_findExtremum (Sound me, double tmin, double tmax, int includeMaxima, int includeMinima) { long imin = Sampled_xToLowIndex (me, tmin), imax = Sampled_xToHighIndex (me, tmax); double iextremum; Melder_assert (NUMdefined (tmin)); Melder_assert (NUMdefined (tmax)); if (imin < 1) imin = 1; if (imax > my nx) imax = my nx; iextremum = findExtremum_3 (my z [1], my ny > 1 ? my z [2] : NULL, imin - 1, imax - imin + 1, includeMaxima, includeMinima); if (iextremum) return my x1 + (imin - 1 + iextremum - 1) * my dx; else return (tmin + tmax) / 2; }
static void menu_cb_voiceless (EDITOR_ARGS) { EDITOR_IAM (PitchEditor); Pitch pitch = (Pitch) my data; long ileft = Sampled_xToHighIndex (pitch, my d_startSelection); long iright = Sampled_xToLowIndex (pitch, my d_endSelection); if (ileft < 1) ileft = 1; if (iright > pitch -> nx) iright = pitch -> nx; Editor_save (me, L"Unvoice"); for (long i = ileft; i <= iright; i ++) { Pitch_Frame frame = & pitch -> frame [i]; for (long cand = 1; cand <= frame -> nCandidates; cand ++) { if (frame -> candidate [cand]. frequency == 0.0) { struct structPitch_Candidate help = frame -> candidate [1]; frame -> candidate [1] = frame -> candidate [cand]; frame -> candidate [cand] = help; } } } FunctionEditor_redraw (me); my broadcastDataChanged (); }
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; }
/* gain used as a constant amplitude multiplyer within a frame of duration my dx. future alternative: convolve gain with a smoother. */ autoSound LPC_and_Sound_filter (LPC me, Sound thee, int useGain) { try { double xmin = my xmin > thy xmin ? my xmin : thy xmin; double xmax = my xmax < thy xmax ? my xmax : thy xmax; if (xmin >= xmax) { Melder_throw (U"Domains of Sound [", thy xmin, U",", thy xmax, U"] and LPC [", my xmin, U",", my xmax, U"] do not overlap."); } // resample sound if samplings don't match autoSound source; if (my samplingPeriod != thy dx) { source = Sound_resample (thee, 1.0 / my samplingPeriod, 50); thee = source.get(); // reference copy; remove at end } autoSound him = Data_copy (thee); double *x = his z[1]; long ifirst = Sampled_xToHighIndex (thee, xmin); long ilast = Sampled_xToLowIndex (thee, xmax); for (long i = ifirst; i <= ilast; i++) { double t = his x1 + (i - 1) * his dx; /* Sampled_indexToX (him, i) */ long iFrame = lround ( (t - my x1) / my dx + 1.0); /* Sampled_xToNearestIndex (me, t) */ if (iFrame < 1) { continue; } if (iFrame > my nx) { break; } double *a = my d_frames[iFrame].a; long m = i > my d_frames[iFrame].nCoefficients ? my d_frames[iFrame].nCoefficients : i - 1; for (long j = 1; j <= m; j++) { x[i] -= a[j] * x[i - j]; } } // Make samples before first frame and after last frame zero. for (long i = 1; i < ifirst; i++) { x[i] = 0.0; } for (long i = ilast + 1; i <= his nx; i++) { x[i] = 0.0; } if (useGain) { for (long i = ifirst; i <= ilast; i++) { double t = his x1 + (i - 1) * his dx; /* Sampled_indexToX (him, i) */ double riFrame = (t - my x1) / my dx + 1; /* Sampled_xToIndex (me, t); */ long iFrame = (long) floor (riFrame); double phase = riFrame - iFrame; if (iFrame < 0 || iFrame > my nx) { x[i] = 0.0; } else if (iFrame == 0) { x[i] *= sqrt (my d_frames[1].gain) * phase; } else if (iFrame == my nx) { x[i] *= sqrt (my d_frames[my nx].gain) * (1.0 - phase); } else x[i] *= phase * sqrt (my d_frames[iFrame + 1].gain) + (1.0 - phase) * sqrt (my d_frames[iFrame].gain); } } return him; } catch (MelderError) { Melder_throw (thee, U": not filtered."); } }
Polygon Sounds_to_Polygon_enclosed (Sound me, Sound thee, int channel, double tmin, double tmax, double ymin, double ymax) { try { bool clip = ymin < ymax; if (my ny > 1 && thy ny > 1 && my ny != thy ny) { Melder_throw ("The numbers of channels of the two sounds have to be equal or 1."); } long numberOfChannels = my ny > thy ny ? my ny : thy ny; if (channel < 1 || channel > numberOfChannels) { Melder_throw ("Channel does not exist."); } // find overlap in the domains with xmin workaround as in Sound_to_Polygon double xmin1 = my x1 - 0.5 * my dx, xmin2 = thy x1 - 0.5 * thy dx ; double xmin = my xmin > thy xmin ? xmin1 : xmin2; double xmax = my xmax < thy xmax ? xmin1 + my nx * my dx : xmin2 + thy nx * thy dx; if (xmax <= xmin) { Melder_throw ("Domains must overlap."); } if (tmin >= tmax) { tmin = xmin; tmax = xmax; } if (tmin < xmin) { tmin = xmin; } if (tmax > xmax) { tmax = xmax; } if (tmin >= xmax || tmax < xmin) { Melder_throw ("Invalid domain."); } long k = 1; long ib1 = Sampled_xToHighIndex (me, tmin); long ie1 = Sampled_xToLowIndex (me, tmax); long n1 = ie1 - ib1 + 1; long ib2 = Sampled_xToHighIndex (thee, tmin); long ie2 = Sampled_xToLowIndex (thee, tmax); long n2 = ie2 - ib2 + 1; long numberOfPoints = n1 + n2 + 4; // me + thee + begin + endpoint + closing autoPolygon him = Polygon_create (numberOfPoints); // my starting point at tmin double y = Vector_getValueAtX (me, tmin, (my ny == 1 ? 1 : channel), Vector_VALUE_INTERPOLATION_LINEAR); his x[k] = tmin; his y[k++] = CLIP_Y (y, ymin, ymax); // my samples for (long i = ib1; i <= ie1; i++) { double t = my x1 + (i - 1) * my dx; y = my z[my ny == 1 ? 1 : channel][i]; his x[k] = t; his y[k++] = CLIP_Y (y, ymin, ymax); } // my end point at tmax y = Vector_getValueAtX (me, tmax, (my ny == 1 ? 1 : channel), Vector_VALUE_INTERPOLATION_LINEAR); his x[k] = tmax; his y[k++] = y; // thy starting point at tmax y = Vector_getValueAtX (thee, tmax, (thy ny == 1 ? 1 : channel), Vector_VALUE_INTERPOLATION_LINEAR); his x[k] = tmax; his y[k++] = y; // thy samples for (long i = ie2; i >= ib2; i--) { double t = thy x1 + (i - 1) * thy dx; y = thy z[thy ny == 1 ? 1 : channel][i]; his x[k] = t; his y[k++] = CLIP_Y (y, ymin, ymax); } // thy end point at tmin y = Vector_getValueAtX (thee, tmin, (thy ny == 1 ? 1 : channel), Vector_VALUE_INTERPOLATION_LINEAR); his x[k] = tmin; his y[k] = y; Melder_assert (k == numberOfPoints); return him.transfer(); } catch (MelderError) { Melder_throw (me, ": no enclosed Polygon created."); } }