Edinburgh Speech Tools  2.1-release
tilt_synthesis.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 : February 1996 - August 98 */
35 /* RFC Synthesis */
36 /* */
37 /*=======================================================================*/
38 
39 #include "tilt.h"
40 #include "EST_unix.h"
41 #include "EST_math.h"
42 #include "EST_tilt.h"
43 #include "EST_Track.h"
44 #include "EST_error.h"
45 
46 
47 void tilt_synthesis(EST_Track &fz, EST_Relation &ev, float f_shift,
48  int no_conn)
49 {
50  tilt_to_rfc(ev);
51 
52  rfc_synthesis(fz, ev, f_shift, no_conn);
53 
54  ev.remove_item_feature("rfc");
55 }
56 
57 void synthesize_rf_event(EST_Track &fz, EST_Features &ev, float peak_f0)
58 {
59  float t, amp, f_shift, a=0, start_f0;
60  float dur=0; // for egcs
61  ssize_t j;
62 
63  f_shift = fz.shift();
64 
65  dur = ev.F("rise_dur");
66  amp = ev.F("rise_amp");
67  start_f0 = peak_f0 - amp;
68 
69  for (j = 0, t = 0.0; t < dur; t += f_shift, ++j)
70  {
71  a = unit_curve(amp, dur, t) + start_f0;
72  if (a > fz.a(j)) // overlap check
73  fz.a(j) = a;
74  fz.set_value(j);
75  }
76 
77  dur = ev.F("fall_dur");
78  amp = ev.F("fall_amp");
79 
80  for (t = 0.0; t < dur; t += f_shift, ++j)
81  {
82  a = unit_curve(amp, dur, t) + peak_f0;
83  if (a > fz.a(j)) // overlap check
84  fz.a(j) = a;
85  fz.set_value(j);
86  }
87  // hack to fill final values because of timing rounding errors
88  for (; j < fz.num_frames(); ++j)
89  fz.a(j) = a;
90 }
91 
92 void fill_connection_values(EST_Track &fz, float start_f0, float start_pos,
93  float end_f0, float end_pos)
94 {
95  float f_shift, m;
96  ssize_t j;
97  f_shift = fz.shift();
98  if ((end_pos - start_pos) == 0)
99  m = 0.0;
100  else
101  m = (end_f0 - start_f0) / (end_pos - start_pos);
102  for (j = 0; j < fz.num_frames()-1; ++j)
103  {
104  fz.a(j) = (m * (float) j * f_shift) + start_f0;
105  fz.set_value(j);
106  }
107  fz.a(fz.num_frames()-1) = end_f0;
108  fz.set_value(fz.num_frames()-1);
109  // hack to fill final values because of timing rounding errors
110  //a = fz.a(j -1); // I Think this is ezafi
111  //for (; j < fz.num_frames(); ++j)
112  //fz.a(j) = a;
113 }
114 
115 
116 void rfc_synthesis(EST_Track &fz, EST_Relation &ev, float f_shift, int no_conn)
117 {
118  EST_Item *e,*nn;
119  EST_Track sub;
120  float start_pos=0, start_f0=0;
121  int start_index, end_index;
122  float end_pos, end_f0;
123  int n;
124 
125  if (event_item(*ev.tail()))
126  n = (int)(ceil((ev.tail()->F("time") +
127  ev.tail()->F("rfc.fall_dur",0)) / f_shift)) + 1;
128  else
129  n = (int)(ceil(ev.tail()->F("time")/ f_shift)) + 1;
130 
131  fz.resize(n, 1);
132  fz.set_equal_space(true);
133  fz.fill(0.0);
134  fz.fill_time(f_shift);
135 
136  // set default to be break (silence)
137  for (ssize_t i = 0; i < fz.num_frames(); ++i)
138  fz.set_break(i);
139 
140  // synthesize events
141  for (e = ev.head(); e != 0; e = e->next())
142  {
143  if (event_item(*e))
144  {
145  start_pos = e->F("time") - e->F("rfc.rise_dur");
146  end_pos = e->F("time") + e->F("rfc.fall_dur");
147 
148  if ((start_pos / f_shift-(int)start_pos / f_shift)>.5)
149  start_index=int(start_pos / f_shift+1);
150  else
151  start_index = (int) start_pos / f_shift;
152  if(end_pos / f_shift-(int)end_pos / f_shift>.5)
153  end_index = int( end_pos / f_shift+1);
154  else
155  end_index = (int) end_pos / f_shift;
156 // cout << "a: " << fz.equal_space() << endl;
157 
158  fz.sub_track(sub, start_index, (end_index - start_index) + 1,
159  0, EST_ALL);
160 
161 // cout << "a: " << fz.equal_space() << endl;
162 // cout << "b: " << sub.equal_space() << endl;
163 
164  synthesize_rf_event(sub, e->A("rfc"), e->F("ev.f0"));
165  }
166  }
167 
168  if (no_conn)
169  return;
170 
171  // synthesize connections
172  for (e = ev.head(); e->next() != 0; e = e->next())
173  {
174  if (e->S("name") == "phrase_end")
175  continue;
176  nn = e->next();
177 
178  // calculate start and stop times, with additional
179  // optional adjustment for rise and falls on events
180 
181  start_f0 = e->F("ev.f0") + e->F("rfc.fall_amp", 0.0);
182  start_pos= e->F("time") + e->F("rfc.fall_dur", 0.0);
183 
184  end_f0 = nn->F("ev.f0") - nn->F("rfc.rise_amp", 0.0);
185  end_pos = nn->F("time") - nn->F("rfc.rise_dur", 0.0);
186 
187  if ((start_pos / f_shift-(int)start_pos / f_shift)>.5)
188  start_index=int(start_pos / f_shift+1);
189  else
190  start_index = (int) start_pos / f_shift;
191  if(end_pos / f_shift-(int)end_pos / f_shift>.5)
192  end_index = int( end_pos / f_shift+1);
193  else
194  end_index = (int) end_pos / f_shift;
195 
196 
197  if (start_index >= end_index) // no connection needed
198  continue;
199 
200  fz.sub_track(sub, start_index, end_index - start_index+1 , 0, EST_ALL);
201 
202  fill_connection_values(sub, start_f0, start_pos, end_f0, end_pos);
203  }
204 }
205 
206 /*
207 
208 // find event portions of fz in contour, cut out, and send one by one
209 // to individual labeller.
210 void fill_rise_fall_values(EST_Track &fz, float amp, float dur, float
211  start_f0, float start_pos, float f_shift, EST_String type, int nframes)
212 {
213  float t, a;
214 
215  // this ensures rounding errors don't multiply
216  ssize_t j = (int) rint(start_pos / f_shift);
217  int n = 0;
218 
219 // for (t = 0.0; t < (dur + (f_shift /2.0)); t += f_shift, ++j, ++n)
220  for (t = 0.0; n < nframes; t += f_shift, ++j, ++n)
221  {
222  a = unit_curve(type, amp, dur, t) + start_f0;
223  if (a > fz.a(j)) // overlap check
224  fz.a(j) = a;
225  fz.set_value(j);
226  }
227  cout << "curve frames: " << n << endl;
228 }
229 
230 void fill_connection_values(EST_Track &fz, float start_f0, float start_pos,
231  float end_f0, float end_pos,
232  float f_shift)
233 {
234  // this ensures rounding errors don't multiply
235  ssize_t j = (ssize_t) rint(start_pos / f_shift);
236 
237  float m = (end_f0 - start_f0) / (end_pos - start_pos);
238 
239  if (!finite(m))
240  m = 0.0;
241 
242  int pos = fz.index(start_pos);
243 
244  for (j = pos; j < (fz.index(end_pos) + 1); ++j)
245  {
246  fz.a(j) = (m * (float) (j -pos) * f_shift) + start_f0;
247  fz.set_value(j);
248  }
249 }
250 
251 
252 void fill_rise_fall_values(EST_Track &fz, float amp, float start_f0)
253 {
254  float t, a;
255  ssize_t j;
256  float f_shift = fz.shift();
257  float dur = fz.num_frames() * f_shift;
258 
259  for (j = 0, t = 0.0; j < fz.num_frames(); t += f_shift, ++j)
260  {
261  a = unit_curve("RISE", amp, dur, t) + start_f0;
262  if (a > fz.a(j)) // overlap check
263  fz.a(j) = a;
264  fz.set_value(j);
265  }
266 }
267 
268 void fill_connection_values(EST_Track &fz, float start_f0, float end_f0)
269 {
270  // this ensures rounding errors don't multiply
271  ssize_t j;
272  float f_shift = fz.shift();
273  float dur = fz.num_frames() * f_shift;
274 
275  float m = (end_f0 - start_f0) / dur;
276 
277  if (!finite(m))
278  m = 0.0;
279 
280  for (j = 0 j < fz.num_frames(); ++j)
281  {
282  fz.a(j) = (m * (float)j * f_shift) + start_f0;
283  fz.set_value(j);
284  }
285 
286 }
287 
288 
289 #if 0
290 void start_f0_pos(EST_Item *e, const EST_String &type, float &start_f0,
291  float &start_pos)
292 {
293  if (type == "RISE")
294  {
295  start_f0 = e->F("ev.f0");
296  start_pos = e->F("position") - e->F("rfc.rise_dur");
297  }
298  else
299  {
300  start_f0 = e->F("ev.f0") + e->F("rfc.rise_amp");
301  start_pos = e->F("position");
302  }
303 }
304 #endif
305 
306 static float find_start_pos(EST_Item *e, const EST_String &type)
307 {
308  //cout << "find start position for " << *e << endl;
309  if (type == "RISE")
310  return e->F("position") - e->F("rfc.rise_dur");
311  else
312  return e->F("position");
313 }
314 
315 static float find_start_f0(EST_Item *e, const EST_String &type)
316 {
317  //cout << "find start f0 for " << *e<< endl;
318  if (type == "RISE")
319  return e->F("ev.f0");
320  else
321  return e->F("ev.f0") + e->F("rfc.rise_amp");
322 }
323 
324 float rfc_dur(EST_Item *e)
325 {
326  return e->F("rfc.rise_dur") + e->F("rfc.fall_dur");
327 }
328 
329 float rfc_amp(EST_Item *e)
330 {
331  return e->F("rfc.rise_amp") + e->F("rfc.fall_amp");
332 }
333 
334 
335 
336 int rfc_synthesis_ld(EST_Track &fz, EST_Relation &ev, float f_shift, int no_conn)
337 {
338  EST_Item *e,*nn;
339  EST_Track sub;
340  float start_pos=0, start_f0=0;
341  EST_String type;
342  (void)no_conn;
343  int start_index, nframes, end_index;
344  float length, end_pos;
345 
346  float last_time = ev.tail()->F("position") + rfc_dur(ev.tail());
347  int n = (int)(2 + (last_time / f_shift));
348  fz.resize(n, 1);
349  fz.fill(0.0);
350  fz.fill_time(f_shift);
351 
352  fill_rfc_types(ev);
353 
354  // set default to be break (silence)
355  for (ssize_t i = 0; i < fz.num_frames(); ++i)
356  fz.set_break(i);
357 
358  for (e = ev.head(); e != 0; e = e->next())
359  {
360  // cout << "\ntype: " << e->fS("rfc.type") << endl;
361  //cout << "\ntype: " << *e << endl;
362  if (e->f("rfc.type",1) == "RISEFALL")
363  {
364  start_f0 = find_start_f0(e,"RISE");
365  start_pos = find_start_pos(e,"RISE");
366 
367  start_index = (int) rint(start_pos / f_shift);
368  nframes = (int)((e->F("rfc.rise_dur")+ (f_shift /2.0))/f_shift);
369  fz.sub_track(sub, start_index, nframes, 0, EST_ALL);
370 
371  fill_rise_fall_values(sub, e->F("rfc.rise_amp"), start_f0);
372  cout << "rise subtrack: " << sub;
373 
374  start_index = (int) rint(find_start_pos(e, "FALL") / f_shift);
375  nframes = (int)((e->F("rfc.fall_dur") +(f_shift /2.0))/f_shift);
376  fz.sub_track(sub, start_index, nframes, 0, EST_ALL);
377 
378  fill_rise_fall_values(sub, e->F("rfc.fall_amp"),
379  find_start_f0(e,"FALL"));
380 
381  cout << "fall subtrack: " << sub;
382 
383 
384  fill_rise_fall_values(sub, e->F("rfc.fall_amp"), e->F("rfc.fall_dur"),
385  find_start_f0(e,"FALL"),
386  find_start_pos(e,"FALL"),
387  f_shift, "FALL", nframes);
388 
389 
390  }
391  else if (e->f("rfc.type",1) == "RISE")
392  {
393  start_f0 = find_start_f0(e,"RISE");
394  start_pos = find_start_pos(e,"RISE");
395 
396  start_index = (int) rint(start_pos / f_shift);
397  nframes = (int)((e->F("rfc.rise_dur")+ (f_shift /2.0))/f_shift);
398  fz.sub_track(sub, start_index, nframes, 0, EST_ALL);
399 
400  fill_rise_fall_values(sub, e->F("rfc.rise_amp"), start_f0);
401 
402 
403  fill_rise_fall_values(fz, e->F("rfc.rise_amp"),
404  e->F("rfc.rise_dur"),
405  start_f0, start_pos,
406  f_shift, "RISE", nframes);
407 
408 
409  }
410  else if (e->f("rfc.type",1) == "FALL")
411  {
412  start_f0 = find_start_f0(e, "FALL");
413  start_pos = find_start_pos(e, "FALL");
414 
415  nframes = (int)((e->F("rfc.fall_dur")+ (f_shift /2.0))/f_shift);
416  start_index = (int) rint(find_start_pos(e, "FALL") / f_shift);
417  fz.sub_track(sub, start_index, nframes, 0, EST_ALL);
418 
419  fill_rise_fall_values(fz, e->F("rfc.fall_amp"),
420  e->F("ev.f0"));
421 
422  fill_rise_fall_values(fz, e->F("rfc.fall_amp"),
423  e->F("rfc.fall_dur"), e->F("ev.f0"),
424  e->F("position"), f_shift,
425  "FALL", nframes);
426 
427  }
428  else
429  {
430  EST_Item *nn,*pp;
431 
432  if (no_conn)
433  continue;
434 
435  if (e->f("name",1) == "phrase_end")
436  {
437  if (e->f_present("ev.f0"))
438  {
439  pp = e->prev();
440 
441  fill_connection_values(fz, start_f0 + rfc_amp(pp),
442  start_pos
443  + rfc_dur(pp), e->F("ev.f0"),
444  e->F("position"), f_shift);
445 
446  }
447  }
448  else if (e->f("name", 1) == "phrase_start")
449  {
450  //cout << "phrase start:\n" << *e << endl;
451  if ((nn = e->next()) == 0)
452  EST_error("phrase start command occurs as last item "
453  "in rfc synthesis\n");
454  else if (event_item(*nn))
455  {
456  start_f0 = find_start_f0(nn,"RISE");
457  start_pos = find_start_pos(nn,"RISE");
458  }
459  else
460  {
461  start_f0 = nn->F("ev.f0");
462  start_pos = nn->F("position");
463  }
464 
465  fill_connection_values(fz, e->F("ev.f0"),
466  e->F("position"),
467  start_f0,start_pos, f_shift);
468 
469  }
470  else if (e->f("name") == "pause")
471  {}
472  else
473  EST_error("Unable to synthesis intonation element %s\n",
474  (const char *)(e->fS("name")));
475  continue;
476  }
477  if (((nn = e->next()) != 0) && (event_item(*nn)))
478  {
479  float f0 = start_f0+rfc_amp(e);
480  float pos = start_pos + rfc_dur(e);
481  float end_f0 = find_start_f0(nn,"RISE");
482  float end_pos = find_start_pos(nn,"RISE");
483  fill_connection_values(fz, f0, pos, end_f0, end_pos, f_shift);
484  }
485  }
486 }
487 */
EST_Item * head() const
Definition: EST_Relation.h:121
float unit_curve(float amp, float dur, float t)
Definition: tilt_utils.cc:374
EST_Item * tail() const
Definition: EST_Relation.h:127
void set_value(ssize_t i)
set frame i to be a value
Definition: EST_Track.cc:133
void set_break(ssize_t i)
set frame i to be a break
Definition: EST_Track.cc:124
int ssize_t
const int EST_ALL
void resize(ssize_t num_frames, int num_channels, bool preserve=1)
Definition: EST_Track.cc:214
void sub_track(EST_Track &st, int start_frame=0, int nframes=EST_ALL, int start_chan=0, int nchans=EST_ALL)
Definition: EST_Track.cc:1100
void rfc_synthesis(EST_Track &fz, EST_Relation &ev, float f_shift, int no_conn)
Generate an F0 contour given a list RFC events.
float & a(ssize_t i, int c=0)
Definition: EST_Track.cc:1025
void tilt_to_rfc(EST_Features &tilt, EST_Features &rfc)
Convert a single set of local tilt parameters to local RFC parameters.
Definition: tilt_utils.cc:197
EST_FMatrix sub(const EST_FMatrix &a, ssize_t row, ssize_t col)
Definition: vec_mat_aux.cc:187
float F(const EST_String &name) const
Definition: EST_Item.h:135
void fill_connection_values(EST_Track &fz, float start_f0, float start_pos, float end_f0, float end_pos)
void tilt_synthesis(EST_Track &fz, EST_Relation &ev, float f_shift, int no_conn)
Generate an F0 contour given a list Tilt events.
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
EST_Item * next() const
Definition: EST_Item.h:348
void fill(float v)
Definition: EST_Track.h:501
int event_item(EST_Item &e)
Definition: tilt_utils.cc:410
const EST_String S(const EST_String &name) const
Definition: EST_Item.h:144
float shift() const
Definition: EST_Track.cc:602
void remove_item_feature(const EST_String &name)
void synthesize_rf_event(EST_Track &fz, EST_Features &ev, float peak_f0)
void set_equal_space(bool t)
Definition: EST_Track.h:675
void fill_time(float t, int start=1)
Definition: EST_Track.cc:789
float F(const EST_String &path) const
Definition: EST_Features.h:136