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