changeset 245:cdfd0948a852

* First cut at properly integrating the segmenter and making it work right
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 09 Jan 2008 16:50:04 +0000
parents f599563a4663
children 0105e9b916a9
files dsp/chromagram/ConstantQ.cpp dsp/chromagram/ConstantQ.h dsp/segmentation/ClusterMeltSegmenter.cpp dsp/segmentation/ClusterMeltSegmenter.h dsp/segmentation/SavedFeatureSegmenter.h dsp/segmentation/cluster_melt.h dsp/segmentation/cluster_segmenter.c dsp/segmentation/cluster_segmenter.h dsp/segmentation/segment.h hmm/hmm.h maths/pca/pca.h qm-dsp.pro
diffstat 12 files changed, 157 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/dsp/chromagram/ConstantQ.cpp	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/chromagram/ConstantQ.cpp	Wed Jan 09 16:50:04 2008 +0000
@@ -10,6 +10,8 @@
 #include "ConstantQ.h"
 #include "dsp/transforms/FFT.h"
 
+#include <iostream>
+
 //---------------------------------------------------------------------------
 // nextpow2 returns the smallest integer n such that 2^n >= x.
 static double nextpow2(double x) {
@@ -168,11 +170,15 @@
     m_dQ = 1/(pow(2,(1/(double)m_BPO))-1);	// Work out Q value for Filter bank
     m_uK = (unsigned int) ceil(m_BPO * log(m_FMax/m_FMin)/log(2.0));	// No. of constant Q bins
 
+    std::cerr << "ConstantQ::initialise: rate = " << m_FS << ", fmin = " << m_FMin << ", fmax = " << m_FMax << ", bpo = " << m_BPO << ", K = " << m_uK << ", Q = " << m_dQ << std::endl;
+
     // work out length of fft required for this constant Q Filter bank
     m_FFTLength = (int) pow(2, nextpow2(ceil( m_dQ*m_FS/m_FMin )));
 
     m_hop = m_FFTLength/8; // <------ hop size is window length divided by 32
 
+    std::cerr << "ConstantQ::initialise: -> fft length = " << m_FFTLength << ", hop = " << m_hop << std::endl;
+
     // allocate memory for cqdata
     m_CQdata = new double [2*m_uK];
 }
