cannam@0
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@0
|
2
|
cannam@0
|
3 /*
|
cannam@0
|
4 QM DSP Library
|
cannam@0
|
5
|
cannam@0
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@84
|
7 This file 2005-2006 Christian Landone.
|
Chris@84
|
8
|
Chris@84
|
9 This program is free software; you can redistribute it and/or
|
Chris@84
|
10 modify it under the terms of the GNU General Public License as
|
Chris@84
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@84
|
12 License, or (at your option) any later version. See the file
|
Chris@84
|
13 COPYING included with this distribution for more information.
|
cannam@0
|
14 */
|
cannam@0
|
15
|
cannam@0
|
16 #include <iostream>
|
cannam@0
|
17 #include <cmath>
|
cannam@16
|
18 #include "maths/MathUtilities.h"
|
cannam@0
|
19 #include "Chromagram.h"
|
cannam@0
|
20
|
cannam@0
|
21 //----------------------------------------------------------------------------
|
cannam@0
|
22
|
cannam@51
|
23 Chromagram::Chromagram( ChromaConfig Config ) :
|
cannam@51
|
24 m_skGenerated(false)
|
cannam@0
|
25 {
|
cannam@0
|
26 initialise( Config );
|
cannam@0
|
27 }
|
cannam@0
|
28
|
cannam@0
|
29 int Chromagram::initialise( ChromaConfig Config )
|
cannam@0
|
30 {
|
cannam@0
|
31 m_FMin = Config.min; // min freq
|
cannam@0
|
32 m_FMax = Config.max; // max freq
|
cannam@0
|
33 m_BPO = Config.BPO; // bins per octave
|
cannam@34
|
34 m_normalise = Config.normalise; // if frame normalisation is required
|
cannam@0
|
35
|
cannam@0
|
36 // No. of constant Q bins
|
cannam@0
|
37 m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
|
cannam@0
|
38
|
cannam@0
|
39 // Create array for chroma result
|
cannam@0
|
40 m_chromadata = new double[ m_BPO ];
|
cannam@0
|
41
|
cannam@0
|
42 // Create Config Structure for ConstantQ operator
|
cannam@0
|
43 CQConfig ConstantQConfig;
|
cannam@0
|
44
|
cannam@0
|
45 // Populate CQ config structure with parameters
|
cannam@0
|
46 // inherited from the Chroma config
|
cannam@0
|
47 ConstantQConfig.FS = Config.FS;
|
cannam@0
|
48 ConstantQConfig.min = m_FMin;
|
cannam@0
|
49 ConstantQConfig.max = m_FMax;
|
cannam@0
|
50 ConstantQConfig.BPO = m_BPO;
|
cannam@0
|
51 ConstantQConfig.CQThresh = Config.CQThresh;
|
cannam@0
|
52
|
cannam@0
|
53 // Initialise ConstantQ operator
|
cannam@0
|
54 m_ConstantQ = new ConstantQ( ConstantQConfig );
|
cannam@0
|
55
|
cannam@0
|
56 // Initialise working arrays
|
cannam@0
|
57 m_frameSize = m_ConstantQ->getfftlength();
|
cannam@0
|
58 m_hopSize = m_ConstantQ->gethop();
|
cannam@0
|
59
|
cannam@64
|
60 // Initialise FFT object
|
cannam@64
|
61 m_FFT = new FFTReal(m_frameSize);
|
cannam@64
|
62
|
cannam@0
|
63 m_FFTRe = new double[ m_frameSize ];
|
cannam@0
|
64 m_FFTIm = new double[ m_frameSize ];
|
cannam@0
|
65 m_CQRe = new double[ m_uK ];
|
cannam@0
|
66 m_CQIm = new double[ m_uK ];
|
cannam@0
|
67
|
cannam@32
|
68 m_window = 0;
|
cannam@32
|
69 m_windowbuf = 0;
|
cannam@32
|
70
|
cannam@0
|
71 return 1;
|
cannam@0
|
72 }
|
cannam@0
|
73
|
cannam@0
|
74 Chromagram::~Chromagram()
|
cannam@0
|
75 {
|
cannam@0
|
76 deInitialise();
|
cannam@0
|
77 }
|
cannam@0
|
78
|
cannam@0
|
79 int Chromagram::deInitialise()
|
cannam@0
|
80 {
|
cannam@32
|
81 delete[] m_windowbuf;
|
cannam@32
|
82 delete m_window;
|
cannam@32
|
83
|
cannam@0
|
84 delete [] m_chromadata;
|
cannam@0
|
85
|
cannam@0
|
86 delete m_FFT;
|
cannam@0
|
87
|
cannam@0
|
88 delete m_ConstantQ;
|
cannam@0
|
89
|
cannam@0
|
90 delete [] m_FFTRe;
|
cannam@0
|
91 delete [] m_FFTIm;
|
cannam@0
|
92 delete [] m_CQRe;
|
cannam@0
|
93 delete [] m_CQIm;
|
cannam@0
|
94 return 1;
|
cannam@0
|
95 }
|
cannam@0
|
96
|
cannam@0
|
97 //----------------------------------------------------------------------------------
|
cannam@0
|
98 // returns the absolute value of complex number xx + i*yy
|
cannam@0
|
99 double Chromagram::kabs(double xx, double yy)
|
cannam@0
|
100 {
|
cannam@0
|
101 double ab = sqrt(xx*xx + yy*yy);
|
cannam@0
|
102 return(ab);
|
cannam@0
|
103 }
|
cannam@0
|
104 //-----------------------------------------------------------------------------------
|
cannam@0
|
105
|
cannam@0
|
106
|
cannam@0
|
107 void Chromagram::unityNormalise(double *src)
|
cannam@0
|
108 {
|
cannam@0
|
109 double min, max;
|
cannam@0
|
110
|
cannam@0
|
111 double val = 0;
|
cannam@0
|
112
|
cannam@0
|
113 MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
|
cannam@0
|
114
|
cannam@0
|
115 for( unsigned int i = 0; i < m_BPO; i++ )
|
cannam@0
|
116 {
|
cannam@0
|
117 val = src[ i ] / max;
|
cannam@0
|
118
|
cannam@0
|
119 src[ i ] = val;
|
cannam@0
|
120 }
|
cannam@0
|
121 }
|
cannam@0
|
122
|
cannam@0
|
123
|
cannam@32
|
124 double* Chromagram::process( const double *data )
|
cannam@0
|
125 {
|
cannam@51
|
126 if (!m_skGenerated) {
|
cannam@51
|
127 // Generate CQ Kernel
|
cannam@51
|
128 m_ConstantQ->sparsekernel();
|
cannam@51
|
129 m_skGenerated = true;
|
cannam@51
|
130 }
|
cannam@51
|
131
|
cannam@32
|
132 if (!m_window) {
|
cannam@32
|
133 m_window = new Window<double>(HammingWindow, m_frameSize);
|
cannam@32
|
134 m_windowbuf = new double[m_frameSize];
|
cannam@32
|
135 }
|
cannam@32
|
136
|
cannam@32
|
137 for (int i = 0; i < m_frameSize; ++i) {
|
cannam@32
|
138 m_windowbuf[i] = data[i];
|
cannam@32
|
139 }
|
cannam@32
|
140 m_window->cut(m_windowbuf);
|
cannam@32
|
141
|
Chris@114
|
142 m_FFT->forward(m_windowbuf, m_FFTRe, m_FFTIm);
|
cannam@3
|
143
|
cannam@3
|
144 return process(m_FFTRe, m_FFTIm);
|
cannam@3
|
145 }
|
cannam@3
|
146
|
cannam@32
|
147 double* Chromagram::process( const double *real, const double *imag )
|
cannam@3
|
148 {
|
cannam@51
|
149 if (!m_skGenerated) {
|
cannam@51
|
150 // Generate CQ Kernel
|
cannam@51
|
151 m_ConstantQ->sparsekernel();
|
cannam@51
|
152 m_skGenerated = true;
|
cannam@51
|
153 }
|
cannam@51
|
154
|
cannam@3
|
155 // initialise chromadata to 0
|
cannam@3
|
156 for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
|
cannam@0
|
157
|
cannam@0
|
158 double cmax = 0.0;
|
cannam@0
|
159 double cval = 0;
|
cannam@0
|
160 // Calculate ConstantQ frame
|
cannam@3
|
161 m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
|
cannam@0
|
162
|
cannam@0
|
163 // add each octave of cq data into Chromagram
|
cannam@0
|
164 const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
|
cannam@3
|
165 for (unsigned octave = 0; octave <= octaves; octave++)
|
cannam@0
|
166 {
|
cannam@0
|
167 unsigned firstBin = octave*m_BPO;
|
cannam@3
|
168 for (unsigned i = 0; i < m_BPO; i++)
|
cannam@0
|
169 {
|
cannam@0
|
170 m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
|
cannam@0
|
171 }
|
cannam@0
|
172 }
|
cannam@0
|
173
|
cannam@34
|
174 MathUtilities::normalise(m_chromadata, m_BPO, m_normalise);
|
cannam@0
|
175
|
cannam@0
|
176 return m_chromadata;
|
cannam@0
|
177 }
|
cannam@0
|
178
|
cannam@0
|
179
|