Beispiel #1
0
Sound Sound_resample (Sound me, double samplingFrequency, long precision) {
	double upfactor = samplingFrequency * my dx;
	if (fabs (upfactor - 2) < 1e-6) return Sound_upsample (me);
	if (fabs (upfactor - 1) < 1e-6) return Data_copy (me);
	try {
		long numberOfSamples = lround ((my xmax - my xmin) * samplingFrequency);
		if (numberOfSamples < 1)
			Melder_throw (U"The resampled Sound would have no samples.");
		autoSound filtered = NULL;
		if (upfactor < 1.0) {   // need anti-aliasing filter?
			long nfft = 1, antiTurnAround = 1000;
			while (nfft < my nx + antiTurnAround * 2) nfft *= 2;
			autoNUMvector <double> data (1, nfft);
			filtered.reset (Sound_create (my ny, my xmin, my xmax, my nx, my dx, my x1));
			for (long channel = 1; channel <= my ny; channel ++) {
				for (long i = 1; i <= nfft; i ++) {
					data [i] = 0;
				}
				NUMvector_copyElements (my z [channel], & data [antiTurnAround], 1, my nx);
				NUMrealft (data.peek(), nfft, 1);   // go to the frequency domain
				for (long i = (long) floor (upfactor * nfft); i <= nfft; i ++) {
					data [i] = 0;   // filter away high frequencies
				}
				data [2] = 0.0;
				NUMrealft (data.peek(), nfft, -1);   // return to the time domain
				double factor = 1.0 / nfft;
				double *to = filtered -> z [channel];
				for (long i = 1; i <= my nx; i ++) {
					to [i] = data [i + antiTurnAround] * factor;
				}
			}
			me = filtered.peek();   // reference copy; remove at end
		}
		autoSound thee = Sound_create (my ny, my xmin, my xmax, numberOfSamples, 1.0 / samplingFrequency,
			0.5 * (my xmin + my xmax - (numberOfSamples - 1) / samplingFrequency));
		for (long channel = 1; channel <= my ny; channel ++) {
			double *from = my z [channel];
			double *to = thy z [channel];
			if (precision <= 1) {
				for (long i = 1; i <= numberOfSamples; i ++) {
					double x = Sampled_indexToX (thee.peek(), i);
					double index = Sampled_xToIndex (me, x);
					long leftSample = (long) floor (index);
					double fraction = index - leftSample;
					to [i] = leftSample < 1 || leftSample >= my nx ? 0.0 :
						(1 - fraction) * from [leftSample] + fraction * from [leftSample + 1];
				}
			} else {
				for (long i = 1; i <= numberOfSamples; i ++) {
					double x = Sampled_indexToX (thee.peek(), i);
					double index = Sampled_xToIndex (me, x);
					to [i] = NUM_interpolate_sinc (my z [channel], my nx, index, precision);
				}
			}
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not resampled.");
	}
}
Beispiel #2
0
Sound Sound_upsample (Sound me) {
	try {
		long nfft = 1;
		while (nfft < my nx + 2000) nfft *= 2;
		autoSound thee = Sound_create (my ny, my xmin, my xmax, my nx * 2, my dx / 2, my x1 - my dx / 4);
		for (long channel = 1; channel <= my ny; channel ++) {
			autoNUMvector <double> data (1, 2 * nfft);   // zeroing is important...
			NUMvector_copyElements (my z [channel], & data [1000], 1, my nx);   // ...because this fills only part of the sound
			NUMrealft (data.peek(), nfft, 1);
			long imin = (long) (nfft * 0.95);
			for (long i = imin + 1; i <= nfft; i ++) {
				data [i] *= ((double) (nfft - i)) / (nfft - imin);
			}
			data [2] = 0.0;
			NUMrealft (data.peek(), 2 * nfft, -1);
			double factor = 1.0 / nfft;
			for (long i = 1; i <= thy nx; i ++) {
				thy z [channel] [i] = data [i + 2000] * factor;
			}
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not upsampled.");
	}
}
Beispiel #3
0
Sound Sound_resample (Sound me, double samplingFrequency, long precision) {
	double *data = NULL;
	double upfactor = samplingFrequency * my dx;
	long numberOfSamples = floor ((my xmax - my xmin) * samplingFrequency + 0.5), i;
	Sound thee = NULL, filtered = NULL;
	if (fabs (upfactor - 2) < 1e-6) return Sound_upsample (me);
	if (fabs (upfactor - 1) < 1e-6) return (structSound *)Data_copy (me);
	if (numberOfSamples < 1)
		return (structSound *)Melder_errorp ("Cannot resample to 0 samples.");
	thee = Sound_create (my ny, my xmin, my xmax, numberOfSamples, 1.0 / samplingFrequency,
		0.5 * (my xmin + my xmax - (numberOfSamples - 1) / samplingFrequency)); cherror
	if (upfactor < 1.0) {   /* Need anti-aliasing filter? */
		long nfft = 1, antiTurnAround = 1000;
		while (nfft < my nx + antiTurnAround * 2) nfft *= 2;
		data = NUMdvector (1, nfft); cherror
		filtered = Sound_create (my ny, my xmin, my xmax, my nx, my dx, my x1); cherror
		for (long channel = 1; channel <= my ny; channel ++) {
			for (long i = 1; i <= nfft; i ++) {
				data [i] = 0;
			}
			NUMdvector_copyElements (my z [channel], data + antiTurnAround, 1, my nx);
			NUMrealft (data, nfft, 1); cherror   /* Go to the frequency domain. */
			for (long i = floor (upfactor * nfft); i <= nfft; i ++) {
				data [i] = 0;   /* Filter away high frequencies. */
			}
			data [2] = 0.0;
			NUMrealft (data, nfft, -1); cherror   /* Return to the time domain. */
			double factor = 1.0 / nfft;
			double *to = filtered -> z [channel];
			for (long i = 1; i <= my nx; i ++) {
				to [i] = data [i + antiTurnAround] * factor;
			}
		}
		me = filtered;   /* Reference copy. Remove at end. */
	}
Beispiel #4
0
Sound Sound_upsample (Sound me) {
	double *data = NULL;
	Sound thee = NULL;

	long nfft = 1;
	while (nfft < my nx + 2000) nfft *= 2;
	thee = Sound_create (my ny, my xmin, my xmax, my nx * 2, my dx / 2, my x1); cherror
	data = NUMdvector (1, 2 * nfft); cherror
	for (long channel = 1; channel <= my ny; channel ++) {
		NUMdvector_copyElements (my z [channel], data + 1000, 1, my nx);
		NUMrealft (data, nfft, 1); cherror
		long imin = (long) (nfft * 0.95);
		for (long i = imin + 1; i <= nfft; i ++) {
			data [i] *= ((double) (nfft - i)) / (nfft - imin);
		}
		data [2] = 0.0;
		NUMrealft (data, 2 * nfft, -1); cherror
		double factor = 1.0 / nfft;
		for (long i = 1; i <= thy nx; i ++) {
			thy z [channel] [i] = data [i + 2000] * factor;
		}
	}
end:
	NUMdvector_free (data, 1);
	iferror forget (thee);
	return thee;
}
Beispiel #5
0
autoSound Spectrum_to_Sound (Spectrum me) {
	try {
		double *re = my z [1], *im = my z [2];
		double lastFrequency = my x1 + (my nx - 1) * my dx;
		int originalNumberOfSamplesProbablyOdd = im [my nx] != 0.0 || my xmax - lastFrequency > 0.25 * my dx;
		if (my x1 != 0.0)
			Melder_throw (U"A Fourier-transformable Spectrum must have a first frequency of 0 Hz, not ", my x1, U" Hz.");
		long numberOfSamples = 2 * my nx - ( originalNumberOfSamplesProbablyOdd ? 1 : 2 );
		autoSound thee = Sound_createSimple (1, 1 / my dx, numberOfSamples * my dx);
		double *amp = thy z [1];
		double scaling = my dx;
		amp [1] = re [1] * scaling;
		for (long i = 2; i < my nx; i ++) {
			amp [i + i - 1] = re [i] * scaling;
			amp [i + i] = im [i] * scaling;
		}
		if (originalNumberOfSamplesProbablyOdd) {
			amp [numberOfSamples] = re [my nx] * scaling;
			if (numberOfSamples > 1) amp [2] = im [my nx] * scaling;
		} else {
			amp [2] = re [my nx] * scaling;
		}
		NUMrealft (amp, numberOfSamples, -1);
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Sound.");
	}
}
Beispiel #6
0
autoSpectrum Spectrum_lpcSmoothing (Spectrum me, int numberOfPeaks, double preemphasisFrequency) {
	try {
		double gain, a [100];
		long numberOfCoefficients = 2 * numberOfPeaks;

		autoSound sound = Spectrum_to_Sound (me);
		NUMpreemphasize_f (sound -> z [1], sound -> nx, sound -> dx, preemphasisFrequency);	 	
		
		NUMburg (sound -> z [1], sound -> nx, a, numberOfCoefficients, & gain);
		for (long i = 1; i <= numberOfCoefficients; i ++) a [i] = - a [i];
		autoSpectrum thee = Data_copy (me);

		long nfft = 2 * (thy nx - 1);
		long ndata = numberOfCoefficients < nfft ? numberOfCoefficients : nfft - 1;
		double scale = 10 * (gain > 0 ? sqrt (gain) : 1) / numberOfCoefficients;
		autoNUMvector <double> data (1, nfft);
		data [1] = 1;
		for (long i = 1; i <= ndata; i ++)
			data [i + 1] = a [i];
		NUMrealft (data.peek(), nfft, 1);
		double *re = thy z [1];
		double *im = thy z [2];
		re [1] = scale / data [1];
		im [1] = 0.0;
		long halfnfft = nfft / 2;
		for (long i = 2; i <= halfnfft; i ++) {
			double real = data [i + i - 1], imag = data [i + i];
			re [i] = scale / sqrt (real * real + imag * imag) / (1 + thy dx * (i - 1) / preemphasisFrequency);
			im [i] = 0;
		}
		re [halfnfft + 1] = scale / data [2] / (1 + thy dx * halfnfft / preemphasisFrequency);
		im [halfnfft + 1] = 0.0;
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not smoothed.");
	}
}
Beispiel #7
0
Sound Sound_autoCorrelate (Sound me, enum kSounds_convolve_scaling scaling, enum kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
	try {
		long numberOfChannels = my ny, n1 = my nx, n2 = n1 + n1 - 1, nfft = 1;
		while (nfft < n2) nfft *= 2;
		autoNUMvector <double> data (1, nfft);
		double my_xlast = my x1 + (n1 - 1) * my dx;
		autoSound thee = Sound_create (numberOfChannels, my xmin - my xmax, my xmax - my xmin, n2, my dx, my x1 - my_xlast);
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			double *a = my z [channel];
			for (long i = n1; i > 0; i --) data [i] = a [i];
			for (long i = n1 + 1; i <= nfft; i ++) data [i] = 0.0;
			NUMrealft (data.peek(), nfft, 1);
			data [1] *= data [1];
			data [2] *= data [2];
			for (long i = 3; i <= nfft; i += 2) {
				data [i] = data [i] * data [i] + data [i + 1] * data [i + 1];
				data [i + 1] = 0.0;   // reverse me by taking the conjugate of data1
			}
			NUMrealft (data.peek(), nfft, -1);
			a = thy z [channel];
			for (long i = 1; i < n1; i ++) {
				a [i] = data [i + (nfft - (n1 - 1))];   // data for the first part ("negative lags") is at the end of data
			}
			for (long i = 1; i <= n1; i ++) {
				a [i + (n1 - 1)] = data [i];   // data for the second part ("positive lags") is at the beginning of data
			}
		}
		switch (signalOutsideTimeDomain) {
			case kSounds_convolve_signalOutsideTimeDomain_ZERO: {
				// do nothing
			} break;
			case kSounds_convolve_signalOutsideTimeDomain_SIMILAR: {
				for (long channel = 1; channel <= numberOfChannels; channel ++) {
					double *a = thy z [channel];
					double edge = n1;
					for (long i = 1; i < edge; i ++) {
						double factor = edge / i;
						a [i] *= factor;
						a [n2 + 1 - i] *= factor;
					}
				}
			} break;
			//case kSounds_convolve_signalOutsideTimeDomain_PERIODIC: {
				// do nothing
			//} break;
			default: Melder_fatal (U"Sounds_autoCorrelate: unimplemented outside-time-domain strategy ", signalOutsideTimeDomain);
		}
		switch (scaling) {
			case kSounds_convolve_scaling_INTEGRAL: {
				Vector_multiplyByScalar (thee.peek(), my dx / nfft);
			} break;
			case kSounds_convolve_scaling_SUM: {
				Vector_multiplyByScalar (thee.peek(), 1.0 / nfft);
			} break;
			case kSounds_convolve_scaling_NORMALIZE: {
				double normalizationFactor = Matrix_getNorm (me) * Matrix_getNorm (me);
				if (normalizationFactor != 0.0) {
					Vector_multiplyByScalar (thee.peek(), 1.0 / nfft / normalizationFactor);
				}
			} break;
			case kSounds_convolve_scaling_PEAK_099: {
				Vector_scale (thee.peek(), 0.99);
			} break;
			default: Melder_fatal (U"Sounds_autoCorrelate: unimplemented scaling ", scaling);
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": autocorrelation not computed.");
	}
}
Beispiel #8
0
Sound Sounds_crossCorrelate (Sound me, Sound thee, enum kSounds_convolve_scaling scaling, enum kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
	try {
		if (my ny > 1 && thy ny > 1 && my ny != thy ny)
			Melder_throw (U"The numbers of channels of the two sounds have to be equal or 1.");
		if (my dx != thy dx)
			Melder_throw (U"The sampling frequencies of the two sounds have to be equal.");
		long numberOfChannels = my ny > thy ny ? my ny : thy ny;
		long n1 = my nx, n2 = thy nx;
		long n3 = n1 + n2 - 1, nfft = 1;
		while (nfft < n3) nfft *= 2;
		autoNUMvector <double> data1 (1, nfft);
		autoNUMvector <double> data2 (1, nfft);
		double my_xlast = my x1 + (n1 - 1) * my dx;
		autoSound him = Sound_create (numberOfChannels, thy xmin - my xmax, thy xmax - my xmin, n3, my dx, thy x1 - my_xlast);
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			double *a = my z [my ny == 1 ? 1 : channel];
			for (long i = n1; i > 0; i --) data1 [i] = a [i];
			for (long i = n1 + 1; i <= nfft; i ++) data1 [i] = 0.0;
			a = thy z [thy ny == 1 ? 1 : channel];
			for (long i = n2; i > 0; i --) data2 [i] = a [i];
			for (long i = n2 + 1; i <= nfft; i ++) data2 [i] = 0.0;
			NUMrealft (data1.peek(), nfft, 1);
			NUMrealft (data2.peek(), nfft, 1);
			data2 [1] *= data1 [1];
			data2 [2] *= data1 [2];
			for (long i = 3; i <= nfft; i += 2) {
				double temp = data1 [i] * data2 [i] + data1 [i + 1] * data2 [i + 1];   // reverse me by taking the conjugate of data1
				data2 [i + 1] = data1 [i] * data2 [i + 1] - data1 [i + 1] * data2 [i];   // reverse me by taking the conjugate of data1
				data2 [i] = temp;
			}
			NUMrealft (data2.peek(), nfft, -1);
			a = him -> z [channel];
			for (long i = 1; i < n1; i ++) {
				a [i] = data2 [i + (nfft - (n1 - 1))];   // data for the first part ("negative lags") is at the end of data2
			}
			for (long i = 1; i <= n2; i ++) {
				a [i + (n1 - 1)] = data2 [i];   // data for the second part ("positive lags") is at the beginning of data2
			}
		}
		switch (signalOutsideTimeDomain) {
			case kSounds_convolve_signalOutsideTimeDomain_ZERO: {
				// do nothing
			} break;
			case kSounds_convolve_signalOutsideTimeDomain_SIMILAR: {
				for (long channel = 1; channel <= numberOfChannels; channel ++) {
					double *a = his z [channel];
					double edge = n1 < n2 ? n1 : n2;
					for (long i = 1; i < edge; i ++) {
						double factor = edge / i;
						a [i] *= factor;
						a [n3 + 1 - i] *= factor;
					}
				}
			} break;
			//case kSounds_convolve_signalOutsideTimeDomain_PERIODIC: {
				// do nothing
			//} break;
			default: Melder_fatal (U"Sounds_crossCorrelate: unimplemented outside-time-domain strategy ", signalOutsideTimeDomain);
		}
		switch (scaling) {
			case kSounds_convolve_scaling_INTEGRAL: {
				Vector_multiplyByScalar (him.peek(), my dx / nfft);
			} break;
			case kSounds_convolve_scaling_SUM: {
				Vector_multiplyByScalar (him.peek(), 1.0 / nfft);
			} break;
			case kSounds_convolve_scaling_NORMALIZE: {
				double normalizationFactor = Matrix_getNorm (me) * Matrix_getNorm (thee);
				if (normalizationFactor != 0.0) {
					Vector_multiplyByScalar (him.peek(), 1.0 / nfft / normalizationFactor);
				}
			} break;
			case kSounds_convolve_scaling_PEAK_099: {
				Vector_scale (him.peek(), 0.99);
			} break;
			default: Melder_fatal (U"Sounds_crossCorrelate: unimplemented scaling ", scaling);
		}
		return him.transfer();
	} catch (MelderError) {
		Melder_throw (me, U" & ", thee, U": not cross-correlated.");
	}
}