]> git.sesse.net Git - pitch/blobdiff - pitch.cpp
Start a bit above DC, to combat microphones with huge low-frequency content.
[pitch] / pitch.cpp
index 1c272f1080b734bb7ae891611660edf6c915d2c0..36be752bbd66e87163e71921348a95644ebf8b6b 100644 (file)
--- a/pitch.cpp
+++ b/pitch.cpp
@@ -46,7 +46,7 @@ int main()
        in = reinterpret_cast<double *> (fftw_malloc(sizeof(double) * FFT_LENGTH / PAD_FACTOR));
        in_windowed = reinterpret_cast<double *> (fftw_malloc(sizeof(double) * FFT_LENGTH));
        out = reinterpret_cast<std::complex<double> *> (fftw_malloc(sizeof(std::complex<double>) * (FFT_LENGTH / 2 + 1)));
-       bins = reinterpret_cast<double *> (fftw_malloc(sizeof(double) * FFT_LENGTH / 2 + 1));
+       bins = reinterpret_cast<double *> (fftw_malloc(sizeof(double) * (FFT_LENGTH / 2 + 1)));
 
        memset(in, 0, sizeof(double) * FFT_LENGTH / PAD_FACTOR);
 
@@ -60,7 +60,8 @@ int main()
                fftw_execute(p);
                find_peak_magnitudes(out, bins, FFT_LENGTH);
                std::pair<double, double> peak = find_peak(bins, FFT_LENGTH);
-               peak = adjust_for_overtones(peak, bins, FFT_LENGTH);
+               if (peak.first > 0.0)
+                       peak = adjust_for_overtones(peak, bins, FFT_LENGTH);
 
                if (peak.first < 50.0 || peak.second - log10(FFT_LENGTH) < 0.0) {
 #if TUNING == WELL_TEMPERED_GUITAR
@@ -189,10 +190,10 @@ void find_peak_magnitudes(std::complex<double> *in, double *out, unsigned num_sa
 
 std::pair<double, double> find_peak(double *in, unsigned num_samples)
 {
-       double best_peak = in[0];
-       unsigned best_bin = 0;
+       double best_peak = in[5];
+       unsigned best_bin = 5;
 
-       for (unsigned i = 1; i < num_samples / 2 + 1; ++i) {
+       for (unsigned i = 6; i < num_samples / 2 + 1; ++i) {
                if (in[i] > best_peak) {
                        best_peak = in[i];
                        best_bin = i;
@@ -224,9 +225,9 @@ std::pair<double, double> find_peak(double *in, unsigned num_samples)
                        best_bin /= i;
 
                        // consider sliding one bin up or down
-                       if (best_bin > 0 && in[best_bin - 1] > in[best_bin] && in[best_bin - 1] > in[best_bin - 2]) {
+                       if (best_bin > 1 && in[best_bin - 1] > in[best_bin] && in[best_bin - 1] > in[best_bin - 2]) {
                                --best_bin;
-                       } else if (best_bin < num_samples / 2 && in[best_bin + 1] > in[best_bin] && in[best_bin + 1] > in[best_bin + 2]) {
+                       } else if (best_bin < num_samples / 2 - 1 && in[best_bin + 1] > in[best_bin] && in[best_bin + 1] > in[best_bin + 2]) {
                                ++best_bin;
                        }
                           
@@ -234,6 +235,9 @@ std::pair<double, double> find_peak(double *in, unsigned num_samples)
                }
        }
 
+       if (best_bin == 0 || best_bin == num_samples / 2) {
+               return std::make_pair(-1.0, 0.0);
+       }
        std::pair<double, double> peak = 
                interpolate_peak(in[best_bin - 1],
                                 in[best_bin],
@@ -255,6 +259,8 @@ std::pair<double, double> adjust_for_overtones(std::pair<double, double> base, d
                unsigned middle = unsigned(floor(freq_to_bin(base.first, num_samples) * i + 0.5));
                unsigned lower = middle - (i+1)/2, upper = middle + (i+1)/2;
 
+               if (lower < 1)
+                       lower = 1;
                if (upper >= num_samples)
                        upper = num_samples - 2;