CCs_to_DTW.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* CCs_to_DTW.c
  2. *
  3. * Dynamic Time Warp of two CCs.
  4. *
  5. * Copyright (C) 1993-2017 David Weenink
  6. *
  7. * This code is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * This code is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /*
  21. djmw 2001
  22. djmw 20020315 GPL header
  23. djmw 20080122 float -> double
  24. */
  25. #include "CCs_to_DTW.h"
  26. static void regression (CC me, integer frame, double r[], integer nr) {
  27. // sum(i^2;i=-n..n) = 2n^3/3 + n^2 +n/3 = n (n (2n/3 + 1) + 1/3);
  28. integer nrd2 = nr / 2;
  29. double sumsq = nrd2 * (nrd2 * (nr / 3.0 + 1.0) + 1.0 / 3.0);
  30. if (frame <= nrd2 || frame >= my nx - nrd2) {
  31. return;
  32. }
  33. for (integer i = 0; i <= my maximumNumberOfCoefficients; i ++) {
  34. r [i] = 0.0;
  35. }
  36. integer nmin = CC_getMinimumNumberOfCoefficients (me, frame - nrd2, frame + nrd2);
  37. for (integer i = 0; i <= nmin; i ++) {
  38. double ri = 0;
  39. for (integer j = -nrd2; j <= nrd2; j ++) {
  40. CC_Frame cf = & my frame[frame + j];
  41. double c = i == 0 ? cf -> c0 : cf -> c [i];
  42. ri += c * j;
  43. }
  44. r [i] = ri / sumsq / my dx;
  45. }
  46. }
  47. autoDTW CCs_to_DTW (CC me, CC thee, double wc, double wle, double wr, double wer, double dtr) {
  48. try {
  49. integer nr = Melder_ifloor (dtr / my dx);
  50. Melder_require (my maximumNumberOfCoefficients == thy maximumNumberOfCoefficients,
  51. U"CC orders should be equal.");
  52. Melder_require (! (wr != 0.0 && nr < 2),
  53. U"Time window for regression is too small.");
  54. if (nr % 2 == 0) {
  55. nr ++;
  56. }
  57. if (wr != 0.0) {
  58. Melder_casual (nr, U" frames used for regression coefficients.");
  59. }
  60. autoDTW him = DTW_create (my xmin, my xmax, my nx, my dx, my x1, thy xmin, thy xmax, thy nx, thy dx, thy x1);
  61. autoNUMvector <double> ri ((integer) 0, my maximumNumberOfCoefficients);
  62. autoNUMvector <double> rj ((integer) 0, my maximumNumberOfCoefficients);
  63. /* Calculate distance matrix. */
  64. autoMelderProgress progess (U"CCs_to_DTW");
  65. for (integer i = 1; i <= my nx; i ++) {
  66. CC_Frame fi = & my frame [i];
  67. regression (me, i, ri.peek(), nr);
  68. for (integer j = 1; j <= thy nx; j ++) {
  69. CC_Frame fj = & thy frame [j];
  70. longdouble dist = 0.0, distr = 0.0;
  71. /* Cepstral distance. */
  72. if (wc != 0.0) {
  73. for (integer k = 1; k <= fj -> numberOfCoefficients; k ++) {
  74. double d = fi -> c [k] - fj -> c [k];
  75. dist += d * d;
  76. }
  77. dist *= wc;
  78. }
  79. /* Log energy distance. */
  80. if (wle != 0.0) {
  81. double d = fi -> c0 - fj -> c0;
  82. dist += wle * d * d;
  83. }
  84. /* Regression distance. */
  85. if (wr != 0.0) {
  86. regression (thee, j, rj.peek(), nr);
  87. for (integer k = 1; k <= fj -> numberOfCoefficients; k ++) {
  88. double d = ri [k] - rj [k];
  89. distr += d * d;
  90. }
  91. dist += wr * distr;
  92. }
  93. /* Regression on c[0]: log(energy) */
  94. if (wer != 0.0) {
  95. if (wr == 0.0) {
  96. regression (thee, j, rj.peek(), nr);
  97. }
  98. double d = ri [0] - rj [0];
  99. dist += wer * d * d;
  100. }
  101. dist /= wc + wle + wr + wer;
  102. his z [i] [j] = sqrt ((double) dist); // prototype along y-direction
  103. }
  104. if (i % 10 == 1) {
  105. Melder_progress (0.999 * i / my nx, U"Calculate distances: frame ", i, U" from ", my nx, U".");
  106. }
  107. }
  108. return him;
  109. } catch (MelderError) {
  110. Melder_throw (U"DTW not created from CCs.");
  111. }
  112. }
  113. /* End of file CCs_to_DTW.cpp */