double RealTier_getMean_curve (I, double tmin, double tmax) { iam (RealTier); if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } /* Autowindow. */ double area = RealTier_getArea (me, tmin, tmax); if (area == NUMundefined) return NUMundefined; return area / (tmax - tmin); }
autoSound Sound_Point_Pitch_Duration_to_Sound (Sound me, PointProcess pulses, PitchTier pitch, DurationTier duration, double maxT) { try { long ipointleft, ipointright; double deltat = 0, handledTime = my xmin; double startOfSourceNoise, endOfSourceNoise, startOfTargetNoise, endOfTargetNoise; double durationOfSourceNoise, durationOfTargetNoise; double startOfSourceVoice, endOfSourceVoice, startOfTargetVoice, endOfTargetVoice; double durationOfSourceVoice, durationOfTargetVoice; double startingPeriod, finishingPeriod, ttarget, voicelessPeriod; if (duration -> points.size == 0) Melder_throw (U"No duration points."); /* * Create a Sound long enough to hold the longest possible duration-manipulated sound. */ autoSound thee = Sound_create (1, my xmin, my xmin + 3 * (my xmax - my xmin), 3 * my nx, my dx, my x1); /* * Below, I'll abbreviate the voiced interval as "voice" and the voiceless interval as "noise". */ if (pitch && pitch -> points.size) for (ipointleft = 1; ipointleft <= pulses -> nt; ipointleft = ipointright + 1) { /* * Find the beginning of the voice. */ startOfSourceVoice = pulses -> t [ipointleft]; // the first pulse of the voice startingPeriod = 1.0 / RealTier_getValueAtTime (pitch, startOfSourceVoice); startOfSourceVoice -= 0.5 * startingPeriod; // the first pulse is in the middle of a period /* * Measure one noise. */ startOfSourceNoise = handledTime; endOfSourceNoise = startOfSourceVoice; durationOfSourceNoise = endOfSourceNoise - startOfSourceNoise; startOfTargetNoise = startOfSourceNoise + deltat; endOfTargetNoise = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, endOfSourceNoise); durationOfTargetNoise = endOfTargetNoise - startOfTargetNoise; /* * Copy the noise. */ voicelessPeriod = NUMrandomUniform (0.008, 0.012); ttarget = startOfTargetNoise + 0.5 * voicelessPeriod; while (ttarget < endOfTargetNoise) { double tsource; double tleft = startOfSourceNoise, tright = endOfSourceNoise; int i; for (i = 1; i <= 15; i ++) { double tsourcemid = 0.5 * (tleft + tright); double ttargetmid = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, tsourcemid); if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid; } tsource = 0.5 * (tleft + tright); copyBell (me, tsource, voicelessPeriod, voicelessPeriod, thee.get(), ttarget); voicelessPeriod = NUMrandomUniform (0.008, 0.012); ttarget += voicelessPeriod; } deltat += durationOfTargetNoise - durationOfSourceNoise; /* * Find the end of the voice. */ for (ipointright = ipointleft + 1; ipointright <= pulses -> nt; ipointright ++) if (pulses -> t [ipointright] - pulses -> t [ipointright - 1] > maxT) break; ipointright --; endOfSourceVoice = pulses -> t [ipointright]; // the last pulse of the voice finishingPeriod = 1.0 / RealTier_getValueAtTime (pitch, endOfSourceVoice); endOfSourceVoice += 0.5 * finishingPeriod; // the last pulse is in the middle of a period /* * Measure one voice. */ durationOfSourceVoice = endOfSourceVoice - startOfSourceVoice; /* * This will be copied to an interval with a different location and duration. */ startOfTargetVoice = startOfSourceVoice + deltat; endOfTargetVoice = startOfTargetVoice + RealTier_getArea (duration, startOfSourceVoice, endOfSourceVoice); durationOfTargetVoice = endOfTargetVoice - startOfTargetVoice; /* * Copy the voiced part. */ ttarget = startOfTargetVoice + 0.5 * startingPeriod; while (ttarget < endOfTargetVoice) { double tsource, period; long isourcepulse; double tleft = startOfSourceVoice, tright = endOfSourceVoice; int i; for (i = 1; i <= 15; i ++) { double tsourcemid = 0.5 * (tleft + tright); double ttargetmid = startOfTargetVoice + RealTier_getArea (duration, startOfSourceVoice, tsourcemid); if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid; } tsource = 0.5 * (tleft + tright); period = 1.0 / RealTier_getValueAtTime (pitch, tsource); isourcepulse = PointProcess_getNearestIndex (pulses, tsource); copyBell2 (me, pulses, isourcepulse, period, period, thee.get(), ttarget, maxT); ttarget += period; } deltat += durationOfTargetVoice - durationOfSourceVoice; handledTime = endOfSourceVoice; } /* * Copy the remaining unvoiced part, if we are at the end. */ startOfSourceNoise = handledTime; endOfSourceNoise = my xmax; durationOfSourceNoise = endOfSourceNoise - startOfSourceNoise; startOfTargetNoise = startOfSourceNoise + deltat; endOfTargetNoise = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, endOfSourceNoise); durationOfTargetNoise = endOfTargetNoise - startOfTargetNoise; voicelessPeriod = NUMrandomUniform (0.008, 0.012); ttarget = startOfTargetNoise + 0.5 * voicelessPeriod; while (ttarget < endOfTargetNoise) { double tsource; double tleft = startOfSourceNoise, tright = endOfSourceNoise; for (int i = 1; i <= 15; i ++) { double tsourcemid = 0.5 * (tleft + tright); double ttargetmid = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, tsourcemid); if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid; } tsource = 0.5 * (tleft + tright); copyBell (me, tsource, voicelessPeriod, voicelessPeriod, thee.get(), ttarget); voicelessPeriod = NUMrandomUniform (0.008, 0.012); ttarget += voicelessPeriod; } /* * Find the number of trailing zeroes and hack the sound's time domain. */ thy xmax = thy xmin + RealTier_getArea (duration, my xmin, my xmax); if (fabs (thy xmax - my xmax) < 1e-12) thy xmax = my xmax; // common situation thy nx = Sampled_xToLowIndex (thee.get(), thy xmax); if (thy nx > 3 * my nx) thy nx = 3 * my nx; return thee; } catch (MelderError) { Melder_throw (me, U": not manipulated."); } }