File: Landmark.cpp

package info (click to toggle)
audacity 0.98-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,896 kB
  • ctags: 4,089
  • sloc: cpp: 26,099; ansic: 4,961; sh: 2,465; makefile: 156; perl: 23
file content (105 lines) | stat: -rw-r--r-- 2,634 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**********************************************************************

  Audacity: A Digital Audio Editor

  Landmark.cpp

  Dominic Mazzoni

  Pitch detector based on "landmark" algorithm by Cooper and Ng,
  University of Leeds SCS, Division of AI.

  \cite{cooper94}

**********************************************************************/

#include <stdlib.h>

#ifndef SQ
#define SQ(X) ((X)*(X))
#endif

int GetLandmarkPeriod(int numSamples, double *sample)
{
   const int max_zeros = 100;
   const int numLandmarks = 6;  // should be even
   const int regionSizeThreshold = 10;
   int numZeros;
   int zeros[max_zeros];
   double shape[max_zeros][numLandmarks];

   int x, z, l;

   // Find all (positive) zero-crossings

   numZeros = 0;
   for (x = 1; x < numSamples && numZeros < max_zeros; x++)
      if (sample[x - 1] < 0.0 && sample[x] >= 0.0)
         zeros[numZeros++] = x;

   if (numZeros < 3)
      return 0;

   // Extract the "shape" of each region

   for (z = 0; z < (numZeros - 1); z++) {
      int len = (zeros[z + 1] - zeros[z]);
      for (l = 0; l < (numLandmarks / 2); l++) {
         x = zeros[z] + (l + 1) * len / (numLandmarks + 2);
         shape[z][l] = sample[x];
         x = zeros[z] + (l + 2 +
                         (numLandmarks / 2)) * len / (numLandmarks + 2);
         shape[z][l + (numLandmarks / 2)] = sample[x];
      }
   }

  /***PRINT
  for(z=0; z<(numZeros-1); z++) {
	for(l=0; l<numLandmarks; l++)
	  printf("%5.2lf ",shape[z][l]);
	printf("\n");
  }*/

   // Find largest region
   int largest = 0;
   int largestSize = zeros[1] - zeros[0];

   for (z = 1; z < (numZeros - 1); z++)
      if (zeros[z + 1] - zeros[z] > largestSize) {
         largest = z;
         largestSize = zeros[z + 1] - zeros[z];
      }
   // Compare largest with all other regions

   int best = largest;
   double bestSimilarity = 0.0;

   for (z = 0; z < (numZeros - 1); z++)
      if (z != largest &&
          abs((zeros[z + 1] - zeros[z]) -
              (zeros[largest + 1] - zeros[largest]))
          < regionSizeThreshold) {

         double asq = 0.0, bsq = 0.0, ab = 0.0;
         double score = 0.0;

         for (l = 0; l < numLandmarks; l++) {

            // Should move this line out of loop
            asq += SQ(shape[largest][l]);
            bsq += SQ(shape[z][l]);
            ab += shape[largest][l] * shape[z][l];
         }

         score = ab / (asq + bsq - ab); // \cite{cooper94, Page 5}

         if (score > bestSimilarity) {
            best = z;
            bestSimilarity = score;
         }
      }

   int period = abs(zeros[best] - zeros[largest]);

   return period;
}