--- a/dsp/chromagram/ConstantQ.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/chromagram/ConstantQ.h	Wed Jan 09 16:50:04 2008 +0000
@@ -16,11 +16,11 @@
 #include "maths/MathUtilities.h"
 
 struct CQConfig{
-    unsigned int FS;
-    double min;
-    double max;
-    unsigned int BPO;
-    double CQThresh;
+    unsigned int FS;   // samplerate
+    double min;        // minimum frequency
+    double max;        // maximum frequency
+    unsigned int BPO;  // bins per octave
+    double CQThresh;   // threshold
 };
 
 class ConstantQ {
--- a/dsp/segmentation/ClusterMeltSegmenter.cpp	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/ClusterMeltSegmenter.cpp	Wed Jan 09 16:50:04 2008 +0000
@@ -11,15 +11,16 @@
 #include <cmath>
 
 #include "ClusterMeltSegmenter.h"
-#include "lib_constQ.h"
 #include "cluster_segmenter.h"
 #include "segment.h"
 
+#include "dsp/transforms/FFT.h"
+
 ClusterMeltSegmenter::ClusterMeltSegmenter(ClusterMeltSegmenterParams params) : window(NULL),
 constq(NULL),
 featureType(params.featureType),
+hopSize(params.hopSize),
 windowSize(params.windowSize),
-hopSize(params.hopSize),
 fmin(params.fmin),
 fmax(params.fmax),
 nbins(params.nbins),
@@ -36,47 +37,102 @@
 	samplerate = fs;
 	if (featureType != FEATURE_TYPE_UNKNOWN)
 	{
-		ncoeff = static_cast<int>(ceil(nbins * (log(fmax / static_cast<double>(fmin))) / log(2.0)));
-		constq = init_constQ(fmin, fmax, nbins, samplerate, ncoeff);	
+//!!!		ncoeff = static_cast<int>(ceil(nbins * (log(fmax / static_cast<double>(fmin))) / log(2.0)));
+		CQConfig config;
+		config.FS = samplerate;
+		config.min = fmin;
+		config.max = fmax;
+		config.BPO = nbins;
+		config.CQThresh = 0.0054;
+		constq = new ConstantQ(config);
+//!!!		constq = init_constQ(fmin, fmax, nbins, samplerate, ncoeff);	
+		ncoeff = constq->getK();
 	}
 }
 
 ClusterMeltSegmenter::~ClusterMeltSegmenter() 
 {
-	delete [] window;
-	if (constq)
-		close_constQ(constq);
+	delete window;
+	delete constq;
+//!!!	if (constq)
+//		close_constQ(constq);
+}
+
+int
+ClusterMeltSegmenter::getWindowsize()
+{
+	if (featureType != FEATURE_TYPE_UNKNOWN) {
+		std::cerr << "rate = " << samplerate << ", fft length = " << constq->getfftlength() << ", fmin = " << fmin << ", fmax = " << fmax << ", nbins = " << nbins << ", K = " << constq->getK() << ", Q = " << constq->getQ() << std::endl;
+		return constq->getfftlength();
+	} else {
+		return static_cast<int>(windowSize * samplerate);
+	}
+}
+
+int
+ClusterMeltSegmenter::getHopsize()
+{
+	return static_cast<int>(hopSize * samplerate);
 }
 
 void ClusterMeltSegmenter::extractFeatures(double* samples, int nsamples)
 {
 	// create a new window if needed
+/*!!!
 	if (!window || nsamples != windowLength)
 	{
 		if (window)
 			delete [] window;
-		window = hamming_p(nsamples);
+//		Window<double>(HammingWindow, nsamples).cut
+//!!!		window = hamming_p(nsamples);
 		windowLength = nsamples;
 	}	
-	
+*/
+	if (!window || window->getSize() != nsamples) {
+		delete window;
+		window = new Window<double>(HammingWindow, nsamples);
+	}
+
 	// copy the samples before windowing in case we need them for something else
 	double* frame = new double[nsamples];
-	for (int i = 0; i < nsamples; i++)
-		frame[i] = samples[i] * window[i];
+//	for (int i = 0; i < nsamples; i++)
+//		frame[i] = samples[i] * window[i];
+	window->cut(frame);
 	
+	std::cerr << "nsamples = " << nsamples << std::endl;
+
+	double *real = new double[nsamples];
+	double *imag = new double[nsamples];
+
+	FFT::process(nsamples, false, frame, 0, real, imag);
+
+	double *cqre = new double[ncoeff];
+	double *cqim = new double[ncoeff];
+
+	constq->process(real, imag, cqre, cqim);
+
 	// extract const-Q
-	do_constQ(constq, frame, nsamples);
-	int ncq = constq->ncoeff;
+//!!!	do_constQ(constq, frame, nsamples);
+//	int ncq = constq->ncoeff;
+
+	delete [] frame;
+	delete [] real;
+	delete [] imag;
 	
-	delete [] frame;
-	
-	if (ncq == ncoeff)		// else feature extraction failed
-	{
-		vector<double> cq(ncq);
-		for (int i = 0; i < ncq; i++)
-			cq[i] = constq->absconstQtransform[i];
+//!!!	if (ncq == ncoeff)		// else feature extraction failed
+//	{
+//		vector<double> cq(ncq);
+//		for (int i = 0; i < ncq; i++)
+//			cq[i] = constq->absconstQtransform[i];
+		vector<double> cq(ncoeff);
+		for (int i = 0; i < ncoeff; ++i) {
+			cq[i] = sqrt(cqre[i] * cqre[i] + cqim[i] * cqim[i]);
+		}
 		features.push_back(cq);
-	}
+//	}
+
+		delete[] cqre;
+		delete[] cqim;
 }
 
 void ClusterMeltSegmenter::segment(int m)
