PitchTier_to_PointProcess.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /* PitchTier_to_PointProcess.cpp
  2. *
  3. * Copyright (C) 1992-2011,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 "PitchTier_to_PointProcess.h"
  19. #include "Pitch_to_PitchTier.h"
  20. autoPointProcess PitchTier_to_PointProcess (PitchTier me) {
  21. try {
  22. autoPointProcess thee = PointProcess_create (my xmin, my xmax, 1000);
  23. double area = 0.5; // imagine an event half a period before the beginning
  24. integer size = my points.size;
  25. if (size == 0) return thee;
  26. for (integer interval = 0; interval <= size; interval ++) {
  27. double t1 = ( interval == 0 ? my xmin : my points.at [interval] -> number );
  28. Melder_assert (isdefined (t1));
  29. double t2 = ( interval == size ? my xmax : my points.at [interval + 1] -> number );
  30. Melder_assert (isdefined (t2));
  31. double f1 = my points.at [interval == 0 ? 1 : interval] -> value;
  32. Melder_assert (isdefined (f1));
  33. double f2 = my points.at [interval == size ? size : interval + 1] -> value;
  34. Melder_assert (isdefined (f2));
  35. area += (t2 - t1) * 0.5 * (f1 + f2);
  36. while (area >= 1.0) {
  37. double slope = (f2 - f1) / (t2 - t1), discriminant;
  38. area -= 1.0;
  39. discriminant = f2 * f2 - 2.0 * area * slope;
  40. if (discriminant < 0.0) discriminant = 0.0; // catch rounding errors
  41. PointProcess_addPoint (thee.get(), t2 - 2.0 * area / (f2 + sqrt (discriminant)));
  42. }
  43. }
  44. return thee;
  45. } catch (MelderError) {
  46. Melder_throw (me, U": not converted to PointProcess.");
  47. }
  48. }
  49. autoPointProcess PitchTier_Pitch_to_PointProcess (PitchTier me, Pitch vuv) {
  50. try {
  51. autoPointProcess fullPoint = PitchTier_to_PointProcess (me);
  52. autoPointProcess thee = PointProcess_create (my xmin, my xmax, fullPoint -> maxnt);
  53. /*
  54. * Copy only voiced parts to result.
  55. */
  56. for (integer i = 1; i <= fullPoint -> nt; i ++) {
  57. double t = fullPoint -> t [i];
  58. if (Pitch_isVoiced_t (vuv, t)) {
  59. PointProcess_addPoint (thee.get(), t);
  60. }
  61. }
  62. return thee;
  63. } catch (MelderError) {
  64. Melder_throw (me, U" & ", vuv, U": not converted to PointProcess.");
  65. }
  66. }
  67. static int PointProcess_isVoiced_t (PointProcess me, double t, double maxT) {
  68. integer imid = PointProcess_getNearestIndex (me, t);
  69. if (imid == 0) return 0;
  70. double tmid = my t [imid];
  71. int leftVoiced = imid > 1 && tmid - my t [imid - 1] <= maxT;
  72. int rightVoiced = imid < my nt && my t [imid + 1] - tmid <= maxT;
  73. if ((leftVoiced && t <= tmid) || (rightVoiced && t >= tmid)) return 1;
  74. if (leftVoiced && t < 1.5 * tmid - 0.5 * my t [imid - 1]) return 1;
  75. if (rightVoiced && t > 1.5 * tmid - 0.5 * my t [imid + 1]) return 1;
  76. return 0;
  77. }
  78. autoPointProcess PitchTier_Point_to_PointProcess (PitchTier me, PointProcess vuv, double maxT) {
  79. try {
  80. autoPointProcess fullPoint = PitchTier_to_PointProcess (me);
  81. autoPointProcess thee = PointProcess_create (my xmin, my xmax, fullPoint -> maxnt);
  82. /*
  83. * Copy only voiced parts to result.
  84. */
  85. for (integer i = 1; i <= fullPoint -> nt; i ++) {
  86. double t = fullPoint -> t [i];
  87. if (PointProcess_isVoiced_t (vuv, t, maxT)) {
  88. PointProcess_addPoint (thee.get(), t);
  89. }
  90. }
  91. return thee;
  92. } catch (MelderError) {
  93. Melder_throw (me, U" & ", vuv, U": not converted to PointProcess.");
  94. }
  95. }
  96. autoPitchTier PointProcess_to_PitchTier (PointProcess me, double maximumInterval) {
  97. try {
  98. autoPitchTier thee = PitchTier_create (my xmin, my xmax);
  99. for (integer i = 1; i < my nt; i ++) {
  100. double interval = my t [i + 1] - my t [i];
  101. if (interval <= maximumInterval) {
  102. RealTier_addPoint (thee.get(), my t [i] + 0.5 * interval, 1.0 / interval);
  103. }
  104. }
  105. return thee;
  106. } catch (MelderError) {
  107. Melder_throw (me, U": not converted to PitchTier.");
  108. }
  109. }
  110. autoPitchTier Pitch_PointProcess_to_PitchTier (Pitch me, PointProcess pp) {
  111. try {
  112. autoPitchTier temp = Pitch_to_PitchTier (me);
  113. autoPitchTier thee = PitchTier_PointProcess_to_PitchTier (temp.get(), pp);
  114. return thee;
  115. } catch (MelderError) {
  116. Melder_throw (me, U" & ", pp, U": not converted to PitchTier.");
  117. }
  118. }
  119. autoPitchTier PitchTier_PointProcess_to_PitchTier (PitchTier me, PointProcess pp) {
  120. try {
  121. if (my points.size == 0) Melder_throw (U"No pitch points.");
  122. autoPitchTier thee = PitchTier_create (pp -> xmin, pp -> xmax);
  123. for (integer i = 1; i <= pp -> nt; i ++) {
  124. double time = pp -> t [i];
  125. double value = RealTier_getValueAtTime (me, time);
  126. RealTier_addPoint (thee.get(), time, value);
  127. }
  128. return thee;
  129. } catch (MelderError) {
  130. Melder_throw (me, U" & ", pp, U": not converted to PitchTier.");
  131. }
  132. }
  133. autoTableOfReal PitchTier_downto_TableOfReal (PitchTier me, int useSemitones) {
  134. try {
  135. autoTableOfReal thee = RealTier_downto_TableOfReal (me, U"Time", U"F0");
  136. if (useSemitones)
  137. for (integer i = 1; i <= thy numberOfRows; i ++)
  138. thy data [i] [2] = NUMhertzToSemitones (thy data [i] [2]);
  139. return thee;
  140. } catch (MelderError) {
  141. Melder_throw (me, U": not converted to TableOfReal.");
  142. }
  143. }
  144. /* End of file PitchTier_to_PointProcess.cpp */