kopia lustrzana https://github.com/jameshball/osci-render
58 wiersze
1.6 KiB
C++
58 wiersze
1.6 KiB
C++
#include "PitchDetector.h"
|
|
#include "../PluginProcessor.h"
|
|
|
|
PitchDetector::PitchDetector(OscirenderAudioProcessor& audioProcessor) : AudioBackgroundThread("PitchDetector", audioProcessor.threadManager), audioProcessor(audioProcessor) {}
|
|
|
|
void PitchDetector::runTask(const std::vector<OsciPoint>& points) {
|
|
// buffer is for 2 channels, so we need to only use one
|
|
for (int i = 0; i < fftSize; i++) {
|
|
fftData[i] = points[i].x;
|
|
}
|
|
|
|
forwardFFT.performFrequencyOnlyForwardTransform(fftData.data());
|
|
|
|
// get frequency of the peak
|
|
int maxIndex = 0;
|
|
for (int i = 0; i < fftSize / 2; ++i) {
|
|
if (frequencyFromIndex(i) < 20 || frequencyFromIndex(i) > 20000) {
|
|
continue;
|
|
}
|
|
|
|
auto current = fftData[i];
|
|
if (current > fftData[maxIndex]) {
|
|
maxIndex = i;
|
|
}
|
|
}
|
|
|
|
frequency = frequencyFromIndex(maxIndex);
|
|
triggerAsyncUpdate();
|
|
}
|
|
|
|
int PitchDetector::prepareTask(double sampleRate, int samplesPerBlock) {
|
|
this->sampleRate = sampleRate;
|
|
return fftSize;
|
|
}
|
|
|
|
void PitchDetector::handleAsyncUpdate() {
|
|
juce::SpinLock::ScopedLockType scope(lock);
|
|
for (auto& callback : callbacks) {
|
|
callback(frequency);
|
|
}
|
|
}
|
|
|
|
int PitchDetector::addCallback(std::function<void(float)> callback) {
|
|
juce::SpinLock::ScopedLockType scope(lock);
|
|
callbacks.push_back(callback);
|
|
return callbacks.size() - 1;
|
|
}
|
|
|
|
void PitchDetector::removeCallback(int index) {
|
|
juce::SpinLock::ScopedLockType scope(lock);
|
|
callbacks.erase(callbacks.begin() + index);
|
|
}
|
|
|
|
float PitchDetector::frequencyFromIndex(int index) {
|
|
auto binWidth = sampleRate / fftSize;
|
|
return index * binWidth;
|
|
}
|