Sound_and_LPC_robust.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* Sound_and_LPC_robust.cpp
  2. *
  3. * Copyright (C) 1994-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 20030814 First version
  20. djmw 20061218 To Melder_information<x> format
  21. djmw 20070103 Sound interface changes
  22. djmw 20080122 float -> double
  23. djmw 20101008 New LPC_Frame_filterInverse interface.
  24. djmw 20110302 Corrected a number of pointer initialisations
  25. djmw 20111027 +Sound_to_Formant_robust
  26. */
  27. #include "LPC_and_Formant.h"
  28. #include "Sound_and_LPC.h"
  29. #include "Sound_and_LPC_robust.h"
  30. #include "Sound_extensions.h"
  31. #include "SVD.h"
  32. #include "Vector.h"
  33. #include "NUM2.h"
  34. struct huber_struct {
  35. autoSound e;
  36. double k_stdev, tol, tol_svd;
  37. integer iter, itermax;
  38. int wantlocation, wantscale;
  39. double location, scale;
  40. integer n, p;
  41. autoVEC w, work, a, c;
  42. autoMAT covar;
  43. autoSVD svd;
  44. };
  45. static void huber_struct_init (struct huber_struct *hs, double windowDuration, integer p, double samplingFrequency, double location, int wantlocation) {
  46. hs -> e = Sound_createSimple (1, windowDuration, samplingFrequency);
  47. hs -> k_stdev = hs -> tol = hs -> tol_svd = hs -> scale = 0.0;
  48. hs -> iter = 1;
  49. hs -> itermax = 1;
  50. hs -> wantlocation = wantlocation;
  51. if (! wantlocation) {
  52. hs -> location = location;
  53. }
  54. hs -> wantscale = 1; integer n = hs -> e -> nx;
  55. hs -> n = n;
  56. hs -> p = p;
  57. hs -> w = VECzero (n);
  58. hs -> work = VECraw (n);
  59. hs -> a = VECraw (p);
  60. hs -> c = VECzero (p);
  61. hs -> covar = MATzero (p, p);
  62. hs -> svd = SVD_create (p, p);
  63. }
  64. static void huber_struct_getWeights (struct huber_struct *hs, constVEC e) {
  65. Melder_assert (e.size == hs -> n);
  66. double kstdev = hs -> k_stdev * hs -> scale;
  67. double *w = hs -> w.at;
  68. for (integer i = 1 ; i <= hs -> n; i ++) {
  69. double ei = e [i] - hs -> location;
  70. w [i] = ei > -kstdev && ei < kstdev ? 1.0 : kstdev / fabs (ei);
  71. }
  72. }
  73. static void huber_struct_getWeightedCovars (struct huber_struct *hs, VEC s) {
  74. Melder_assert (s.size == hs -> n);
  75. integer p = hs -> p, n = hs -> n;
  76. double *w = hs -> w.at, **covar = hs -> covar.at, *c = hs -> c.at;
  77. for (integer i = 1; i <= p; i ++) {
  78. for (integer j = i; j <= p; j ++) {
  79. double tmp = 0.0;
  80. for (integer k = p + 1; k <= s.size; k ++) {
  81. tmp += s [k - j] * s [k - i] * w [k];
  82. }
  83. covar [i] [j] = covar [j] [i] = tmp;
  84. }
  85. double tmp = 0.0;
  86. for (integer k = p + 1; k <= n; k ++) {
  87. tmp += s [k - i] * s [k] * w [k];
  88. }
  89. c [i] = -tmp;
  90. }
  91. }
  92. static void huber_struct_solvelpc (struct huber_struct *hs) {
  93. SVD me = hs -> svd.get();
  94. matrixcopy_preallocated(my u.get(), hs -> covar.get());
  95. SVD_setTolerance (me, hs -> tol_svd);
  96. SVD_compute (me);
  97. autoVEC x = SVD_solve (me, hs -> c.get());
  98. VECcopy_preallocated (hs -> a.get(), x.get());
  99. }
  100. void LPC_Frames_Sound_huber (LPC_Frame me, Sound thee, LPC_Frame him, struct huber_struct *hs) {
  101. integer p = my nCoefficients > his nCoefficients ? his nCoefficients : my nCoefficients;
  102. integer n = hs -> e -> nx > thy nx ? thy nx : hs -> e -> nx;
  103. hs -> iter = 0;
  104. hs -> scale = 1e308;
  105. hs -> p = p;
  106. double s0;
  107. do {
  108. Sound hse = hs -> e.get();
  109. for (integer i = 1; i <= thy nx; i ++) {
  110. hse -> z [1] [i] = thy z [1] [i];
  111. }
  112. LPC_Frame_Sound_filterInverse (him, hse, 1);
  113. s0 = hs -> scale;
  114. VEC work = hs -> work.get();
  115. NUMstatistics_huber (hs -> e -> z.row(1), & (hs -> location), hs -> wantlocation, & (hs -> scale), hs -> wantscale, hs -> k_stdev, hs -> tol, & work);
  116. huber_struct_getWeights (hs, hs -> e -> z.row(1));
  117. huber_struct_getWeightedCovars (hs, thy z.row(1));
  118. // Solve C a = [-] c */
  119. try {
  120. huber_struct_solvelpc (hs);
  121. } catch (MelderError) {
  122. // Copy the starting lpc coeffs */
  123. for (integer i = 1; i <= p; i ++) {
  124. his a [i] = my a [i];
  125. }
  126. throw MelderError();
  127. }
  128. for (integer i = 1; i <= p; i ++) {
  129. his a [i] = hs -> a [i];
  130. }
  131. (hs -> iter) ++;
  132. } while ( (hs -> iter < hs -> itermax) && (fabs (s0 - hs -> scale) > hs -> tol * s0));
  133. }
  134. #if 0
  135. autoSound e;
  136. double k, tol, tol_svd;
  137. integer iter, itermax;
  138. bool wantlocation, wantscale;
  139. double location, scale;
  140. integer n, p;
  141. double *w, *work;
  142. double *a;
  143. double **covar, *c;
  144. autoSVD svd;
  145. #endif
  146. autoLPC LPC_Sound_to_LPC_robust (LPC thee, Sound me, double analysisWidth, double preEmphasisFrequency, double k_stdev,
  147. int itermax, double tol, bool wantlocation) {
  148. struct huber_struct struct_huber;
  149. try {
  150. double t1, samplingFrequency = 1.0 / my dx, tol_svd = 0.000001;
  151. double location = 0, windowDuration = 2 * analysisWidth; /* Gaussian window */
  152. integer numberOfFrames, frameErrorCount = 0, iter = 0;
  153. integer p = thy maxnCoefficients;
  154. Melder_require (my xmin == thy xmin && my xmax == thy xmax, U"Time domains should be equal.");
  155. Melder_require (my dx == thy samplingPeriod, U"Sampling intervals should be equal.");
  156. Melder_require (Melder_roundDown (windowDuration / my dx) > p, U"Analysis window too short.");
  157. Sampled_shortTermAnalysis (me, windowDuration, thy dx, & numberOfFrames, & t1);
  158. Melder_require (numberOfFrames == thy nx && t1 == thy x1, U"Incorrect retrieved analysis width.");
  159. autoSound sound = Data_copy (me);
  160. autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency);
  161. autoSound window = Sound_createGaussian (windowDuration, samplingFrequency);
  162. autoLPC him = Data_copy (thee);
  163. huber_struct_init (&struct_huber, windowDuration, p, samplingFrequency, location, wantlocation);
  164. struct_huber.k_stdev = k_stdev;
  165. struct_huber.tol = tol;
  166. struct_huber.tol_svd = tol_svd;
  167. struct_huber.itermax = itermax;
  168. autoMelderProgress progess (U"LPC analysis");
  169. Sound_preEmphasis (sound.get(), preEmphasisFrequency);
  170. for (integer i = 1; i <= numberOfFrames; i ++) {
  171. LPC_Frame lpc = (LPC_Frame) & thy d_frames [i];
  172. LPC_Frame lpcto = (LPC_Frame) & his d_frames [i];
  173. double t = Sampled_indexToX (thee, i);
  174. Sound_into_Sound (sound.get(), sframe.get(), t - windowDuration / 2);
  175. Vector_subtractMean (sframe.get());
  176. Sounds_multiply (sframe.get(), window.get());
  177. try {
  178. LPC_Frames_Sound_huber (lpc, sframe.get(), lpcto, & struct_huber);
  179. } catch (MelderError) {
  180. frameErrorCount ++;
  181. }
  182. iter += struct_huber.iter;
  183. if (i % 10 == 1)
  184. Melder_progress ((double) i / numberOfFrames,
  185. U"LPC analysis of frame ", i, U" out of ", numberOfFrames, U".");
  186. }
  187. if (frameErrorCount) Melder_warning (U"Results of ", frameErrorCount,
  188. U" frame(s) out of ", numberOfFrames, U" could not be optimised.");
  189. //Melder_casual (U"Number of iterations: ", iter, U"\n Average per frame: ", (double) iter / numberOfFrames);
  190. return him;
  191. } catch (MelderError) {
  192. Melder_throw (me, U": no robust LPC created.");
  193. }
  194. }
  195. autoFormant Sound_to_Formant_robust (Sound me, double dt_in, double numberOfFormants, double maximumFrequency,
  196. double halfdt_window, double preEmphasisFrequency, double safetyMargin, double k, int itermax, double tol, bool wantlocation)
  197. {
  198. double dt = dt_in > 0.0 ? dt_in : halfdt_window / 4.0;
  199. double nyquist = 0.5 / my dx;
  200. integer predictionOrder = Melder_ifloor (2 * numberOfFormants);
  201. try {
  202. autoSound sound;
  203. if (maximumFrequency <= 0.0 || fabs (maximumFrequency / nyquist - 1.0) < 1.0e-12) {
  204. sound = Data_copy (me); // will be modified
  205. } else {
  206. sound = Sound_resample (me, maximumFrequency * 2.0, 50);
  207. }
  208. autoLPC lpc = Sound_to_LPC_auto (sound.get(), predictionOrder, halfdt_window, dt, preEmphasisFrequency);
  209. autoLPC lpcr = LPC_Sound_to_LPC_robust (lpc.get(), sound.get(), halfdt_window, preEmphasisFrequency, k, itermax, tol, wantlocation);
  210. autoFormant thee = LPC_to_Formant (lpcr.get(), safetyMargin);
  211. return thee;
  212. } catch (MelderError) {
  213. Melder_throw (me, U": no robust Formant created.");
  214. }
  215. }
  216. /* End of file Sound_and_LPC_robust.cpp */