LPC_and_Tube.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* LPC_and_Tube.cpp
  2. *
  3. * Copyright (C) 1993-2018 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 20020612 GPL header
  20. djmw 20041020 struct Tube_Frame -> struct structTube_Frame; struct LPC_Frame -> struct structLPC_Frame;
  21. struct Formant_Frame->struct structFormant_Frame
  22. djmw 20051005 Always make a VocalTract with length 0.01 m when isundef(wakita_length).
  23. */
  24. #include "LPC_and_Tube.h"
  25. #include "LPC_and_Formant.h"
  26. #include "LPC_to_Spectrum.h"
  27. #include "SpectrumTier.h"
  28. #include "VocalTract_to_Spectrum.h"
  29. #include "NUM2.h"
  30. // IEEE: Programs fo digital signal processing section 4.3 LPTRN
  31. void LPC_Frame_into_Tube_Frame_rc (LPC_Frame me, Tube_Frame thee) {
  32. integer p = my nCoefficients;
  33. Melder_assert (p <= thy nSegments); //TODO
  34. autoVEC b = VECraw (p);
  35. autoVEC a = VECcopy (my a.get());
  36. double *rc = thy c;
  37. for (integer m = p; m > 0; m --) {
  38. rc [m] = a [m];
  39. Melder_require (rc [m] <= 1.0, U"Relection coefficient [", m, U"] should be smaller than 1.");
  40. for (integer i = 1; i < m; i ++)
  41. b [i] = a [i];
  42. for (integer i = 1; i < m; i ++)
  43. a [i] = (b [i] - rc [m] * b [m - i]) / (1.0 - rc [m] * rc [m]);
  44. }
  45. }
  46. void LPC_Frame_into_Tube_Frame_area (LPC_Frame me, Tube_Frame thee) {
  47. struct structTube_Frame rc_struct = { 0 };
  48. Tube_Frame rc = & rc_struct;
  49. Tube_Frame_init (rc, my nCoefficients, thy length);
  50. LPC_Frame_into_Tube_Frame_rc (me, rc);
  51. Tube_Frames_rc_into_area (rc, thee);
  52. rc -> destroy ();
  53. }
  54. double VocalTract_LPC_Frame_getMatchingLength (VocalTract me, LPC_Frame thee, double glottalDamping, bool radiationDamping, bool internalDamping) {
  55. try {
  56. // match the average distance between the first two formants in the VocaTract and the LPC spectrum
  57. integer numberOfFrequencies = 1000;
  58. double maximumFrequency = 5000.0;
  59. autoSpectrum vts = VocalTract_to_Spectrum (me, numberOfFrequencies, maximumFrequency, glottalDamping, radiationDamping, internalDamping);
  60. double samplingFrequency = 1000.0 * my nx;
  61. autoSpectrum lps = Spectrum_create (0.5 * samplingFrequency, numberOfFrequencies);
  62. LPC_Frame_into_Spectrum (thee, lps.get(), 0, 50);
  63. autoSpectrumTier vtst = Spectrum_to_SpectrumTier_peaks (vts.get());
  64. autoSpectrumTier lpst = Spectrum_to_SpectrumTier_peaks (lps.get());
  65. double vt_f1 = vtst -> points.at [1] -> number, vt_f2 = vtst -> points.at [2] -> number;
  66. double lp_f1 = lpst -> points.at [1] -> number, lp_f2 = lpst -> points.at [2] -> number;
  67. double df1 = lp_f1 - vt_f1, df2 = lp_f2 - vt_f2, df = 0.5 * (df1 + df2);
  68. double dl = - df / lp_f2;
  69. return my dx * my nx * (1 + dl);
  70. } catch (MelderError) {
  71. Melder_throw (U"Length could not be determined from VocalTract and LPC_Frame.");
  72. }
  73. }
  74. double LPC_Frame_getVTL_wakita (LPC_Frame me, double samplingPeriod, double refLength) {
  75. struct structLPC_Frame lpc_struct;
  76. LPC_Frame lpc = & lpc_struct;
  77. struct structFormant_Frame f_struct;
  78. Formant_Frame f = & f_struct;
  79. struct structTube_Frame rc_struct, af_struct;
  80. Tube_Frame rc = & rc_struct, af = & af_struct;
  81. try {
  82. integer m = my nCoefficients;
  83. double length, dlength = 0.001, wakita_length = undefined;
  84. double varMin = 1e308;
  85. memset (& lpc_struct, 0, sizeof (lpc_struct));
  86. memset (& f_struct, 0, sizeof (f_struct));
  87. memset (& rc_struct, 0, sizeof (rc_struct));
  88. memset (& af_struct, 0, sizeof (af_struct));
  89. LPC_Frame_init (lpc, m);
  90. Tube_Frame_init (rc, m, refLength);
  91. Tube_Frame_init (af, m, refLength);
  92. // Step 2
  93. LPC_Frame_into_Formant_Frame (me, f, samplingPeriod, 0);
  94. // LPC_Frame_into_Formant_Frame performs the Formant_Frame_init !!
  95. Melder_require (f -> nFormants > 0, U"Not enough formants.");
  96. double *area = af -> c;
  97. double lmin = length = 0.10;
  98. double plength = refLength;
  99. while (length <= 0.25) {
  100. // Step 3
  101. double fscale = plength / length;
  102. for (integer i = 1; i <= f -> nFormants; i ++) {
  103. f -> formant [i].frequency *= fscale;
  104. f -> formant [i].bandwidth *= fscale;
  105. }
  106. /*
  107. 20000125: Bovenstaande schaling van f1/b1 kan ook gedaan worden door
  108. MGfb_to_a (f, b, nf, samplingFrequency*length/refLength, a1)
  109. De berekening is extreem gevoelig voor de samplefrequentie: een zelfde
  110. stel f,b waardes geven andere lengtes afhankelijk van Fs. Ook het
  111. weglaten van een hogere formant heeft consekwenties.
  112. De refLength zou eigenlijk vast moeten liggen op
  113. refLength=c*aantalFormanten/Fs waarbij c=340 m/s (geluidssnelheid).
  114. Bij Fs=10000 zou aantalFormanten=5 zijn en refLength -> 0.17 m
  115. */
  116. // step 4
  117. Formant_Frame_into_LPC_Frame (f, lpc, samplingPeriod);
  118. // step 5
  119. rc -> length = length;
  120. LPC_Frame_into_Tube_Frame_rc (lpc, rc);
  121. // step 6.1
  122. Tube_Frames_rc_into_area (rc, af);
  123. // step 6.2 Log(areas)
  124. double logSum = 0.0;
  125. for (integer i = 1; i <= af -> nSegments; i ++) {
  126. area [i] = log (area [i]);
  127. logSum += area [i];
  128. }
  129. // step 6.3 and 7
  130. double var = 0.0;
  131. for (integer i = 1; i <= af -> nSegments; i ++) {
  132. double delta = area [i] - logSum / af -> nSegments;
  133. var += delta * delta;
  134. }
  135. if (var < varMin) {
  136. lmin = length; varMin = var;
  137. }
  138. plength = length;
  139. length += dlength;
  140. }
  141. wakita_length = lmin;
  142. f -> destroy ();
  143. lpc -> destroy ();
  144. rc -> destroy ();
  145. af -> destroy ();
  146. return wakita_length;
  147. } catch (MelderError) {
  148. f -> destroy ();
  149. lpc -> destroy ();
  150. rc -> destroy ();
  151. af -> destroy ();
  152. return undefined;
  153. }
  154. }
  155. int Tube_Frame_into_LPC_Frame_area (Tube_Frame me, LPC_Frame thee) {
  156. (void) me;
  157. (void) thee;
  158. return 0;
  159. }
  160. int Tube_Frame_into_LPC_Frame_rc (Tube_Frame me, LPC_Frame thee) {
  161. (void) me;
  162. (void) thee;
  163. return 0;
  164. }
  165. void VocalTract_setLength (VocalTract me, double newLength) {
  166. my xmax = newLength;
  167. my dx = newLength / my nx;
  168. my x1 = 0.5 * my dx;
  169. }
  170. autoVocalTract LPC_to_VocalTract (LPC me, double time, double glottalDamping, bool radiationDamping, bool internalDamping) {
  171. try {
  172. integer iframe = Sampled_xToLowIndex (me, time); // ppgb: BUG? Is rounding down the correct thing to do? not nearestIndex?
  173. if (iframe < 1) iframe = 1;
  174. if (iframe > my nx) iframe = my nx;
  175. LPC_Frame lpc = & my d_frames [iframe];
  176. autoVocalTract thee = LPC_Frame_to_VocalTract (lpc, 0.17);
  177. double length = VocalTract_LPC_Frame_getMatchingLength (thee.get(), lpc, glottalDamping, radiationDamping, internalDamping);
  178. VocalTract_setLength (thee.get(), length);
  179. return thee;
  180. } catch (MelderError) {
  181. Melder_throw (me, U": no VocalTract created.");
  182. }
  183. }
  184. autoVocalTract LPC_Frame_to_VocalTract (LPC_Frame me, double length) {
  185. try {
  186. integer m = my nCoefficients;
  187. autoVEC area = VECzero (m + 1);
  188. NUMlpc_lpc_to_area (my a.at, m, area.at);
  189. autoVocalTract thee = VocalTract_create (m, length / m);
  190. // area [lips..glottis] (m^2) to VocalTract [glottis..lips] (m^2)
  191. for (integer i = 1; i <= m; i ++) {
  192. thy z [1] [i] = area [m + 1 - i];
  193. }
  194. return thee;
  195. } catch (MelderError) {
  196. Melder_throw (U"No VocalTract created from LPC_Frame.");
  197. }
  198. }
  199. autoVocalTract LPC_to_VocalTract (LPC me, double time, double length) {
  200. try {
  201. integer iframe = Sampled_xToNearestIndex (me, time);
  202. if (iframe < 1) iframe = 1;
  203. if (iframe > my nx) iframe = my nx;
  204. LPC_Frame lpc = & my d_frames [iframe];
  205. autoVocalTract thee = LPC_Frame_to_VocalTract (lpc, length);
  206. return thee;
  207. } catch (MelderError) {
  208. Melder_throw (me, U": no VocalTract created.");
  209. }
  210. }
  211. /* End of file LPC_and_Tube.cpp */