Пример #1
0
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.");
	}
}
Пример #2
0
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.");
	}
}