31 #include "../config.h"
32 #include "../math/mathtools.h"
33 #include "../piano/piano.h"
34 #include "../system/log.h"
84 LogV(
"KeyRecognizer: starting initialization");
91 LogV(
"KeyRecognizer: initialization finished");
118 EptAssert(piano,
"The piano has to be set.");
119 EptAssert(fftPointer,
"The fft data has to exist.");
120 EptAssert(fftPointer->isValid(),
"Invaild fft data");
122 if (forceRestart)
stop();
191 std::vector<double> &fft =
mFFTPtr->fft;
193 int sr =
mFFTPtr->samplingRate;
195 auto qtof = [n,sr] (
double q) {
return sr*q/(2*n); };
197 int q1 = std::max(0,ftoq(f/1.04));
198 int q2 = std::min(ftoq(f*1.04),n);
200 for (
int q=q1; q<=q2; ++q) if (fft[q]>max)
226 const double threshold = 0.09;
227 std::vector<double> &fft =
mFFTPtr->fft;
229 int sr =
mFFTPtr->samplingRate;
231 auto qtof = [n,sr] (
double q) {
return sr*q/(2*n); };
232 const int q1=ftoq(20), q2=ftoq(1000), q3=ftoq(4500);
234 if (n<=0 or q1<0 or q3>=n)
return 0;
235 for (
int q=q1; q<=q3; ++q)
242 if (m2/m1/n > threshold)
245 for (
int q=q2; q<q3; ++q) if (fft[q]>max)
306 const int Q =
mFFTPtr->fft.size();
307 std::function<double(double)> mtoq = [
this,Q] (
double m)
337 auto decibel = [norm](
double x) {
return 10*log10(x/norm);};
338 auto dB= MathTools::transformVector<double>(
mLogSpec,decibel);
339 Write(
"02-dB.dat",dB);
343 for (
int i=0; i<
M; ++i)
347 int a = std::max(0,i-w);
348 int b = std::min(M,i+1);
350 for (
int k=a; k<b; ++k) sum+=dB[k]*dB[k];
362 if (m1>=0 and m1<=m2 and m2<=M)
391 static const int width=
M/300;
392 static const int partials=20;
393 static const double B=0.000;
395 static std::vector<double> kernel(
M);
399 auto setpeak = [] (
int m,
double amplitude)
400 {
for (
int n=m-width; n<=m+width; n++) kernel[(n+
M)%
M]=amplitude*(width-std::abs(n-m)); };
403 auto partial = [] (
int n,
double B)
404 {
return n * sqrt((1+B*n*n)/(1+B)); };
407 auto partialindex = [
this,partial] (
int n,
double B,
int div)
408 {
return ftom(
fmin*partial(n,B)/partial(div,B)); };
411 auto intensity = [] (
int n) {
return pow(static_cast<double>(n),-0.3); };
414 for (
int div=2; div<=4; div++) for (int n=1; n<=30; ++n) if (n%div>0)
if (n>div-2)
415 setpeak(partialindex(n,B,div),-0.3*intensity(n));
417 for (
int n=1; n<=partials; ++n) setpeak(partialindex(n, B, 1),intensity(n));
422 Write(
"05-keyrecog-kernel.dat",kernel,
true);
446 for (
size_t n = 0; n <
mFlatFFT.size(); ++n)
470 if (mConcertPitch<=390 or mConcertPitch>500)
return -1;
474 double c = 0.000019394+0.079694594*d-0.003718646*d*d
475 + 0.000450934*d*d*d + 0.000003724*d*d*d*d;
487 #if CONFIG_ENABLE_XMGRACE
488 std::ofstream os(filename);
489 for (uint m=0; m<v.size(); ++m)
492 if (log) os <<
mtof(m) <<
"\t" << v[m] << std::endl;
493 else os << m <<
"\t" << v[m] << std::endl;
497 (void)filename; (void)v; (void)log;
498 #endif // CONFIG_ENABLE_XMGRACE
FFTDataPointer mFFTPtr
Pointer to Fourier transform.
double detectForcedFrequency()
Detect forced key.
virtual void stop()
Stop the thread.
#define CHECK_CANCEL_THREAD
FFT_Implementation mFFT
Instance of FFT implementation.
std::vector< double > mFlatSpectrum
DoubleLogarithmic spectrum (LogLogSpec)
void signalPreprocessing()
Preprocessing of the signal.
Callback class for KeyRecognizer.
void init(bool optimize)
Initialization of the KeyRecognizer.
void constructLogSpec()
Construct logarithmic spectrum.
int mKeyNumberOfA
Index of the A-key.
static const int M
Number of bins (powers of 2,3,5)
KeyRecognizer(KeyRecognizerCallback *callback)
Constructor of the KeyRecognizer.
int ftom(double f)
Map frequency to bin index.
double getEqualTempFrequency(int keynumber, double cents=0, double A4=0) const
Function returning the equal temperament.
bool isThreadRunning() const
Flag to check if the thread is running.
static void setThreadName(std::string s)
Specify the name of the thread.
void Write(std::string filename, std::vector< double > &v, bool log=true)
FFTComplexVector mFlatFFT
Fourier transform of LogLogSpec.
double mConcertPitch
Actual frequency of the A-key.
bool mKeyForced
Flag indicating that the key is forced.
void defineKernel()
Define the kernel vector for key recognition.
double estimateFrequency()
Estimate frequency for a given log-log spectrum.
const Keyboard & getKeyboard() const
void workerFunction() overridefinal
Main worker function for executing the key recognition thread.
std::vector< double > mLogSpec
Logarithmic spectrum (LogSpec)
virtual void start()
Start the thread.
static const double logfmax
Log of maximal frequency.
double detectFrequencyInTreble()
Detect keys in the treble.
const Piano * mPiano
Pointer to the piano data.
void recognizeKey(bool forceRestart, const Piano *piano, FFTDataPointer fftPointer, int selectedKey, bool keyForced)
Start key recognition.
virtual void keyRecognized(int keyIndex, double frequency)=0
int mNumberOfKeys
Number of piano keys.
int getKeyNumberOfA4() const
const double & getConcertPitch() const
static const double fmax
Frequency of bin M-1.
int mSelectedKey
Number of the actually selected key.
FFTComplexVector mKernelFFT
Fourier transform of the kernel.
KeyRecognizerCallback * mCallback
Pointer to the caller.
std::shared_ptr< FFTData > FFTDataPointer
Shared pointer of FFTData.
FFTRealVector mConvolution
Convolution vector.
static const double fmin
Frequency of bin 0.
static const double logfmin
Log of minimal frequency.
int getNumberOfKeys() const
void optimize(FFTRealVector &in)
Optimize plan for the forward transfomation.
void calculateFFT(const FFTRealVector &in, FFTComplexVector &out)
Foward FFT, mapping a real vector with size N to a complex one with size N/2+1.
double mtof(int m)
Map bin index to frequency.
int findNearestKey(double f)
Find the nearest key for a given frequency.