@@ -95,7 +151,8 @@
 {
 	if (constq)
 	{
-		close_constQ(constq);		// finished extracting features
+//!!!		close_constQ(constq);		// finished extracting features
+		delete constq;
 		constq = NULL;
 	}
 	
--- a/dsp/segmentation/ClusterMeltSegmenter.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/ClusterMeltSegmenter.h	Wed Jan 09 16:50:04 2008 +0000
@@ -11,8 +11,9 @@
 
 #include "segment.h"
 #include "Segmenter.h"
-#include "hmm.h"
-#include "lib_constQ.h"
+#include "hmm/hmm.h"
+#include "base/Window.h"
+#include "dsp/chromagram/ConstantQ.h"
 
 using std::vector;
 
@@ -40,8 +41,8 @@
 	ClusterMeltSegmenter(ClusterMeltSegmenterParams params);
 	virtual ~ClusterMeltSegmenter();
 	virtual void initialise(int samplerate);
-	virtual int getWindowsize() { return static_cast<int>(windowSize * samplerate); }
-	virtual int getHopsize() { return static_cast<int>(hopSize * samplerate); }
+	virtual int getWindowsize();
+	virtual int getHopsize();
 	virtual void extractFeatures(double* samples, int nsamples);
 	void setFeatures(const vector<vector<double> >& f);		// provide the features yourself
 	virtual void segment();		// segment into default number of segment-types
@@ -51,9 +52,9 @@
 	//void mpeg7ConstQ();
 	void makeSegmentation(int* q, int len);
 	
-	double* window;
-	int windowLength;			// in samples
-	constQ_t* constq;	
+	Window<double> *window;
+//	int windowLength;			// in samples
+	ConstantQ* constq;	
 	model_t* model;				// the HMM
 	//vector<int> stateSequence;
 	//vector<int> segmentTypeSequence;
--- a/dsp/segmentation/SavedFeatureSegmenter.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/SavedFeatureSegmenter.h	Wed Jan 09 16:50:04 2008 +0000
@@ -11,7 +11,7 @@
 
 #include "segment.h"
 #include "Segmenter.h"
-#include "hmm.h"
+#include "hmm/hmm.h"
 
 using std::vector;
 
@@ -58,4 +58,5 @@
 	int nclusters;
 	int histogramLength;
 	int neighbourhoodLimit;
-};
\ No newline at end of file
+};
+
--- a/dsp/segmentation/cluster_melt.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/cluster_melt.h	Wed Jan 09 16:50:04 2008 +0000
@@ -12,6 +12,10 @@
 #include <stdlib.h>
 #include <math.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void cluster_melt(double *h,		/* normalised histograms, as a vector in row major order */
 				  int m,			/* number of dimensions (i.e. histogram bins) */
 				  int n,			/* number of histograms */
@@ -22,4 +26,8 @@
 				  int *c			/* sequence of cluster assignments */
 );
 
-#endif
\ No newline at end of file
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/dsp/segmentation/cluster_segmenter.c	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/cluster_segmenter.c	Wed Jan 09 16:50:04 2008 +0000
@@ -36,6 +36,7 @@
 			sum += chroma[t][b];
 		for (b = 0; b < bins; b++)
 			chroma[t][b] /= sum;
+		*/
 		/* normalise to unit max - NO this made results much worse!
 		maxchroma = 0;
 		for (b = 0; b < bins; b++)
--- a/dsp/segmentation/cluster_segmenter.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/cluster_segmenter.h	Wed Jan 09 16:50:04 2008 +0000
@@ -17,8 +17,12 @@
 
 #include "segment.h"
 #include "cluster_melt.h"
-#include "hmm.h"
-#include "pca.h"
+#include "hmm/hmm.h"
+#include "maths/pca/pca.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* applies MPEG-7 normalisation to constant-Q features, storing normalised envelope (norm) in last feature dimension */
 void mpeg7_constq(double** features, int nframes, int ncoeff);
