Formant.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /* Formant.cpp
  2. *
  3. * Copyright (C) 1992-2012,2014,2015,2016,2017 Paul Boersma
  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.
  13. * See the GNU 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. #include "Formant.h"
  19. #include "oo_DESTROY.h"
  20. #include "Formant_def.h"
  21. #include "oo_COPY.h"
  22. #include "Formant_def.h"
  23. #include "oo_EQUAL.h"
  24. #include "Formant_def.h"
  25. #include "oo_CAN_WRITE_AS_ENCODING.h"
  26. #include "Formant_def.h"
  27. #include "oo_READ_TEXT.h"
  28. #include "Formant_def.h"
  29. #include "oo_WRITE_TEXT.h"
  30. #include "Formant_def.h"
  31. #include "oo_READ_BINARY.h"
  32. #include "Formant_def.h"
  33. #include "oo_WRITE_BINARY.h"
  34. #include "Formant_def.h"
  35. #include "oo_DESCRIPTION.h"
  36. #include "Formant_def.h"
  37. #include "enums_getText.h"
  38. #include "Formant_enums.h"
  39. #include "enums_getValue.h"
  40. #include "Formant_enums.h"
  41. Thing_implement (Formant, Sampled, 2); // version 1 = with intensity, 2 = double
  42. void structFormant :: v_info () {
  43. structDaata :: v_info ();
  44. MelderInfo_writeLine (U"Time domain:");
  45. MelderInfo_writeLine (U" Start time: ", xmin, U" seconds");
  46. MelderInfo_writeLine (U" End time: ", xmax, U" seconds");
  47. MelderInfo_writeLine (U" Total duration: ", xmax - xmin, U" seconds");
  48. MelderInfo_writeLine (U"Time sampling:");
  49. MelderInfo_writeLine (U" Number of frames: ", nx);
  50. MelderInfo_writeLine (U" Time step: ", dx, U" seconds");
  51. MelderInfo_writeLine (U" First frame centred at: ", x1, U" seconds");
  52. }
  53. double structFormant :: v_getValueAtSample (integer iframe, integer which, int units) {
  54. Formant_Frame frame = & d_frames [iframe];
  55. integer iformant = which >> 1;
  56. if (iformant < 1 || iformant > frame -> nFormants) return undefined;
  57. double frequency = frame -> formant [iformant]. frequency;
  58. if ((which & 1) == 0) {
  59. return units ? NUMhertzToBark (frequency) : frequency;
  60. } else {
  61. double bandwidth = frame -> formant [iformant]. bandwidth;
  62. if (units) {
  63. double fleft = frequency - 0.5 * bandwidth, fright = frequency + 0.5 * bandwidth;
  64. fleft = ( fleft <= 0.0 ? 0.0 : NUMhertzToBark (fleft) ); // prevent undefined
  65. fright = NUMhertzToBark (fright);
  66. return fright - fleft;
  67. }
  68. return bandwidth;
  69. }
  70. return undefined;
  71. }
  72. autoFormant Formant_create (double tmin, double tmax, integer nt, double dt, double t1,
  73. integer maximumNumberOfFormants)
  74. {
  75. try {
  76. autoFormant me = Thing_new (Formant);
  77. Sampled_init (me.get(), tmin, tmax, nt, dt, t1);
  78. my d_frames = NUMvector <structFormant_Frame> (1, nt);
  79. my maxnFormants = maximumNumberOfFormants;
  80. return me;
  81. } catch (MelderError) {
  82. Melder_throw (U"Formant object not created.");
  83. }
  84. }
  85. integer Formant_getMinNumFormants (Formant me) {
  86. integer minNumFormants = 100000000;
  87. for (integer iframe = 1; iframe <= my nx; iframe ++)
  88. if (my d_frames [iframe]. nFormants < minNumFormants)
  89. minNumFormants = my d_frames [iframe]. nFormants;
  90. return minNumFormants;
  91. }
  92. integer Formant_getMaxNumFormants (Formant me) {
  93. integer maxNumFormants = 0;
  94. for (integer iframe = 1; iframe <= my nx; iframe ++)
  95. if (my d_frames [iframe]. nFormants > maxNumFormants)
  96. maxNumFormants = my d_frames [iframe]. nFormants;
  97. return maxNumFormants;
  98. }
  99. void Formant_drawTracks (Formant me, Graphics g, double tmin, double tmax, double fmax, bool garnish) {
  100. integer itmin, itmax, ntrack = Formant_getMinNumFormants (me);
  101. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
  102. if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return;
  103. Graphics_setInner (g);
  104. Graphics_setWindow (g, tmin, tmax, 0.0, fmax);
  105. for (integer itrack = 1; itrack <= ntrack; itrack ++) {
  106. for (integer iframe = itmin; iframe < itmax; iframe ++) {
  107. Formant_Frame curFrame = & my d_frames [iframe], nextFrame = & my d_frames [iframe + 1];
  108. double x1 = Sampled_indexToX (me, iframe), x2 = Sampled_indexToX (me, iframe + 1);
  109. double f1 = curFrame -> formant [itrack]. frequency;
  110. double f2 = nextFrame -> formant [itrack]. frequency;
  111. if (isdefined (x1) && isdefined (f1) && isdefined (x2) && isdefined (f2))
  112. Graphics_line (g, x1, f1, x2, f2);
  113. }
  114. }
  115. Graphics_unsetInner (g);
  116. if (garnish) {
  117. Graphics_drawInnerBox (g);
  118. Graphics_textBottom (g, true, U"Time (s)");
  119. Graphics_textLeft (g, true, U"Formant frequency (Hz)");
  120. Graphics_marksBottom (g, 2, true, true, false);
  121. Graphics_marksLeftEvery (g, 1.0, 1000.0, true, true, true);
  122. }
  123. }
  124. void Formant_drawSpeckles_inside (Formant me, Graphics g, double tmin, double tmax, double fmin, double fmax,
  125. double suppress_dB)
  126. {
  127. integer itmin, itmax;
  128. double maximumIntensity = 0.0, minimumIntensity;
  129. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
  130. if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return;
  131. Graphics_setWindow (g, tmin, tmax, fmin, fmax);
  132. for (integer iframe = itmin; iframe <= itmax; iframe ++) {
  133. Formant_Frame frame = & my d_frames [iframe];
  134. if (frame -> intensity > maximumIntensity)
  135. maximumIntensity = frame -> intensity;
  136. }
  137. if (maximumIntensity == 0.0 || suppress_dB <= 0.0)
  138. minimumIntensity = 0.0; // ignore
  139. else
  140. minimumIntensity = maximumIntensity / pow (10.0, suppress_dB / 10.0);
  141. for (integer iframe = itmin; iframe <= itmax; iframe ++) {
  142. Formant_Frame frame = & my d_frames [iframe];
  143. double x = Sampled_indexToX (me, iframe);
  144. if (frame -> intensity < minimumIntensity) continue;
  145. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++) {
  146. double frequency = frame -> formant [iformant]. frequency;
  147. if (frequency >= fmin && frequency <= fmax)
  148. Graphics_speckle (g, x, frequency);
  149. }
  150. }
  151. }
  152. void Formant_drawSpeckles (Formant me, Graphics g, double tmin, double tmax, double fmax, double suppress_dB,
  153. bool garnish)
  154. {
  155. Graphics_setInner (g);
  156. Formant_drawSpeckles_inside (me, g, tmin, tmax, 0.0, fmax, suppress_dB);
  157. Graphics_unsetInner (g);
  158. if (garnish) {
  159. Graphics_drawInnerBox (g);
  160. Graphics_textBottom (g, true, U"Time (s)");
  161. Graphics_textLeft (g, true, U"Formant frequency (Hz)");
  162. Graphics_marksBottom (g, 2, true, true, false);
  163. Graphics_marksLeftEvery (g, 1.0, 1000.0, true, true, true);
  164. }
  165. }
  166. void Formant_formula_bandwidths (Formant me, conststring32 formula, Interpreter interpreter) {
  167. try {
  168. integer nrow = Formant_getMaxNumFormants (me);
  169. if (nrow < 1)
  170. Melder_throw (U"No formants available.");
  171. autoMatrix mat = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, 0.5, nrow + 0.5, nrow, 1.0, 1.0);
  172. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  173. Formant_Frame frame = & my d_frames [iframe];
  174. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++)
  175. mat -> z [iformant] [iframe] = frame -> formant [iformant]. bandwidth;
  176. }
  177. Matrix_formula (mat.get(), formula, interpreter, nullptr);
  178. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  179. Formant_Frame frame = & my d_frames [iframe];
  180. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++)
  181. frame -> formant [iformant]. bandwidth = mat -> z [iformant] [iframe];
  182. }
  183. } catch (MelderError) {
  184. Melder_throw (me, U": bandwidth formula not executed.");
  185. }
  186. }
  187. void Formant_formula_frequencies (Formant me, conststring32 formula, Interpreter interpreter) {
  188. try {
  189. integer nrow = Formant_getMaxNumFormants (me);
  190. if (nrow < 1)
  191. Melder_throw (U"No formants available.");
  192. autoMatrix mat = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, 0.5, nrow + 0.5, nrow, 1.0, 1.0);
  193. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  194. Formant_Frame frame = & my d_frames [iframe];
  195. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++)
  196. mat -> z [iformant] [iframe] = frame -> formant [iformant]. frequency;
  197. }
  198. Matrix_formula (mat.get(), formula, interpreter, nullptr);
  199. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  200. Formant_Frame frame = & my d_frames [iframe];
  201. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++)
  202. frame -> formant [iformant]. frequency = mat -> z [iformant] [iframe];
  203. }
  204. } catch (MelderError) {
  205. Melder_throw (me, U": frequency formula not executed.");
  206. }
  207. }
  208. void Formant_getExtrema (Formant me, integer iformant, double tmin, double tmax, double *fmin, double *fmax) {
  209. if (fmin) *fmin = 0.0;
  210. if (fmax) *fmax = 0.0;
  211. if (iformant < 1) return;
  212. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
  213. integer itmin, itmax;
  214. if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return;
  215. for (integer iframe = itmin; iframe <= itmax; iframe ++) {
  216. Formant_Frame frame = & my d_frames [iframe];
  217. if (iformant > frame -> nFormants) continue;
  218. double f = frame -> formant [iformant]. frequency;
  219. if (f == 0.0) continue;
  220. if (fmin) if (f < *fmin || *fmin == 0.0) *fmin = f;
  221. if (fmax) if (f > *fmax) *fmax = f;
  222. }
  223. }
  224. void Formant_getMinimumAndTime (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate,
  225. double *return_minimum, double *return_timeOfMinimum)
  226. {
  227. Sampled_getMinimumAndX (me, tmin, tmax, iformant << 1, (int) unit, interpolate, return_minimum, return_timeOfMinimum);
  228. if (return_minimum && *return_minimum <= 0.0) *return_minimum = undefined;
  229. }
  230. double Formant_getMinimum (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate) {
  231. double minimum;
  232. Formant_getMinimumAndTime (me, iformant, tmin, tmax, unit, interpolate, & minimum, nullptr);
  233. return minimum;
  234. }
  235. double Formant_getTimeOfMinimum (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate) {
  236. double time;
  237. Formant_getMinimumAndTime (me, iformant, tmin, tmax, unit, interpolate, nullptr, & time);
  238. return time;
  239. }
  240. void Formant_getMaximumAndTime (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate,
  241. double *return_maximum, double *return_timeOfMaximum)
  242. {
  243. Sampled_getMaximumAndX (me, tmin, tmax, iformant << 1, (int) unit, interpolate, return_maximum, return_timeOfMaximum);
  244. if (return_maximum && *return_maximum <= 0.0) *return_maximum = undefined; // unlikely
  245. }
  246. double Formant_getMaximum (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate) {
  247. double maximum;
  248. Formant_getMaximumAndTime (me, iformant, tmin, tmax, unit, interpolate, & maximum, nullptr);
  249. return maximum;
  250. }
  251. double Formant_getTimeOfMaximum (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit, int interpolate) {
  252. double time;
  253. Formant_getMaximumAndTime (me, iformant, tmin, tmax, unit, interpolate, nullptr, & time);
  254. return time;
  255. }
  256. double Formant_getQuantile (Formant me, integer iformant, double quantile, double tmin, double tmax, kFormant_unit unit) {
  257. return Sampled_getQuantile (me, tmin, tmax, quantile, iformant << 1, (int) unit);
  258. }
  259. double Formant_getMean (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit) {
  260. return Sampled_getMean (me, tmin, tmax, iformant << 1, (int) unit, true);
  261. }
  262. double Formant_getStandardDeviation (Formant me, integer iformant, double tmin, double tmax, kFormant_unit unit) {
  263. if (iformant < 1 || isundef (tmin) || isundef (tmax)) return undefined;
  264. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
  265. integer itmin, itmax;
  266. if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return undefined;
  267. double mean = Formant_getMean (me, iformant, tmin, tmax, unit);
  268. double sum = 0.0;
  269. integer n = 0;
  270. for (integer iframe = itmin; iframe <= itmax; iframe ++) {
  271. Formant_Frame frame = & my d_frames [iframe];
  272. if (iformant > frame -> nFormants) continue;
  273. double f = frame -> formant [iformant]. frequency;
  274. if (f == 0.0) continue;
  275. if (unit == kFormant_unit::BARK) f = NUMhertzToBark (f);
  276. n += 1;
  277. sum += (f - mean) * (f - mean);
  278. }
  279. if (n > 1) return sqrt (sum / (n - 1));
  280. return undefined;
  281. }
  282. double Formant_getValueAtTime (Formant me, integer iformant, double time, kFormant_unit unit) {
  283. return Sampled_getValueAtX (me, time, iformant << 1, (int) unit, true);
  284. }
  285. double Formant_getBandwidthAtTime (Formant me, integer iformant, double time, kFormant_unit unit) {
  286. return Sampled_getValueAtX (me, time, (iformant << 1) + 1, (int) unit, true);
  287. }
  288. double Formant_getQuantileOfBandwidth (Formant me, integer iformant, double quantile, double tmin, double tmax, kFormant_unit unit) {
  289. return Sampled_getQuantile (me, tmin, tmax, quantile, (iformant << 1) + 1, (int) unit);
  290. }
  291. void Formant_scatterPlot (Formant me, Graphics g, double tmin, double tmax,
  292. integer iformant1, double fmin1, double fmax1, integer iformant2, double fmin2, double fmax2,
  293. double size_mm, conststring32 mark, bool garnish)
  294. {
  295. if (iformant1 < 1 || iformant2 < 1) return;
  296. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
  297. integer itmin, itmax;
  298. if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return;
  299. if (fmax1 == fmin1)
  300. Formant_getExtrema (me, iformant1, tmin, tmax, & fmin1, & fmax1);
  301. if (fmax1 == fmin1) return;
  302. if (fmax2 == fmin2)
  303. Formant_getExtrema (me, iformant2, tmin, tmax, & fmin2, & fmax2);
  304. if (fmax2 == fmin2) return;
  305. Graphics_setInner (g);
  306. Graphics_setWindow (g, fmin1, fmax1, fmin2, fmax2);
  307. for (integer iframe = itmin; iframe <= itmax; iframe ++) {
  308. Formant_Frame frame = & my d_frames [iframe];
  309. if (iformant1 > frame -> nFormants || iformant2 > frame -> nFormants) continue;
  310. double x = frame -> formant [iformant1]. frequency;
  311. double y = frame -> formant [iformant2]. frequency;
  312. if (x == 0.0 || y == 0.0) continue;
  313. Graphics_mark (g, x, y, size_mm, mark);
  314. }
  315. Graphics_unsetInner (g);
  316. if (garnish) {
  317. Graphics_drawInnerBox (g);
  318. Graphics_textBottom (g, true, Melder_cat (U"%%F_", iformant1, U" (Hz)"));
  319. Graphics_textLeft (g, true, Melder_cat (U"%%F_", iformant2, U" (Hz)"));
  320. Graphics_marksBottom (g, 2, true, true, false);
  321. Graphics_marksLeft (g, 2, true, true, false);
  322. }
  323. }
  324. autoMatrix Formant_to_Matrix (Formant me, integer iformant) {
  325. try {
  326. autoMatrix thee = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, 1.0, 1.0, 1, 1.0, 1.0);
  327. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  328. Formant_Frame frame = & my d_frames [iframe];
  329. thy z [1] [iframe] = iformant <= frame -> nFormants ?
  330. frame -> formant [iformant]. frequency : 0.0;
  331. }
  332. return thee;
  333. } catch (MelderError) {
  334. Melder_throw (me, U": frequencies of formant ", iformant, U" not converted to Matrix.");
  335. }
  336. }
  337. autoMatrix Formant_to_Matrix_bandwidths (Formant me, integer iformant) {
  338. try {
  339. autoMatrix thee = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, 1.0, 1.0, 1, 1.0, 1.0);
  340. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  341. Formant_Frame frame = & my d_frames [iframe];
  342. thy z [1] [iframe] = iformant <= frame -> nFormants ?
  343. frame -> formant [iformant]. bandwidth : 0.0;
  344. }
  345. return thee;
  346. } catch (MelderError) {
  347. Melder_throw (me, U": bandwidths of formant ", iformant, U" not converted to Matrix.");
  348. }
  349. }
  350. /*** Viterbi methods. ***/
  351. struct fparm { Formant me, thee; double dfCost, bfCost, octaveJumpCost, refF [1 + 5]; };
  352. static double getLocalCost (integer iframe, integer icand, integer itrack, void *closure) {
  353. struct fparm *me = (struct fparm *) closure;
  354. Formant_Frame frame = & my my d_frames [iframe];
  355. Formant_Formant candidate;
  356. if (icand > frame -> nFormants) return 1e30;
  357. candidate = & frame -> formant [icand];
  358. /*if (candidate -> frequency <= 0.0) candidate -> frequency = 0.001;
  359. Melder_fatal (U"Weird formant frequency ", candidate -> frequency, U" Hz.")*/;
  360. Melder_assert (candidate -> bandwidth > 0.0);
  361. Melder_assert (itrack > 0 && itrack <= 5);
  362. return my dfCost * fabs (candidate -> frequency - my refF [itrack]) +
  363. my bfCost * candidate -> bandwidth / candidate -> frequency;
  364. }
  365. static double getTransitionCost (integer iframe, integer icand1, integer icand2, integer itrack, void *closure) {
  366. struct fparm *me = (struct fparm *) closure;
  367. Formant_Frame prevFrame = & my my d_frames [iframe - 1], curFrame = & my my d_frames [iframe];
  368. double f1, f2;
  369. (void) itrack;
  370. if (icand1 > prevFrame -> nFormants || icand2 > curFrame -> nFormants) return 1e30;
  371. f1 = prevFrame -> formant [icand1]. frequency;
  372. f2 = curFrame -> formant [icand2]. frequency;
  373. /*Melder_assert (f1 > 0.0);*/
  374. /*Melder_assert (f2 > 0.0);*/
  375. return my octaveJumpCost * fabs (NUMlog2 (f1 / f2));
  376. }
  377. static void putResult (integer iframe, integer place, integer itrack, void *closure) {
  378. struct fparm *me = (struct fparm *) closure;
  379. Melder_assert (iframe > 0 && iframe <= my my nx);
  380. Melder_assert (itrack > 0 && itrack <= 5);
  381. Melder_assert (place > 0);
  382. Melder_assert (place <= my my d_frames [iframe]. nFormants);
  383. my thy d_frames [iframe]. formant [itrack] = my my d_frames [iframe]. formant [place];
  384. }
  385. autoFormant Formant_tracker (Formant me, integer ntrack,
  386. double refF1, double refF2, double refF3, double refF4, double refF5,
  387. double dfCost, /* Per kHz. */
  388. double bfCost, double octaveJumpCost)
  389. {
  390. try {
  391. integer nformmin = Formant_getMinNumFormants (me);
  392. struct fparm parm;
  393. if (ntrack > nformmin) Melder_throw (U"Number of tracks (", ntrack, U") should not exceed minimum number of formants (", nformmin, U").");
  394. autoFormant thee = Formant_create (my xmin, my xmax, my nx, my dx, my x1, ntrack);
  395. for (integer iframe = 1; iframe <= thy nx; iframe ++) {
  396. thy d_frames [iframe]. formant = NUMvector <structFormant_Formant> (1, ntrack);
  397. thy d_frames [iframe]. nFormants = ntrack;
  398. thy d_frames [iframe]. intensity = my d_frames [iframe]. intensity;
  399. }
  400. /* BUG: limit costs to 1e10 or so */
  401. parm.me = me;
  402. parm.thee = thee.get();
  403. parm.dfCost = dfCost / 1000.0; // per Hz
  404. parm.bfCost = bfCost;
  405. parm.octaveJumpCost = octaveJumpCost;
  406. parm.refF [1] = refF1;
  407. parm.refF [2] = refF2;
  408. parm.refF [3] = refF3;
  409. parm.refF [4] = refF4;
  410. parm.refF [5] = refF5;
  411. NUM_viterbi_multi (my nx, my maxnFormants, ntrack,
  412. getLocalCost, getTransitionCost, putResult, & parm);
  413. return thee;
  414. } catch (MelderError) {
  415. Melder_throw (me, U": not tracked.");
  416. }
  417. }
  418. autoTable Formant_downto_Table (Formant me, bool includeFrameNumbers,
  419. bool includeTimes, integer timeDecimals,
  420. bool includeIntensity, integer intensityDecimals,
  421. bool includeNumberOfFormants, integer frequencyDecimals,
  422. bool includeBandwidths)
  423. {
  424. try {
  425. autoTable thee = Table_createWithoutColumnNames (my nx, includeFrameNumbers + includeTimes + includeIntensity +
  426. includeNumberOfFormants + my maxnFormants * (1 + includeBandwidths));
  427. integer icol = 0;
  428. if (includeFrameNumbers) Table_setColumnLabel (thee.get(), ++ icol, U"frame");
  429. if (includeTimes) Table_setColumnLabel (thee.get(), ++ icol, U"time(s)");
  430. if (includeIntensity) Table_setColumnLabel (thee.get(), ++ icol, U"intensity");
  431. if (includeNumberOfFormants) Table_setColumnLabel (thee.get(), ++ icol, U"nformants");
  432. for (integer iformant = 1; iformant <= my maxnFormants; iformant ++) {
  433. Table_setColumnLabel (thee.get(), ++ icol, Melder_cat (U"F", iformant, U"(Hz)"));
  434. if (includeBandwidths) { Table_setColumnLabel (thee.get(), ++ icol, Melder_cat (U"B", iformant, U"(Hz)")); }
  435. }
  436. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  437. icol = 0;
  438. if (includeFrameNumbers)
  439. Table_setNumericValue (thee.get(), iframe, ++ icol, iframe);
  440. if (includeTimes)
  441. Table_setStringValue (thee.get(), iframe, ++ icol, Melder_fixed (my x1 + (iframe - 1) * my dx, timeDecimals));
  442. Formant_Frame frame = & my d_frames [iframe];
  443. if (includeIntensity)
  444. Table_setStringValue (thee.get(), iframe, ++ icol, Melder_fixed (frame -> intensity, intensityDecimals));
  445. if (includeNumberOfFormants)
  446. Table_setNumericValue (thee.get(), iframe, ++ icol, frame -> nFormants);
  447. for (integer iformant = 1; iformant <= frame -> nFormants; iformant ++) {
  448. Formant_Formant formant = & frame -> formant [iformant];
  449. Table_setStringValue (thee.get(), iframe, ++ icol, Melder_fixed (formant -> frequency, frequencyDecimals));
  450. if (includeBandwidths)
  451. Table_setStringValue (thee.get(), iframe, ++ icol, Melder_fixed (formant -> bandwidth, frequencyDecimals));
  452. }
  453. for (integer iformant = frame -> nFormants + 1; iformant <= my maxnFormants; iformant ++) {
  454. Table_setNumericValue (thee.get(), iframe, ++ icol, undefined);
  455. if (includeBandwidths)
  456. Table_setNumericValue (thee.get(), iframe, ++ icol, undefined);
  457. }
  458. }
  459. return thee;
  460. } catch (MelderError) {
  461. Melder_throw (me, U": not converted to Table.");
  462. }
  463. }
  464. void Formant_list (Formant me, bool includeFrameNumbers,
  465. bool includeTimes, integer timeDecimals,
  466. bool includeIntensity, integer intensityDecimals,
  467. bool includeNumberOfFormants, integer frequencyDecimals,
  468. bool includeBandwidths)
  469. {
  470. try {
  471. autoTable table = Formant_downto_Table (me, includeFrameNumbers, includeTimes, timeDecimals,
  472. includeIntensity, intensityDecimals,
  473. includeNumberOfFormants, frequencyDecimals, includeBandwidths);
  474. Table_list (table.get(), false);
  475. } catch (MelderError) {
  476. Melder_throw (me, U": not listed.");
  477. }
  478. }
  479. /* End of file Formant.cpp */