summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorFerran Pujol Camins <ferranpujolcamins@gmail.com>2019-06-08 13:02:42 +0200
committerFerran Pujol Camins <ferranpujolcamins@gmail.com>2019-06-08 13:02:42 +0200
commitc86cc16ae05b23c7a10131d9ec71d7eb9e0ef2fd (patch)
tree4b34b3504d7559b0d96e35e38b3af90ddd1a2f4d /lib
parentf2610e3e142f313ddb0ccc906ab763723fdc9d8a (diff)
parent8ebba3f352bb77604e2a505a0115253a58627cad (diff)
Merge branch 'master' into migrate-to-QJSEngine
Diffstat (limited to 'lib')
-rw-r--r--lib/qm-dsp/CONTRIBUTING.md79
-rw-r--r--lib/qm-dsp/README.md59
-rw-r--r--lib/qm-dsp/README.txt35
-rw-r--r--lib/qm-dsp/base/Restrict.h17
-rw-r--r--lib/qm-dsp/dsp/chromagram/Chromagram.cpp36
-rw-r--r--lib/qm-dsp/dsp/chromagram/Chromagram.h55
-rw-r--r--lib/qm-dsp/dsp/chromagram/ConstantQ.cpp131
-rw-r--r--lib/qm-dsp/dsp/chromagram/ConstantQ.h6
-rw-r--r--lib/qm-dsp/dsp/keydetection/GetKeyMode.cpp299
-rw-r--r--lib/qm-dsp/dsp/keydetection/GetKeyMode.h12
-rw-r--r--lib/qm-dsp/dsp/rateconversion/DecimatorB.cpp1
-rw-r--r--lib/qm-dsp/dsp/rateconversion/Resampler.cpp64
-rw-r--r--lib/qm-dsp/dsp/rateconversion/Resampler.h1
-rw-r--r--lib/qm-dsp/dsp/segmentation/ClusterMeltSegmenter.cpp19
-rw-r--r--lib/qm-dsp/dsp/segmentation/Segmenter.cpp17
-rw-r--r--lib/qm-dsp/dsp/segmentation/cluster_melt.c4
-rw-r--r--lib/qm-dsp/dsp/segmentation/cluster_segmenter.c2
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/DFProcess.cpp15
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/DFProcess.h2
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/FiltFilt.cpp57
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/FiltFilt.h17
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/Filter.cpp148
-rw-r--r--lib/qm-dsp/dsp/signalconditioning/Filter.h72
-rw-r--r--lib/qm-dsp/dsp/tempotracking/DownBeat.cpp2
-rw-r--r--lib/qm-dsp/dsp/tempotracking/TempoTrack.cpp52
-rw-r--r--lib/qm-dsp/dsp/tempotracking/TempoTrack.h36
-rw-r--r--lib/qm-dsp/dsp/tonal/TCSgram.cpp2
-rw-r--r--lib/qm-dsp/dsp/tonal/TonalEstimator.h4
-rw-r--r--lib/qm-dsp/dsp/transforms/DCT.cpp91
-rw-r--r--lib/qm-dsp/dsp/transforms/DCT.h85
-rw-r--r--lib/qm-dsp/dsp/transforms/FFT.cpp2
-rw-r--r--lib/qm-dsp/dsp/transforms/FFT.h6
-rw-r--r--lib/qm-dsp/dsp/wavelet/Wavelet.cpp11
-rw-r--r--lib/qm-dsp/dsp/wavelet/Wavelet.h4
-rw-r--r--lib/qm-dsp/ext/kissfft/CHANGELOG4
-rw-r--r--lib/qm-dsp/ext/kissfft/README134
-rw-r--r--lib/qm-dsp/ext/kissfft/README.simd78
-rw-r--r--lib/qm-dsp/ext/kissfft/TIPS39
-rw-r--r--lib/qm-dsp/ext/kissfft/kiss_fft.c5
-rw-r--r--lib/qm-dsp/ext/kissfft/kissfft.hh300
-rw-r--r--lib/qm-dsp/ext/kissfft/tools/kiss_fftr.c (renamed from lib/qm-dsp/ext/kissfft/kiss_fftr.c)2
-rw-r--r--lib/qm-dsp/ext/kissfft/tools/kiss_fftr.h (renamed from lib/qm-dsp/ext/kissfft/kiss_fftr.h)2
-rw-r--r--lib/qm-dsp/maths/CosineDistance.cpp2
-rw-r--r--lib/qm-dsp/maths/MathUtilities.cpp84
-rw-r--r--lib/qm-dsp/maths/MathUtilities.h54
-rw-r--r--lib/qm-dsp/maths/Polyfit.h103
-rw-r--r--lib/qm-dsp/maths/pca/pca.c2
-rw-r--r--lib/qm-dsp/mixxx-changes.patch272
48 files changed, 1898 insertions, 626 deletions
diff --git a/lib/qm-dsp/CONTRIBUTING.md b/lib/qm-dsp/CONTRIBUTING.md
new file mode 100644
index 0000000000..6f6229e610
--- /dev/null
+++ b/lib/qm-dsp/CONTRIBUTING.md
@@ -0,0 +1,79 @@
+
+Contributing
+============
+
+The qm-dsp library is maintained in a Github repository at
+https://github.com/c4dm/qm-dsp.
+
+
+Reporting bugs
+--------------
+
+Please use Github issues for bug reports. Try to make them as specific
+as possible. For example, describe an input that triggers some
+particular behaviour, and tell us how that behaviour differs from what
+you expected.
+
+If your bug can be reproduced by processing an audio file using one of
+the QM Vamp Plugins (https://github.com/c4dm/qm-vamp-plugins), which
+are built using this library, that might be a good way to illustrate
+the problem.
+
+
+Pull requests
+-------------
+
+We're happy to see pull requests, and can pull them directly in some
+circumstances.
+
+ * Please make sure your change compiles without warnings and passes
+ the existing tests.
+
+ * Please follow the code style guidelines (see below).
+
+ * Please make it as easy as possible to verify the behaviour of the
+ pull request, for example by adding a new test in the `tests`
+ directory. This library has only limited test coverage, but we
+ would like to expand it, and prefer not to make changes unless they
+ are backed by tests.
+
+ * Please provide your changes under terms which permit Queen Mary
+ University of London to relicense the code for commercial
+ purposes. The qm-dsp library as a whole is provided under the GPL,
+ but QM also make commercial licences available separately, and
+ cannot accept any pull request whose copyright status would prevent
+ that. In practice, this means any non-trivial change not
+ originating from QM must be explicitly licensed using a BSD-like
+ licence text, either in the source file itself or in an
+ accompanying file. See `thread/BlockAllocator.h` for an example of
+ typical language.
+
+Please note also that fixes which change the behaviour of the existing
+QM Vamp Plugins will need particularly close scrutiny - these are
+reasonably widely used and, even where they have defects, changes may
+cause problems for users and will at least need to be documented with
+the plugins. For this reason it may take some time for such changes to
+be reviewed or integrated.
+
+
+Code style
+----------
+
+ * C++ code must compile with the C++98 standard, except for the unit
+ tests which are C++14
+
+ * Classes are named `LikeThis` - functions, methods, and local
+ variables `likeThis` - class member variables `m_likeThis`
+
+ * Indentation is four spaces at a time (no tabs)
+
+ * The opening brace for a block goes at the end of the line, except
+ at the start of a function or class definition where it gets a line
+ of its own
+
+ * Please use braces around any conditional or loop block that
+ occupies its own line
+
+Some of the older code in this library does not follow these
+guidelines - usually this means the code needs to be updated.
+
diff --git a/lib/qm-dsp/README.md b/lib/qm-dsp/README.md
new file mode 100644
index 0000000000..20bcb60f04
--- /dev/null
+++ b/lib/qm-dsp/README.md
@@ -0,0 +1,59 @@
+
+QM-DSP library
+==============
+
+This is a C++ library of functions for Digital Signal Processing and
+Music Informatics purposes developed in the [Centre for Digital
+Music](http://c4dm.eecs.qmul.ac.uk) at Queen Mary, University of
+London.
+
+It is used by [QM Vamp Plugins](http://isophonics.net/QMVampPlugins)
+amongst other things.
+
+Despite the assertive name "qm-dsp", it is not "the official QM DSP
+library", just one library for DSP that happens to have been written
+at QM. It got this name because nothing else was using it at the time.
+
+
+Compiling the library
+---------------------
+
+ - Linux: `make -f build/linux/Makefile.linux64`
+
+ - Mac: `make -f build/osx/Makefile.osx`
+
+ - Windows (MSVC): Use the project file `build/msvc/QMDSP.vcxproj`
+
+To build and run unit tests as well, add the `test` target to your
+Make invocation, e.g. `make -f build/linux/Makefile.linux64
+test`. Tests require the Boost library.
+
+
+Licence
+-------
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version. See the file COPYING included with
+this distribution for more information.
+
+This code is Copyright (c) 2006-2019 Queen Mary, University of London,
+with the following exceptions:
+
+ - `ext/kissfft` - Copyright (c) 2003-2010 Mark Borgerding
+
+ - `maths/pca/pca.c` - Fionn Murtagh, from StatLib, used with permission
+
+ - `maths/Polyfit.h` - by Allen Miller, David J Taylor and others;
+also for Delphi in the the JEDI Math Library, under the Mozilla Public
+License
+
+ - `thread/BlockAllocator.h` - derived from FSB Allocator by Juha
+Nieminen, under a BSD-style license
+
+See individual files for further authorship details.
+
+If you wish to use this code in a proprietary application or product
+for which the terms of the GPL are not appropriate, please contact QM
+Innovation https://www.qminnovation.co.uk/ for licensing terms.
diff --git a/lib/qm-dsp/README.txt b/lib/qm-dsp/README.txt
deleted file mode 100644
index 6927c7a1b8..0000000000
--- a/lib/qm-dsp/README.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-QM-DSP library
-==============
-
-This is a C++ library of functions for DSP and Music Informatics
-purposes developed at Queen Mary, University of London.
-It is used by the QM Vamp Plugins (q.v.) amongst other things.
-
-This code is Copyright (c) 2006-2015 Queen Mary, University of London,
-with the following exceptions:
-
-ext/kissfft -- Copyright (c) 2003-2010 Mark Borgerding
-
-maths/pca.c -- Fionn Murtagh, from StatLib; with permission
-
-maths/Polyfit.h -- Allen Miller, David J Taylor and others; also for
-Delphi in the the JEDI Math Library, under the Mozilla Public License
-
-thread/BlockAllocator.h -- derived from FSB Allocator by Juha Nieminen,
-under BSD-style license
-
-See individual files for further authorship details.
-
-
-License
-=======
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version. See the file
-COPYING included with this distribution for more information.
-
-
diff --git a/lib/qm-dsp/base/Restrict.h b/lib/qm-dsp/base/Restrict.h
new file mode 100644
index 0000000000..723a8b3b67
--- /dev/null
+++ b/lib/qm-dsp/base/Restrict.h
@@ -0,0 +1,17 @@
+
+#ifndef QM_DSP_RESTRICT_H
+#define QM_DSP_RESTRICT_H
+
+#ifdef _MSC_VER
+#define QM_R__ __restrict
+#endif
+
+#ifdef __GNUC__
+#define QM_R__ __restrict__
+#endif
+
+#ifndef QM_R__
+#define QM_R__
+#endif
+
+#endif
diff --git a/lib/qm-dsp/dsp/chromagram/Chromagram.cpp b/lib/qm-dsp/dsp/chromagram/Chromagram.cpp
index a8597a5ddd..9f40b1d2f1 100644
--- a/lib/qm-dsp/dsp/chromagram/Chromagram.cpp
+++ b/lib/qm-dsp/dsp/chromagram/Chromagram.cpp
@@ -33,8 +33,9 @@ int Chromagram::initialise( ChromaConfig Config )
m_BPO = Config.BPO; // bins per octave
m_normalise = Config.normalise; // if frame normalisation is required
- // No. of constant Q bins
- m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
+ // Extend range to a full octave
+ double octaves = log(m_FMax / m_FMin) / log(2.0);
+ m_FMax = m_FMin * pow(2.0, ceil(octaves));
// Create array for chroma result
m_chromadata = new double[ m_BPO ];
@@ -44,7 +45,7 @@ int Chromagram::initialise( ChromaConfig Config )
// Populate CQ config structure with parameters
// inherited from the Chroma config
- ConstantQConfig.FS = Config.FS;
+ ConstantQConfig.FS = Config.FS;
ConstantQConfig.min = m_FMin;
ConstantQConfig.max = m_FMax;
ConstantQConfig.BPO = m_BPO;
@@ -53,6 +54,9 @@ int Chromagram::initialise( ChromaConfig Config )
// Initialise ConstantQ operator
m_ConstantQ = new ConstantQ( ConstantQConfig );
+ // No. of constant Q bins
+ m_uK = m_ConstantQ->getK();
+
// Initialise working arrays
m_frameSize = m_ConstantQ->getfftlength();
m_hopSize = m_ConstantQ->gethop();
@@ -112,7 +116,7 @@ void Chromagram::unityNormalise(double *src)
MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
- for( unsigned int i = 0; i < m_BPO; i++ )
+ for (int i = 0; i < m_BPO; i++)
{
val = src[ i ] / max;
@@ -121,7 +125,7 @@ void Chromagram::unityNormalise(double *src)
}
-double* Chromagram::process( const double *data )
+double *Chromagram::process(const double *data)
{
if (!m_skGenerated) {
// Generate CQ Kernel
@@ -139,12 +143,20 @@ double* Chromagram::process( const double *data )
}
m_window->cut(m_windowbuf);
+ // The frequency-domain version expects pre-fftshifted input - so
+ // we must do the same here
+ for (int i = 0; i < m_frameSize/2; ++i) {
+ double tmp = m_windowbuf[i];
+ m_windowbuf[i] = m_windowbuf[i + m_frameSize/2];
+ m_windowbuf[i + m_frameSize/2] = tmp;
+ }
+
m_FFT->forward(m_windowbuf, m_FFTRe, m_FFTIm);
return process(m_FFTRe, m_FFTIm);
}
-double* Chromagram::process( const double *real, const double *imag )
+double *Chromagram::process(const double *real, const double *imag)
{
if (!m_skGenerated) {
// Generate CQ Kernel
@@ -153,19 +165,17 @@ double* Chromagram::process( const double *real, const double *imag )
}
// initialise chromadata to 0
- for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
+ for (int i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
- double cmax = 0.0;
- double cval = 0;
// Calculate ConstantQ frame
m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
// add each octave of cq data into Chromagram
- const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
- for (unsigned octave = 0; octave <= octaves; octave++)
+ const int octaves = m_uK / m_BPO;
+ for (int octave = 0; octave < octaves; octave++)
{
- unsigned firstBin = octave*m_BPO;
- for (unsigned i = 0; i < m_BPO; i++)
+ int firstBin = octave*m_BPO;
+ for (int i = 0; i < m_BPO; i++)
{
m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
}
diff --git a/lib/qm-dsp/dsp/chromagram/Chromagram.h b/lib/qm-dsp/dsp/chromagram/Chromagram.h
index bd928f5d48..ca68ee9071 100644
--- a/lib/qm-dsp/dsp/chromagram/Chromagram.h
+++ b/lib/qm-dsp/dsp/chromagram/Chromagram.h
@@ -20,11 +20,11 @@
#include "base/Window.h"
#include "ConstantQ.h"
-struct ChromaConfig{
- unsigned int FS;
+struct ChromaConfig {
+ double FS;
double min;
double max;
- unsigned int BPO;
+ int BPO;
double CQThresh;
MathUtilities::NormaliseType normalise;
};
@@ -35,19 +35,44 @@ class Chromagram
public:
Chromagram( ChromaConfig Config );
~Chromagram();
-
- double* process( const double *data ); // time domain
- double* process( const double *real, const double *imag ); // frequency domain
- void unityNormalise( double* src );
+
+ /**
+ * Process a time-domain input signal of length equal to
+ * getFrameSize().
+ *
+ * The returned buffer contains the chromagram values indexed by
+ * bin, with the number of values corresponding to the BPO field
+ * in the ChromaConfig supplied at construction. It is owned by
+ * the Chromagram object and is reused from one process call to
+ * the next.
+ */
+ double *process(const double *data);
+
+ /**
+ * Process a frequency-domain input signal generated from a
+ * time-domain signal of length equal to getFrameSize() that has
+ * been windowed and "fftshifted" to place the zero index in the
+ * centre of the frame. The real and imag buffers must each
+ * contain the full getFrameSize() frequency bins.
+ *
+ * The returned buffer contains the chromagram values indexed by
+ * bin, with the number of values corresponding to the BPO field
+ * in the ChromaConfig supplied at construction. It is owned by
+ * the Chromagram object and is reused from one process call to
+ * the next.
+ */
+ double *process(const double *real, const double *imag);
+
+ void unityNormalise(double* src);
// Complex arithmetic
double kabs( double real, double imag );
// Results
- unsigned int getK() { return m_uK;}
- unsigned int getFrameSize() { return m_frameSize; }
- unsigned int getHopSize() { return m_hopSize; }
-
+ int getK() { return m_uK;}
+ int getFrameSize() { return m_frameSize; }
+ int getHopSize() { return m_hopSize; }
+
private:
int initialise( ChromaConfig Config );
int deInitialise();
@@ -58,13 +83,13 @@ private:
double* m_chromadata;
double m_FMin;
double m_FMax;
- unsigned int m_BPO;
- unsigned int m_uK;
+ int m_BPO;
+ int m_uK;
MathUtilities::NormaliseType m_normalise;
- unsigned int m_frameSize;
- unsigned int m_hopSize;
+ int m_frameSize;
+ int m_hopSize;
FFTReal* m_FFT;
ConstantQ* m_ConstantQ;
diff --git a/lib/qm-dsp/dsp/chromagram/ConstantQ.cpp b/lib/qm-dsp/dsp/chromagram/ConstantQ.cpp
index b764235fcd..a5b1c12105 100644
--- a/lib/qm-dsp/dsp/chromagram/ConstantQ.cpp
+++ b/lib/qm-dsp/dsp/chromagram/ConstantQ.cpp
@@ -117,28 +117,29 @@ void ConstantQ::sparsekernel()
FFT m_FFT(m_FFTLength);
- for (unsigned k = m_uK; k--; )
- {
- for (unsigned u=0; u < m_FFTLength; u++)
- {
+ for (unsigned k = m_uK; k--;) {
+ for (unsigned u=0; u < m_FFTLength; u++) {
hammingWindowRe[u] = 0;
hammingWindowIm[u] = 0;
}
- // Computing a hamming window
- const unsigned hammingLength = (int) ceil( m_dQ * m_FS / ( m_FMin * pow(2,((double)(k))/(double)m_BPO)));
+ const double samplesPerCycle =
+ m_FS / (m_FMin * pow(2, (double)k / (double)m_BPO));
+
+ // Computing a hamming window
+ const unsigned hammingLength = (int) ceil(
+ m_dQ * samplesPerCycle);
unsigned origin = m_FFTLength/2 - hammingLength/2;
- for (unsigned i=0; i<hammingLength; i++)
- {
- const double angle = 2*PI*m_dQ*i/hammingLength;
- const double real = cos(angle);
- const double imag = sin(angle);
- const double absol = hamming(hammingLength, i)/hammingLength;
- hammingWindowRe[ origin + i ] = absol*real;
- hammingWindowIm[ origin + i ] = absol*imag;
- }
+ for (unsigned i=0; i<hammingLength; i++) {
+ const double angle = 2*PI*i/samplesPerCycle;
+ const double real = cos(angle);
+ const double imag = sin(angle);
+ const double absol = hamming(hammingLength, i)/hammingLength;
+ hammingWindowRe[ origin + i ] = absol*real;
+ hammingWindowIm[ origin + i ] = absol*imag;
+ }
for (unsigned i = 0; i < m_FFTLength/2; ++i) {
double temp = hammingWindowRe[i];
@@ -149,24 +150,24 @@ void ConstantQ::sparsekernel()
hammingWindowIm[i + m_FFTLength/2] = temp;
}
- //do fft of hammingWindow
- m_FFT.process( 0, hammingWindowRe, hammingWindowIm, transfHammingWindowRe, transfHammingWindowIm );
-
-
- for (unsigned j=0; j<( m_FFTLength ); j++)
- {
- // perform thresholding
- const double squaredBin = squaredModule( transfHammingWindowRe[ j ], transfHammingWindowIm[ j ]);
- if (squaredBin <= squareThreshold) continue;
-
- // Insert non-zero position indexes, doubled because they are floats
- sk->is.push_back(j);
- sk->js.push_back(k);
-
- // take conjugate, normalise and add to array sparkernel
- sk->real.push_back( transfHammingWindowRe[ j ]/m_FFTLength);
- sk->imag.push_back(-transfHammingWindowIm[ j ]/m_FFTLength);
- }
+ //do fft of hammingWindow
+ m_FFT.process( 0, hammingWindowRe, hammingWindowIm, transfHammingWindowRe, transfHammingWindowIm );
+
+
+ for (unsigned j=0; j<( m_FFTLength ); j++) {
+ // perform thresholding
+ const double squaredBin = squaredModule( transfHammingWindowRe[ j ], transfHammingWindowIm[ j ]);
+ if (squaredBin <= squareThreshold) {
+ continue;
+ }
+ // Insert non-zero position indexes
+ sk->is.push_back(j);
+ sk->js.push_back(k);
+
+ // take conjugate, normalise and add to array sparkernel
+ sk->real.push_back( transfHammingWindowRe[ j ]/m_FFTLength);
+ sk->imag.push_back(-transfHammingWindowIm[ j ]/m_FFTLength);
+ }
}
@@ -256,10 +257,9 @@ double* ConstantQ::process( const double* fftdata )
SparseKernel *sk = m_sparseKernel;
- for (unsigned row=0; row<2*m_uK; row++)
- {
- m_CQdata[ row ] = 0;
- m_CQdata[ row+1 ] = 0;
+ for (unsigned row=0; row<2*m_uK; row++) {
+ m_CQdata[ row ] = 0;
+ m_CQdata[ row+1 ] = 0;
}
const unsigned *fftbin = &(sk->is[0]);
const unsigned *cqbin = &(sk->js[0]);
@@ -267,17 +267,19 @@ double* ConstantQ::process( const double* fftdata )
const double *imag = &(sk->imag[0]);
const unsigned int sparseCells = sk->real.size();
- for (unsigned i = 0; i<sparseCells; i++)
- {
- const unsigned row = cqbin[i];
- const unsigned col = fftbin[i];
- const double & r1 = real[i];
- const double & i1 = imag[i];
- const double & r2 = fftdata[ (2*m_FFTLength) - 2*col - 2 ];
- const double & i2 = fftdata[ (2*m_FFTLength) - 2*col - 2 + 1 ];
- // add the multiplication
- m_CQdata[ 2*row ] += (r1*r2 - i1*i2);
- m_CQdata[ 2*row+1] += (r1*i2 + i1*r2);
+ for (unsigned i = 0; i<sparseCells; i++) {
+ const unsigned row = cqbin[i];
+ const unsigned col = fftbin[i];
+ if (col == 0) {
+ continue;
+ }
+ const double & r1 = real[i];
+ const double & i1 = imag[i];
+ const double & r2 = fftdata[ (2*m_FFTLength) - 2*col - 2 ];
+ const double & i2 = fftdata[ (2*m_FFTLength) - 2*col - 2 + 1 ];
+ // add the multiplication
+ m_CQdata[ 2*row ] += (r1*r2 - i1*i2);
+ m_CQdata[ 2*row+1] += (r1*i2 + i1*r2);
}
return m_CQdata;
@@ -300,7 +302,7 @@ void ConstantQ::initialise( CQConfig Config )
// work out length of fft required for this constant Q Filter bank
m_FFTLength = (int) pow(2, nextpow2(ceil( m_dQ*m_FS/m_FMin )));
- m_hop = m_FFTLength/8; // <------ hop size is window length divided by 32
+ m_hop = m_FFTLength/8;
// std::cerr << "ConstantQ::initialise: -> fft length = " << m_FFTLength << ", hop = " << m_hop << std::endl;
@@ -324,10 +326,9 @@ void ConstantQ::process(const double *FFTRe, const double* FFTIm,
SparseKernel *sk = m_sparseKernel;
- for (unsigned row=0; row<m_uK; row++)
- {
- CQRe[ row ] = 0;
- CQIm[ row ] = 0;
+ for (unsigned row=0; row<m_uK; row++) {
+ CQRe[ row ] = 0;
+ CQIm[ row ] = 0;
}
const unsigned *fftbin = &(sk->is[0]);
@@ -336,16 +337,18 @@ void ConstantQ::process(const double *FFTRe, const double* FFTIm,
const double *imag = &(sk->imag[0]);
const unsigned int sparseCells = sk->real.size();
- for (unsigned i = 0; i<sparseCells; i++)
- {
- const unsigned row = cqbin[i];
- const unsigned col = fftbin[i];
- const double & r1 = real[i];
- const double & i1 = imag[i];
- const double & r2 = FFTRe[ m_FFTLength - col - 1 ];
- const double & i2 = FFTIm[ m_FFTLength - col - 1 ];
- // add the multiplication
- CQRe[ row ] += (r1*r2 - i1*i2);
- CQIm[ row ] += (r1*i2 + i1*r2);
+ for (unsigned i = 0; i<sparseCells; i++) {
+ const unsigned row = cqbin[i];
+ const unsigned col = fftbin[i];
+ if (col == 0) {
+ continue;
+ }
+ const double & r1 = real[i];
+ const double & i1 = imag[i];
+ const double & r2 = FFTRe[ m_FFTLength - col ];
+ const double & i2 = FFTIm[ m_FFTLength - col ];
+ // add the multiplication
+ CQRe[ row ] += (r1*r2 - i1*i2);
+ CQIm[ row ] += (r1*i2 + i1*r2);
}
}
diff --git a/lib/qm-dsp/dsp/chromagram/ConstantQ.h b/lib/qm-dsp/dsp/chromagram/ConstantQ.h
index c06f60a9d0..7507a1f964 100644
--- a/lib/qm-dsp/dsp/chromagram/ConstantQ.h
+++ b/lib/qm-dsp/dsp/chromagram/ConstantQ.h
@@ -20,8 +20,8 @@
#include "maths/MathAliases.h"
#include "maths/MathUtilities.h"
-struct CQConfig{
- unsigned int FS; // samplerate
+struct CQConfig {
+ double FS; // samplerate
double min; // minimum frequency
double max; // maximum frequency
unsigned int BPO; // bins per octave
@@ -58,7 +58,7 @@ private:
void deInitialise();
double* m_CQdata;
- unsigned int m_FS;
+