Edinburgh Speech Tools 2.4-release
 
Loading...
Searching...
No Matches
tilt_analysis.cc
1/*************************************************************************/
2/* */
3/* Centre for Speech Technology Research */
4/* University of Edinburgh, UK */
5/* Copyright (c) 1996 */
6/* All Rights Reserved. */
7/* */
8/* Permission is hereby granted, free of charge, to use and distribute */
9/* this software and its documentation without restriction, including */
10/* without limitation the rights to use, copy, modify, merge, publish, */
11/* distribute, sublicense, and/or sell copies of this work, and to */
12/* permit persons to whom this work is furnished to do so, subject to */
13/* the following conditions: */
14/* 1. The code must retain the above copyright notice, this list of */
15/* conditions and the following disclaimer. */
16/* 2. Any modifications must be clearly marked as such. */
17/* 3. Original authors' names are not deleted. */
18/* 4. The authors' names are not used to endorse or promote products */
19/* derived from this software without specific prior written */
20/* permission. */
21/* */
22/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30/* THIS SOFTWARE. */
31/* */
32/*************************************************************************/
33/* Author : Paul Taylor */
34/* Date : March 1998 */
35/*-----------------------------------------------------------------------*/
36/* Tilt Analysis */
37/* */
38/*=======================================================================*/
39
40#include <cstdlib>
41#include "EST_math.h"
42#include "EST_tilt.h"
43#include "tilt.h"
44#include "EST_Track.h"
45#include "EST_track_aux.h"
46#include "EST_Features.h"
47#include "EST_error.h"
48
49static int match_rf_point(EST_Track &fz, int b_start, int b_stop,
50 int e_start, int e_stop,
51 int &mi, int &mj);
52
53static void make_int_item(EST_Item &e, const EST_String name, float end,
54 float start_pos,
55 float start_f0,
56 float peak_pos,
57 float peak_f0);
58
59//void rfc_segment_features_only(EST_Relation &ev);
60//void convert_to_event(EST_Relation &ev);
61
62static int rf_match(EST_Track &fz, EST_Item &ev, float range);
63
64static int zero_cross(EST_Track &fz);
65
66static int comp_extract(EST_Track &fz, EST_Track &part, float &start, float
67 &end, float min);
68//void segment_to_event(EST_Relation &ev);
69//void event_to_segment(EST_Relation &ev, float min_length = 0.01);
70
71void int_segment_to_unit(EST_Relation &a, EST_Relation &ev);
72
73static void convert_to_local(EST_Relation &ev);
74
75static void silence_f0(EST_Relation &ev, EST_Track &fz);
76
77static void add_phrases(EST_Relation &ev);
78
79
80// find event portions of fz in contour, cut out, and send one by one
81// to individual labeller.
82
83// This routine takes an Fz contour and a list of potential events,
84// and peforms RFC matching on them. It returns a list of events with RFC
85// parameters marked.
86//
87// The algorithm works as follows:
88//
89// make a list of events, with start and stop times.
90//
91// for every event
92// {
93// find start and stop times.
94// call comp_extract() to get best section of contour that
95// falls between these times. If no suitable contour is found the
96// event is deleted and not labelled.
97// call rf_match to determine the optimal start and end times for
98// that section
99// }
100//
101// Now add connections between non-overlapping events. Overlapping events
102// get readjusted to make them simply adjacent
103
104void default_rfc_params(EST_Features &op)
105{
106 op.set("start_limit", 0.1);
107 op.set("stop_limit", 0.1);
108 op.set("range", 0.3);
109 op.set("min_event_duration", 0.03);
110}
111void print_event(EST_Item &ev);
112
113void rfc_analysis(EST_Track &fz, EST_Relation &ev, EST_Features &op)
114{
115 EST_Item *e, *tmp, *n;
116 float start_search, end_search;
117 EST_Track part;
118 EST_Relation eva;
119
120 if (op.present("debug"))
121 {
122 cout << "rfc_recognise\n";
123 cout << ev;
124 }
125
126 int_segment_to_unit(ev, eva);
127
128 if (op.present("debug"))
129 {
130 cout << "rfc_recognise\n";
131 cout << ev;
132 }
133
134 // fill values in event labels using matching algorithms
135 for (e = ev.head(); e != 0; e = n)
136 {
137 n = inext(e);
138 // cout << endl << endl;
139 if (!event_item(*e))
140 continue;
141 end_search = e->F("end") + op.F("stop_limit");
142 start_search = e->F("start") - op.F("start_limit");
143
144 if (op.present("debug"))
145 {
146 cout << "start = " << e->F("start") << " End "
147 << e->F("end")<< endl;
148 cout << "s start = " << start_search << " sEnd "
149 << end_search << endl;
150 cout << *e << endl;;
151 }
152
153 if (comp_extract(fz, part, start_search, end_search,
154 op.F("min_event_duration")))
155 rf_match(part, *e, op.F("range"));
156 else
157 ev.remove_item(e);
158 }
159
160 // hack to deal with cases where no events exist
161 if (ev.head() == 0)
162 {
163 tmp = ev.append();
164 make_int_item(*tmp, "sil", fz.t(0), fz.t(fz.num_frames() - 1),
165 0.0, 0.0, 0.0);
166 }
167
168 silence_f0(ev, fz);
169 add_phrases(ev);
170
171 // cout << endl << endl << ev;
172 convert_to_local(ev);
173
174 // make sure events don't overlap
175// adjust_overlaps(ev);
176
177 ev.f.set("intonation_style", "rfc");
178
179 if (op.present("debug"))
180 {
181 cout << "After RFC analysis\n";
182 cout << ev;
183 }
184}
185
186// convert intonation stream from segment type to event type description.
187// Note this has to be done in 2 loops.
188
189// Create a section of fz contour, bounded by times "start" and "end".
190// The created contour is defined to be the largest single continuous
191// section of contour bounded by the two times. If no fz contour exits within
192// the limits an error is returned.
193
194static void convert_to_local(EST_Item *e)
195{
196 if (e->S("rfc.type", "0") == "RISEFALL")
197 {
198 e->set("rfc.rise_amp", (e->F("rfc.peak_f0") - e->F("ev.start_f0")));
199 e->set("rfc.rise_dur", (e->F("rfc.peak_pos") - e->F("start")));
200 e->set("rfc.fall_amp", (e->F("rfc.end_f0") - e->F("rfc.peak_f0")));
201 e->set("rfc.fall_dur", (e->F("end") - e->F("rfc.peak_pos")));
202 e->set("ev.f0", e->F("rfc.peak_f0"));
203// e->set("ev.f0", e->F("rfc.peak_f0") - e->F("rfc.rise_amp"));
204
205 e->A("rfc").remove("peak_f0");
206 e->A("rfc").remove("peak_pos");
207 e->A("rfc").remove("end_f0");
208 e->A("rfc").remove("type");
209 e->A("ev").remove("start_f0");
210 }
211 else if (e->S("rfc.type", "0") == "RISE")
212 {
213 e->set("rfc.rise_amp", (e->F("rfc.end_f0") - e->F("ev.start_f0")));
214 e->set("rfc.rise_dur", (e->F("end") - e->F("start")));
215 e->set("rfc.fall_amp", 0.0);
216 e->set("rfc.fall_dur", 0.0);
217 e->set("ev.f0", e->F("rfc.end_f0"));
218// e->set("ev.f0", e->F("rfc.end_f0") - e->F("rfc.rise_amp"));
219
220 e->A("rfc").remove("peak_f0");
221 e->A("rfc").remove("peak_pos");
222 e->A("rfc").remove("end_f0");
223 e->A("rfc").remove("type");
224 e->A("ev").remove("start_f0");
225 }
226 else if (e->S("rfc.type", "0") == "FALL")
227 {
228 e->set("rfc.rise_amp", 0.0);
229 e->set("rfc.rise_dur", 0.0);
230 e->set("rfc.fall_amp", (e->F("rfc.end_f0") - e->F("ev.start_f0")));
231 e->set("rfc.fall_dur", (e->F("end") - e->F("start")));
232 e->set("ev.f0", e->F("ev.start_f0"));
233
234 e->A("rfc").remove("peak_f0");
235 e->A("rfc").remove("peak_pos");
236 e->A("rfc").remove("end_f0");
237 e->A("rfc").remove("type");
238 e->A("ev").remove("start_f0");
239 }
240 if (!e->f_present("time"))
241 e->set("time", (e->F("end") - e->F("rfc.fall_dur")));
242}
243
244void convert_to_local(EST_Relation &ev)
245{
246 EST_Item *e;
247
248 for (e = ev.head(); e; e = inext(e))
249 convert_to_local(e);
250
251 // cout << "c to l \n\n\n" << ev << endl << endl;
252
253// ev.remove_item_feature("rfc.peak_f0");
254// ev.remove_item_feature("rfc.peak_pos");
255 ev.remove_item_feature("ev.start_f0");
256 ev.remove_item_feature("start");
257// ev.remove_item_feature("rfc.end_f0");
258 ev.remove_item_feature("end");
259// remove_item_feature(ev, "int_event");
260
261 ev.f.set("timing_style", "event");
262}
263
264void extract2(EST_Track &orig, float start, float end, EST_Track &ret);
265
266static int comp_extract(EST_Track &fz, EST_Track &part, float &start, float
267 &end, float min_length)
268{
269 int i;
270 int continuous = 1;
271 cout.precision(6);
272 EST_Track tr_tmp, tmp2;
273
274 if (start > end)
275 EST_error("Illegal start and end times: %f %f\n", start, end);
276
277// int from = fz.index(start);
278// int to = fz.index_below(end);
279
280 // cout << "full f0 = " << fz.num_frames() << endl;
281// fz.copy_sub_track(tr_tmp, from, to, 0, EST_ALL);
282
283// cout << "sub_track: " << tr_tmp;
284
285 extract2(fz, start, end, tr_tmp);
286
287// cout << "tr_tmp 1\n" << tr_tmp;
288 tr_tmp.rm_trailing_breaks();
289// cout << "tr_tmp 2\n" << tr_tmp;
290
291// cout << "end " << tr_tmp.end() << " start "<< tr_tmp.start() << endl;
292
293// i = tr_tmp.num_frames();
294
295// cout << "starting i = " << tr_tmp.num_frames() << endl;
296// cout << "starting i = " << tr_tmp.num_channels() << endl;
297// cout << "found end at " << i << tr_tmp.t(i) << endl;
298
299// cout << "tr_tmp 1\n" << tr_tmp;
300 if ((tr_tmp.end() - tr_tmp.start()) < min_length)
301 {
302 cout << "Contour too small for analysis\n";
303 return 0;
304 }
305
306 for (i = 0; i < tr_tmp.num_frames(); ++i)
307 if (tr_tmp.track_break(i))
308 continuous = 0;
309
310 // if no breaks are found in this section return.
311 if (continuous)
312 {
313 part = tr_tmp;
314 return 1;
315 }
316
317 // tracks can legitimately have breaks in them due to the
318 // search region overlapping a silence. In this case we find
319 // the longest single section
320 // cout << "tilt_analysis: This contour has a break in it\n";
321
322 int longest, s_c, s_l;
323 longest = s_c = s_l = 0;
324
325 for (i = 0; i < tr_tmp.num_frames(); ++i)
326 if (tr_tmp.track_break(i))
327 {
328 if ((i - s_c) > longest)
329 {
330 longest = i - s_c - 1;
331 s_l = s_c;
332 }
333 // skip to next real values
334 for (;(i < tr_tmp.num_frames()) && (tr_tmp.track_break(i)); ++i)
335 s_c = i;
336 }
337
338 if ((i - s_c) > longest)
339 {
340 longest = i - s_c - 1;
341 s_l = s_c;
342 }
343
344 // cout << "Longest fragment is " << longest << " starting at " << s_l <<endl;
345 // cout << "Times: " << tr_tmp.t(s_l) << " : " <<tr_tmp.t(s_l + longest) << endl;
346
347 extract2(tr_tmp, tr_tmp.t(s_l), tr_tmp.t(s_l + longest), part);
348// cout << "Part\n" << part;
349 part.rm_trailing_breaks();
350 start = part.t(0);
351 end = part.t(part.num_frames()-1);
352
353 return 1;
354
355}
356
357static int zero_cross(EST_Track &fz)
358{
359 for (int i = 0; i < fz.num_frames() - 1; ++i)
360 if ((fz.a(i) >= 0.0) && (fz.a(i + 1) < 0.0))
361 return i;
362
363 return -1;
364}
365
366// 1. There should be a more sophisticated decision about whether there
367// should be a risefall analysis, and if so, where the peak (zero cross)
368// region should be.
369// 2. There should be minimum endforced distances for rises and falls.
370
371static int rf_match(EST_Track &fz, EST_Item &ev, float range)
372{
373 int n;
374 EST_Track diff;
375 int start, stop;
376 int b_start, b_stop, e_start, e_stop, region;
377 EST_Features empty;
378
379 if (fz.num_frames() <= 0)
380 {
381 ev.set("start", 0.0);
382 ev.set("ev", empty);
383 ev.set("rfc", empty);
384 ev.set("ev.start_f0", 0.0);
385 ev.set("rfc.peak_f0", 0.0);
386 ev.set("rfc.peak_pos", 0.0);
387 }
388
389 diff = differentiate(fz);
390
391 // cout << "Extracted Contour:\n";
392 // cout << fz;
393
394 n = zero_cross(diff);
395
396 if (n >= 0) // rise + fall combination
397 {
398 // cout << "zero crossing at point " << n << " time " << fz.t(n) << endl;
399 b_start = 0;
400 stop = n;
401 // find rise part
402 region = (int)(range * float(stop - b_start));
403 // ensure region is bigger than 0
404 region = region > 0 ? region : 1;
405
406 b_stop = b_start + region;
407 e_start = stop - region;
408 e_stop = stop + region;
409 // ensure regions are separate
410 e_start = (e_start < b_stop)? b_stop : e_start;
411
412 //printf("rise: b_start %d, b_stop %d, end %d, end stop%d\n", b_start,
413 // b_stop, e_start, e_stop);
414 match_rf_point(fz, b_start, b_stop, e_start, e_stop, start, stop);
415 // cout << "Rise is at start: " << start << " Stop = " << stop << endl;
416
417 ev.set("ev.start_f0", fz.a(start));
418 ev.set("start", fz.t(start));
419
420 // find fall part. The start of the search is FIXED by the position
421 // of where the rise stopped
422
423 b_start = n;
424 b_stop = n + 1;
425 e_stop = fz.num_frames() - 1;
426 region = (int)(range * float(e_stop - b_start));
427 region = region > 0 ? region : 1;
428 e_start = e_stop - region;
429
430 // printf("fall: b_start %d, b_stop %d, end %d, end stop%d\n", b_start,
431 // b_stop, e_start, e_stop);
432
433 match_rf_point(fz, b_start, b_stop, e_start, e_stop, start, stop);
434 // cout << "Fall is at start: " << start << " Stop = " << stop << endl;
435 // cout << "region: " << region << endl;
436 // cout << "stop could be " << e_stop << " value " << fz.t(e_stop) << endl;
437 // cout << "start could be " << e_start << " value " << fz.t(e_start) << endl;
438
439 ev.set("rfc.peak_f0", fz.a(start));
440 ev.set("rfc.peak_pos", fz.t(start));
441 ev.set("rfc.end_f0", fz.a(stop));
442
443 ev.set("end", fz.t(stop));
444 ev.set("rfc.type", "RISEFALL");
445
446/* ev.set("rfc.setpeak_f0", fz.a(start));
447 ev.fA("rfc").set("peak_pos", fz.t(start));
448 ev.fA("rfc",1).set("end_f0", fz.a(stop));
449
450 ev.set("end", fz.t(stop));
451
452 ev.fA("rfc").set("type", "RISEFALL");
453*/
454 // cout << "peak pos: " << ev.F("rfc.peak_pos") << endl;
455 // cout << "peak pos: " << ev.A("rfc").F("peak_pos") << endl;
456 // cout << "rfc:\n" << ev.A("rfc") << endl;
457 // cout << "labelled event: " << ev << endl;
458 }
459 else // separate rise or fall
460 {
461 b_start = 0;
462 e_stop = fz.num_frames() - 1;
463
464 region = (int)(range * float(e_stop - b_start));
465 region = region > 0 ? region : 1;
466
467 b_stop = b_start + region;
468 e_start = e_stop - region;
469
470 // printf("b_start %d, b_stop %d, end start %d, end stop%d\n", b_start,
471 // b_stop, e_start, e_stop);
472
473 match_rf_point(fz, b_start, b_stop, e_start, e_stop, start, stop);
474
475 ev.set("start", fz.t(start));
476 ev.set("ev.start_f0", fz.a(start));
477 ev.set("rfc.peak_f0", 0.0);
478 ev.set("rfc.peak_pos", 0.0);
479
480 ev.set("rfc.end_f0", fz.a(stop));
481 ev.set("end", fz.t(stop));
482
483 // cout << "start " << fz.t(start) << " end " << fz.t(stop) << endl;
484
485 if (fz.a(fz.index(fz.start())) < fz.a(fz.index(fz.end())))
486 ev.set("rfc.type", "RISE");
487 else
488 ev.set("rfc.type", "FALL");
489
490 // cout << "labelled event: " << ev << endl;
491 }
492 return 0;
493}
494
495static void silence_f0(EST_Relation &ev, EST_Track &fz)
496{
497 EST_Item * e;
498 int i;
499
500 for (e = ev.head(); e; e = inext(e))
501 if (sil_item(*e))
502 {
503 i = fz.prev_non_break(fz.index(e->F("start")));
504
505 e->set("ev.start_f0", fz.a(i));
506 i = fz.next_non_break(fz.index(e->F("end")));
507 e->set("ev.end_f0", fz.a(i));
508 }
509}
510
511static void add_phrases(EST_Relation &ev)
512{
513 EST_Item *e, *n, *s;
514
515 // cout << "phrase edges: " << endl;
516 // cout << ev;
517
518 for (e = ev.head(); e; e = n)
519 {
520 n = inext(e);
521 if (sil_item(*e))
522 {
523 if (e != ev.head())
524 {
525 s = e->insert_before();
526 s->set("name", "phrase_end");
527 s->set("ev.f0", e->F("ev.start_f0"));
528 s->set("time", e->F("start"));
529 }
530 if (e != ev.tail())
531 {
532 s = e->insert_after();
533 s->set("name", "phrase_start");
534 s->set("ev.f0", e->F("ev.end_f0"));
535 s->set("time", e->F("end"));
536 }
537 }
538 }
539
540 for (e = ev.head(); e; e = n)
541 {
542 n = inext(e);
543 if (sil_item(*e))
544 ev.remove_item(e);
545 }
546}
547
548/*
549static void add_phrases(EST_Relation &ev, bool phrase_edges)
550{
551 EST_Item *e, *n, *s, *p;
552 float min_duration = 0.02;
553
554 cout << "phrase edges: " << phrase_edges << endl;
555 cout << ev;
556
557 for (e = ev.head(); inext(e); e = n)
558 {
559 n = inext(e);
560 p = iprev(e);
561 if (!sil_item(*e))
562 continue;
563
564 s = 0;
565
566 if ((e != ev.head()) && (phrase_edges
567 || (p &&(e->F("start") - p->F("end"))
568 > min_duration)))
569 {
570 s = e->insert_before();
571 s->set("name", "phrase_end");
572 s->set("ev.f0", e->F("ev.start_f0", 1));
573 s->set("position", e->F("start"));
574 }
575
576 if (phrase_edges || (n &&((n->F("start")- e->F("end")) >min_duration)))
577 {
578 s = e->insert_after();
579 s->set("name", "phrase_start");
580 s->set("ev.f0", e->F("ev.end_f0",1));
581 s->set("position", e->F("end"));
582 }
583
584 if (s == 0)
585 {
586 s = e->insert_before();
587 s->set("name", "pause");
588 s->set("position", e->F("start"));
589 }
590 }
591
592 s = e->insert_after();
593 s->set("name", "phrase_end");
594 s->set("ev.f0", e->F("ev.start_f0", 1));
595 s->set("position", e->F("end"));
596
597 for (e = ev.head(); e; e = n)
598 {
599 n = inext(e);
600 if (sil_item(*e))
601 ev.remove_item(e);
602 }
603 cout << "end phrase edges\n";
604}
605*/
606static void make_int_item(EST_Item &tmp,
607 const EST_String name, float end, float start,
608 float start_f0, float peak_pos,
609 float peak_f0)
610
611{
612 tmp.set_name(name);
613 EST_Features dummy;
614
615 tmp.set("start", start);
616 tmp.set("end", end);
617 tmp.set("ev", dummy);
618 tmp.set("ev.start_f0", start_f0);
619
620 if ((name != "sil") && (name != "c"))
621 {
622 tmp.set("rfc", dummy);
623 tmp.set("rfc.peak_pos", peak_pos);
624 tmp.set("rfc.peak_f0", peak_f0);
625 tmp.set("rfc.pos", 1);
626 }
627}
628
629static float distance(EST_Track &fz, int pos, EST_Track &new_fz, int
630 num_points)
631{
632 int i;
633 float distance = 0.0;
634 float diff;
635
636 for (i = 0; i < num_points; ++i)
637 {
638 diff = fz.a(i + pos) - new_fz.a(i);
639 /* dprintf("o = %f, n = %f\n", old_contour[i + pos],
640 new_contour[i]); */
641 distance += (diff * diff);
642 }
643 return (distance);
644}
645
646static float weight(float duration)
647{
648 (void)duration;
649 /* return ((MAX_DUR + 0.7) - duration); */
650 return(1.0);
651}
652
653// Return indexs in fz to best fitting region of monomial curve to
654// fz contour. The search is bounded by the b/e_start an b/e_stop
655// values. The contour fz, should have no breaks in it.
656
657static int match_rf_point(EST_Track &fz, int b_start, int b_stop,
658 int e_start, int e_stop, int &mi, int &mj)
659{
660 int i, j, k;
661 float s_pos, e_pos, s_freq, e_freq, t;
662 float amp, duration, dist, ndist;
663 float min_dist = MAXFLOAT;
664 int length;
665 EST_Track new_fz(fz.num_frames(), 1);
666 float f_shift;
667
668 mi = mj = 0; // set values to zero for safety
669
670 if ((b_start >= b_stop) || (b_start < 0))
671 {
672 cerr << "Illegal beginning search region in match_rf_point:" <<
673 b_start << "-" << b_stop << endl;
674 return -1;
675 }
676 if ((e_start >= e_stop) || (e_stop > fz.num_frames()))
677 {
678 cerr << "Illegal ending search region in match_rf_point:" <<
679 e_start << "-" << e_stop << endl;
680 return -1;
681 }
682
683 f_shift = fz.shift();
684 duration = 0.0;
685
686 for (i = b_start; i < b_stop; ++i)
687 for (j = e_start; j < e_stop; ++j)
688 {
689 s_pos = fz.t(i);
690 s_freq = fz.a(i);
691
692 e_pos = fz.t(j);
693 e_freq = fz.a(j);
694
695 duration = e_pos - s_pos;
696 amp = e_freq - s_freq;
697 length = j - i;
698
699 for (k = 0; k < length + 1; ++k)
700 {
701 t = ((float) k) * f_shift;
702 new_fz.a(k) = (amp * fncurve(duration, t, 2.0))
703 + s_freq;
704 }
705
706 dist = distance(fz, i, new_fz, length);
707 ndist = dist / (duration * 100.0);
708 ndist *= weight(duration);
709
710 if (ndist < min_dist)
711 {
712 min_dist = ndist;
713 mi = i;
714 mj = j;
715 }
716 }
717 return 0;
718}
719
720/*
721#if 0
722
723static void fill_f0_values(EST_Track &fz, EST_Relation &ev)
724{
725 EST_Item *e;
726 float start_a;
727 int pos;
728 float prev = 0.0;
729
730 for (e = ev.head(); e != 0; e = inext(e))
731 {
732 if (e->name() == "sil")
733 {
734 pos = fz.index(prev);
735 pos = fz.prev_non_break(pos);
736 start_a = pos > 0 ? fz.a(pos) : 0.0;
737 }
738 else if (e->name() == "c")
739 {
740 pos = fz.index(prev);;
741 pos = fz.next_non_break(pos);
742 start_a = fz.a(pos);
743 }
744 else
745 start_a = fz.a(prev);
746
747 e->set("ev:start_f0", start_a);
748 e->set("start", prev);
749 // cout << "setting start to be " << start_a << " at pos " << pos << endl;
750 // cout << *e << " " << *RFCS(*e) << endl;
751
752 if (e->f("rfc:type") == "RISEFALL")
753 {
754 start_a = fz.a(e->F("rfc:peak_pos"));
755 e->set("rfc:peak_f0", start_a);
756 }
757 prev = e->f("end");
758 }
759}
760
761static void insert_silence(EST_Item *n, EST_Track &fz, int i, int j)
762{
763 EST_Item *prev_item, *new_sil;
764 float min_length = 0.015;
765 float sil_start, sil_end, start_f0;
766
767 sil_start = i > 0 ? fz.t(i - 1) : 0.0;
768 sil_end = fz.t(j);
769
770 if ((sil_end - sil_start) < min_length)
771 return;
772
773 // add silence
774 start_f0 = (i > 0) ? fz.a(i -1) : fz.a(i);
775 new_sil = n->insert_after();
776 make_int_item(*new_sil, "sil", sil_end, sil_start, start_f0, 0.0, 0.0);
777 new_sil->set("rfc:type", "SIL");
778
779 // if silence leaves a gap, make a new element before it
780 if ((sil_start - n->F("start")) < min_length)
781 return;
782
783 // make new element, setting end time to silence start time.
784 prev_item = n->prev()->insert_before();
785 make_int_item(*prev_item, n->name(), sil_start, 0.0, n->f("ev:start_f0"),
786 0.0,0.0);
787
788 // now tidy up values of existing element
789 n->set("ev:start_f0", fz.a(j));
790 n->set("start", sil_end);
791}
792
793static void add_phrases_old(EST_Relation &ev, EST_Track &fz)
794{
795 int i;
796 EST_Item *e, *n, *s;
797 bool sil = false;
798 float start, end;
799
800 for (e = ev.head(); inext(e); e = n)
801 {
802 n = inext(e);
803 start = e->F("end");
804 end = n->F("start");
805 sil = false;
806
807 cout << endl << endl;
808
809 cout << *e << endl;
810 cout << *n << endl;
811
812 cout << "start = " << start << endl;
813 cout << "end = " << end << endl;
814
815 for (i = fz.index(start); i < fz.index(end); ++i)
816 {
817 cout << i << endl;
818 cout << fz.val(i) << endl;
819 if ((!sil) &&(!fz.val(i)))
820 {
821 cout << "phrase_end\n";
822 sil = true;
823 s = e->insert_after();
824 s->set("name", "phrase_end");
825 s->set("position", fz.t(i - 1));
826 if (i > (fz.index(start) + 1))
827 s->set("ev:f0", fz.a(i - 1));
828 e = s;
829 }
830
831 if (sil && fz.val(i)) // just come out of silence
832 {
833 cout << "phrase_start\n";
834 sil = false;
835 s = e->insert_after();
836 s->set("name", "phrase_start");
837 s->set("position", fz.t(i));
838 s->set("ev:f0", fz.a(i));
839 }
840 }
841 }
842}
843
844static void add_silences(EST_Track &fz, EST_Relation &ev,
845 float end_sil_length)
846{
847 int i, j;
848 EST_Item *e;
849
850 for (i = 0; i < fz.num_frames(); ++i)
851 if (fz.track_break(i))
852 {
853 for (j = i; j < fz.num_frames(); ++j)
854 if (fz.val(j))
855 break;
856 if (j == fz.num_frames()) // off end of array
857 break;
858 cout << "silence between " <<i << " and " << j << endl;
859 // cout << " " << fz.t(i) << " and " << fz.t(j) << endl;
860
861 for (e = ev.head(); e != 0; e = inext(e))
862 if (e->F("end") >= fz.t(j))
863 break;
864 insert_silence(e, fz, i, j);
865 // for (e = ev.head(); e != 0; e = inext(e))
866 // cout << *e << " : " << *RFCS(*e) << endl;
867
868 i = j;
869 }
870
871 if (sil_item(*ev.tail()))
872 return;
873
874 float start_f0 = fz.a(fz.end());
875
876 e = ev.append();
877 make_int_item(*e, "sil", fz.end() + end_sil_length, fz.end(),
878 start_f0, 0.0, 0.0);
879 e->set("rfc:type", "SIL");
880}
881*/
882/*static void minimum_duration(EST_Relation &ev, float min_dur)
883{
884 EST_Item *e, *n;
885
886 for (e = ev.head(); e != 0; e = n)
887 {
888 n = inext(e);
889 if (dur(*e) < min_dur)
890 ev.remove_item(e);
891 }
892}
893
894static void adjust_overlaps(EST_Relation &ev)
895{
896 EST_Item *e, *n;
897 float pos=0.0;
898
899 for (e = ev.head(); inext(e) != 0; e = e->next())
900 {
901 n = inext(e);
902 if (e->F("end") > n->F("start"))
903 {
904*/
905/* cout << "Overlapping events " << *e <<":" << *n << endl;
906 // case a: genuine overlap
907 if (n->F("end") > e->F("end"))
908 {
909 cout << "case A\n";
910// pos = (e->F("end") + start(n)) / 2.0;
911 }
912
913 // case b: second element is enclosed by first
914 else if (n->F("end") <= e->F("end"))
915 {
916 cout << "case A\n";
917// pos = start(n);
918 }
919
920 // case c: second element is before first
921* else if ((n->F("end") < e->F("end")) &&
922 (start(n) < start(e)))
923 {
924 cout << "case A\n";
925 pos = (n->F("end") + start(e)) / 2.0;
926 }
927 else
928 cout << "No overlap conditions met\n";
929 // cout << "pos =" << pos << endl;
930*/
931/* e->set("end", pos);
932 n->set("start", pos);
933 cout << endl << endl;
934 }
935 }
936
937 // The overlap adjustments may cause the peak position to lie outside
938 // the start and end points. This checks for this and makes an
939 // arbitrary adjustment
940 for (e = ev.head(); inext(e) != 0; e = inext(e))
941 if ((e->f("rfc:type") == "RISEFALL") && (e->F("rfc:peak_pos") <
942 e->F("start")))
943 e->set("rfc:peak_pos",
944 (e->F("start") + e->F("end") / 2.0));
945}
946
947static void conn_ends(EST_Track &fz, EST_Relation &ev, float min_length)
948{
949 EST_Item *e, *n, *tmp;
950 float t, f0;
951 const float ARB_DISTANCE = 0.1;
952
953 cout << min_length << endl;
954
955 for (e = ev.head(); inext(e) != 0; e = inext(e))
956 {
957 n = inext(e);
958 cout << *e << ":";
959 cout << "n: " << n->F("start") << " e "<< e->F("end") << endl;
960
961 if ((n->F("start") - e->F("end")) > min_length)
962 {
963 cout << "making connection\n";
964 tmp = n->insert_before();
965 make_int_item(*tmp, "c", n->f("start"), e->f("start"),
966 e->f("rfc:end_f0"), 0.0, 0.0);
967
968 e = inext(e); // advance after new connection
969 }
970 else
971 {
972 t = (n->F("start") + e->F("end")) /2.0;
973 n->set("start", t);
974 e->set("end", t);
975 }
976 }
977
978 t = (ev.head())->f("start"); // store time of start of first event
979
980 // insert silence at beginning if contour doesn't start at near time 0
981 // if (fz.start() > fz.shift())
982 // {
983 // tmp = make_int_item("sil", fz.start(), 0.0, 0.0, 0.0, 0.0);
984 // ev.prepend(tmp);
985 // }
986 // add connection between silence and first event
987
988 tmp = ev.head()->insert_after();
989 make_int_item(*tmp, "c", t, 0.0, fz.a(fz.start()), 0.0, 0.0);
990
991 if ((ev.tail()->F("end") + min_length) < fz.end())
992 {
993 f0 = fz.a(ev.tail()->F("end"));
994 // add connection after last event.
995 //ev.insert_after(ev.tail(), tmp);
996 tmp = ev.append();
997 make_int_item(*tmp, "c", fz.end(), 0.0, f0, 0.0, 0.0);
998 }
999
1000 // add silence, an arbitrary distance after end - what a hack!
1001 // ev.insert_after(ev.tail(), tmp);
1002 tmp = ev.append();
1003 make_int_item(*tmp, "sil", fz.end() + ARB_DISTANCE,
1004 0.0, fz.a(fz.end()), 0.0, 0.0);
1005}
1006*/
1007
1008
1009
void set(const EST_String &name, int ival)
void remove(const EST_String &name)
const float F(const EST_String &path) const
int present(const EST_String &name) const
void set(const EST_String &name, int ival)
Definition EST_Item.h:179
const EST_String S(const EST_String &name) const
Definition EST_Item.h:143
EST_Features & A(const EST_String &name) const
Definition EST_Item.h:163
const float F(const EST_String &name) const
Definition EST_Item.h:134
int f_present(const EST_String &name) const
Definition EST_Item.h:230
void remove_item_feature(const EST_String &name)
void remove_item(EST_Item *item)
EST_Features f
EST_Item * head() const
EST_Item * tail() const
int track_break(int i) const
return true if frame i is a break
Definition EST_Track.h:633
float & t(int i=0)
return time position of frame i
Definition EST_Track.h:477
float & a(int i, int c=0)
int next_non_break(int i) const
Definition EST_Track.cc:629
float start() const
return time of first value in track
Definition EST_Track.cc:591
int num_frames() const
return number of frames in track
Definition EST_Track.h:650
float end() const
return time of last value in track
Definition EST_Track.cc:584
int index(float t) const
return the frame index nearest time t
Definition EST_Track.cc:470
float shift() const
Definition EST_Track.cc:599
int prev_non_break(int i) const
Definition EST_Track.cc:644