FahlGrahn Audio v1.0.0
Loading...
Searching...
No Matches
Tuner.h
1#pragma once
2
3class Tuner
4{
5 public:
6 static float detectPitchAutocorrelation(const float *input, int bufferSize, double sampleRate)
7 {
8 float maxValue = 0.0f;
9 int bestLag = -1;
10
11 // Step 1: Remove DC offset
12 float mean = 0.0f;
13 for (int i = 0; i < bufferSize; ++i)
14 mean += input[i];
15 mean /= bufferSize;
16
17 std::vector<float> centered(static_cast<unsigned long>(bufferSize));
18 for (unsigned long i = 0; i < static_cast<unsigned long>(bufferSize); ++i)
19 centered[i] = input[i] - mean;
20
21 // Step 2: Autocorrelation
22 std::vector<float> correlation(static_cast<unsigned long>(bufferSize) / 2); // Store for interpolation
23 int minLag = static_cast<int>(sampleRate / 500.0f); // Max 500 Hz
24 int maxLag = static_cast<int>(sampleRate / 40.0f); // Min 40 Hz
25 maxLag = std::min(maxLag, bufferSize - 1);
26
27 for (int lag = minLag; lag < maxLag; ++lag)
28 {
29 float sum = 0.0f;
30 for (unsigned long i = 0; i < static_cast<unsigned long>(bufferSize - lag); ++i)
31 sum += centered[i] * centered[i + static_cast<unsigned long>(lag)];
32
33 correlation[static_cast<unsigned long>(lag)] = sum;
34
35 if (sum > maxValue)
36 {
37 maxValue = sum;
38 bestLag = lag;
39 }
40 }
41
42 if (bestLag <= minLag || bestLag >= maxLag - 1)
43 return 0.0f; // Can't interpolate at edges
44
45 // After calculating maxValue and bestLag
46
47 // Step 2.5: Check if the maximum correlation is strong enough
48 float energy = 0.0f;
49 for (unsigned long i = 0; i < static_cast<unsigned long>(bufferSize); ++i)
50 energy += centered[i] * centered[i];
51
52 // Simple threshold: if the maximum correlation is too small compared to energy
53 if (maxValue < 0.8f * energy) // <-- You can tweak 0.1f (10%) to taste
54 return 0.0f;
55
56 // Step 3: Parabolic Interpolation
57 float y1 = correlation[static_cast<unsigned long>(bestLag)];
58 float y2 = correlation[static_cast<unsigned long>(bestLag) + 1];
59 float y0 = correlation[static_cast<unsigned long>(bestLag) - 1];
60
61 // Formula: https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html
62 float shift = 0.5f * (y0 - y2) / (y0 - 2.0f * y1 + y2);
63 float interpolatedLag = static_cast<float>(bestLag) + shift;
64
65 // Step 4: Convert to frequency
66 if (interpolatedLag > 0.0f)
67 return static_cast<float>(sampleRate) / interpolatedLag;
68
69 return 0.0f;
70 }
71};
Definition Tuner.h:4