summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile29
-rw-r--r--autocorrelation.cpp29
-rw-r--r--autocorrelation.h20
-rw-r--r--fft.cpp26
-rw-r--r--fft.h11
-rw-r--r--testsuite.cpp (renamed from main.cpp)23
-rw-r--r--tuner.cpp24
-rw-r--r--tuner.h28
-rw-r--r--tunerdemo.cpp35
10 files changed, 180 insertions, 48 deletions
diff --git a/.gitignore b/.gitignore
index 360a8c3..149e563 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*.o
-fft
+tunerdemo
+testsuite
diff --git a/Makefile b/Makefile
index b945f7c..c78f4d7 100644
--- a/Makefile
+++ b/Makefile
@@ -7,20 +7,39 @@ CXXFLAGS=-stdlib=libc++ -Wall -O2 -std=c++17
#CXXFLAGS=-Wall -O2 -std=c++17 -nostdinc++ -I/usr/lib/llvm-7/include/c++/v1 -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc
# -march=native -mtune=native # doesn't help for gcc
-all: fft
+DESTDIR=/
+PREFIX=/usr/local/bin
-fft: fft.o main.o
+all: tunerdemo testsuite
+
+tunerdemo: fft.o autocorrelation.o tuner.o tunerdemo.o
+ $(CXX) $(CXXFLAGS) -o $@ $^
+
+testsuite: fft.o autocorrelation.o tuner.o testsuite.o
$(CXX) $(CXXFLAGS) -o $@ $^
fft.o: fft.cpp fft.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
-main.o: main.cpp fft.h
+autocorrelation.o: autocorrelation.cpp autocorrelation.h
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+tuner.o: tuner.cpp tuner.h
$(CXX) $(CXXFLAGS) -c -o $@ $<
+testsuite.o: testsuite.cpp fft.h autocorrelation.h tuner.h
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+tunerdemo.o: tunerdemo.cpp fft.h autocorrelation.h tuner.h
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+test: testsuite
+ ./testsuite
+
install:
+ install tunerdemo $(DESTDIR)/$(PREFIX)/tunerdemo
clean:
- rm -f fft *.o
+ rm -f tunerdemo *.o
-.PHONY: clean
+.PHONY: clean install all test
diff --git a/autocorrelation.cpp b/autocorrelation.cpp
new file mode 100644
index 0000000..5c778c1
--- /dev/null
+++ b/autocorrelation.cpp
@@ -0,0 +1,29 @@
+#include "autocorrelation.h"
+
+#include "fft.h"
+
+struct RIT::AutoCorrelation::Impl {
+public:
+ Impl(int size): mFft(std::make_shared<RIT::FFT>(size)), mIfft(mFft) {}
+ std::shared_ptr<RIT::FFT> mFft;
+ RIT::IFFT mIfft;
+};
+
+RIT::AutoCorrelation::AutoCorrelation(int size): mImpl(std::make_unique<RIT::AutoCorrelation::Impl>(size))
+{
+}
+
+RIT::AutoCorrelation::~AutoCorrelation()
+{
+}
+
+std::vector<std::complex<double>> RIT::AutoCorrelation::operator()(const std::vector<std::complex<double>> &v) const
+{
+ auto result = (*mImpl->mFft)(v);
+
+ std::transform(std::begin(result), std::end(result), std::begin(result),
+ [=](const auto& x){return x * std::conj(x);});
+
+ return mImpl->mIfft(result);
+}
+
diff --git a/autocorrelation.h b/autocorrelation.h
new file mode 100644
index 0000000..3be0802
--- /dev/null
+++ b/autocorrelation.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <complex>
+#include <memory>
+#include <vector>
+
+namespace RIT {
+
+class AutoCorrelation {
+public:
+ AutoCorrelation(int size);
+ ~AutoCorrelation();
+ std::vector<std::complex<double>> operator()(const std::vector<std::complex<double>> &v) const;
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl;
+}; // class AutoCorrelation
+
+} // namespace RIT
diff --git a/fft.cpp b/fft.cpp
index 7d76e23..a8009ad 100644
--- a/fft.cpp
+++ b/fft.cpp
@@ -42,7 +42,6 @@ RIT::FFT::FFT(int size, bool halfOnly): mSize(size), order(size), expLUT(size/2)
}
}
-
std::vector<std::complex<double>> RIT::FFT::operator()(const std::vector<std::complex<double>> &v) const {
if (v.size() != mSize)
throw std::length_error("Bad input size");
@@ -159,28 +158,3 @@ std::vector<std::complex<double>> RIT::IFFT::operator()(const std::vector<std::c
return result;
}
-struct RIT::AutoCorrelation::Impl {
-public:
- Impl(int size): mFft(std::make_shared<RIT::FFT>(size)), mIfft(mFft) {}
- std::shared_ptr<RIT::FFT> mFft;
- RIT::IFFT mIfft;
-};
-
-RIT::AutoCorrelation::AutoCorrelation(int size): mImpl(std::make_unique<RIT::AutoCorrelation::Impl>(size))
-{
-}
-
-RIT::AutoCorrelation::~AutoCorrelation()
-{
-}
-
-std::vector<std::complex<double>> RIT::AutoCorrelation::operator()(const std::vector<std::complex<double>> &v) const
-{
- auto result = (*mImpl->mFft)(v);
-
- std::transform(std::begin(result), std::end(result), std::begin(result),
- [=](const auto& x){return x * std::conj(x);});
-
- return mImpl->mIfft(result);
-}
-
diff --git a/fft.h b/fft.h
index 8c1e161..980b4b3 100644
--- a/fft.h
+++ b/fft.h
@@ -44,17 +44,6 @@ private:
std::unique_ptr<Impl> mImpl;
}; // class IFFT
-class AutoCorrelation {
-public:
- AutoCorrelation(int size);
- ~AutoCorrelation();
- std::vector<std::complex<double>> operator()(const std::vector<std::complex<double>> &v) const;
-
-private:
- struct Impl;
- std::unique_ptr<Impl> mImpl;
-}; // class AutoCorrelation
-
std::vector<double> magnitudes(std::vector<std::complex<double>>& v);
} // namespace RIT
diff --git a/main.cpp b/testsuite.cpp
index 3945cff..2b8042b 100644
--- a/main.cpp
+++ b/testsuite.cpp
@@ -1,6 +1,8 @@
// FFT Test
#include "fft.h"
+#include "autocorrelation.h"
+#include "tuner.h"
#include <complex>
#include <chrono>
@@ -236,6 +238,16 @@ public:
}
};
+class MeasureTuner_RR: public Measure {
+ RIT::Tuner mTuner;
+ RIT::Pitch mPitch;
+public:
+ MeasureTuner_RR(const Data& in): Measure(in), mTuner(in.size(), 44100) { mName = "Tuner RR";}
+ void run_impl() override {
+ mPitch = mTuner(mIn);
+ }
+};
+
int main(int argc, char* argv[]) {
std::vector<std::complex<double>> v(4096, 0);
@@ -254,17 +266,18 @@ int main(int argc, char* argv[]) {
MeasureFFT_RR_half measureFFT_RR_half(v, measureFFT_RR);
measureFFT_RR_half.run();
-
+
MeasureFFT_RR_half_magnitudes measureFFT_RR_half_magnitudes(v, measureDFT);
measureFFT_RR_half_magnitudes.run();
MeasureIFFT_RR measureIFFT_RR(v);
measureIFFT_RR.run();
-
+
MeasureAutoCorrelation_RR measureAutoCorrelation_RR(v);
measureAutoCorrelation_RR.run();
-
- return 0;
-}
+ MeasureTuner_RR measureTuner_RR(v);
+ measureTuner_RR.run();
+ return 0;
+}
diff --git a/tuner.cpp b/tuner.cpp
new file mode 100644
index 0000000..d1833a3
--- /dev/null
+++ b/tuner.cpp
@@ -0,0 +1,24 @@
+#include "tuner.h"
+
+#include "autocorrelation.h"
+#include "fft.h"
+
+struct RIT::Tuner::Impl {
+public:
+ Impl(int size, int f_sample): mAC(size), m_f_sample(f_sample) {}
+ RIT::AutoCorrelation mAC;
+ int m_f_sample;
+};
+
+RIT::Tuner::Tuner(int size, int f_sample): mImpl(std::make_unique<RIT::Tuner::Impl>(size, f_sample))
+{
+}
+
+RIT::Tuner::~Tuner(){}
+
+RIT::Pitch RIT::Tuner::operator() (const std::vector<std::complex<double>> &v)
+{
+ std::vector<std::complex<double>> autoCorrelation = mImpl->mAC(v);
+
+ return Pitch();
+}
diff --git a/tuner.h b/tuner.h
new file mode 100644
index 0000000..df17c0f
--- /dev/null
+++ b/tuner.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <complex>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace RIT {
+
+struct Pitch {
+ double f{}; // in Hz
+ double deviation{}; // 0.0 == perfect, +/-1.0: at next note
+ std::string name; // "" for none, "A", "A#", ... for notes
+};
+
+class Tuner {
+public:
+ Tuner(int size, int f_sample);
+ ~Tuner();
+
+ Pitch operator() (const std::vector<std::complex<double>> &v);
+
+private:
+ struct Impl;
+ std::unique_ptr<Impl> mImpl;
+}; // class Tuner
+
+} // namespace RIT
diff --git a/tunerdemo.cpp b/tunerdemo.cpp
new file mode 100644
index 0000000..716bd8e
--- /dev/null
+++ b/tunerdemo.cpp
@@ -0,0 +1,35 @@
+#include "tuner.h"
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+
+using namespace std::chrono_literals;
+
+const int sampleFrequency = 44100;
+const int fftSize = 4096;
+
+std::vector<std::complex<double>> sample()
+{
+ return std::vector<std::complex<double>>(fftSize, 0.0);
+}
+
+int main(int argc, char* argv[]) {
+ RIT::Tuner tuner(fftSize, sampleFrequency);
+
+ std::vector<std::complex<double>> dataIn = sample();
+
+ while (true) {
+ auto start = std::chrono::high_resolution_clock::now();
+ RIT::Pitch pitch = tuner(dataIn);
+ auto end = std::chrono::high_resolution_clock::now();
+ std::cout << "Detected Note: " << pitch.name
+ << " Deviation: " << pitch.deviation
+ << " Frequency: " << pitch.f
+ << ", took " << std::chrono::nanoseconds(end - start).count() * 0.000001 << "ms"
+ << std::endl;
+ std::this_thread::sleep_until(start + 100ms);
+ }
+
+ return 0;
+}