Mercurial > hg > constant-q-cpp
changeset 32:ba648b8672bd
Much of the actual CQ processing logic
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Wed, 06 Nov 2013 08:10:33 +0000 |
parents | 01a3e110bf8d |
children | f6ef28b02be4 |
files | cpp-qm-dsp/CQKernel.cpp cpp-qm-dsp/CQKernel.h cpp-qm-dsp/ConstantQ.cpp cpp-qm-dsp/ConstantQ.h cpp-qm-dsp/test.cpp |
diffstat | 5 files changed, 101 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/cpp-qm-dsp/CQKernel.cpp Tue Nov 05 16:58:18 2013 +0000 +++ b/cpp-qm-dsp/CQKernel.cpp Wed Nov 06 08:10:33 2013 +0000 @@ -143,6 +143,11 @@ } } + cerr << "size = " << m_kernel.data.size() << "*" << m_kernel.data[0].size() << " (fft size = " << m_p.fftSize << ")" << endl; + + assert(m_kernel.data.size() == m_p.binsPerOctave * m_p.atomsPerFrame); + assert(m_kernel.data[0].size() == m_p.fftSize); + cerr << "density = " << double(nnz) / double(m_p.binsPerOctave * m_p.atomsPerFrame * m_p.fftSize) << " (" << nnz << " of " << m_p.binsPerOctave * m_p.atomsPerFrame * m_p.fftSize << ")" << endl; finaliseKernel(); @@ -235,4 +240,24 @@ m_kernel = sk; } +vector<C> +CQKernel::process(const vector<C> &cv) +{ + // matrix multiply m_kernel.data by in, converting in to complex + // as we go + int ncols = m_p.fftSize; + int nrows = m_p.binsPerOctave * m_p.atomsPerFrame; + + vector<C> rv(nrows, C(0, 0)); + + for (int i = 0; i < nrows; ++i) { + for (int j = 0; j < m_kernel.data[i].size(); ++j) { + rv[i] += cv[j + m_kernel.origin[i]] * m_kernel.data[i][j]; + } + } + + return rv; +} + +
--- a/cpp-qm-dsp/CQKernel.h Tue Nov 05 16:58:18 2013 +0000 +++ b/cpp-qm-dsp/CQKernel.h Wed Nov 06 08:10:33 2013 +0000 @@ -29,6 +29,9 @@ Properties getProperties() const { return m_p; } + std::vector<std::complex<double> > process + (const std::vector<std::complex<double> > &); + private: Properties m_p; FFT *m_fft;
--- a/cpp-qm-dsp/ConstantQ.cpp Tue Nov 05 16:58:18 2013 +0000 +++ b/cpp-qm-dsp/ConstantQ.cpp Wed Nov 06 08:10:33 2013 +0000 @@ -17,6 +17,8 @@ using std::cerr; using std::endl; +typedef std::complex<double> C; + ConstantQ::ConstantQ(double sampleRate, double minFreq, double maxFreq, @@ -81,7 +83,7 @@ m_buffers.push_back(vector<double>(m_extraLatencies[i], 0.0)); } - m_fft = new FFT(m_p.fftSize); + m_fft = new FFTReal(m_p.fftSize); m_bigBlockSize = m_p.fftSize * pow(2, m_octaves) / 2; cerr << "m_bigBlockSize = " << m_bigBlockSize << " for " << m_octaves << " octaves" << endl; @@ -97,9 +99,72 @@ m_buffers[i].insert(m_buffers[i].end(), dec.begin(), dec.end()); } - //!!! do the work! + vector<vector<double> > out; - vector<vector<double> > out; + //!!!! need some mechanism for handling remaining samples at the end + + while (m_buffers[0].size() >= m_bigBlockSize) { + vector<vector<double> > chunk = processBigBlock(); + for (int i = 0; i < m_octaves; ++i) { + vector<double> v; + v.insert(v.end(), + m_buffers[i].begin() + m_bigBlockSize/pow(2,i), m_buffers[i].end()); + m_buffers[i] = v; + } + out.insert(out.end(), chunk.begin(), chunk.end()); + } + return out; } +vector<vector<double> > +ConstantQ::processBigBlock() +{ + vector<vector<double> > out; + + for (int i = 0; i < pow(2, m_octaves - 1) * m_p.atomsPerFrame; ++i) { + out.push_back(vector<double>()); + } + cerr << "returning " << out.size() << " cols per big block" << endl; + + for (int i = 0; i < m_octaves; ++i) { + int n = pow(2, (m_octaves - i - 1)); + cerr << "octave " << i+1 << " of " << m_octaves << ", n = " << n << endl; + for (int j = 0; j < n; ++j) { + int origin = j * m_p.fftSize; //!!! no -- it's the hop but how does that add up? + vector<vector<double> > block = + processOctaveBlock(m_buffers[i].data() + origin); + + //... + } + } + + return out; +} + +vector<vector<double> > +ConstantQ::processOctaveBlock(const double *data) +{ + vector<double> ro(m_p.fftSize, 0.0); + vector<double> io(m_p.fftSize, 0.0); + m_fft->forward(data, ro.data(), io.data()); + + vector<C> cv; + for (int i = 0; i < m_p.fftSize; ++i) { + cv.push_back(C(ro[i], io[i])); + } + + vector<C> cqrowvec = m_kernel->process(cv); + + vector<vector<double> > cqblock; + for (int i = 0; i < m_p.binsPerOctave; ++i) { + cqblock.push_back(vector<double>()); + for (int j = 0; j < m_p.atomsPerFrame; ++j) { + cqblock[i].push_back(abs(cqrowvec[i * m_p.atomsPerFrame + j])); + } + } + + return cqblock; +} + +
--- a/cpp-qm-dsp/ConstantQ.h Tue Nov 05 16:58:18 2013 +0000 +++ b/cpp-qm-dsp/ConstantQ.h Wed Nov 06 08:10:33 2013 +0000 @@ -8,7 +8,7 @@ #include <vector> class Resampler; -class FFT; +class FFTReal; class ConstantQ { @@ -37,9 +37,11 @@ int m_totalLatency; std::vector<int> m_extraLatencies; // per resampler, to make up to total - FFT *m_fft; + FFTReal *m_fft; void initialise(); + std::vector<std::vector<double> > processBigBlock(); + std::vector<std::vector<double> > processOctaveBlock(const double *data); }; #endif