qm-dsp 1.8
GetKeyMode.cpp
Go to the documentation of this file.
1/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2/*
3 Copyright (c) 2005 Centre for Digital Music ( C4DM )
4 Queen Mary Univesrity of London
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version. See the file
10 COPYING included with this distribution for more information.
11*/
12// GetKeyMode.cpp: implementation of the CGetKeyMode class.
13//
15
16#include "GetKeyMode.h"
17#include "maths/MathUtilities.h"
18#include "base/Pitch.h"
19
20#include <iostream>
21
22#include <cstring>
23#include <cstdlib>
24
25// Chords profile
26static double MajProfile[36] =
27{ 0.0384, 0.0629, 0.0258, 0.0121, 0.0146, 0.0106, 0.0364, 0.0610, 0.0267,
28 0.0126, 0.0121, 0.0086, 0.0364, 0.0623, 0.0279, 0.0275, 0.0414, 0.0186,
29 0.0173, 0.0248, 0.0145, 0.0364, 0.0631, 0.0262, 0.0129, 0.0150, 0.0098,
30 0.0312, 0.0521, 0.0235, 0.0129, 0.0142, 0.0095, 0.0289, 0.0478, 0.0239};
31
32static double MinProfile[36] =
33{ 0.0375, 0.0682, 0.0299, 0.0119, 0.0138, 0.0093, 0.0296, 0.0543, 0.0257,
34 0.0292, 0.0519, 0.0246, 0.0159, 0.0234, 0.0135, 0.0291, 0.0544, 0.0248,
35 0.0137, 0.0176, 0.0104, 0.0352, 0.0670, 0.0302, 0.0222, 0.0349, 0.0164,
36 0.0174, 0.0297, 0.0166, 0.0222, 0.0401, 0.0202, 0.0175, 0.0270, 0.0146};
37//
38
39
41// Construction/Destruction
43
44GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,
45 double hpcpAverage, double medianAverage ) :
46 m_hpcpAverage( hpcpAverage ),
47 m_medianAverage( medianAverage ),
48 m_ChrPointer(0),
49 m_DecimatedBuffer(0),
50 m_ChromaBuffer(0),
51 m_MeanHPCP(0),
52 m_MajCorr(0),
53 m_MinCorr(0),
54 m_Keys(0),
55 m_MedianFilterBuffer(0),
56 m_SortedBuffer(0),
57 m_keyStrengths(0)
58{
60
61 // Chromagram configuration parameters
63 m_ChromaConfig.FS = lrint(sampleRate/(double)m_DecimationFactor);
65
66 // Set C (= MIDI #12) as our base :
67 // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc.
69 (48, 0, tuningFrequency);
71 (96, 0, tuningFrequency);
72
74 m_ChromaConfig.CQThresh = 0.0054;
75
76 // Chromagram inst.
78
79 // Get calculated parameters from chroma object
81 // override hopsize for this application
84
85// std::cerr << "chroma frame size = " << m_ChromaFrameSize << ", decimation factor = " << m_DecimationFactor << " therefore block size = " << getBlockSize() << std::endl;
86
87 // Chromagram average and estimated key median filter lengths
90
91 // Reset counters
92 m_bufferindex = 0;
95
96 // Spawn objectc/arrays
98
100 memset( m_ChromaBuffer, 0, sizeof(double) * m_BPO * m_ChromaBuffersize);
101
102 m_MeanHPCP = new double[m_BPO];
103
104 m_MajCorr = new double[m_BPO];
105 m_MinCorr = new double[m_BPO];
106 m_Keys = new double[2*m_BPO];
107
109 memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize);
110
111 m_SortedBuffer = new int[ m_MedianWinsize ];
112 memset( m_SortedBuffer, 0, sizeof(int)*m_MedianWinsize);
113
116
117 m_keyStrengths = new double[24];
118}
119
121{
122
123 delete m_Chroma;
124 delete m_Decimator;
125
126 delete [] m_DecimatedBuffer;
127 delete [] m_ChromaBuffer;
128 delete [] m_MeanHPCP;
129 delete [] m_MajCorr;
130 delete [] m_MinCorr;
131 delete [] m_Keys;
132 delete [] m_MedianFilterBuffer;
133 delete [] m_SortedBuffer;
134
135 delete[] m_keyStrengths;
136}
137
138double GetKeyMode::krumCorr(double *pData1, double *pData2, unsigned int length)
139{
140 double retVal= 0.0;
141
142 double num = 0;
143 double den = 0;
144 double mX = MathUtilities::mean( pData1, length );
145 double mY = MathUtilities::mean( pData2, length );
146
147 double sum1 = 0;
148 double sum2 = 0;
149
150 for( unsigned int i = 0; i <length; i++ )
151 {
152 num += ( pData1[i] - mX ) * ( pData2[i] - mY );
153
154 sum1 += ( (pData1[i]-mX) * (pData1[i]-mX) );
155 sum2 += ( (pData2[i]-mY) * (pData2[i]-mY) );
156 }
157
158 den = sqrt(sum1 * sum2);
159
160 if( den>0 )
161 retVal = num/den;
162 else
163 retVal = 0;
164
165
166 return retVal;
167}
168
169int GetKeyMode::process(double *PCMData)
170{
171 int key;
172
173 unsigned int j,k;
174
177
179
180
181 // Move bins such that the centre of the base note is in the
182 // middle of its three bins :
183 // Added 21.11.07 by Chris Sutton based on debugging with Katy
184 // Noland + comparison with Matlab equivalent.
186/*
187 std::cout << "raw chroma: ";
188 for (int ii = 0; ii < m_BPO; ++ii) {
189 if (ii % (m_BPO/12) == 0) std::cout << "\n";
190 std::cout << m_ChrPointer[ii] << " ";
191 }
192 std::cout << std::endl;
193*/
194 // populate hpcp values;
195 int cbidx;
196 for( j = 0; j < m_BPO; j++ )
197 {
198 cbidx = (m_bufferindex * m_BPO) + j;
199 m_ChromaBuffer[ cbidx ] = m_ChrPointer[j];
200 }
201
202 //keep track of input buffers;
203 if( m_bufferindex++ >= m_ChromaBuffersize - 1)
204 m_bufferindex = 0;
205
206 // track filling of chroma matrix
209
210 //calculate mean
211 for( k = 0; k < m_BPO; k++ )
212 {
213 double mnVal = 0.0;
214 for( j = 0; j < m_ChromaBufferFilling; j++ )
215 {
216 mnVal += m_ChromaBuffer[ k + (j*m_BPO) ];
217 }
218
219 m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling;
220 }
221
222
223 for( k = 0; k < m_BPO; k++ )
224 {
227
230 }
231
232 for( k = 0; k < m_BPO; k++ )
233 {
234 m_Keys[k] = m_MajCorr[k];
235 m_Keys[k+m_BPO] = m_MinCorr[k];
236 }
237
238 for (k = 0; k < 24; ++k) {
239 m_keyStrengths[k] = 0;
240 }
241
242 for( k = 0; k < m_BPO*2; k++ )
243 {
244 int idx = k / (m_BPO/12);
245 int rem = k % (m_BPO/12);
246 if (rem == 0 || m_Keys[k] > m_keyStrengths[idx]) {
247 m_keyStrengths[idx] = m_Keys[k];
248 }
249
250// m_keyStrengths[k/(m_BPO/12)] += m_Keys[k];
251 }
252
253/*
254 std::cout << "raw keys: ";
255 for (int ii = 0; ii < 2*m_BPO; ++ii) {
256 if (ii % (m_BPO/12) == 0) std::cout << "\n";
257 std::cout << m_Keys[ii] << " ";
258 }
259 std::cout << std::endl;
260
261 std::cout << "key strengths: ";
262 for (int ii = 0; ii < 24; ++ii) {
263 if (ii % 6 == 0) std::cout << "\n";
264 std::cout << m_keyStrengths[ii] << " ";
265 }
266 std::cout << std::endl;
267*/
268 double dummy;
269 // '1 +' because we number keys 1-24, not 0-23.
270 key = 1 + (int)ceil( (double)MathUtilities::getMax( m_Keys, 2* m_BPO, &dummy )/3 );
271
272// std::cout << "key pre-sorting: " << key << std::endl;
273
274
275 //Median filtering
276
277 // track Median buffer initial filling
280
281 //shift median buffer
282 for( k = 1; k < m_MedianWinsize; k++ )
283 {
285 }
286
287 //write new key value into median buffer
289
290
291 //Copy median into sorting buffer, reversed
292 unsigned int ijx = 0;
293 for( k = 0; k < m_MedianWinsize; k++ )
294 {
296 ijx++;
297 }
298
299 qsort(m_SortedBuffer, m_MedianBufferFilling, sizeof(unsigned int),
301/*
302 std::cout << "sorted: ";
303 for (int ii = 0; ii < m_MedianBufferFilling; ++ii) {
304 std::cout << m_SortedBuffer[ii] << " ";
305 }
306 std::cout << std::endl;
307*/
308 int sortlength = m_MedianBufferFilling;
309 int midpoint = (int)ceil((double)sortlength/2);
310
311// std::cout << "midpoint = " << midpoint << endl;
312
313 if( midpoint <= 0 )
314 midpoint = 1;
315
316 key = m_SortedBuffer[midpoint-1];
317
318// std::cout << "returning key = " << key << endl;
319
320 return key;
321}
322
323
325{
326 return (key > 12);
327}
static double MajProfile[36]
static double MinProfile[36]
unsigned int getFrameSize()
Definition Chromagram.h:48
double * process(const double *data)
Decimator carries out a fast downsample by a power-of-two factor.
Definition Decimator.h:25
void process(const double *src, double *dst)
Process inLength samples (as supplied to constructor) from src and write inLength / decFactor samples...
double m_medianAverage
Definition GetKeyMode.h:47
double * m_MeanHPCP
Definition GetKeyMode.h:80
double * m_ChrPointer
Definition GetKeyMode.h:60
ChromaConfig m_ChromaConfig
Definition GetKeyMode.h:54
double * m_keyStrengths
Definition GetKeyMode.h:88
Decimator * m_Decimator
Definition GetKeyMode.h:51
unsigned int m_MedianBufferFilling
Definition GetKeyMode.h:75
unsigned int m_DecimationFactor
Definition GetKeyMode.h:48
double m_hpcpAverage
Definition GetKeyMode.h:46
double * m_MinCorr
Definition GetKeyMode.h:83
Chromagram * m_Chroma
Definition GetKeyMode.h:57
unsigned int m_ChromaBufferFilling
Definition GetKeyMode.h:74
double * m_ChromaBuffer
Definition GetKeyMode.h:79
GetKeyMode(int sampleRate, float tuningFrequency, double hpcpAverage, double medianAverage)
double * m_Keys
Definition GetKeyMode.h:84
unsigned int m_MedianWinsize
Definition GetKeyMode.h:71
int process(double *PCMData)
double * m_DecimatedBuffer
Definition GetKeyMode.h:78
unsigned int m_ChromaBuffersize
Definition GetKeyMode.h:70
double krumCorr(double *pData1, double *pData2, unsigned int length)
unsigned int m_ChromaHopSize
Definition GetKeyMode.h:65
int * m_MedianFilterBuffer
Definition GetKeyMode.h:85
int * m_SortedBuffer
Definition GetKeyMode.h:86
virtual ~GetKeyMode()
unsigned int m_bufferindex
Definition GetKeyMode.h:73
double * m_MajCorr
Definition GetKeyMode.h:82
bool isModeMinor(int key)
unsigned int m_ChromaFrameSize
Definition GetKeyMode.h:63
unsigned int m_BPO
Definition GetKeyMode.h:67
static int compareInt(const void *a, const void *b)
static double mean(const double *src, unsigned int len)
Return the mean of the given array of the given length.
static int getMax(double *data, unsigned int length, double *max=0)
static void circShift(double *data, int length, int shift)
static float getFrequencyForPitch(int midiPitch, float centsOffset=0, float concertA=440.0)
Definition Pitch.cpp:20
double CQThresh
Definition Chromagram.h:28
unsigned int FS
Definition Chromagram.h:24
MathUtilities::NormaliseType normalise
Definition Chromagram.h:29
unsigned int BPO
Definition Chromagram.h:27