@@ -34,5 +38,8 @@
 void constq_segment(int* q, double** features, int frames_read, int bins, int ncoeff, int feature_type, 
 			 int nHMM_states, int histogram_length, int nclusters, int neighbour_limit);
 
+#ifdef __cplusplus
+}
+#endif
 
-#endif
\ No newline at end of file
+#endif
--- a/dsp/segmentation/segment.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/dsp/segmentation/segment.h	Wed Jan 09 16:50:04 2008 +0000
@@ -1,6 +1,10 @@
 #ifndef _SEGMENT_H
 #define _SEGMENT_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  *  segment.h
  *  soundbite
@@ -32,5 +36,9 @@
 	FEATURE_TYPE_CHROMA 
 } feature_types;
 
+#ifdef __cplusplus
+}
 #endif
 
+#endif
+
--- a/hmm/hmm.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/hmm/hmm.h	Wed Jan 09 16:50:04 2008 +0000
@@ -1,6 +1,10 @@
 #ifndef _HMM_H
 #define _HMM_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  *  hmm.h
  *  soundbite
@@ -35,5 +39,9 @@
 double loggauss(double* x, int L, double* mu, double** icov, double detcov, double* y, double* z);
 void hmm_print(model_t* model);
 
+#ifdef __cplusplus
+}
 #endif
 
+#endif
+
--- a/maths/pca/pca.h	Wed Jan 09 10:48:08 2008 +0000
+++ b/maths/pca/pca.h	Wed Jan 09 16:50:04 2008 +0000
@@ -1,6 +1,10 @@
 #ifndef _PCA_H
 #define _PCA_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  *  pca.h
  *  soundbite
@@ -12,6 +16,10 @@
 
 void pca_project(double** data, int n, int m, int ncomponents);
 
+#ifdef __cplusplus
+}
+#endif
+
 
 #endif
 
--- a/qm-dsp.pro	Wed Jan 09 10:48:08 2008 +0000
+++ b/qm-dsp.pro	Wed Jan 09 16:50:04 2008 +0000
@@ -1,5 +1,5 @@
 TEMPLATE = lib
-CONFIG += release warn_on staticlib
+CONFIG += warn_on staticlib release
 CONFIG -= qt
 OBJECTS_DIR = tmp_obj
 MOC_DIR = tmp_moc
@@ -28,6 +28,12 @@
            dsp/onsets/PeakPicking.h \
            dsp/phasevocoder/PhaseVocoder.h \
            dsp/rateconversion/Decimator.h \
+           dsp/segmentation/cluster_melt.h \
+           dsp/segmentation/ClusterMeltSegmenter.h \
+           dsp/segmentation/cluster_segmenter.h \
+           dsp/segmentation/SavedFeatureSegmenter.h \
+           dsp/segmentation/Segmenter.h \
+           dsp/segmentation/segment.h \
            dsp/signalconditioning/DFProcess.h \
            dsp/signalconditioning/Filter.h \
            dsp/signalconditioning/FiltFilt.h \
@@ -53,6 +59,11 @@
            dsp/onsets/PeakPicking.cpp \
            dsp/phasevocoder/PhaseVocoder.cpp \
            dsp/rateconversion/Decimator.cpp \
+           dsp/segmentation/cluster_melt.c \
+           dsp/segmentation/ClusterMeltSegmenter.cpp \
+           dsp/segmentation/cluster_segmenter.c \
+           dsp/segmentation/SavedFeatureSegmenter.cpp \
+           dsp/segmentation/Segmenter.cpp \
            dsp/signalconditioning/DFProcess.cpp \
            dsp/signalconditioning/Filter.cpp \
            dsp/signalconditioning/FiltFilt.cpp \