andrew@0: /* andrew@0: * ChromaOnset.cpp andrew@0: * fileLoaderAndOnsetDetection andrew@0: * andrew@0: * Created by Andrew on 17/01/2012. andrew@0: * Copyright 2012 QMUL. All rights reserved. andrew@0: * andrew@0: */ andrew@0: andrew@0: #include "ChromaOnset.h" andrew@0: andrew@0: //stores the information about our onset event andrew@0: //when it happened andrew@0: //what the chromagram was immeditaely after andrew@0: //what the pitch was using AubioPitch class andrew@0: andrew@0: //FrameHolder holds the audio samples needed to do the harmonic analysis after the fact andrew@0: andrew@0: ChromaOnset::ChromaOnset(){ andrew@0: frameTime = 0; andrew@0: millisTime = 0; andrew@0: chromaCalculated = false; andrew@0: chromaSize = 2048; andrew@0: andrew@0: cgramPtr = new Chromagram(); andrew@0: cgramPtr->initialise(512, chromaSize); andrew@0: andrew@0: onsetIndex = 0; andrew@0: andrew@0: matched = false; andrew@0: //we also store an aubio pitch result - using a Frameholder to hold the frames we need to calculate this on andrew@0: aubioPitch = 0; andrew@0: aubioPitchFound = false; andrew@0: andrew@0: pitchFrameCounter = 0;//counts til time to do pitch detection andrew@0: andrew@0: andrew@0: // aubioPitchDetector = new AubioPitch(); andrew@0: andrew@0: } andrew@0: andrew@0: void ChromaOnset::deleteChromagram(){ andrew@0: delete cgramPtr; andrew@0: //printf("chromagram deleted\n"); andrew@0: } andrew@0: andrew@0: andrew@0: bool ChromaOnset::processFrame(float* frame, const int& length){ andrew@0: bool newlyCalculated = false; andrew@0: if (chromaCalculated == false){ andrew@0: andrew@0: cgramPtr->processframe(frame); andrew@0: andrew@0: if (cgramPtr->chromaready){ andrew@0: andrew@0: float tmpMax = max(cgramPtr->maximumChromaValue, 1.0f); andrew@0: andrew@0: for (int i = 0;i < 12;i++){ andrew@0: chromaValues.push_back(cgramPtr->rawChroma[i]/tmpMax); andrew@0: quantisedChromaValues.push_back(cgramPtr->quantisedChromagram[i]); andrew@0: // printf("chroma [%i] %f max %f quantised %i\n", i, cgramPtr->rawChroma[i], cgramPtr->chroma[i], cgramPtr->quantisedChromagram[i] ); andrew@0: } andrew@0: chromaCalculated = true; andrew@0: newlyCalculated = true; andrew@0: //this would do chord detection andrew@0: // chord.C_Detect(chromoGramm.chroma,chromoGramm.chroma_low); andrew@0: // rootChord[chromaIndex] = chord.root; andrew@0: andrew@0: } andrew@0: andrew@0: } andrew@0: andrew@0: return newlyCalculated; andrew@0: } andrew@0: andrew@0: double ChromaOnset::timeDistanceMillis(const ChromaOnset& secondChromaOnset){ andrew@0: andrew@0: return (abs(secondChromaOnset.millisTime - millisTime)); andrew@0: } andrew@0: andrew@0: double ChromaOnset::pitchDistance(const ChromaOnset& secondChromaOnset){ andrew@0: andrew@0: return (abs(secondChromaOnset.aubioPitch - aubioPitch)); andrew@0: } andrew@0: andrew@0: double ChromaOnset::getQuantisedDistance(ChromaOnset& secondChromaOnset){ andrew@0: andrew@0: return getChromaQuantisedDistance(&secondChromaOnset.quantisedChromaValues[0]); andrew@0: andrew@0: } andrew@0: andrew@0: double ChromaOnset::getChromaQuantisedDistance(float* quantisedChromagramTwo){ andrew@0: andrew@0: double cosineDistance = 0; andrew@0: double quantLengthOne = 0; andrew@0: double quantLengthTwo = 0; andrew@0: for (int i = 0;i < 12;i++){ andrew@0: andrew@0: cosineDistance += quantisedChromaValues[i] * quantisedChromagramTwo[i]; andrew@0: andrew@0: quantLengthOne += quantisedChromaValues[i] * quantisedChromaValues[i]; andrew@0: quantLengthTwo += quantisedChromagramTwo[i] * quantisedChromagramTwo[i]; andrew@0: andrew@0: } andrew@0: andrew@0: if (quantLengthOne > 0 && quantLengthTwo > 0) andrew@0: cosineDistance /= sqrt(quantLengthOne * quantLengthTwo); andrew@0: else andrew@0: cosineDistance = 0; andrew@0: andrew@0: return cosineDistance; andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: double ChromaOnset::chromaDotProductDistance(const ChromaOnset& secondChromaOnset){ andrew@0: double dotProductSum = 0; andrew@0: double chromaOneSum = 0; andrew@0: double chromaTwoSum = 0; andrew@0: if (chromaValues.size() == 12 && secondChromaOnset.chromaValues.size() == 12){ andrew@0: for (int i = 0;i < 12;i++){ andrew@0: dotProductSum += chromaValues[i]*secondChromaOnset.chromaValues[i]; andrew@0: chromaOneSum += chromaValues[i]*chromaValues[i]; andrew@0: chromaTwoSum += secondChromaOnset.chromaValues[i]*secondChromaOnset.chromaValues[i]; andrew@0: } andrew@0: chromaOneSum = sqrt(chromaOneSum); andrew@0: chromaTwoSum = sqrt(chromaTwoSum); andrew@0: if (chromaOneSum > 0 && chromaTwoSum > 0) andrew@0: dotProductSum /= (chromaOneSum*chromaTwoSum); andrew@0: else andrew@0: dotProductSum = 0; andrew@0: } andrew@0: return (dotProductSum); andrew@0: } andrew@0: andrew@0: void ChromaOnset::printInfo(){ andrew@0: andrew@0: printf("ONSET : frametime %i, millis %f pitch %f\n", frameTime, millisTime, aubioPitch); andrew@0: printf("chroma: "); andrew@0: andrew@0: for(int i = 0;i < chromaValues.size();i++) andrew@0: printf("[%i] %1.3f, ", i, chromaValues[i]); andrew@0: andrew@0: printf(".\n"); andrew@0: andrew@0: }