Пример #1
0
Matrix Polygon_to_Matrix (Polygon me) {
	try {
		autoMatrix thee = Matrix_create (1, my numberOfPoints, my numberOfPoints, 1, 1, 1, 2, 2, 1, 1);
		NUMvector_copyElements (my x, thy z [1], 1, my numberOfPoints);
		NUMvector_copyElements (my y, thy z [2], 1, my numberOfPoints);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Matrix.");
	}
}
Пример #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.");
	}
}
Пример #3
0
void Minimizer_minimizeManyTimes (Minimizer me, long numberOfTimes, long maxIterationsPerTime, double tolerance) {
	double fopt = my minimum;
	int monitorSingle = numberOfTimes == 1;

	autoNUMvector<double> popt (NUMvector_copy<double> (my p, 1, my nParameters), 1);

	if (! monitorSingle) {
		Melder_progress (0.0, L"Minimize many times");
	}
	/* on first iteration start with current parameters 27/11/97 */
	for (long i = 1; i <= numberOfTimes; i++) {
		Minimizer_minimize (me, maxIterationsPerTime, tolerance, monitorSingle);
		Melder_casual ("Current %ld: minimum = %.17g", i, my minimum);
		if (my minimum < fopt) {
			NUMvector_copyElements (my p, popt.peek(), 1, my nParameters);
			fopt = my minimum;
		}
		Minimizer_reset (me, 0);
		if (! monitorSingle) {
			try {
				Melder_progress ( (double) i / numberOfTimes, Melder_integer (i), L" from ",
				                   Melder_integer (numberOfTimes)); therror
			} catch (MelderError) {
				Melder_clearError ();   // interrurpt, no error
				break;
			}
		}
	}
	if (! monitorSingle) {
		Melder_progress (1.0, 0);
	}
	Minimizer_reset (me, popt.peek());
}
Пример #4
0
void PointProcess_addPoint (PointProcess me, double t) {
	try {
		if (t == NUMundefined)
			Melder_throw (U"Cannot add a point at an undefined time.");
		if (my nt >= my maxnt) {
			/*
			 * Create without change.
			 */
			autoNUMvector <double> dum (1, 2 * my maxnt);
			NUMvector_copyElements (my t, dum.peek(), 1, my nt);
			/*
			 * Change without error.
			 */
			NUMvector_free (my t, 1);
			my t = dum.transfer();
			my maxnt *= 2;
		}
		if (my nt == 0 || t >= my t [my nt]) {   // special case that often occurs in practice
			my t [++ my nt] = t;
		} else {
			long left = PointProcess_getLowIndex (me, t);
			if (left == 0 || my t [left] != t) {
				for (long i = my nt; i > left; i --) my t [i + 1] = my t [i];
				my nt ++;
				my t [left + 1] = t;
			}
		}
	} catch (MelderError) {
		Melder_throw (me, U": point not added.");
	}
}
Пример #5
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.");
	}
}
Пример #6
0
Sound Sounds_append (Sound me, double silenceDuration, Sound thee) {
	try {
		long nx_silence = lround (silenceDuration / my dx), nx = my nx + nx_silence + thy nx;
		if (my ny != thy ny)
			Melder_throw (U"The numbers of channels are not equal (e.g. one is mono, the other stereo).");
		if (my dx != thy dx)
			Melder_throw (U"The sampling frequencies are not equal.");
		autoSound him = Sound_create (my ny, 0, nx * my dx, nx, my dx, 0.5 * my dx);
		for (long channel = 1; channel <= my ny; channel ++) {
			NUMvector_copyElements (my z [channel], his z [channel], 1, my nx);
			NUMvector_copyElements (thy z [channel], his z [channel] + my nx + nx_silence, 1, thy nx);
		}
		return him.transfer();
	} catch (MelderError) {
		Melder_throw (me, U" & ", thee, U": not appended.");
	}
}
Пример #7
0
autoMatrix VocalTract_to_Matrix (VocalTract me) {
    try {
        autoMatrix thee = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, my ymin, my ymax, my ny, my dy, my y1);
        NUMvector_copyElements (my z [1], thy z [1], 1, my nx);
        return thee;
    } catch (MelderError) {
        Melder_throw (me, U": not converted to Matrix.");
    }
}
Пример #8
0
autoVocalTract Matrix_to_VocalTract (Matrix me) {
    try {
        autoVocalTract thee = VocalTract_create (my nx, my dx);
        NUMvector_copyElements (my z [1], thy z [1], 1, my nx);
        return thee;
    } catch (MelderError) {
        Melder_throw (me, U": not converted to VocalTract.");
    }
}
Пример #9
0
autoTableOfReal SVD_extractSingularValues (SVD me) {
	try {
		long mn_min = MIN (my numberOfRows, my numberOfColumns);
		autoTableOfReal thee = TableOfReal_create (1, mn_min);
		NUMvector_copyElements (my d, thy data[1], 1, mn_min);
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": singular values not extracted.");
	}
}
Пример #10
0
void NUMvector_insert (long elementSize, void **v, long lo, long *hi, long position) {
	try {
		char *result;
		if (! *v) {
			result = reinterpret_cast <char *> (NUMvector (elementSize, lo, lo));
			*hi = lo;
			Melder_assert (position == lo);
		} else {
			result = reinterpret_cast <char *> (NUMvector (elementSize, lo, *hi + 1));
			Melder_assert (position >= lo && position <= *hi + 1);
			NUMvector_copyElements (elementSize, *v, result, lo, position - 1);
			NUMvector_copyElements (elementSize, *v, result + elementSize, position, *hi);
			NUMvector_free (elementSize, *v, lo);
			(*hi) ++;
		}
		*v = result;
	} catch (MelderError) {
		Melder_throw (U"Vector: element not inserted.");
	}
}
Пример #11
0
Sound Matrix_to_Sound_mono (Matrix me, long row) {
	try {
		autoSound thee = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1);
		if (row < 0) row = my ny + 1 + row;
		if (row < 1) row = 1;
		if (row > my ny) row = my ny;
		NUMvector_copyElements (my z [row], thy z [1], 1, my nx);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Sound.");
	}
}
Пример #12
0
static void copyFlat (Sound me, double tmin, double tmax, Sound thee, double tminTarget) {
	long imin = Sampled_xToHighIndex (me, tmin);
	if (imin < 1) imin = 1;
	long imax = Sampled_xToHighIndex (me, tmax) - 1;   // not xToLowIndex: ensure separation of subsequent calls
	if (imax > my nx) imax = my nx;
	if (imax < imin) return;
	long iminTarget = Sampled_xToHighIndex (thee, tminTarget);
	if (iminTarget < 1) iminTarget = 1;
	trace (tmin, U" ", tmax, U" ", tminTarget, U" ", imin, U" ", imax, U" ", iminTarget);
	Melder_assert (iminTarget + imax - imin <= thy nx);
	NUMvector_copyElements (my z [1] + imin, thy z [1] + iminTarget, 0, imax - imin);
}
Пример #13
0
autoPowerCepstrum Matrix_to_PowerCepstrum_row (Matrix me, long row) {
	try {
		autoPowerCepstrum thee = PowerCepstrum_create (my xmax, my nx);
		if (row < 1 || row > my ny) {
			Melder_throw (U"Row number should be between 1 and ", my ny, U" inclusive.");
		}
		NUMvector_copyElements (my z[row], thy z[1], 1, my nx);
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": no PowerCepstrum created.");
	}
}
Пример #14
0
Polygon Matrix_to_Polygon (Matrix me) {
	try {
		if (my nx != 2 && my ny != 2)
			Melder_throw (U"Matrix must have exactly 2 rows or columns.");
		autoPolygon thee = NULL;
		if (my ny == 2) {
			thee.reset (Polygon_create (my nx));
			NUMvector_copyElements (my z [1], thy x, 1, my nx);
			NUMvector_copyElements (my z [2], thy y, 1, my nx);
		} else {
			thee.reset (Polygon_create (my ny));
			for (long i = 1; i <= my ny; i ++) {
				thy x [i] = my z [i] [1];
				thy y [i] = my z [i] [2];
			}
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Polygon.");
	}
}
Пример #15
0
autoSound Sound_filter_stopHannBand (Sound me, double fmin, double fmax, double smooth) {
	try {
		autoSound thee = Data_copy (me);
		if (my ny == 1) {
			autoSpectrum spec = Sound_to_Spectrum (me, true);
			Spectrum_stopHannBand (spec.peek(), fmin, fmax, smooth);
			autoSound him = Spectrum_to_Sound (spec.peek());
			NUMvector_copyElements (his z [1], thy z [1], 1, thy nx);
		} else {
			for (long ichan = 1; ichan <= my ny; ichan ++) {
				autoSound channel = Sound_extractChannel (me, ichan);
				autoSpectrum spec = Sound_to_Spectrum (channel.peek(), true);
				Spectrum_stopHannBand (spec.peek(), fmin, fmax, smooth);
				autoSound him = Spectrum_to_Sound (spec.peek());
				NUMvector_copyElements (his z [1], thy z [ichan], 1, thy nx);
			}
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not filtered (stop Hann band).");
	}
}
Пример #16
0
autoSound Sound_filter_formula (Sound me, const char32 *formula, Interpreter interpreter) {
	try {
		autoSound thee = Data_copy (me);
		if (my ny == 1) {
			autoSpectrum spec = Sound_to_Spectrum (me, true);
			Matrix_formula ((Matrix) spec.peek(), formula, interpreter, nullptr);
			autoSound him = Spectrum_to_Sound (spec.peek());
			NUMvector_copyElements (his z [1], thy z [1], 1, thy nx);
		} else {
			for (long ichan = 1; ichan <= my ny; ichan ++) {
				autoSound channel = Sound_extractChannel (me, ichan);
				autoSpectrum spec = Sound_to_Spectrum (channel.peek(), true);
				Matrix_formula ((Matrix) spec.peek(), formula, interpreter, nullptr);
				autoSound him = Spectrum_to_Sound (spec.peek());
				NUMvector_copyElements (his z [1], thy z [ichan], 1, thy nx);
			}
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not filtered (with formula).");
	}
}
Пример #17
0
autoTableOfReal Discriminant_extractGroupCentroids (Discriminant me) {
    try {
        long m = my groups -> size, n = my eigen -> dimension;
        autoTableOfReal thee = TableOfReal_create (m, n);

        for (long i = 1; i <= m; i ++) {
            SSCP sscp = my groups->at [i];
            TableOfReal_setRowLabel (thee.get(), i, Thing_getName (sscp));
            NUMvector_copyElements (sscp -> centroid, thy data [i], 1, n);
        }
        NUMstrings_copyElements (my groups->at [m] -> columnLabels, thy columnLabels, 1, n);
        return thee;
    } catch (MelderError) {
        Melder_throw (me, U": group centroids not extracted.");
    }
}
Пример #18
0
Sound Sound_extractPart (Sound me, double t1, double t2, enum kSound_windowShape windowShape, double relativeWidth, bool preserveTimes) {
	try {
		/*
		 * We do not clip to the Sound's time domain.
		 * Any samples outside it are taken to be zero.
		 */

		/*
		 * Autowindow.
		 */
		if (t1 == t2) { t1 = my xmin; t2 = my xmax; };
		/*
		 * Allow window tails outside specified domain.
		 */
		if (relativeWidth != 1.0) {
			double margin = 0.5 * (relativeWidth - 1) * (t2 - t1);
			t1 -= margin;
			t2 += margin;
		}
		/*
		 * Determine index range. We use all the real or virtual samples that fit within [t1..t2].
		 */
		long ix1 = 1 + (long) ceil ((t1 - my x1) / my dx);
		long ix2 = 1 + (long) floor ((t2 - my x1) / my dx);
		if (ix2 < ix1) Melder_throw (U"Extracted Sound would contain no samples.");
		/*
		 * Create sound, optionally shifted to [0..t2-t1].
		 */
		autoSound thee = Sound_create (my ny, t1, t2, ix2 - ix1 + 1, my dx, my x1 + (ix1 - 1) * my dx);
		if (! preserveTimes) { thy xmin = 0.0; thy xmax -= t1; thy x1 -= t1; }
		/*
		 * Copy only *real* samples into the new sound.
		 * The *virtual* samples will remain at zero.
		 */
		for (long channel = 1; channel <= my ny; channel ++) {
			NUMvector_copyElements (my z [channel], thy z [channel] + 1 - ix1,
					( ix1 < 1 ? 1 : ix1 ), ( ix2 > my nx ? my nx : ix2 ));
		}
		/*
		 * Multiply by a window that extends throughout the target domain.
		 */
		Sound_multiplyByWindow (thee.peek(), windowShape);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": part not extracted.");
	}
}
Пример #19
0
TableOfReal CCA_and_TableOfReal_predict (CCA me, TableOfReal thee, long from) {
	try {
		long ny = my y -> dimension, nx = my x -> dimension;
		long nev = my y -> numberOfEigenvalues;

		/*
			We can only predict when we have the largest dimension as input
			and the number of coefficients equals the dimension of the smallest.
		*/

		if (ny != nev) {
			Melder_throw (U"There are not enough correlations present for prediction.");
		}

		if (from == 0) {
			from = 1;
		}
		long ncols = thy numberOfColumns - from + 1;
		if (from < 1 || ncols != nx) {
			Melder_throw (U"The number of columns to analyze must be equal to ", nx, U".");
		}

		// ???? dimensions if nx .. ny ??

		autoTableOfReal him = Eigen_and_TableOfReal_project (my x, thee, from, ny);
		autoNUMvector<double> buf (1, ny);

		// u = V a -> a = V'u

		double **v = my y -> eigenvectors;
		double *d = my y -> eigenvalues;
		for (long i = 1; i <= thy numberOfRows; i++) {
			NUMvector_copyElements (his data[i], buf.peek(), 1, ny);
			for (long j = 1; j <= ny; j++) {
				double t = 0.0;
				for (long k = 1; k <= ny; k++) {
					t += sqrt (d[k]) * v[k][j] * buf[k];
				}
				his data [i][j] = t;
			}
		}
		return him.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": no predictions created.");
	}
}
Пример #20
0
Cepstrum Matrix_to_Cepstrum (Matrix me, long row) {
	try {
		autoCepstrum thee = Cepstrum_create (my xmin, my xmax, my nx);
		if (row < 0) {
			row = my ny + 1 - row;
		}
		if (row < 1) {
			row = 1;
		}
		if (row > my ny) {
			row = my ny;
		}
		NUMvector_copyElements (my z[row], thy z[1], 1, my nx);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": no Cepstrum created.");
	}
}
Spectrum Cepstrum_to_Spectrum (Cepstrum me) {
	try {
		autoSound x = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1);
		NUMvector_copyElements	(my z[1], x -> z[1], 1, my nx);
		autoSpectrum thee = Sound_to_Spectrum (x.peek(), TRUE);

		for (long i = 1; i <= thy nx; i++) {
			double ar = exp (thy z[1][i]);
			double ai = thy z[2][i];

			thy z[1][i] = ar * cos (ai);
			thy z[2][i] = ar * sin (ai);
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": no Spectrum created.");
	}
}
Пример #22
0
autoTableOfReal Discriminant_and_TableOfReal_mahalanobis (Discriminant me, TableOfReal thee, long group, bool poolCovarianceMatrices) {
    try {
        if (group < 1 || group > my numberOfGroups) {
            Melder_throw (U"Group does not exist.");
        }
        autoSSCP pool = SSCPList_to_SSCP_pool (my groups.get());
        autoCovariance covg = SSCP_to_Covariance (pool.get(), my numberOfGroups);
        autoCovariance cov = SSCP_to_Covariance (my groups->at [group], 1);
        autoTableOfReal him;
        if (poolCovarianceMatrices) { // use group mean instead of overall mean!
            NUMvector_copyElements (cov -> centroid, covg -> centroid, 1, cov -> numberOfColumns);
            him = Covariance_and_TableOfReal_mahalanobis (covg.get(), thee, false);
        } else {
            him = Covariance_and_TableOfReal_mahalanobis (cov.get(), thee, false);
        }
        return him;
    } catch (MelderError) {
        Melder_throw (U"TableOfReal not created.");
    }
}
Пример #23
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.");
	}
}
Cepstrum Spectrum_to_Cepstrum (Spectrum me) {
	try {
		autoMatrix unwrap = Spectrum_unwrap (me);
		autoSpectrum sx = Data_copy (me);

		// Copy magnitude-squared and unwrapped phase.

		for (long i = 1; i <= my nx; i ++) {
			double xa = unwrap -> z[1][i];
			sx -> z[1][i] = xa > 0 ? 0.5 * log (xa) : -300;
			sx -> z[2][i] = unwrap -> z[2][i];
		}

		// Compute complex cepstrum x.

		autoSound x = Spectrum_to_Sound (sx.peek());
		autoCepstrum thee = Cepstrum_create (0, x -> xmax - x -> xmin, x -> nx);
		NUMvector_copyElements (x -> z[1], thy z[1], 1, x -> nx);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": no Cepstrum created.");
	}
}
Пример #25
0
Sound Sound_extractPartForOverlap (Sound me, double t1, double t2, double overlap) {
	try {
		if (t1 == t2) { t1 = my xmin; t2 = my xmax; };   // autowindow
		if (overlap > 0.0) {
			double margin = 0.5 * overlap;
			t1 -= margin;
			t2 += margin;
		}
		if (t1 < my xmin) t1 = my xmin;   // clip to my time domain
		if (t2 > my xmax) t2 = my xmax;
		/*
		 * Determine index range. We use all the real or virtual samples that fit within [t1..t2].
		 */
		long ix1 = 1 + (long) ceil ((t1 - my x1) / my dx);
		long ix2 = 1 + (long) floor ((t2 - my x1) / my dx);
		if (ix2 < ix1) Melder_throw (U"Extracted Sound would contain no samples.");
		/*
		 * Create sound.
		 */
		autoSound thee = Sound_create (my ny, t1, t2, ix2 - ix1 + 1, my dx, my x1 + (ix1 - 1) * my dx);
		thy xmin = 0.0;
		thy xmax -= t1;
		thy x1 -= t1;
		/*
		 * Copy only *real* samples into the new sound.
		 * The *virtual* samples will remain at zero.
		 */
		for (long channel = 1; channel <= my ny; channel ++) {
			NUMvector_copyElements (my z [channel], thy z [channel] + 1 - ix1,
					( ix1 < 1 ? 1 : ix1 ), ( ix2 > my nx ? my nx : ix2 ));
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": part not extracted.");
	}
}
Пример #26
0
Sound Sounds_concatenate_e (Collection me, double overlapTime) {
	try {
		long numberOfChannels = 0, nx = 0, numberOfSmoothingSamples;
		double dx = 0.0;
		for (long i = 1; i <= my size; i ++) {
			Sound sound = (Sound) my item [i];
			if (numberOfChannels == 0) {
				numberOfChannels = sound -> ny;
			} else if (sound -> ny != numberOfChannels) {
				Melder_throw (U"To concatenate sounds, their numbers of channels (mono, stereo) must be equal.");
			}
			if (dx == 0.0) {
				dx = sound -> dx;
			} else if (sound -> dx != dx) {
				Melder_throw (U"To concatenate sounds, their sampling frequencies must be equal.\n"
						U"You could resample one or more of the sounds before concatenating.");
			}
			nx += sound -> nx;
		}
		numberOfSmoothingSamples = lround (overlapTime / dx);
		autoSound thee = Sound_create (numberOfChannels, 0.0, nx * dx, nx, dx, 0.5 * dx);
		autoNUMvector <double> smoother;
		if (numberOfSmoothingSamples > 0) {
			smoother.reset (1, numberOfSmoothingSamples);
			double factor = NUMpi / numberOfSmoothingSamples;
			for (long i = 1; i <= numberOfSmoothingSamples; i ++) {
				smoother [i] = 0.5 - 0.5 * cos (factor * (i - 0.5));
			}
		}
		nx = 0;
		for (long i = 1; i <= my size; i ++) {
			Sound sound = (Sound) my item [i];
			if (numberOfSmoothingSamples > 2 * sound -> nx)
				Melder_throw (U"At least one of the sounds is shorter than twice the overlap time.\nChoose a shorter overlap time.");
			bool thisIsTheFirstSound = ( i == 1 );
			bool thisIsTheLastSound = ( i == my size );
			bool weNeedSmoothingAtTheStartOfThisSound = ! thisIsTheFirstSound;
			bool weNeedSmoothingAtTheEndOfThisSound = ! thisIsTheLastSound;
			long numberOfSmoothingSamplesAtTheStartOfThisSound = weNeedSmoothingAtTheStartOfThisSound ? numberOfSmoothingSamples : 0;
			long numberOfSmoothingSamplesAtTheEndOfThisSound = weNeedSmoothingAtTheEndOfThisSound ? numberOfSmoothingSamples : 0;
			for (long channel = 1; channel <= numberOfChannels; channel ++) {
				for (long j = 1, mySample = 1, thySample = mySample + nx;
					 j <= numberOfSmoothingSamplesAtTheStartOfThisSound;
					 j ++, mySample ++, thySample ++)
				{
					thy z [channel] [thySample] += sound -> z [channel] [mySample] * smoother [j];   // add
				}
				NUMvector_copyElements (sound -> z [channel], thy z [channel] + nx,
					1 + numberOfSmoothingSamplesAtTheStartOfThisSound, sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound);
				for (long j = 1, mySample = sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound + 1, thySample = mySample + nx;
					 j <= numberOfSmoothingSamplesAtTheEndOfThisSound;
					 j ++, mySample ++, thySample ++)
				{
					thy z [channel] [thySample] = sound -> z [channel] [mySample] * smoother [numberOfSmoothingSamplesAtTheEndOfThisSound + 1 - j];   // replace (or add, which is the same since it's all zeroes to start with)
				}
			}
			nx += sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound;
		}
		thy nx -= numberOfSmoothingSamples * (my size - 1);
		Melder_assert (thy nx == nx);
		thy xmax = thy nx * dx;
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (U"Sounds not concatenated.");
	}
}