c@225
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@225
|
2
|
c@225
|
3 /*
|
c@225
|
4 QM DSP Library
|
c@225
|
5
|
c@225
|
6 Centre for Digital Music, Queen Mary, University of London.
|
c@225
|
7 This file copyright 2005-2006 Christian Landone.
|
c@225
|
8 All rights reserved.
|
c@225
|
9 */
|
c@225
|
10
|
c@225
|
11 #include <iostream>
|
c@225
|
12 #include <cmath>
|
c@241
|
13 #include "maths/MathUtilities.h"
|
c@225
|
14 #include "Chromagram.h"
|
c@225
|
15
|
c@225
|
16 //----------------------------------------------------------------------------
|
c@225
|
17
|
c@225
|
18 Chromagram::Chromagram( ChromaConfig Config )
|
c@225
|
19 {
|
c@225
|
20 initialise( Config );
|
c@225
|
21 }
|
c@225
|
22
|
c@225
|
23 int Chromagram::initialise( ChromaConfig Config )
|
c@225
|
24 {
|
c@225
|
25 m_FMin = Config.min; // min freq
|
c@225
|
26 m_FMax = Config.max; // max freq
|
c@225
|
27 m_BPO = Config.BPO; // bins per octave
|
c@225
|
28 isNormalised = Config.isNormalised; // true if frame normalisation is required
|
c@225
|
29
|
c@225
|
30 // No. of constant Q bins
|
c@225
|
31 m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
|
c@225
|
32
|
c@225
|
33 // Create array for chroma result
|
c@225
|
34 m_chromadata = new double[ m_BPO ];
|
c@225
|
35
|
c@225
|
36 // Initialise FFT object
|
c@225
|
37 m_FFT = new FFT;
|
c@225
|
38
|
c@225
|
39 // Create Config Structure for ConstantQ operator
|
c@225
|
40 CQConfig ConstantQConfig;
|
c@225
|
41
|
c@225
|
42 // Populate CQ config structure with parameters
|
c@225
|
43 // inherited from the Chroma config
|
c@225
|
44 ConstantQConfig.FS = Config.FS;
|
c@225
|
45 ConstantQConfig.min = m_FMin;
|
c@225
|
46 ConstantQConfig.max = m_FMax;
|
c@225
|
47 ConstantQConfig.BPO = m_BPO;
|
c@225
|
48 ConstantQConfig.CQThresh = Config.CQThresh;
|
c@225
|
49
|
c@225
|
50 // Initialise ConstantQ operator
|
c@225
|
51 m_ConstantQ = new ConstantQ( ConstantQConfig );
|
c@225
|
52
|
c@225
|
53 // Initialise working arrays
|
c@225
|
54 m_frameSize = m_ConstantQ->getfftlength();
|
c@225
|
55 m_hopSize = m_ConstantQ->gethop();
|
c@225
|
56
|
c@225
|
57 m_FFTRe = new double[ m_frameSize ];
|
c@225
|
58 m_FFTIm = new double[ m_frameSize ];
|
c@225
|
59 m_CQRe = new double[ m_uK ];
|
c@225
|
60 m_CQIm = new double[ m_uK ];
|
c@225
|
61
|
c@225
|
62 // Generate CQ Kernel
|
c@225
|
63 m_ConstantQ->sparsekernel();
|
c@225
|
64 return 1;
|
c@225
|
65 }
|
c@225
|
66
|
c@225
|
67 Chromagram::~Chromagram()
|
c@225
|
68 {
|
c@225
|
69 deInitialise();
|
c@225
|
70 }
|
c@225
|
71
|
c@225
|
72 int Chromagram::deInitialise()
|
c@225
|
73 {
|
c@225
|
74 delete [] m_chromadata;
|
c@225
|
75
|
c@225
|
76 delete m_FFT;
|
c@225
|
77
|
c@225
|
78 delete m_ConstantQ;
|
c@225
|
79
|
c@225
|
80 delete [] m_FFTRe;
|
c@225
|
81 delete [] m_FFTIm;
|
c@225
|
82 delete [] m_CQRe;
|
c@225
|
83 delete [] m_CQIm;
|
c@225
|
84 return 1;
|
c@225
|
85 }
|
c@225
|
86
|
c@225
|
87 //----------------------------------------------------------------------------------
|
c@225
|
88 // returns the absolute value of complex number xx + i*yy
|
c@225
|
89 double Chromagram::kabs(double xx, double yy)
|
c@225
|
90 {
|
c@225
|
91 double ab = sqrt(xx*xx + yy*yy);
|
c@225
|
92 return(ab);
|
c@225
|
93 }
|
c@225
|
94 //-----------------------------------------------------------------------------------
|
c@225
|
95
|
c@225
|
96
|
c@225
|
97 void Chromagram::unityNormalise(double *src)
|
c@225
|
98 {
|
c@225
|
99 double min, max;
|
c@225
|
100
|
c@225
|
101 double val = 0;
|
c@225
|
102
|
c@225
|
103 MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );
|
c@225
|
104
|
c@225
|
105 for( unsigned int i = 0; i < m_BPO; i++ )
|
c@225
|
106 {
|
c@225
|
107 val = src[ i ] / max;
|
c@225
|
108
|
c@225
|
109 src[ i ] = val;
|
c@225
|
110 }
|
c@225
|
111 }
|
c@225
|
112
|
c@225
|
113
|
c@225
|
114 double* Chromagram::process( double *data )
|
c@225
|
115 {
|
c@228
|
116 // FFT of current frame
|
c@228
|
117 m_FFT->process( m_frameSize, 0, data, NULL, m_FFTRe, m_FFTIm );
|
c@228
|
118
|
c@228
|
119 return process(m_FFTRe, m_FFTIm);
|
c@228
|
120 }
|
c@228
|
121
|
c@228
|
122 double* Chromagram::process( double *real, double *imag )
|
c@228
|
123 {
|
c@228
|
124 // initialise chromadata to 0
|
c@228
|
125 for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
|
c@225
|
126
|
c@225
|
127 double cmax = 0.0;
|
c@225
|
128 double cval = 0;
|
c@225
|
129
|
c@225
|
130 // Calculate ConstantQ frame
|
c@228
|
131 m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
|
c@225
|
132
|
c@225
|
133 // add each octave of cq data into Chromagram
|
c@225
|
134 const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
|
c@228
|
135 for (unsigned octave = 0; octave <= octaves; octave++)
|
c@225
|
136 {
|
c@225
|
137 unsigned firstBin = octave*m_BPO;
|
c@228
|
138 for (unsigned i = 0; i < m_BPO; i++)
|
c@225
|
139 {
|
c@225
|
140 m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
|
c@225
|
141 }
|
c@225
|
142 }
|
c@225
|
143
|
c@225
|
144 if( isNormalised )
|
c@225
|
145 unityNormalise( m_chromadata );
|
c@225
|
146
|
c@225
|
147 return m_chromadata;
|
c@225
|
148 }
|
c@225
|
149
|
c@225
|
150
|