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;
 }