DTW_and_TextGrid.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* DTW_and_TextGrid.cpp
  2. *
  3. * Copyright (C) 1993-2012, 2015 David Weenink
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. djmw 20060906
  20. djmw 20070306: Reverse x and y. Reference should always be vertical!
  21. djmw 20110304 Thing_new
  22. */
  23. #include "DTW_and_TextGrid.h"
  24. // begin old prototypes for compatibility reasons with the past
  25. autoTextGrid DTW_TextGrid_to_TextGrid_old (DTW me, TextGrid thee);
  26. autoIntervalTier DTW_IntervalTier_to_IntervalTier_old (DTW me, IntervalTier thee);
  27. autoTextTier DTW_TextTier_to_TextTier_old (DTW me, TextTier thee);
  28. // end old
  29. /* Get times from TextGrid and substitute new time form the y-times of the DTW. */
  30. autoTextTier DTW_TextTier_to_TextTier (DTW me, TextTier thee, double precision) {
  31. try {
  32. if (fabs (my ymin - thy xmin) <= precision && fabs (my ymax - thy xmax) <= precision) { // map from Y to X
  33. autoTextTier him = Data_copy (thee);
  34. his xmin = my xmin;
  35. his xmax = my xmax;
  36. for (integer i = 1; i <= his points.size; i ++) {
  37. TextPoint textpoint = his points.at [i];
  38. double time = DTW_getXTimeFromYTime (me, textpoint -> number);
  39. textpoint -> number = time;
  40. }
  41. return him;
  42. } else if (fabs (my xmin - thy xmin) <= precision && fabs (my xmax - thy xmax) <= precision) { // map from X to Y
  43. autoTextTier him = Data_copy (thee);
  44. his xmin = my ymin;
  45. his xmax = my ymax;
  46. for (integer i = 1; i <= his points.size; i ++) {
  47. TextPoint textpoint = his points.at [i];
  48. double time = DTW_getYTimeFromXTime (me, textpoint -> number);
  49. textpoint -> number = time;
  50. }
  51. return him;
  52. } else {
  53. Melder_throw (U"The domain of the TextTier and one of the domains of the DTW should be equal.");
  54. }
  55. } catch (MelderError) {
  56. Melder_throw (U"TextTier not created from DTW & TextTier.");
  57. }
  58. }
  59. autoIntervalTier DTW_IntervalTier_to_IntervalTier (DTW me, IntervalTier thee, double precision) {
  60. try {
  61. if (fabs (my ymin - thy xmin) <= precision && fabs (my ymax - thy xmax) <= precision) { // map from Y to X
  62. autoIntervalTier him = Data_copy (thee);
  63. his xmin = my xmin;
  64. his xmax = my xmax;
  65. TextInterval textinterval = his intervals.at [1];
  66. textinterval -> xmin = his xmin;
  67. double xmax = DTW_getXTimeFromYTime (me, textinterval -> xmax);
  68. textinterval -> xmax = xmax;
  69. for (integer i = 2; i <= his intervals.size; i ++) {
  70. textinterval = his intervals.at [i];
  71. textinterval -> xmin = xmax;
  72. xmax = DTW_getXTimeFromYTime (me, textinterval -> xmax);
  73. textinterval -> xmax = xmax;
  74. }
  75. textinterval = his intervals.at [his intervals.size];
  76. textinterval -> xmax = his xmax;
  77. Melder_assert (textinterval -> xmin < textinterval -> xmax);
  78. return him;
  79. } else if (fabs (my xmin - thy xmin) <= precision && fabs (my xmax - thy xmax) <= precision) { // map from X to Y
  80. autoIntervalTier him = Data_copy (thee);
  81. his xmin = my ymin;
  82. his xmax = my ymax;
  83. TextInterval textinterval = his intervals.at [1];
  84. textinterval -> xmin = his xmin;
  85. double xmax = DTW_getYTimeFromXTime (me, textinterval -> xmax);
  86. textinterval -> xmax = xmax;
  87. for (integer i = 2; i <= his intervals.size; i ++) {
  88. textinterval = his intervals.at [i];
  89. textinterval -> xmin = xmax;
  90. xmax = DTW_getYTimeFromXTime (me, textinterval -> xmax);
  91. textinterval -> xmax = xmax;
  92. }
  93. textinterval = his intervals.at [his intervals.size];
  94. textinterval -> xmax = his xmax;
  95. Melder_assert (textinterval -> xmin < textinterval -> xmax);
  96. return him;
  97. } else {
  98. Melder_throw (U"The domain of the IntervalTier and one of the domains of the DTW should be equal.");
  99. }
  100. } catch (MelderError) {
  101. Melder_throw (U"IntervalTier not created from DTW & IntervalTier.");
  102. }
  103. }
  104. autoTextGrid DTW_TextGrid_to_TextGrid (DTW me, TextGrid thee, double precision) {
  105. try {
  106. double tmin, tmax;
  107. if (fabs (my ymin - thy xmin) <= precision && fabs (my ymax - thy xmax) <= precision) {
  108. tmin = my xmin;
  109. tmax = my xmax;
  110. } else if (fabs (my xmin - thy xmin) <= precision && fabs (my xmax - thy xmax) <= precision) {
  111. tmin = my ymin;
  112. tmax = my ymax;
  113. } else {
  114. Melder_throw (U"The domain of the TextGrid should be equal to one of the domains of the DTW.");
  115. }
  116. autoTextGrid him = TextGrid_createWithoutTiers (tmin, tmax);
  117. for (integer i = 1; i <= thy tiers->size; i ++) {
  118. Function anyTier = thy tiers->at [i];
  119. if (anyTier -> classInfo == classIntervalTier) {
  120. autoIntervalTier tier = DTW_IntervalTier_to_IntervalTier (me, (IntervalTier) anyTier, precision);
  121. TextGrid_addTier_copy (him.get(), tier.get());
  122. } else if (anyTier -> classInfo == classTextTier) {
  123. autoTextTier tier = DTW_TextTier_to_TextTier (me, (TextTier) anyTier, precision);
  124. TextGrid_addTier_copy (him.get(), tier.get());
  125. } else {
  126. Melder_throw (U"Unknown tier.");
  127. }
  128. }
  129. return him;
  130. } catch (MelderError) {
  131. Melder_throw (U"TextGrid not created from DTW & TextGrid.");
  132. }
  133. }
  134. autoTable DTW_IntervalTier_to_Table (DTW me, IntervalTier thee, double precision) {
  135. try {
  136. integer numberOfIntervals = thy intervals.size;
  137. autoTable him = Table_createWithColumnNames (numberOfIntervals, U"tmin tmax label dist");
  138. if (fabs (my ymin - thy xmin) <= precision && fabs (my ymax - thy xmax) <= precision) { // map from Y to X
  139. integer pathIndex = 1;
  140. for (integer i = 1; i <= numberOfIntervals; i ++) {
  141. TextInterval textinterval = thy intervals.at [i];
  142. double xmin = DTW_getXTimeFromYTime (me, textinterval -> xmin);
  143. double xmax = DTW_getXTimeFromYTime (me, textinterval -> xmax);
  144. integer ixmin, ixmax;
  145. integer numberOfFrames = Matrix_getWindowSamplesX (me, xmin, xmax, & ixmin, & ixmax);
  146. double sumOfDistances = 0.0;
  147. while (pathIndex < my pathLength && my path [pathIndex].x < ixmax) {
  148. sumOfDistances += my z [my path [pathIndex].y] [my path [pathIndex].x];
  149. pathIndex ++;
  150. }
  151. Table_setNumericValue (him.get(), i, 1, textinterval -> xmin);
  152. Table_setNumericValue (him.get(), i, 2, textinterval -> xmax);
  153. Table_setStringValue (him.get(), i, 3, textinterval -> text.get());
  154. Table_setNumericValue (him.get(), i, 4, sumOfDistances / numberOfFrames);
  155. }
  156. } else if (fabs (my xmin - thy xmin) <= precision && fabs (my xmax - thy xmax) <= precision) { // map from X to Y
  157. integer pathIndex = 1;
  158. for (integer i = 1; i <= numberOfIntervals; i ++) {
  159. TextInterval textinterval = thy intervals.at [i];
  160. double ymin = DTW_getYTimeFromXTime (me, textinterval -> xmin);
  161. double ymax = DTW_getYTimeFromXTime (me, textinterval -> xmax);
  162. integer iymin, iymax;
  163. integer numberOfFrames = Matrix_getWindowSamplesY (me, ymin, ymax, & iymin, & iymax);
  164. double sumOfDistances = 0;
  165. while (pathIndex < my pathLength && my path [pathIndex].y < iymax) {
  166. sumOfDistances += my z [my path [pathIndex].y] [my path [pathIndex].x];
  167. pathIndex ++;
  168. }
  169. Table_setNumericValue (him.get(), i, 1, textinterval -> xmin);
  170. Table_setNumericValue (him.get(), i, 2, textinterval -> xmax);
  171. Table_setStringValue (him.get(), i, 3, textinterval -> text.get());
  172. Table_setNumericValue (him.get(), i, 4, sumOfDistances / numberOfFrames);
  173. }
  174. } else {
  175. Melder_throw (U"The domain of the IntervalTier and one of the domains of the DTW should be equal.");
  176. }
  177. return him;
  178. } catch (MelderError) {
  179. Melder_throw (me, U": no Table with distances created.");
  180. }
  181. }
  182. /* Get times from TextGrid and substitute new time form the y-times of the DTW. */
  183. autoTextTier DTW_TextTier_to_TextTier_old (DTW me, TextTier thee) {
  184. try {
  185. if (my xmin != thy xmin || my xmax != thy xmax) {
  186. Melder_throw (U"The domain of the TextTier and the DTW should be equal.");
  187. }
  188. autoTextTier him = Data_copy (thee);
  189. his xmin = my ymin;
  190. his xmax = my ymax;
  191. for (integer i = 1; i <= his points.size; i ++) {
  192. TextPoint textpoint = his points.at [i];
  193. double time = DTW_getYTimeFromXTime (me, textpoint -> number);
  194. textpoint -> number = time;
  195. }
  196. return him;
  197. } catch (MelderError) {
  198. Melder_throw (U"TextTier not created.");
  199. }
  200. }
  201. autoIntervalTier DTW_IntervalTier_to_IntervalTier_old (DTW me, IntervalTier thee) {
  202. try {
  203. if (my xmin != thy xmin || my xmax != thy xmax) Melder_throw
  204. (U"The domain of the IntervalTier and the DTW should be equal.");
  205. autoIntervalTier him = Data_copy (thee);
  206. his xmin = my ymin;
  207. his xmax = my ymax;
  208. for (integer i = 1; i <= his intervals.size; i ++) {
  209. TextInterval textinterval = his intervals.at [i];
  210. double xmin = DTW_getYTimeFromXTime (me, textinterval -> xmin);
  211. textinterval -> xmin = xmin;
  212. double xmax = DTW_getYTimeFromXTime (me, textinterval -> xmax);
  213. textinterval -> xmax = xmax;
  214. }
  215. return him;
  216. } catch (MelderError) {
  217. Melder_throw (U"IntervalTier not created.");
  218. }
  219. }
  220. autoTextGrid DTW_TextGrid_to_TextGrid_old (DTW me, TextGrid thee) {
  221. try {
  222. autoTextGrid him = Thing_new (TextGrid);
  223. if (my xmin != thy xmin || my xmax != thy xmax) {
  224. Melder_throw (U"The domain of the TextGrid and the y-domain of the DTW should be equal.");
  225. }
  226. his xmin = my ymin;
  227. his xmax = my ymax;
  228. his tiers = FunctionList_create ();
  229. for (integer i = 1; i <= thy tiers->size; i ++) {
  230. Daata anyTier = thy tiers->at [i];
  231. if (anyTier -> classInfo == classIntervalTier) {
  232. autoIntervalTier tier = DTW_IntervalTier_to_IntervalTier_old (me, (IntervalTier) anyTier);
  233. TextGrid_addTier_copy (him.get(), tier.get());
  234. } else if (anyTier -> classInfo == classTextTier) {
  235. autoTextTier tier = DTW_TextTier_to_TextTier_old (me, (TextTier) anyTier);
  236. TextGrid_addTier_copy (him.get(), tier.get());
  237. } else {
  238. Melder_throw (U"Unknown tier.");
  239. }
  240. }
  241. return him;
  242. } catch (MelderError) {
  243. Melder_throw (U"TextGrid not created.");
  244. }
  245. }
  246. /* End of file DTW_and_TextGrid.cpp */