Formant_extensions.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Formant_extensions.cpp
  2. *
  3. * Copyright (C) 2012-2017 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. #include "Formant_extensions.h"
  19. #include "NUM2.h"
  20. void Formant_formula (Formant me, double tmin, double tmax, integer formantmin, integer formantmax, Interpreter interpreter, conststring32 expression) {
  21. try {
  22. integer numberOfPossibleFormants = my maxnFormants;
  23. if (tmax <= tmin) {
  24. tmin = my xmin; tmax = my xmax;
  25. }
  26. if (formantmax >= formantmin) {
  27. formantmin = 1; formantmax = numberOfPossibleFormants;
  28. }
  29. formantmin = formantmin < 1 ? 1 : formantmin;
  30. formantmax = formantmax > numberOfPossibleFormants ? numberOfPossibleFormants : formantmax;
  31. autoMatrix fb = Matrix_create (my xmin, my xmax, my nx, my dx, my x1, 1.0, 2 * numberOfPossibleFormants, 2 * numberOfPossibleFormants, 1.0, 1.0);
  32. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  33. Formant_Frame frame = & my d_frames [iframe];
  34. int numberOfFormants = frame -> nFormants < numberOfPossibleFormants ? frame -> nFormants : numberOfPossibleFormants;
  35. for (integer iformant = 1; iformant <= numberOfFormants; iformant++) {
  36. if (iformant <= frame -> nFormants) {
  37. fb -> z [2 * iformant - 1] [iframe] = frame -> formant [iformant].frequency;
  38. fb -> z [2 * iformant ] [iframe] = frame -> formant [iformant].bandwidth;
  39. }
  40. }
  41. }
  42. // Apply formula
  43. double ymin = 2.0 * formantmin - 1.0, ymax = 2.0 * formantmax;
  44. Matrix_formula_part (fb.get(), tmin, tmax, ymin, ymax, expression, interpreter, nullptr);
  45. // Put results back in Formant
  46. integer ixmin, ixmax, iymin, iymax;
  47. (void) Matrix_getWindowSamplesX (fb.get(), tmin, tmax, & ixmin, & ixmax);
  48. (void) Matrix_getWindowSamplesY (fb.get(), ymin, ymax, & iymin, & iymax);
  49. for (integer iframe = ixmin; iframe <= ixmax; iframe ++) {
  50. // if some of the formant frequencies are set to zero => remove the formant
  51. Formant_Frame frame = & my d_frames [iframe];
  52. int numberOfFormants = frame -> nFormants < formantmax ? frame -> nFormants : formantmax;
  53. int iformantto = formantmin > 1 ? formantmin - 1 : 0;
  54. for (integer iformant = formantmin; iformant <= numberOfFormants; iformant++) {
  55. double frequency = fb -> z [2 * iformant - 1] [iframe];
  56. double bandWidth = fb -> z [2 * iformant ] [iframe];
  57. if (frequency > 0 && bandWidth > 0) {
  58. iformantto++;
  59. frame -> formant [iformantto].frequency = frequency;
  60. frame -> formant [iformantto].bandwidth = bandWidth;
  61. } else {
  62. frame -> formant [iformant].frequency = frame -> formant [iformant].bandwidth = 0.0;
  63. }
  64. }
  65. // shift the (higher) formants down if necessary.
  66. for (integer iformant = formantmax + 1; iformant <= frame -> nFormants; iformant ++) {
  67. double frequency = fb -> z [2 * iformant - 1] [iframe];
  68. double bandWidth = fb -> z [2 * iformant ] [iframe];
  69. if (frequency > 0 && bandWidth > 0) {
  70. iformantto ++;
  71. frame -> formant [iformantto].frequency = frequency;
  72. frame -> formant [iformantto].bandwidth = bandWidth;
  73. } else {
  74. frame -> formant [iformant].frequency = frame -> formant [iformant].bandwidth = 0.0;
  75. }
  76. }
  77. frame -> nFormants = iformantto;
  78. }
  79. } catch (MelderError) {
  80. Melder_throw (me, U": not filtered.");
  81. }
  82. }
  83. autoIntensityTier Formant_Spectrogram_to_IntensityTier (Formant me, Spectrogram thee, integer iformant) {
  84. try {
  85. Melder_require (my xmin == thy xmin && my xmax == thy xmax, U"The start and end times of the Formant and the Spectrogram should be equal.");
  86. Melder_require (iformant > 0 && iformant <= my maxnFormants, U"Formant number should be in the range [1, ", my maxnFormants, U"].");
  87. autoIntensityTier him = IntensityTier_create (my xmin, my xmax);
  88. double previousValue = -80000.0; // can never occur
  89. double previousTime = my xmin;
  90. for (integer iframe = 1; iframe <= my nx; iframe ++) {
  91. Formant_Frame frame = & my d_frames [iframe];
  92. integer numberOfFormants = frame -> nFormants;
  93. double time = Sampled_indexToX (me, iframe);
  94. double value = 0;
  95. if (iformant <= numberOfFormants) {
  96. double f = frame -> formant [iformant].frequency;
  97. value = Matrix_getValueAtXY (thee, time, f);
  98. value = isdefined (value) ? value : 0.0;
  99. }
  100. value = 10.0 * log10 ((value + 1e-30) / 4.0e-10); /* dB / Hz */
  101. if (value != previousValue) {
  102. if (iframe > 1 && previousTime < time - 1.5 * my dx) { // mark the end of the same interval
  103. RealTier_addPoint (him.get(), time - my dx, previousValue);
  104. }
  105. RealTier_addPoint (him.get(), time, value);
  106. previousTime = time;
  107. }
  108. previousValue = value;
  109. }
  110. return him;
  111. } catch (MelderError) {
  112. Melder_throw (U"IntensityTier not created from ", me, U" and ", thee, U".");
  113. }
  114. }
  115. /* End of file Formant_extensions.cpp */