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."); } }
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. */ }
autoIntensity Sound_to_Intensity (Sound me, double minimumPitch, double timeStep, int subtractMeanPressure) { bool veryAccurate = false; if (veryAccurate) { autoSound up = Sound_upsample (me); // because squaring doubles the frequency content, i.e. you get super-Nyquist components return Sound_to_Intensity_ (up.peek(), minimumPitch, timeStep, subtractMeanPressure); } else { return Sound_to_Intensity_ (me, minimumPitch, timeStep, subtractMeanPressure); } }