1 /* FormantPath_to_IntervalTier.cpp
2  *
3  * Copyright (C) 2020 David Weenink
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this work. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "FormantPath_to_IntervalTier.h"
20 
IntervalTier_addCandidate(IntervalTier me,double splitTime,integer candidate)21 static void IntervalTier_addCandidate (IntervalTier me, double splitTime, integer candidate) {
22 	conststring32 label = Melder_integer (candidate);
23 	TextInterval last = my intervals.at [my intervals.size];
24 	last -> xmax = splitTime;
25 	last -> text = Melder_dup (label);
26 	autoTextInterval interval = TextInterval_create (splitTime, my xmax, U"");
27 	my intervals.addItem_move (interval.move());
28 }
29 
FormantPath_to_IntervalTier(FormantPath me,double tmin,double tmax)30 autoIntervalTier FormantPath_to_IntervalTier (FormantPath me, double tmin, double tmax) {
31 	autoIntervalTier thee = IntervalTier_create (tmin, tmax);
32 	integer itmin, itmax;
33 	Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax);
34 	/*
35 		If the interval [tmin,tmax] did not overlap any samples and falls
36 		inbetween two successive samples that have index i1 and i1+1,
37 		itmin == i1+1 && itmax == i1;
38 	*/
39 	integer startIndex = Sampled_xToNearestIndex (me, tmin);
40 	Melder_clipLeft (1_integer, & startIndex);
41 	integer candidate = my path [startIndex];
42 	for (integer itime = itmin; itime <= itmax; itime ++) {
43 		if (my path [itime] != candidate) {
44 			const double endTime = Sampled_indexToX (me, itime) - 0.5 * my dx;
45 			IntervalTier_addCandidate (thee.get(), endTime, candidate);
46 			candidate = my path [itime];
47 		}
48 	}
49 	integer endIndex = Sampled_xToNearestIndex (me, tmax);
50 	Melder_clipRight (& endIndex, my nx);
51 	integer endCandidate = my path [endIndex];
52 	if (endCandidate != candidate) {
53 		const double endTime = Sampled_indexToX (me, itmax) + 0.5 * my dx;
54 		IntervalTier_addCandidate (thee.get(), endTime, candidate);
55 		candidate = endCandidate;
56 	}
57 	/*
58 		Set label on last interval
59 	*/
60 	const TextInterval textInterval = thy intervals.at [thy intervals.size];
61 	TextInterval_setText (textInterval, Melder_integer (candidate));
62 	return thee;
63 }
64 
65 /* End of file FormantPath_to_IntervalTier.cpp */
66