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