summaryrefslogtreecommitdiffhomepage
path: root/tuner.cpp
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2019-02-17 14:53:33 +0100
committerRoland Stigge <stigge@antcom.de>2019-02-17 14:53:33 +0100
commit308a53c389cdc2631860f434989cd57efbf91145 (patch)
tree2eadba9413a881045caedd589cc9aec7fda40134 /tuner.cpp
parentfef594c82518a8fe4c96794852c1fc849c0ed3b3 (diff)
Implemented Tuner
Diffstat (limited to 'tuner.cpp')
-rw-r--r--tuner.cpp40
1 files changed, 37 insertions, 3 deletions
diff --git a/tuner.cpp b/tuner.cpp
index d1833a3..3013390 100644
--- a/tuner.cpp
+++ b/tuner.cpp
@@ -2,12 +2,19 @@
#include "autocorrelation.h"
#include "fft.h"
+#include "util.h"
+
+#include <algorithm>
+#include <cmath>
+
+using namespace RIT;
struct RIT::Tuner::Impl {
public:
- Impl(int size, int f_sample): mAC(size), m_f_sample(f_sample) {}
+ Impl(int size, int f_sample): mAC(size), m_f_sample(f_sample), mSize(size) {}
RIT::AutoCorrelation mAC;
int m_f_sample;
+ int mSize;
};
RIT::Tuner::Tuner(int size, int f_sample): mImpl(std::make_unique<RIT::Tuner::Impl>(size, f_sample))
@@ -16,9 +23,36 @@ RIT::Tuner::Tuner(int size, int f_sample): mImpl(std::make_unique<RIT::Tuner::Im
RIT::Tuner::~Tuner(){}
+namespace {
+ const std::vector<std::string> noteNames{ "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#" };
+ const double base = std::pow(2.0, 1./12);
+
+ RIT::Pitch getPitch(double f)
+ {
+ double noteIndexD = std::log(f / 110.0) / std::log(base) + 0.5;
+
+ double noteIndexI{};
+ double deviation = std::modf(noteIndexD, &noteIndexI) - 0.5;
+ int noteIndex = int(noteIndexI);
+
+ noteIndex %= 12;
+
+ return RIT::Pitch {f, deviation, noteNames[noteIndex]};
+ }
+}
+
RIT::Pitch RIT::Tuner::operator() (const std::vector<std::complex<double>> &v)
{
- std::vector<std::complex<double>> autoCorrelation = mImpl->mAC(v);
+ std::vector<double> autoCorrelation = magnitudes(mImpl->mAC(v));
+
+ auto maxElement = std::max_element(std::begin(autoCorrelation) + 1, std::begin(autoCorrelation) + mImpl->mSize / 2);
+
+ int index = maxElement - std::begin(autoCorrelation);
+
+ if (autoCorrelation[index] > autoCorrelation[index - 1] && autoCorrelation[index] > autoCorrelation[index + 1]) {
+ double f = double(mImpl->m_f_sample) / index;
+ return getPitch(f);
+ }
- return Pitch();
+ return Pitch{};
}