annotate chromagramm/ChordDetect.cpp @ 2:fa2af670b5c5 tip

SoundFileLoader might have moved
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 06 Jan 2012 00:23:26 +0000
parents bcb0d40158f4
children
rev   line source
andrew@0 1 /*
andrew@0 2 * ChordDetect.cpp
andrew@0 3 * ChordDetect
andrew@0 4 *
andrew@0 5 * Created by Adam Stark on 28/04/2008.
andrew@0 6 * Copyright 2008 __MyCompanyName__. All rights reserved.
andrew@0 7 *
andrew@0 8 */
andrew@0 9
andrew@0 10 #include "ChordDetect.h"
andrew@0 11 #include <iostream>
andrew@0 12 #include <math.h>
andrew@0 13 using namespace std;
andrew@0 14
andrew@0 15 ChordDetect :: ChordDetect()
andrew@0 16 {
andrew@0 17
andrew@0 18 bias = 1.06;
andrew@0 19
andrew@0 20 makeprofiles();
andrew@0 21
andrew@0 22 }
andrew@0 23
andrew@0 24 //--------------------------------------------------------------------------------------
andrew@0 25 // destructor
andrew@0 26 ChordDetect :: ~ChordDetect()
andrew@0 27 {
andrew@0 28
andrew@0 29 }
andrew@0 30
andrew@0 31
andrew@0 32 //--------------------------------------------------------------------------------------
andrew@0 33 // main function to be called with 8192 sample frame at 11025 Hz
andrew@0 34 void ChordDetect :: C_Detect(float c[],float c_low[])
andrew@0 35 {
andrew@0 36 for (int i = 0;i < 12;i++)
andrew@0 37 {
andrew@0 38 chroma[i] = c[i];
andrew@0 39 chroma_low[i] = c_low[i];
andrew@0 40 }
andrew@0 41
andrew@0 42 calculateweightings();
andrew@0 43
andrew@0 44 classifychromagram();
andrew@0 45
andrew@0 46 //cout << root << " " << quality << " " << intervals << endl;
andrew@0 47 }
andrew@0 48
andrew@0 49 //--------------------------------------------------------------------------------------
andrew@0 50 // analyse the chromagram and assign it a root note, chord type and any features
andrew@0 51 void ChordDetect :: classifychromagram()
andrew@0 52 {
andrew@0 53 int i;
andrew@0 54 int j;
andrew@0 55 int fifth;
andrew@0 56 int chordindex;
andrew@0 57
andrew@0 58 // remove some of the 5th note energy from chromagram
andrew@0 59 for (i = 0;i < 12;i++)
andrew@0 60 {
andrew@0 61 fifth = (i+7) % 12;
andrew@0 62 chroma[fifth] = chroma[fifth] - (0.1*chroma[i]);
andrew@0 63
andrew@0 64 if (chroma[fifth] < 0)
andrew@0 65 {
andrew@0 66 chroma[fifth] = 0;
andrew@0 67 }
andrew@0 68
andrew@0 69 }
andrew@0 70
andrew@0 71
andrew@0 72 // major chords
andrew@0 73 for (j=0;j < 12;j++)
andrew@0 74 {
andrew@0 75 chord[j] = calcchordvalue(chroma,profiles[j],bias,3);
andrew@0 76 }
andrew@0 77
andrew@0 78 // minor chords
andrew@0 79 for (j=12;j < 24;j++)
andrew@0 80 {
andrew@0 81 chord[j] = calcchordvalue(chroma,profiles[j],bias,3);
andrew@0 82 }
andrew@0 83
andrew@0 84 // diminished 5th chords
andrew@0 85 for (j=24;j < 36;j++)
andrew@0 86 {
andrew@0 87 chord[j] = calcchordvalue(chroma,profiles[j],bias,3);
andrew@0 88 }
andrew@0 89
andrew@0 90 // augmented 5th chords
andrew@0 91 for (j=36;j < 48;j++)
andrew@0 92 {
andrew@0 93 chord[j] = calcchordvalue(chroma,profiles[j],bias,3);
andrew@0 94
andrew@0 95 chord[j] = chord[j] / weight_aug[j-36];
andrew@0 96 }
andrew@0 97
andrew@0 98 // sus2 chords
andrew@0 99 for (j=48;j < 60;j++)
andrew@0 100 {
andrew@0 101 chord[j] = calcchordvalue(chroma,profiles[j],1,3);
andrew@0 102
andrew@0 103 chord[j] = chord[j] / weight_sus[j-48];
andrew@0 104 }
andrew@0 105
andrew@0 106 // sus4 chords
andrew@0 107 for (j=60;j < 72;j++)
andrew@0 108 {
andrew@0 109 chord[j] = calcchordvalue(chroma,profiles[j],1,3);
andrew@0 110
andrew@0 111 chord[j] = chord[j] / weight_sus[j-60];
andrew@0 112 }
andrew@0 113
andrew@0 114 // major 7th chords
andrew@0 115 for (j=72;j < 84;j++)
andrew@0 116 {
andrew@0 117 chord[j] = calcchordvalue(chroma,profiles[j],1,4);
andrew@0 118 }
andrew@0 119
andrew@0 120 // minor 7th chords
andrew@0 121 for (j=84;j < 96;j++)
andrew@0 122 {
andrew@0 123 chord[j] = calcchordvalue(chroma,profiles[j],bias,4);
andrew@0 124 }
andrew@0 125
andrew@0 126 // dominant 7th chords
andrew@0 127 for (j=96;j < 108;j++)
andrew@0 128 {
andrew@0 129 chord[j] = calcchordvalue(chroma,profiles[j],bias,4);
andrew@0 130 }
andrew@0 131
andrew@0 132 chordindex = minindex(chord,108);
andrew@0 133
andrew@0 134 // major
andrew@0 135 if (chordindex < 12)
andrew@0 136 {
andrew@0 137 root = chordindex;
andrew@0 138 quality = 1;
andrew@0 139 intervals = 0;
andrew@0 140 }
andrew@0 141
andrew@0 142 // minor
andrew@0 143 if ((chordindex >= 12) && (chordindex < 24))
andrew@0 144 {
andrew@0 145 root = chordindex-12;
andrew@0 146 quality = 0;
andrew@0 147 intervals = 0;
andrew@0 148 }
andrew@0 149
andrew@0 150 // diminished 5th
andrew@0 151 if ((chordindex >= 24) && (chordindex < 36))
andrew@0 152 {
andrew@0 153 root = chordindex-24;
andrew@0 154 quality = 4;
andrew@0 155 intervals = 0;
andrew@0 156 }
andrew@0 157
andrew@0 158 // augmented 5th
andrew@0 159 if ((chordindex >= 36) && (chordindex < 48))
andrew@0 160 {
andrew@0 161 root = chordindex-36;
andrew@0 162 quality = 6;
andrew@0 163 intervals = 0;
andrew@0 164 }
andrew@0 165
andrew@0 166 // sus2
andrew@0 167 if ((chordindex >= 48) && (chordindex < 60))
andrew@0 168 {
andrew@0 169 root = chordindex-48;
andrew@0 170 quality = 2;
andrew@0 171 intervals = 2;
andrew@0 172 }
andrew@0 173
andrew@0 174 // sus4
andrew@0 175 if ((chordindex >= 60) && (chordindex < 72))
andrew@0 176 {
andrew@0 177 root = chordindex-60;
andrew@0 178 quality = 2;
andrew@0 179 intervals = 4;
andrew@0 180 }
andrew@0 181
andrew@0 182 // major 7th
andrew@0 183 if ((chordindex >= 72) && (chordindex < 84))
andrew@0 184 {
andrew@0 185 root = chordindex-72;
andrew@0 186 quality = 1;
andrew@0 187 intervals = 7;
andrew@0 188 }
andrew@0 189
andrew@0 190 // minor 7th
andrew@0 191 if ((chordindex >= 84) && (chordindex < 96))
andrew@0 192 {
andrew@0 193 root = chordindex-84;
andrew@0 194 quality = 0;
andrew@0 195 intervals = 7;
andrew@0 196 }
andrew@0 197
andrew@0 198 // dominant 7th
andrew@0 199 if ((chordindex >= 96) && (chordindex < 108))
andrew@0 200 {
andrew@0 201 root = chordindex-96;
andrew@0 202 quality = 2;
andrew@0 203 intervals = 7;
andrew@0 204 }
andrew@0 205 }
andrew@0 206
andrew@0 207 //--------------------------------------------------------------------------------------
andrew@0 208 // calculate weightings to help distinguish between sus2/sus4 and aug chords
andrew@0 209 void ChordDetect :: calculateweightings()
andrew@0 210 {
andrew@0 211 int i;
andrew@0 212 float maxval = 0;
andrew@0 213 int fifth;
andrew@0 214 int augfifth;
andrew@0 215
andrew@0 216 maxval = max(chroma_low,12);
andrew@0 217
andrew@0 218 // normalise chroma low
andrew@0 219 for (i = 0;i < 12;i++)
andrew@0 220 {
andrew@0 221 chroma_low[i] = chroma_low[i] / maxval;
andrew@0 222 }
andrew@0 223
andrew@0 224 // make weight for sus chords
andrew@0 225 for (i = 0;i < 12;i++)
andrew@0 226 {
andrew@0 227 fifth = i+7;
andrew@0 228 augfifth = i+8;
andrew@0 229
andrew@0 230 if (fifth >= 12)
andrew@0 231 {
andrew@0 232 fifth = fifth-12;
andrew@0 233 }
andrew@0 234
andrew@0 235 if (augfifth >= 12)
andrew@0 236 {
andrew@0 237 augfifth = augfifth-12;
andrew@0 238 }
andrew@0 239
andrew@0 240 weight_sus[i] = chroma_low[i] + (chroma_low[fifth]/2);
andrew@0 241 weight_aug[i] = chroma_low[i] + (chroma_low[augfifth]/2);
andrew@0 242 }
andrew@0 243
andrew@0 244 maxval = max(weight_sus,12);
andrew@0 245 // normalise weight_sus
andrew@0 246 for (i = 0;i < 12;i++)
andrew@0 247 {
andrew@0 248 weight_sus[i] = weight_sus[i] / maxval;
andrew@0 249 }
andrew@0 250
andrew@0 251 maxval = max(weight_aug,12);
andrew@0 252 // normalise weight_aug
andrew@0 253 for (i = 0;i < 12;i++)
andrew@0 254 {
andrew@0 255 weight_aug[i] = weight_aug[i] / maxval;
andrew@0 256 }
andrew@0 257
andrew@0 258
andrew@0 259 }
andrew@0 260
andrew@0 261
andrew@0 262 //--------------------------------------------------------------------------------------
andrew@0 263 // return delta value indicating how similar the chroma is to the chord template - lower value = more similar
andrew@0 264 float ChordDetect :: calcchordvalue(float c[],float T[],float biasval, float N)
andrew@0 265 {
andrew@0 266 float sum = 0;
andrew@0 267 float delta;
andrew@0 268
andrew@0 269 for (int i=0;i < 12;i++)
andrew@0 270 {
andrew@0 271 sum = sum + ((1-T[i])*(pow(c[i],2)));
andrew@0 272 }
andrew@0 273
andrew@0 274 delta = sqrt(sum) / ((12 - N)*biasval);
andrew@0 275
andrew@0 276 return delta;
andrew@0 277 }
andrew@0 278
andrew@0 279
andrew@0 280 //--------------------------------------------------------------------------------------
andrew@0 281 // returns max value of an array
andrew@0 282 float ChordDetect :: max(float array[],int length)
andrew@0 283 {
andrew@0 284 float max = 0;
andrew@0 285
andrew@0 286 for (int i=0;i < length;i++)
andrew@0 287 {
andrew@0 288 if (array[i] > max)
andrew@0 289 {
andrew@0 290 max = array[i];
andrew@0 291 }
andrew@0 292 }
andrew@0 293
andrew@0 294 return max;
andrew@0 295 }
andrew@0 296
andrew@0 297 //--------------------------------------------------------------------------------------
andrew@0 298 // returns index of minimum value of array
andrew@0 299 int ChordDetect :: minindex(float array[],int length)
andrew@0 300 {
andrew@0 301 float min = 10000;
andrew@0 302 int minindex = 0;
andrew@0 303 int i;
andrew@0 304
andrew@0 305 for (i = 0;i < length;i++)
andrew@0 306 {
andrew@0 307 if (array[i] < min)
andrew@0 308 {
andrew@0 309 min = array[i];
andrew@0 310 minindex = i;
andrew@0 311 }
andrew@0 312 }
andrew@0 313
andrew@0 314 return minindex;
andrew@0 315 }
andrew@0 316
andrew@0 317 //--------------------------------------------------------------------------------------
andrew@0 318 // calculates bit mask chord profiles
andrew@0 319 void ChordDetect :: makeprofiles()
andrew@0 320 {
andrew@0 321 int i;
andrew@0 322 int t;
andrew@0 323 int j = 0;
andrew@0 324 int root;
andrew@0 325 int third;
andrew@0 326 int fifth;
andrew@0 327 int seventh;
andrew@0 328
andrew@0 329 float v1 = 1;
andrew@0 330 float v2 = 1;
andrew@0 331 float v3 = 1;
andrew@0 332
andrew@0 333 // set profiles matrix to all zeros
andrew@0 334 for (j = 0;j < 108;j++)
andrew@0 335 {
andrew@0 336 for (t = 0;t < 12;t++)
andrew@0 337 {
andrew@0 338 profiles[j][t] = 0;
andrew@0 339 }
andrew@0 340 }
andrew@0 341
andrew@0 342 // reset j to zero to begin creating profiles
andrew@0 343 j = 0;
andrew@0 344
andrew@0 345 // major chords
andrew@0 346 for (i = 0;i < 12;i++)
andrew@0 347 {
andrew@0 348 root = i % 12;
andrew@0 349 third = (i+4) % 12;
andrew@0 350 fifth = (i+7) % 12;
andrew@0 351
andrew@0 352 profiles[j][root] = v1;
andrew@0 353 profiles[j][third] = v2;
andrew@0 354 profiles[j][fifth] = v3;
andrew@0 355
andrew@0 356 j++;
andrew@0 357 }
andrew@0 358
andrew@0 359 // minor chords
andrew@0 360 for (i = 0;i < 12;i++)
andrew@0 361 {
andrew@0 362 root = i % 12;
andrew@0 363 third = (i+3) % 12;
andrew@0 364 fifth = (i+7) % 12;
andrew@0 365
andrew@0 366 profiles[j][root] = v1;
andrew@0 367 profiles[j][third] = v2;
andrew@0 368 profiles[j][fifth] = v3;
andrew@0 369
andrew@0 370 j++;
andrew@0 371 }
andrew@0 372
andrew@0 373 // diminished chords
andrew@0 374 for (i = 0;i < 12;i++)
andrew@0 375 {
andrew@0 376 root = i % 12;
andrew@0 377 third = (i+3) % 12;
andrew@0 378 fifth = (i+6) % 12;
andrew@0 379
andrew@0 380 profiles[j][root] = v1;
andrew@0 381 profiles[j][third] = v2;
andrew@0 382 profiles[j][fifth] = v3;
andrew@0 383
andrew@0 384 j++;
andrew@0 385 }
andrew@0 386
andrew@0 387 // augmented chords
andrew@0 388 for (i = 0;i < 12;i++)
andrew@0 389 {
andrew@0 390 root = i % 12;
andrew@0 391 third = (i+4) % 12;
andrew@0 392 fifth = (i+8) % 12;
andrew@0 393
andrew@0 394 profiles[j][root] = v1;
andrew@0 395 profiles[j][third] = v2;
andrew@0 396 profiles[j][fifth] = v3;
andrew@0 397
andrew@0 398 j++;
andrew@0 399 }
andrew@0 400
andrew@0 401 // sus2 chords
andrew@0 402 for (i = 0;i < 12;i++)
andrew@0 403 {
andrew@0 404 root = i % 12;
andrew@0 405 third = (i+2) % 12;
andrew@0 406 fifth = (i+7) % 12;
andrew@0 407
andrew@0 408 profiles[j][root] = v1;
andrew@0 409 profiles[j][third] = v2;
andrew@0 410 profiles[j][fifth] = v3;
andrew@0 411
andrew@0 412 j++;
andrew@0 413 }
andrew@0 414
andrew@0 415 // sus4 chords
andrew@0 416 for (i = 0;i < 12;i++)
andrew@0 417 {
andrew@0 418 root = i % 12;
andrew@0 419 third = (i+5) % 12;
andrew@0 420 fifth = (i+7) % 12;
andrew@0 421
andrew@0 422 profiles[j][root] = v1;
andrew@0 423 profiles[j][third] = v2;
andrew@0 424 profiles[j][fifth] = v3;
andrew@0 425
andrew@0 426 j++;
andrew@0 427 }
andrew@0 428
andrew@0 429 // major 7th chords
andrew@0 430 for (i = 0;i < 12;i++)
andrew@0 431 {
andrew@0 432 root = i % 12;
andrew@0 433 third = (i+4) % 12;
andrew@0 434 fifth = (i+7) % 12;
andrew@0 435 seventh = (i+11) % 12;
andrew@0 436
andrew@0 437 profiles[j][root] = v1;
andrew@0 438 profiles[j][third] = v2;
andrew@0 439 profiles[j][fifth] = v3;
andrew@0 440 profiles[j][seventh] = v3;
andrew@0 441
andrew@0 442 j++;
andrew@0 443 }
andrew@0 444
andrew@0 445 // minor 7th chords
andrew@0 446 for (i = 0;i < 12;i++)
andrew@0 447 {
andrew@0 448 root = i % 12;
andrew@0 449 third = (i+3) % 12;
andrew@0 450 fifth = (i+7) % 12;
andrew@0 451 seventh = (i+10) % 12;
andrew@0 452
andrew@0 453 profiles[j][root] = v1;
andrew@0 454 profiles[j][third] = v2;
andrew@0 455 profiles[j][fifth] = v3;
andrew@0 456 profiles[j][seventh] = v3;
andrew@0 457
andrew@0 458 j++;
andrew@0 459 }
andrew@0 460
andrew@0 461 // dominant 7th chords
andrew@0 462 for (i = 0;i < 12;i++)
andrew@0 463 {
andrew@0 464 root = i % 12;
andrew@0 465 third = (i+4) % 12;
andrew@0 466 fifth = (i+7) % 12;
andrew@0 467 seventh = (i+10) % 12;
andrew@0 468
andrew@0 469 profiles[j][root] = v1;
andrew@0 470 profiles[j][third] = v2;
andrew@0 471 profiles[j][fifth] = v3;
andrew@0 472 profiles[j][seventh] = v3;
andrew@0 473
andrew@0 474 j++;
andrew@0 475 }
andrew@0 476 }