Mercurial > hg > lowfreq
changeset 6:e502cf649389
Fixes to bin counting, etc
author | Chris Cannam |
---|---|
date | Tue, 11 Mar 2014 18:36:24 +0000 |
parents | bf742ae09443 |
children | 4a777e3b515e |
files | LowFreq.cpp |
diffstat | 1 files changed, 42 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/LowFreq.cpp Mon Mar 10 16:03:53 2014 +0000 +++ b/LowFreq.cpp Tue Mar 11 18:36:24 2014 +0000 @@ -8,6 +8,7 @@ #include <cstdio> using std::cerr; +using std::cout; using std::endl; using std::vector; @@ -224,16 +225,19 @@ d.description = ""; d.unit = ""; d.hasFixedBinCount = true; - d.binCount = m_n/2 + 1; + d.binCount = m_n; d.hasKnownExtents = false; d.isQuantized = false; d.sampleType = OutputDescriptor::FixedSampleRate; d.sampleRate = float(getTargetSampleRate()) / float(getTargetStepSize()); + +//!!! We need to make sure the input sample rate / d.sampleRate is an +//!!! integer (otherwise e.g. SV won't display correctly) char namebuf[50]; - for (int i = 0; i <= m_n/2; ++i) { + for (int i = 0; i < m_n; ++i) { sprintf(namebuf, "%.3gHz", double(getOutputBinFrequency(i))); d.binNames.push_back(namebuf); } @@ -316,18 +320,18 @@ // We want to return a number of bins n between frequencies fmin // and fmax. - // The bin frequency for bin n of an n-point fft is fs (the sample - // rate), with the top half aliasing the bottom half. So in theory - // we can downsample to a sample rate of fmax*2 and then run an - // m-point FFT, where m is sufficient to give us n bins remaining - // between fmin and fmax. For m then we calculate fmax / - // ((fmax-fmin)/n). + // The bin frequency for bin j of an n-point fft is fs/n*j (where + // fs is the sample rate), with the top half aliasing the bottom + // half. To get a max bin frequency of fmax, in theory we can + // downsample to a sample rate of fmax*2 and then run an m-point + // FFT, where m is sufficient to give us n bins remaining between + // fmin and fmax. We get m by calculating fmax / ((fmax-fmin)/n). // However, our resampler introduces artifacts close to its cutoff // frequency within the filter transition band so we probably - // shouldn't aim to resample to exactly fmax*2. Instead we - // resample to fmax*4 and carry out an FFT of twice the expected - // number of bins. + // shouldn't aim to resample to fmax*2. Instead we resample to + // fmax*4 and carry out an FFT of twice the length. (We could + // resample closer to fmax, but the sums make my brain hurt.) m_resampler = new Resampler(int(round(m_inputSampleRate)), getTargetSampleRate()); @@ -343,30 +347,32 @@ << ", resampler latency " << m_resampler->getLatency() << ", fft size " << getFFTSize() << endl; - //!!! output has wrong number of bins + //!!! want to make sure our output sample rate is //!!! not handling resampler latency - - //!!! how do we know the fft size is long enough to capture the low frequencies we want? } int LowFreq::getTargetSampleRate() const { - // See notes in reset() - return int(ceil(m_fmax)) * 4; + int tfs = int(ceil(m_fmax)) * 4; + cerr << "LowFreq::getTargetSampleRate: for range " << m_fmin << " -> " << m_fmax + << " target rate is " << tfs << endl; + return tfs; } int LowFreq::getTargetStepSize() const { - return int(round(m_n * (1.0 - (m_overlap / 100.0)))); + int step = int(round(getFFTSize() * (1.0 - (m_overlap / 100.0)))); + cerr << "LowFreq::getTargetStepSize: step is " << step << endl; + return step; } int LowFreq::getFFTSize() const { - int fftSize = 2 * int(ceil(m_fmax / ((m_fmax - m_fmin) / m_n))); + int fftSize = 4 * int(ceil(m_fmax / ((m_fmax - m_fmin) / m_n))); cerr << "LowFreq::getFFTSize: for range " << m_fmin << " -> " << m_fmax << " and n = " << m_n << ", fft size is " << fftSize << endl; return fftSize; @@ -375,7 +381,7 @@ int LowFreq::getFirstOutputBin() const { - int first = int(floor(m_fmin / getFFTSize())); + int first = int(ceil(m_fmin / getFFTSize())); cerr << "LowFreq::getFirstOutputBin: for range " << m_fmin << " -> " << m_fmax << " and n = " << m_n << ", bin is " << first << endl; return first; @@ -396,6 +402,8 @@ data[i] = inputBuffers[0][i]; } + cout << "timestamp: " << timestamp << endl; + vector<double> resampled = m_resampler->process(data, m_blockSize); m_buffer.insert(m_buffer.end(), resampled.begin(), resampled.end()); @@ -417,7 +425,7 @@ { FeatureSet fs; - while (!m_buffer.empty() && int(m_buffer.size()) < m_n) { + while (!m_buffer.empty() && int(m_buffer.size()) < getFFTSize()) { m_buffer.push_back(0.0); } @@ -443,13 +451,23 @@ double *windowed = new double[sz]; m_window->cut(m_buffer.data(), windowed); + cout << "in: "; + for (int i = 0; i < sz; ++i) { + cout << windowed[i] << " "; + } + cout << endl; + m_fft->process(false, windowed, 0, realOut, imagOut); - for (int i = 0; i <= m_n/2; ++i) { - int ix = getFirstOutputBin() + i; - f.values.push_back(realOut[ix] * realOut[ix] + - imagOut[ix] * imagOut[ix]); + cout << "out: "; + int base = getFirstOutputBin(); + for (int i = 0; i < m_n; ++i) { + int ix = base + i; + float mag = (realOut[ix] * realOut[ix] + imagOut[ix] * imagOut[ix]); + f.values.push_back(mag); + cout << mag << " "; } + cout << endl; return f; }