changeset 23:4f2f28d5df58

Fix frequency calculation in cpp, and some diagnostics
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 01 Nov 2013 17:58:39 +0000
parents 701900c371b0
children 3973be829352
files cpp-qm-dsp/CQKernel.cpp cpp-qm-dsp/test.cpp yeti/cqtkernel.yeti
diffstat 3 files changed, 67 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/cpp-qm-dsp/CQKernel.cpp	Fri Nov 01 16:13:22 2013 +0000
+++ b/cpp-qm-dsp/CQKernel.cpp	Fri Nov 01 17:58:39 2013 +0000
@@ -8,8 +8,11 @@
 #include <cmath>
 #include <cassert>
 #include <vector>
+#include <iostream>
 
 using std::vector;
+using std::cerr;
+using std::endl;
 
 CQKernel::CQKernel(double sampleRate, double maxFreq, int binsPerOctave)
 {
@@ -70,18 +73,18 @@
 	for (int i = 0; i < (int)win.size(); ++i) {
 	    win[i] = sqrt(win[i]) / nk;
 	}
-	
-	double fk = m_p.minFrequency * pow(2, ((k-1.0) * bpo));
+
+	double fk = m_p.minFrequency * pow(2, ((k-1.0) / bpo));
 
 	vector<double> reals, imags;
 	
 	for (int i = 0; i < nk; ++i) {
-	    double arg = 2.0 * M_PI * fk * i / m_p.sampleRate;
-	    reals[i] = win[i] * cos(arg);
-	    imags[i] = win[i] * sin(arg);
+	    double arg = (2.0 * M_PI * fk * i) / m_p.sampleRate;
+	    reals.push_back(win[i] * cos(arg));
+	    imags.push_back(win[i] * sin(arg));
 	}
 
-	int atomOffset = m_p.firstCentre - ceil(nk/2);
+	int atomOffset = m_p.firstCentre - int(ceil(nk/2.0));
 
 	for (int i = 0; i < m_p.atomsPerFrame; ++i) {
 
@@ -92,12 +95,12 @@
 
 	    for (int j = 0; j < nk; ++j) {
 		rin[j + shift] = reals[j];
-		iin[i + shift] = imags[j];
+		iin[j + shift] = imags[j];
 	    }
 
 	    vector<double> rout(m_p.fftSize, 0.0);
 	    vector<double> iout(m_p.fftSize, 0.0);
-		
+
 	    m_fft->process(false,
 			   rin.data(), iin.data(),
 			   rout.data(), iout.data());
@@ -105,9 +108,11 @@
 	    int firstNZ = -1, lastNZ = -1;
 
 	    for (int j = 0; j < m_p.fftSize; ++j) {
-		if (sqrt(rout[i] * rout[i] + iout[i] * iout[i]) >= thresh) {
+		if (sqrt(rout[j] * rout[j] + iout[j] * iout[j]) >= thresh) {
 		    lastNZ = j;
 		    if (firstNZ < 0) firstNZ = j;
+		} else {
+		    rout[j] = iout[j] = 0;
 		}
 	    }
 
@@ -128,11 +133,52 @@
 	}
     }
 
-    assert((int)m_kernel.offsets.size() == m_p.binsPerOctave);
-    assert((int)m_kernel.real.size() == m_p.binsPerOctave);
-    assert((int)m_kernel.imag.size() == m_p.binsPerOctave);
+    assert((int)m_kernel.offsets.size() == m_p.binsPerOctave * m_p.atomsPerFrame);
+    assert((int)m_kernel.real.size() == m_p.binsPerOctave * m_p.atomsPerFrame);
+    assert((int)m_kernel.imag.size() == m_p.binsPerOctave * m_p.atomsPerFrame);
+
+    // print density as diagnostic
+
+    int nnz = 0;
+    for (int i = 0; i < m_kernel.offsets.size(); ++i) {
+	assert(m_kernel.real[i].size() == m_kernel.imag[i].size());
+	for (int j = 0; j < m_kernel.real[i].size(); ++j) {
+	    if (m_kernel.real[i][j] != 0.0 ||
+		m_kernel.imag[i][j] != 0.0) {
+		++nnz;
+	    }
+	}
+    }
+
+    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;
 
     //!!! and normalise
+
+/* far too laborious
+
+    int wx1 = -1, wx2 = -1;
+    double wm1 = 0, wm2 = 0;
+
+    for (int i = 0; i < m_kernel.real[0].size(); ++i) {
+	m = m_kernel.real[0][i] * m_kernel.real[0][i] +
+	    m_kernel.imag[0][i] * m_kernel.imag[0][i];
+	if (wx1 == -1 || m > wm1) {
+	    wx1 = i + m_kernel.offsets[0];
+	    wm1 = m;
+	}
+    }
+    
+    int n = m_kernel.offsets.size() - 1;
+    for (int i = 0; i < m_kernel.real[n].size(); ++i) {
+	m = m_kernel.real[n][i] * m_kernel.real[n][i] +
+	    m_kernel.imag[n][i] * m_kernel.imag[n][i];
+	if (wx2 == -1 || m > wm1) {
+	    wx2 = i + m_kernel.offsets[n];
+	    wm2 = m;
+	}
+    }
+
+*/    
 }
 
 
--- a/cpp-qm-dsp/test.cpp	Fri Nov 01 16:13:22 2013 +0000
+++ b/cpp-qm-dsp/test.cpp	Fri Nov 01 17:58:39 2013 +0000
@@ -5,7 +5,7 @@
 
 int main(int argc, char **argv)
 {
-    CQKernel k(96000, 48000, 24);
+    CQKernel k(48000, 24000, 24);
 
     std::cerr << "Q = " << k.getProperties().Q << std::endl;
 
--- a/yeti/cqtkernel.yeti	Fri Nov 01 16:13:22 2013 +0000
+++ b/yeti/cqtkernel.yeti	Fri Nov 01 17:58:39 2013 +0000
@@ -47,16 +47,16 @@
     kernels = map do k:
     
         nk = round(bigQ * sampleRate / (minFreq * (pow 2 ((k-1)/binsPerOctave))));
-    
+
         // the cq MATLAB toolbox uses a symmetric window for
         // blackmanharris -- which is odd because it uses a periodic one
         // for other types. Oh well
         win = bf.divideBy nk
            (bf.sqrt
                (window.windowFunction (BlackmanHarris ()) [Symmetric true] nk));
-        
+
         fk = minFreq * (pow 2 ((k-1)/binsPerOctave));
-    
+
         genKernel f = bf.multiply win
            (vec.fromList
                (map do i: f (2 * pi * fk * i / sampleRate) done [0..nk-1]));
@@ -74,11 +74,11 @@
                (complex.complexArray
                    (vec.concat [shift, reals])
                    (vec.concat [shift, imags]));
-    
+
             map do c:
                 if complex.magnitude c <= thresh then complex.zero else c fi
                 done specKernel;
-    
+
         done [1..winNr];
     
     done [1..binsPerOctave];
@@ -87,7 +87,7 @@
        (cm.scaled (1/fftSize)
            (cm.newComplexMatrix (RowMajor()) (concat kernels)));
     
-    eprintln "density = \(cm.density kmat)";
+    eprintln "density = \(cm.density kmat) (\(cm.nonZeroValues kmat) of \(cm.width kmat * cm.height kmat))";
     
     // Normalisation
     
@@ -102,6 +102,8 @@
     weight = (fftHop / fftSize) / (bf.mean (bf.abs wK));
     weight = sqrt(weight);
 
+    eprintln "weight = \(weight)";
+    
     {
         kernel = cm.scaled weight kmat,
         fftSize,