andrew@0
|
1 /*
|
andrew@0
|
2 * ChromaOnset.cpp
|
andrew@0
|
3 * fileLoaderAndOnsetDetection
|
andrew@0
|
4 *
|
andrew@0
|
5 * Created by Andrew on 17/01/2012.
|
andrew@0
|
6 * Copyright 2012 QMUL. All rights reserved.
|
andrew@0
|
7 *
|
andrew@0
|
8 */
|
andrew@0
|
9
|
andrew@0
|
10 #include "ChromaOnset.h"
|
andrew@0
|
11
|
andrew@0
|
12 //stores the information about our onset event
|
andrew@0
|
13 //when it happened
|
andrew@0
|
14 //what the chromagram was immeditaely after
|
andrew@0
|
15 //what the pitch was using AubioPitch class
|
andrew@0
|
16
|
andrew@0
|
17 //FrameHolder holds the audio samples needed to do the harmonic analysis after the fact
|
andrew@0
|
18
|
andrew@0
|
19 ChromaOnset::ChromaOnset(){
|
andrew@0
|
20 frameTime = 0;
|
andrew@0
|
21 millisTime = 0;
|
andrew@0
|
22 chromaCalculated = false;
|
andrew@0
|
23 chromaSize = 2048;
|
andrew@0
|
24
|
andrew@0
|
25 cgramPtr = new Chromagram();
|
andrew@0
|
26 cgramPtr->initialise(512, chromaSize);
|
andrew@0
|
27
|
andrew@0
|
28 onsetIndex = 0;
|
andrew@0
|
29
|
andrew@0
|
30 matched = false;
|
andrew@0
|
31 //we also store an aubio pitch result - using a Frameholder to hold the frames we need to calculate this on
|
andrew@0
|
32 aubioPitch = 0;
|
andrew@0
|
33 aubioPitchFound = false;
|
andrew@0
|
34
|
andrew@0
|
35 pitchFrameCounter = 0;//counts til time to do pitch detection
|
andrew@0
|
36
|
andrew@0
|
37
|
andrew@0
|
38 // aubioPitchDetector = new AubioPitch();
|
andrew@0
|
39
|
andrew@0
|
40 }
|
andrew@0
|
41
|
andrew@0
|
42 void ChromaOnset::deleteChromagram(){
|
andrew@0
|
43 delete cgramPtr;
|
andrew@0
|
44 //printf("chromagram deleted\n");
|
andrew@0
|
45 }
|
andrew@0
|
46
|
andrew@0
|
47
|
andrew@0
|
48 bool ChromaOnset::processFrame(float* frame, const int& length){
|
andrew@0
|
49 bool newlyCalculated = false;
|
andrew@0
|
50 if (chromaCalculated == false){
|
andrew@0
|
51
|
andrew@0
|
52 cgramPtr->processframe(frame);
|
andrew@0
|
53
|
andrew@0
|
54 if (cgramPtr->chromaready){
|
andrew@0
|
55
|
andrew@0
|
56 float tmpMax = max(cgramPtr->maximumChromaValue, 1.0f);
|
andrew@0
|
57
|
andrew@0
|
58 for (int i = 0;i < 12;i++){
|
andrew@0
|
59 chromaValues.push_back(cgramPtr->rawChroma[i]/tmpMax);
|
andrew@0
|
60 quantisedChromaValues.push_back(cgramPtr->quantisedChromagram[i]);
|
andrew@0
|
61 // printf("chroma [%i] %f max %f quantised %i\n", i, cgramPtr->rawChroma[i], cgramPtr->chroma[i], cgramPtr->quantisedChromagram[i] );
|
andrew@0
|
62 }
|
andrew@0
|
63 chromaCalculated = true;
|
andrew@0
|
64 newlyCalculated = true;
|
andrew@0
|
65 //this would do chord detection
|
andrew@0
|
66 // chord.C_Detect(chromoGramm.chroma,chromoGramm.chroma_low);
|
andrew@0
|
67 // rootChord[chromaIndex] = chord.root;
|
andrew@0
|
68
|
andrew@0
|
69 }
|
andrew@0
|
70
|
andrew@0
|
71 }
|
andrew@0
|
72
|
andrew@0
|
73 return newlyCalculated;
|
andrew@0
|
74 }
|
andrew@0
|
75
|
andrew@0
|
76 double ChromaOnset::timeDistanceMillis(const ChromaOnset& secondChromaOnset){
|
andrew@0
|
77
|
andrew@0
|
78 return (abs(secondChromaOnset.millisTime - millisTime));
|
andrew@0
|
79 }
|
andrew@0
|
80
|
andrew@0
|
81 double ChromaOnset::pitchDistance(const ChromaOnset& secondChromaOnset){
|
andrew@0
|
82
|
andrew@0
|
83 return (abs(secondChromaOnset.aubioPitch - aubioPitch));
|
andrew@0
|
84 }
|
andrew@0
|
85
|
andrew@0
|
86 double ChromaOnset::getQuantisedDistance(ChromaOnset& secondChromaOnset){
|
andrew@0
|
87
|
andrew@0
|
88 return getChromaQuantisedDistance(&secondChromaOnset.quantisedChromaValues[0]);
|
andrew@0
|
89
|
andrew@0
|
90 }
|
andrew@0
|
91
|
andrew@0
|
92 double ChromaOnset::getChromaQuantisedDistance(float* quantisedChromagramTwo){
|
andrew@0
|
93
|
andrew@0
|
94 double cosineDistance = 0;
|
andrew@0
|
95 double quantLengthOne = 0;
|
andrew@0
|
96 double quantLengthTwo = 0;
|
andrew@0
|
97 for (int i = 0;i < 12;i++){
|
andrew@0
|
98
|
andrew@0
|
99 cosineDistance += quantisedChromaValues[i] * quantisedChromagramTwo[i];
|
andrew@0
|
100
|
andrew@0
|
101 quantLengthOne += quantisedChromaValues[i] * quantisedChromaValues[i];
|
andrew@0
|
102 quantLengthTwo += quantisedChromagramTwo[i] * quantisedChromagramTwo[i];
|
andrew@0
|
103
|
andrew@0
|
104 }
|
andrew@0
|
105
|
andrew@0
|
106 if (quantLengthOne > 0 && quantLengthTwo > 0)
|
andrew@0
|
107 cosineDistance /= sqrt(quantLengthOne * quantLengthTwo);
|
andrew@0
|
108 else
|
andrew@0
|
109 cosineDistance = 0;
|
andrew@0
|
110
|
andrew@0
|
111 return cosineDistance;
|
andrew@0
|
112
|
andrew@0
|
113
|
andrew@0
|
114 }
|
andrew@0
|
115
|
andrew@0
|
116 double ChromaOnset::chromaDotProductDistance(const ChromaOnset& secondChromaOnset){
|
andrew@0
|
117 double dotProductSum = 0;
|
andrew@0
|
118 double chromaOneSum = 0;
|
andrew@0
|
119 double chromaTwoSum = 0;
|
andrew@0
|
120 if (chromaValues.size() == 12 && secondChromaOnset.chromaValues.size() == 12){
|
andrew@0
|
121 for (int i = 0;i < 12;i++){
|
andrew@0
|
122 dotProductSum += chromaValues[i]*secondChromaOnset.chromaValues[i];
|
andrew@0
|
123 chromaOneSum += chromaValues[i]*chromaValues[i];
|
andrew@0
|
124 chromaTwoSum += secondChromaOnset.chromaValues[i]*secondChromaOnset.chromaValues[i];
|
andrew@0
|
125 }
|
andrew@0
|
126 chromaOneSum = sqrt(chromaOneSum);
|
andrew@0
|
127 chromaTwoSum = sqrt(chromaTwoSum);
|
andrew@0
|
128 if (chromaOneSum > 0 && chromaTwoSum > 0)
|
andrew@0
|
129 dotProductSum /= (chromaOneSum*chromaTwoSum);
|
andrew@0
|
130 else
|
andrew@0
|
131 dotProductSum = 0;
|
andrew@0
|
132 }
|
andrew@0
|
133 return (dotProductSum);
|
andrew@0
|
134 }
|
andrew@0
|
135
|
andrew@0
|
136 void ChromaOnset::printInfo(){
|
andrew@0
|
137
|
andrew@0
|
138 printf("ONSET : frametime %i, millis %f pitch %f\n", frameTime, millisTime, aubioPitch);
|
andrew@0
|
139 printf("chroma: ");
|
andrew@0
|
140
|
andrew@0
|
141 for(int i = 0;i < chromaValues.size();i++)
|
andrew@0
|
142 printf("[%i] %1.3f, ", i, chromaValues[i]);
|
andrew@0
|
143
|
andrew@0
|
144 printf(".\n");
|
andrew@0
|
145
|
andrew@0
|
146 } |