kopia lustrzana https://github.com/jameshball/osci-render
54 wiersze
1.5 KiB
C++
54 wiersze
1.5 KiB
C++
#include "PitchDetector.h"
|
|
#include "PitchDetector.h"
|
|
|
|
PitchDetector::PitchDetector(OscirenderAudioProcessor& p, std::function<void(float)> frequencyCallback) : juce::Thread("PitchDetector"), audioProcessor(p), frequencyCallback(frequencyCallback) {
|
|
startThread();
|
|
}
|
|
|
|
PitchDetector::~PitchDetector() {
|
|
audioProcessor.audioProducer.unregisterConsumer(consumer);
|
|
stopThread(1000);
|
|
}
|
|
|
|
void PitchDetector::run() {
|
|
audioProcessor.audioProducer.registerConsumer(consumer);
|
|
|
|
while (!threadShouldExit()) {
|
|
auto buffer = consumer->startProcessing();
|
|
|
|
// buffer is for 2 channels, so we need to only use one
|
|
for (int i = 0; i < fftSize; i++) {
|
|
fftData[i] = buffer->at(2 * i);
|
|
}
|
|
|
|
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);
|
|
|
|
consumer->finishedProcessing();
|
|
triggerAsyncUpdate();
|
|
}
|
|
}
|
|
|
|
void PitchDetector::handleAsyncUpdate() {
|
|
frequencyCallback(frequency);
|
|
}
|
|
|
|
float PitchDetector::frequencyFromIndex(int index) {
|
|
auto binWidth = audioProcessor.currentSampleRate / fftSize;
|
|
return index * binWidth;
|
|
}
|