static int PointProcess_isVoiced_t (PointProcess me, double t, double maxT) { long imid = PointProcess_getNearestIndex (me, t); if (imid == 0) return 0; double tmid = my t [imid]; int leftVoiced = imid > 1 && tmid - my t [imid - 1] <= maxT; int rightVoiced = imid < my nt && my t [imid + 1] - tmid <= maxT; if ((leftVoiced && t <= tmid) || (rightVoiced && t >= tmid)) return 1; if (leftVoiced && t < 1.5 * tmid - 0.5 * my t [imid - 1]) return 1; if (rightVoiced && t > 1.5 * tmid - 0.5 * my t [imid + 1]) return 1; return 0; }
autoSound Sound_Point_Point_to_Sound (Sound me, PointProcess source, PointProcess target, double maxT) { try { autoSound thee = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1); if (source -> nt < 2 || target -> nt < 2) { // almost completely voiceless? NUMvector_copyElements (my z [1], thy z [1], 1, my nx); return thee; } for (long i = 1; i <= target -> nt; i ++) { double tmid = target -> t [i]; double tleft = i > 1 ? target -> t [i - 1] : my xmin; double tright = i < target -> nt ? target -> t [i + 1] : my xmax; double leftWidth = tmid - tleft, rightWidth = tright - tmid; int leftVoiced = i > 1 && leftWidth <= maxT; int rightVoiced = i < target -> nt && rightWidth <= maxT; long isource = PointProcess_getNearestIndex (source, tmid); if (! leftVoiced) leftWidth = rightWidth; // symmetric bell if (! rightVoiced) rightWidth = leftWidth; // symmetric bell if (leftVoiced || rightVoiced) { copyBell2 (me, source, isource, leftWidth, rightWidth, thee.get(), tmid, maxT); if (! leftVoiced) { double startOfFlat = ( i == 1 ? tleft : (tleft + tmid) / 2.0 ); double endOfFlat = tmid - leftWidth; copyFlat (me, startOfFlat, endOfFlat, thee.get(), startOfFlat); copyFall (me, endOfFlat, tmid, thee.get(), endOfFlat); } else if (! rightVoiced) { double startOfFlat = tmid + rightWidth; double endOfFlat = ( i == target -> nt ? tright : (tmid + tright) / 2.0 ); copyRise (me, tmid, startOfFlat, thee.get(), startOfFlat); copyFlat (me, startOfFlat, endOfFlat, thee.get(), startOfFlat); } } else { double startOfFlat = ( i == 1 ? tleft : (tleft + tmid) / 2.0 ); double endOfFlat = ( i == target -> nt ? tright : (tmid + tright) / 2.0 ); copyFlat (me, startOfFlat, endOfFlat, thee.get(), startOfFlat); } } return thee; } catch (MelderError) { Melder_throw (me, U": not manipulated."); } }
void PointProcess_removePointNear (PointProcess me, double t) { PointProcess_removePoint (me, PointProcess_getNearestIndex (me, t)); }
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."); } }