Mercurial > hg > lowfreq
changeset 9:ec39b9aa9f78
Handle resampler latency and FFT alignment padding
author | Chris Cannam |
---|---|
date | Wed, 12 Mar 2014 12:47:47 +0000 |
parents | c037af3977e1 |
children | 0a56b08b373f |
files | LowFreq.cpp LowFreq.h |
diffstat | 2 files changed, 49 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/LowFreq.cpp Wed Mar 12 12:01:54 2014 +0000 +++ b/LowFreq.cpp Wed Mar 12 12:47:47 2014 +0000 @@ -61,6 +61,8 @@ m_n(defaultN), m_blockSize(0), m_roundedInputRate(round(inputSampleRate)), + m_drop(0), + m_pad(0), m_resampler(0), m_fft(0), m_window(0) @@ -344,6 +346,7 @@ m_resampler = new Resampler(m_roundedInputRate, getTargetSampleRate()); + m_fft = new FFT(getFFTSize()); m_window = new Window<double>(HanningWindow, getFFTSize()); m_buffer = std::vector<double>(); @@ -356,7 +359,22 @@ << ", resampler latency " << m_resampler->getLatency() << ", fft size " << getFFTSize() << endl; - //!!! not handling resampler latency + // Resampler's declared latency is its output latency. We need to + // drop that number of samples from the start of its output... + m_drop = m_resampler->getLatency(); + + // ...and add enough padding at the end of its input to ensure at + // least that number of samples come back. + m_pad = int(ceil((double(m_drop) * m_roundedInputRate) / + getTargetSampleRate())); + + // We also need to make sure that the FFT frames are properly + // aligned. That is, the first returned column is expected to show + // an FFT frame centred on time zero. So we need to pre-pad the + // buffer with half the FFT length. + for (int i = 0; i < getFFTSize()/2; ++i) { + m_buffer.push_back(0.0); + } } int @@ -446,6 +464,15 @@ vector<double> resampled = m_resampler->process(data, m_blockSize); m_buffer.insert(m_buffer.end(), resampled.begin(), resampled.end()); + if (m_drop > 0) { + int dropHere = m_drop; + if (dropHere > int(m_buffer.size())) { + dropHere = int(m_buffer.size()); + } + advanceBy(dropHere); + m_drop -= dropHere; + } + delete[] data; FeatureSet fs; @@ -464,8 +491,15 @@ { FeatureSet fs; - while (!m_buffer.empty() && int(m_buffer.size()) < getFFTSize()) { - m_buffer.push_back(0.0); + double *padding = new double[m_pad]; + for (int i = 0; i < m_pad; ++i) { + padding[i] = 0.0; + } + vector<double> lastBit = m_resampler->process(padding, m_pad); + m_buffer.insert(m_buffer.end(), lastBit.begin(), lastBit.end()); + + for (int i = 0; i < getFFTSize() * 2 - getTargetStepSize(); ++i) { + m_buffer.push_back(0.0); } while (int(m_buffer.size()) >= getFFTSize()) { @@ -505,7 +539,13 @@ void LowFreq::advance() { - std::vector<double> advanced(m_buffer.data() + getTargetStepSize(), + advanceBy(getTargetStepSize()); +} + +void +LowFreq::advanceBy(int n) +{ + std::vector<double> advanced(m_buffer.data() + n, m_buffer.data() + m_buffer.size()); m_buffer = advanced;
--- a/LowFreq.h Wed Mar 12 12:01:54 2014 +0000 +++ b/LowFreq.h Wed Mar 12 12:47:47 2014 +0000 @@ -81,6 +81,7 @@ protected: Feature processColumn(); void advance(); + void advanceBy(int); int getTargetSampleRate() const; int getTargetStepSize() const; @@ -97,6 +98,10 @@ bool m_nonIntegralInputRate; int m_roundedInputRate; + // for handling resampler latency: + int m_drop; + int m_pad; + Resampler *m_resampler; FFT *m_fft; Window<double> *m_window;