void Sound_playPart (Sound me, double tmin, double tmax, int (*callback) (void *closure, int phase, double tmin, double tmax, double t), void *closure) { try { long ifsamp = lround (1.0 / my dx), bestSampleRate = MelderAudio_getOutputBestSampleRate (ifsamp); if (ifsamp == bestSampleRate) { struct SoundPlay *thee = (struct SoundPlay *) & thePlayingSound; double *fromLeft = my z [1], *fromRight = my ny > 1 ? my z [2] : NULL; MelderAudio_stopPlaying (MelderAudio_IMPLICIT); long i1, i2; if ((thy numberOfSamples = Matrix_getWindowSamplesX (me, tmin, tmax, & i1, & i2)) < 1) return; thy tmin = tmin; thy tmax = tmax; thy dt = my dx; thy t1 = my x1; thy callback = callback; thy closure = closure; thy silenceBefore = (long) (ifsamp * MelderAudio_getOutputSilenceBefore ()); thy silenceAfter = (long) (ifsamp * MelderAudio_getOutputSilenceAfter ()); int numberOfChannels = my ny; NUMvector_free (thy buffer, 1); // just in case thy buffer = NUMvector <short> (1, (i2 - i1 + 1 + thy silenceBefore + thy silenceAfter) * numberOfChannels); thy i1 = i1; thy i2 = i2; short *to = thy buffer + thy silenceBefore * numberOfChannels; if (numberOfChannels > 2) { for (long i = i1; i <= i2; i ++) { for (long chan = 1; chan <= my ny; chan ++) { long value = (long) round (my z [chan] [i] * 32768.0); * ++ to = value < -32768 ? -32768 : value > 32767 ? 32767 : value; } } } else if (numberOfChannels == 2) { for (long i = i1; i <= i2; i ++) { long valueLeft = (long) round (fromLeft [i] * 32768.0); * ++ to = valueLeft < -32768 ? -32768 : valueLeft > 32767 ? 32767 : valueLeft; long valueRight = (long) round (fromRight [i] * 32768.0); * ++ to = valueRight < -32768 ? -32768 : valueRight > 32767 ? 32767 : valueRight; } } else { for (long i = i1; i <= i2; i ++) { long value = (long) round (fromLeft [i] * 32768.0); * ++ to = value < -32768 ? -32768 : value > 32767 ? 32767 : value; } } if (thy callback) thy callback (thy closure, 1, tmin, tmax, tmin); MelderAudio_play16 (thy buffer + 1, ifsamp, thy silenceBefore + thy numberOfSamples + thy silenceAfter, numberOfChannels, melderPlayCallback, thee); } else { autoSound resampled = Sound_resample (me, bestSampleRate, 1); Sound_playPart (resampled.peek(), tmin, tmax, callback, closure); // recursively } } catch (MelderError) { Melder_throw (me, U": not played."); } }
void LongSound_playPart (LongSound me, double tmin, double tmax, Sound_PlayCallback callback, Thing boss) { struct LongSoundPlay *thee = (struct LongSoundPlay *) & thePlayingLongSound; MelderAudio_stopPlaying (MelderAudio_IMPLICIT); Melder_free (thy resampledBuffer); // just in case, and after playing has stopped try { int fits = LongSound_haveWindow (me, tmin, tmax); long bestSampleRate = MelderAudio_getOutputBestSampleRate (my sampleRate), n, i1, i2; if (! fits) Melder_throw (U"Sound too long (", tmax - tmin, U" seconds)."); /* * Assign to *thee only after stopping the playing sound. */ thy tmin = tmin; thy tmax = tmax; thy callback = callback; thy boss = boss; if ((n = Sampled_getWindowSamples (me, tmin, tmax, & i1, & i2)) < 2) return; if (bestSampleRate == my sampleRate) { thy numberOfSamples = n; thy dt = 1 / my sampleRate; thy t1 = my x1; thy i1 = i1; thy i2 = i2; thy silenceBefore = (long) (my sampleRate * MelderAudio_getOutputSilenceBefore ()); thy silenceAfter = (long) (my sampleRate * MelderAudio_getOutputSilenceAfter ()); if (thy callback) thy callback (thy boss, 1, tmin, tmax, tmin); if (thy silenceBefore > 0 || thy silenceAfter > 0 || 1) { thy resampledBuffer = Melder_calloc (int16, (thy silenceBefore + thy numberOfSamples + thy silenceAfter) * my numberOfChannels); memcpy (& thy resampledBuffer [thy silenceBefore * my numberOfChannels], & my buffer [(i1 - my imin) * my numberOfChannels], thy numberOfSamples * sizeof (int16) * my numberOfChannels); MelderAudio_play16 (thy resampledBuffer, my sampleRate, thy silenceBefore + thy numberOfSamples + thy silenceAfter, my numberOfChannels, melderPlayCallback, thee); } else { MelderAudio_play16 (my buffer + (i1 - my imin) * my numberOfChannels, my sampleRate, thy numberOfSamples, my numberOfChannels, melderPlayCallback, thee); } } else { long newSampleRate = bestSampleRate; long newN = ((double) n * newSampleRate) / my sampleRate - 1; long silenceBefore = (long) (newSampleRate * MelderAudio_getOutputSilenceBefore ()); long silenceAfter = (long) (newSampleRate * MelderAudio_getOutputSilenceAfter ()); int16 *resampledBuffer = Melder_calloc (int16, (silenceBefore + newN + silenceAfter) * my numberOfChannels); int16 *from = my buffer + (i1 - my imin) * my numberOfChannels; // guaranteed: from [0 .. (my imax - my imin + 1) * nchan] double t1 = my x1, dt = 1.0 / newSampleRate; thy numberOfSamples = newN; thy dt = dt; thy t1 = t1 + i1 / my sampleRate; thy i1 = 0; thy i2 = newN - 1; thy silenceBefore = silenceBefore; thy silenceAfter = silenceAfter; thy resampledBuffer = resampledBuffer; if (my numberOfChannels == 1) { for (long i = 0; i < newN; i ++) { double t = t1 + i * dt; // from t1 to t1 + (newN-1) * dt double index = (t - t1) * my sampleRate; // from 0 long flore = index; // DANGEROUS: Implicitly rounding down... double fraction = index - flore; resampledBuffer [i + silenceBefore] = (1.0 - fraction) * from [flore] + fraction * from [flore + 1]; } } else if (my numberOfChannels == 2) { for (long i = 0; i < newN; i ++) { double t = t1 + i * dt; double index = (t - t1) * my sampleRate; long flore = index; double fraction = index - flore; long ii = i + silenceBefore; resampledBuffer [ii + ii] = (1.0 - fraction) * from [flore + flore] + fraction * from [flore + flore + 2]; resampledBuffer [ii + ii + 1] = (1.0 - fraction) * from [flore + flore + 1] + fraction * from [flore + flore + 3]; } } else { for (long i = 0; i < newN; i ++) { double t = t1 + i * dt; double index = (t - t1) * my sampleRate; long flore = index; double fraction = index - flore; long ii = (i + silenceBefore) * my numberOfChannels; for (long chan = 0; chan < my numberOfChannels; chan ++) { resampledBuffer [ii + chan] = (1.0 - fraction) * from [flore * my numberOfChannels + chan] + fraction * from [(flore + 1) * my numberOfChannels + chan]; } } } if (thy callback) thy callback (thy boss, 1, tmin, tmax, tmin); MelderAudio_play16 (resampledBuffer, newSampleRate, silenceBefore + newN + silenceAfter, my numberOfChannels, melderPlayCallback, thee); } //Melder_free (thy resampledBuffer); // cannot do that, because MelderAudio_play16 isn't necessarily synchronous } catch (MelderError) { Melder_free (thy resampledBuffer); Melder_throw (me, U": not played."); } }