示例#1
0
autoConfusion Confusion_groupStimuli (Confusion me, const char32 *labels, const char32 *newLabel, long newpos) {
	try {
		long ncondense = Melder_countTokens (labels);
		autoNUMvector<long> irow (1, my numberOfRows);

		for (long i = 1; i <= my numberOfRows; i++) {
			irow[i] = i;
		}

		for (char32 *token = Melder_firstToken (labels); token != nullptr; token = Melder_nextToken ()) {
			for (long i = 1; i <= my numberOfRows; i++) {
				if (Melder_equ (token, my rowLabels[i])) {
					irow[i] = 0;
					break;
				}
			}
		}
		long nfound = 0;
		for (long i = 1; i <= my numberOfRows; i++) {
			if (irow[i] == 0) {
				nfound ++;
			}
		}
		if (nfound == 0) {
			Melder_throw (U"Invalid stimulus labels.");
		}
		if (nfound != ncondense) {
			Melder_warning (U"One or more of the given stimulus labels are suspect.");
		}
		long newnstim = my numberOfRows - nfound + 1;
		if (newpos < 1) {
			newpos = 1;
		}
		if (newpos > newnstim) {
			newpos = newnstim;
		}
		autoConfusion thee = Confusion_create (newnstim, my numberOfColumns);
		NUMstrings_copyElements (my columnLabels, thy columnLabels, 1, my numberOfColumns);

		TableOfReal_setRowLabel (thee.get(), newpos, newLabel);
		long inewrow = 1;
		for (long i = 1; i <= my numberOfRows; i++) {
			long rowpos = newpos;
			if (irow[i] > 0) {
				if (inewrow == newpos) {
					inewrow++;
				}
				rowpos = inewrow;
				inewrow++;
				TableOfReal_setRowLabel (thee.get(), rowpos, my rowLabels[i]);
			}
			for (long j = 1; j <= my numberOfColumns; j++) {
				thy data[rowpos][j] += my data[i][j];
			}
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": stimuli not grouped.");
	}
}
示例#2
0
autoMixingMatrix MixingMatrix_createSimple (long numberOfChannels, long numberOfComponents, char32 *elements) {
	try {
		long inum = 1, ntokens = Melder_countTokens (elements);
		if (ntokens == 0) {
			Melder_throw (U"No matrix elements.");
		}
		long nwanted = numberOfChannels * numberOfComponents;

		autoMixingMatrix me = MixingMatrix_create (numberOfChannels, numberOfComponents);

		// Construct the full matrix from the elements
		double number;
		for (char32 *token = Melder_firstToken (elements); token != nullptr && inum <= ntokens; token = Melder_nextToken (), inum++) {
			long irow = (inum - 1) / numberOfComponents + 1;
			long icol = (inum - 1) % numberOfComponents + 1;
			Interpreter_numericExpression (0, token, &number);

			my data[irow][icol] = number;
		}
		if (ntokens < nwanted) {
			for (long i = inum; i <= nwanted; i++) {
				long irow = (inum - 1) / numberOfComponents + 1;
				long icol = (inum - 1) % numberOfComponents + 1;
				my data[irow][icol] = number; // repeat the last number given!
			}
		}
		return me;
	} catch (MelderError) {
		Melder_throw (U"MixingMatrix not created.");
	}
}
示例#3
0
autoConfusion Confusion_groupResponses (Confusion me, const char32 *labels, const char32 *newLabel, long newpos) {
	try {
		long ncondense = Melder_countTokens (labels);
		autoNUMvector<long> icol (1, my numberOfColumns);

		for (long i = 1; i <= my numberOfColumns; i++) {
			icol[i] = i;
		}

		for (char32 *token = Melder_firstToken (labels); token != 0; token = Melder_nextToken ()) {
			for (long i = 1; i <= my numberOfColumns; i++) {
				if (Melder_equ (token, my columnLabels[i])) {
					icol[i] = 0;
					break;
				}
			}
		}
		long nfound = 0;
		for (long i = 1; i <= my numberOfColumns; i++) {
			if (icol[i] == 0) {
				nfound ++;
			}
		}
		if (nfound == 0) {
			Melder_throw (U"Invalid response labels.");
		}
		if (nfound != ncondense) {
			Melder_warning (U"One or more of the given response labels are suspect.");
		}
		long newnresp = my numberOfColumns - nfound + 1;
		if (newpos < 1) {
			newpos = 1;
		}
		if (newpos > newnresp) {
			newpos = newnresp;
		}
		autoConfusion thee = Confusion_create (my numberOfRows, newnresp);
		NUMstrings_copyElements (my rowLabels, thy rowLabels, 1, my numberOfRows);
		TableOfReal_setColumnLabel (thee.get(), newpos, newLabel);
		long inewcol = 1;
		for (long i = 1; i <= my numberOfColumns; i++) {
			long colpos = newpos;
			if (icol[i] > 0) {
				if (inewcol == newpos) {
					inewcol++;
				}
				colpos = inewcol;
				inewcol++;
				TableOfReal_setColumnLabel (thee.get(), colpos, my columnLabels[i]);
			}
			for (long j = 1; j <= my numberOfRows; j++) {
				thy data[j][colpos] += my data[j][i];
			}
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": responses not grouped.");
	}
}
示例#4
0
double *NUMstring_to_numbers (const char32 *s, long *numbers_found) {
	*numbers_found = Melder_countTokens (s);
	if (*numbers_found < 1) {
		Melder_throw (U"Empty string.");
	}
	autoNUMvector<double> numbers (1, *numbers_found);
	long inum = 1;
	for (char32 *token = Melder_firstToken (s); token != 0; token = Melder_nextToken (), inum++) {
		Interpreter_numericExpression (0, token, &numbers[inum]);
	}
	return numbers.transfer();
}
示例#5
0
autoCrossCorrelationTable CrossCorrelationTable_createSimple (char32 *covars, char32 *centroid, long numberOfSamples) {
	try {
		long dimension = Melder_countTokens (centroid);
		long ncovars = Melder_countTokens (covars);
		long ncovars_wanted = dimension * (dimension + 1) / 2;
		if (ncovars != ncovars_wanted) Melder_throw (U"The number of matrix elements and the number of "
			        U"centroid elements are not in concordance. There should be \"d(d+1)/2\" matrix values and \"d\" centroid values.");

		autoCrossCorrelationTable me = CrossCorrelationTable_create (dimension);

		// Construct the full matrix from the upper-diagonal elements

		long inum = 1, irow = 1;
		for (char32 *token = Melder_firstToken (covars); token != nullptr && inum <= ncovars_wanted; token = Melder_nextToken (), inum++) {
			double number;
			long nmissing = (irow - 1) * irow / 2;
			long inumc = inum + nmissing;
			irow = (inumc - 1) / dimension + 1;
			long icol = ( (inumc - 1) % dimension) + 1;
			Interpreter_numericExpression (nullptr, token, &number);
			my data[irow][icol] = my data[icol][irow] = number;
			if (icol == dimension) {
				irow++;
			}
		}

		inum = 1;
		for (char32 *token = Melder_firstToken (centroid); token != nullptr && inum <= dimension; token = Melder_nextToken (), inum++) {
			double number;
			Interpreter_numericExpression (nullptr, token, &number);
			my centroid[inum] = number;
		}
		my numberOfObservations = numberOfSamples;
		return me;
	} catch (MelderError) {
		Melder_throw (U"CrossCorrelationTable not created.");
	}
}
autoStrings Strings_createAsTokens (const char32 *string) {
	try {
		autoStrings me = Thing_new (Strings);
		my numberOfStrings =  Melder_countTokens (string);
		my strings = NUMvector<char32 *> (1, my numberOfStrings);
		long i = 1;
		for (char32 *token = Melder_firstToken (string); token != 0; token = Melder_nextToken ()) {
			my strings[i++] = Melder_dup (token);
		}
		return me;
	} catch (MelderError) {
		Melder_throw (U"Strings from characters not created.");
	}
}
示例#7
0
autoConfusion Confusion_createSimple (const char32 *labels) {
	try {
		long numberOfLabels = Melder_countTokens (labels);
		if (numberOfLabels < 1) {
			Melder_throw (U"Not enough labels.");
		}
		autoConfusion me = Confusion_create (numberOfLabels, numberOfLabels);
		long ilabel = 1;
		for (char32 *token = Melder_firstToken (labels); token != 0; token = Melder_nextToken ()) {
			for (long i = 1; i <= ilabel - 1; i++) {
				if (Melder_cmp (token, my rowLabels[i]) == 0) {
					Melder_throw (U"Label ", i, U"and ", ilabel, U"may not be equal.");
				}
			}
			TableOfReal_setRowLabel (me.get(), ilabel, token);
			TableOfReal_setColumnLabel (me.get(), ilabel, token);
			ilabel++;
		}
		return me;
	} catch (MelderError) {
		Melder_throw (U"Simple Confusion not created.");
	}
}
// We assume that the Sound and the SpeechSynthesizer have the same samplingFrequency
// schakel waarschuwingen over stiltedetectie uit
autoTextGrid SpeechSynthesizer_and_Sound_and_TextInterval_align (SpeechSynthesizer me, Sound thee, TextInterval him, double silenceThreshold, double minSilenceDuration, double minSoundingDuration) {
	try {
		if (thy xmin != his xmin || thy xmax != his xmax) {
			Melder_throw (U"Domains of Sound and TextGrid must be equal.");
		}
		if (fabs (1.0 / thy dx - my d_samplingFrequency) > NUMfpp -> eps) {
			Melder_throw (U"The sampling frequencies of the SpeechSynthesizer and the Sound must be equal.");
		}
		long numberOfTokens = Melder_countTokens (his text);
		if (numberOfTokens == 0) {
			Melder_throw (U"The interval has no text.");
		}
		// Remove silent intervals from start and end of sounds
		double minPitch = 200, timeStep = 0.005, precision = thy dx;
		double t1_thee, t2_thee;
		autoSound s_thee = Sound_trimSilencesAtStartAndEnd (thee, 0.0, minPitch, timeStep,
			silenceThreshold, minSilenceDuration, minSoundingDuration, &t1_thee, &t2_thee);
		double s_thee_duration = s_thee -> xmax - s_thee -> xmin;
		bool hasSilence_thee = fabs (t1_thee - thy xmin) > precision || fabs (t2_thee - thy xmax) > precision;

		if (my d_estimateWordsPerMinute) {
			// estimate speaking rate with the number of words per minute from the text
			double wordsPerMinute_rawTokens = 60.0 * numberOfTokens / s_thee_duration;
			// compensation for long words: 5 characters / word
			double wordsPerMinute_rawText = 60.0 * (str32len (his text) / 5.0) / s_thee_duration;
			my d_wordsPerMinute =  (long) floor (0.5 * (wordsPerMinute_rawTokens + wordsPerMinute_rawText));
		}
		autoTextGrid tg2;
		autoSound s2 = SpeechSynthesizer_and_TextInterval_to_Sound (me, him, & tg2);
		autoTextGrid silentTextGrid;
		/*
		 * For the synthesizer the silence threshold has to be < -30 dB, otherwise fricatives will not
		 * be found as sounding! This is ok since silences are almost at zero amplitudes
		 * We also have to decrease the minimum silence and minimum sounding duration to catch, for example,
		 * the final plosive "t" from the word "text"
		 *
		 */
		double s2_silenceThreshold = -40.0, s2_minSilenceDuration = 0.05, s2_minSoundingDuration = 0.05;
		double t1_s2, t2_s2;
		autoSound s_s2 = Sound_trimSilencesAtStartAndEnd (s2.peek(), 0.0, minPitch, timeStep,
			s2_silenceThreshold, s2_minSilenceDuration, s2_minSoundingDuration, & t1_s2, & t2_s2);
		double s_s2_duration = s_s2 -> xmax - s_s2 -> xmin;
		bool hasSilence_s2 = fabs (t1_s2 - s2 -> xmin) > precision || fabs (t2_s2 - s2 -> xmax) > precision;
		if (hasSilence_s2) {
			silentTextGrid = TextGrid_extractPart (tg2.peek(), t1_s2, t2_s2, true);
		}
		double analysisWidth = 0.02, dt = 0.005, band = 0.0;
		// compare the durations of the two sounds to get an indication of the slope constraint of the DTW
		double slope = s_thee_duration / s_s2_duration;
		slope = slope > 1 ? slope : 1 / slope;
        int constraint = slope < 1.5 ? 4 : (slope < 2 ? 3 : (slope < 3 ? 2 : 1));
		//autoMFCC m1 = Sound_to_MFCC ((hasSilence_thee ? s_thee.peek() : thee),
		//	numberOfCoefficients, analysisWidth, dt, f1_mel, fmax_mel, df_mel);
		//autoMFCC m2 = Sound_to_MFCC ((hasSilence_s2 ? s_s2.peek() : s2.peek()),
		//	numberOfCoefficients, analysisWidth, dt, f1_mel, fmax_mel, df_mel);
		//double wc = 1, wle = 0, wr = 0, wer = 0, dtr = 0;
		//int matchStart = 1, matchEnd = 1, constraint = 4; // no 1/3 1/2 2/3
		//autoDTW dtw = CCs_to_DTW (m1.peek(), m2.peek(), wc, wle, wr, wer, dtr, matchStart, matchEnd, constraint);
        autoDTW dtw = Sounds_to_DTW ((hasSilence_thee ? s_thee.peek() : thee), (hasSilence_s2 ? s_s2.peek() : s2.peek()), analysisWidth, dt, band, constraint);
		autoTextGrid result = DTW_and_TextGrid_to_TextGrid (dtw.peek(),
			(hasSilence_s2 ? silentTextGrid.peek() : tg2.peek()), precision);
		if (hasSilence_thee) {
			if (t1_thee > thy xmin) {
				TextGrid_setEarlierStartTime (result.peek(), thy xmin, U"", U"");
			}
			if (t2_thee < thy xmax) {
				TextGrid_setLaterEndTime (result.peek(), thy xmax, U"", U"");
			}
		}
		return result;
	} catch (MelderError) {
		Melder_throw (U"Sound and TextInterval not aligned.");
	}
}