andrew@0: /* andrew@0: * midiEventHolder.cpp andrew@0: * midiCannamReader3 andrew@0: * andrew@0: * Created by Andrew on 19/07/2011. andrew@0: * Copyright 2011 QMUL. All rights reserved. andrew@0: * andrew@0: */ andrew@0: //hello andrew@0: andrew@0: #include "midiEventHolder.h" andrew@0: andrew@0: midiEventHolder::midiEventHolder(){ andrew@0: // recordedNoteOnIndex = 0; andrew@0: andrew@0: width = ofGetWidth(); andrew@0: height = ofGetHeight(); andrew@0: screenWidth= &width; andrew@0: screenHeight = &height; andrew@0: andrew@0: ticksPerScreen = 4000; andrew@0: tickLocation = 0; andrew@0: pulsesPerQuarternote = 240; andrew@0: noteArrayIndex = 0; andrew@0: noteMinimum = 30; andrew@0: noteMaximum = 96; andrew@0: andrew@4: minimumMatchSpeed = 0.0; andrew@4: maximumMatchSpeed = 2.0; andrew@2: andrew@0: likelihoodWidth = 100; andrew@2: likelihoodToNoiseRatio = 0.02; andrew@0: andrew@9: bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05 andrew@2: bayesStruct.speedDecayWidth = 20; andrew@2: bayesStruct.speedDecayAmount = 10; andrew@2: andrew@3: speedPriorValue = 1.0; andrew@2: andrew@2: matchWindowWidth = 8000;//window size for matching in ms andrew@0: andrew@1: bayesStruct.resetSize(matchWindowWidth); andrew@2: bayesStruct.setPositionDistributionScalar(1); andrew@2: andrew@0: bayesStruct.resetSpeedSize(200); andrew@0: bayesStruct.setRelativeSpeedScalar(0.01); andrew@0: bayesStruct.relativeSpeedPrior.getMaximum(); andrew@2: //bayesStruct.simpleExample(); andrew@2: andrew@6: andrew@6: speedWindowWidthMillis = 4000; andrew@3: speedPriorValue = 1.0; andrew@0: noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); andrew@4: andrew@6: confidenceWeightingUsed = false; andrew@6: andrew@9: drawPhaseMode = true; andrew@9: andrew@4: printf("lookup index %f value %f\n", bayesStruct.prior.getLookupIndex(100, 30., 10.0), bayesStruct.prior.gaussianLookupTable[(int)bayesStruct.prior.getLookupIndex(100, 30., 10.0)]); andrew@0: } andrew@0: andrew@0: andrew@0: andrew@0: void midiEventHolder::reset(){ andrew@2: //called when we start playing andrew@2: andrew@0: noteArrayIndex = 0; andrew@0: tickLocation = 0; andrew@0: lastPeriodUpdateTime = ofGetElapsedTimeMillis(); andrew@0: bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); andrew@0: numberOfScreensIn = 0; andrew@0: // recordedNoteOnIndex = 0; andrew@0: bayesStruct.setNewDistributionOffsets(0); andrew@0: bayesStruct.posterior.offset = 0; andrew@0: andrew@0: playedEventTimes.clear(); andrew@0: playedNoteOnMatrix.clear(); andrew@0: matchMatrix.clear(); andrew@5: bestMatchIndex = 0; andrew@0: andrew@0: bayesStruct.resetSpeedToOne(); andrew@3: bayesStruct.setSpeedPrior(speedPriorValue); andrew@5: setMatchedNotesBackToFalse(); andrew@5: } andrew@5: andrew@5: void midiEventHolder::setMatchedNotesBackToFalse(){ andrew@5: for (int i = 0;i < noteOnMatches.size();i++) andrew@5: noteOnMatches[i] = false; andrew@0: } andrew@0: andrew@1: void midiEventHolder::clearAllEvents(){ andrew@1: recordedNoteOnMatrix.clear(); andrew@1: matchesFound.clear(); andrew@1: noteOnMatches.clear(); andrew@1: recordedEventTimes.clear(); andrew@1: andrew@1: //played events: andrew@1: playedEventTimes.clear(); andrew@1: playedNoteOnMatrix.clear(); andrew@1: matchMatrix.clear(); andrew@1: } andrew@1: andrew@0: void midiEventHolder::printNotes(){ andrew@0: printf("RECORDED MATRIX"); andrew@0: for (int i = 0;i < recordedNoteOnMatrix.size();i++){ andrew@0: printf("%i :: %i @ %f\n", recordedNoteOnMatrix[i][0], recordedNoteOnMatrix[i][1], recordedEventTimes[i]); andrew@0: } andrew@0: } andrew@0: andrew@0: andrew@0: double midiEventHolder::getEventTimeTicks(double millis){ andrew@0: return (millis * pulsesPerQuarternote / period); andrew@0: } andrew@0: andrew@0: double midiEventHolder::getEventTimeMillis(double ticks){ andrew@0: return (period * ticks / (double) pulsesPerQuarternote); andrew@0: } andrew@0: andrew@0: void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){ andrew@0: andrew@0: //MOVE INTO BAYESSTRUCT?? XXX andrew@0: //bayesStruct.copyPriorToPosterior(); andrew@0: //why was this here?? andrew@0: bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way andrew@0: //bayesStruct.copyPriorToPosterior(); andrew@0: //need to get new MAP position and set the offset of the arrays andrew@0: //currently bestEstimate is the approx for the new MAP position andrew@0: andrew@0: andrew@0: //add the new event to our played information matrix andrew@0: IntVector v; andrew@0: v.push_back(pitch); andrew@0: v.push_back(velocity); andrew@0: playedNoteOnMatrix.push_back(v); andrew@0: andrew@0: andrew@0: //would update the arrays at this point to show where out current location (phase) and tempo is. andrew@2: // double timeNow = ofGetElapsedTimeMillis() - startTime; andrew@2: double timeNow = timePlayed;// - startTime; andrew@2: recentNoteOnTime = timePlayed; andrew@0: andrew@2: // printf("Max time %f OF time %f \n", timePlayed, timeNow); andrew@0: andrew@0: playedEventTimes.push_back(timePlayed); andrew@0: andrew@2: // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; andrew@2: double timeDifference = timePlayed - bayesStruct.lastEventTime; andrew@0: andrew@9: // printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime); andrew@0: //addnoise to the tempo distribution andrew@2: //bayesStruct.decaySpeedDistribution(timeDifference); andrew@2: if (timeDifference > 50){ andrew@2: bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.); andrew@2: // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.); andrew@2: } andrew@2: andrew@2: bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate; andrew@2: bayesStruct.updateBestEstimate(); andrew@2: bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); andrew@0: andrew@0: // double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate); andrew@0: //was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis andrew@0: andrew@0: timeString = "Pitch:"+ofToString(pitch); andrew@0: timeString += ", time now:"+ofToString(timeNow, 1); andrew@0: timeString += " TD "+ofToString(timeDifference, 1); andrew@0: timeString += " offset "+ofToString(bayesStruct.posterior.offset , 0); andrew@0: timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0); andrew@0: // timeString += " Previous time" + ofToString(newMAPestimateTime,0); andrew@9: timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 2); andrew@9: timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2); andrew@0: andrew@0: // newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); andrew@0: // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0); andrew@0: andrew@0: //then we recalculate the window start based on MAP being central andrew@0: //then we do the matches on these and the likelihood on these. andrew@0: andrew@0: bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2))); andrew@0: // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); andrew@0: andrew@0: timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0); andrew@0: timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1); andrew@10: timeString += " error "+ofToString(minimumMatchError, 0); andrew@9: timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1); andrew@9: timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 1); andrew@0: andrew@0: andrew@0: //be able to draw the prior in correct location relative to the midi notes andrew@2: //this calculates the cross update of all possible speeds and all possible positions andrew@0: bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference); andrew@0: andrew@0: andrew@0: timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1); andrew@0: timeString += " notearrayindex "+ofToString(noteArrayIndex, 0); andrew@0: //when this is off teh screen there is a problem somehow XXX andrew@0: bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); andrew@0: // bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); andrew@0: //trying to switch to prior andrew@0: andrew@2: //bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); andrew@2: bayesStruct.lastEventTime = timePlayed; andrew@0: andrew@0: //do the cross update to find current posterior for location andrew@1: // totalConfidence= 0; andrew@0: int numberOfMatchesFound = findLocalMatches(pitch); andrew@0: setMatchLikelihoods(numberOfMatchesFound); andrew@0: bayesStruct.calculatePosterior(); andrew@0: andrew@0: //having found matches we have matches for new note and matches for previous notes andrew@6: if (!confidenceWeightingUsed) andrew@0: findLocalTempoPairs(); andrew@6: else andrew@6: findLocalTempoPairsWeightedForConfidence(); andrew@0: andrew@2: //bayesStruct.addGaussianNoiseToSpeedPosterior(10); andrew@0: andrew@0: } andrew@0: andrew@0: int midiEventHolder::findLocalMatches(int notePitch){ andrew@0: andrew@0: //here we find the matches to the new note within appropriate range andrew@0: andrew@1: matchString = ""; andrew@0: andrew@0: windowStartTime = max(0.0,(bayesStruct.bestEstimate - matchWindowWidth/2));//was playPositionInMillis andrew@0: int numberOfMatches = findMatch(notePitch, windowStartTime, windowStartTime + matchWindowWidth); andrew@5: andrew@0: andrew@1: matchString += " pitch: "+ofToString(notePitch)+" matches "+ofToString(numberOfMatches)+" win start "+ofToString(windowStartTime); andrew@1: andrew@0: return numberOfMatches; andrew@0: andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void midiEventHolder::setMatchLikelihoods(int numberOfMatches){ andrew@0: //reset the offset to match the prior andrew@0: bayesStruct.likelihood.offset = bayesStruct.prior.offset; andrew@0: bayesStruct.likelihood.zero();//set to zero andrew@0: andrew@2: double quantity = likelihoodToNoiseRatio / numberOfMatches; andrew@0: andrew@0: for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){ andrew@0: // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset); andrew@0: //this is the vent time since start of file andrew@0: if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){ andrew@1: // double confidenceMeasure = 0; andrew@1: // if (totalConfidence > 0) andrew@6: // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence; andrew@2: andrew@2: bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, quantity);//* confidenceMeasure andrew@0: }//end if andrew@0: } andrew@2: bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length); andrew@0: } andrew@0: andrew@0: int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){ andrew@0: andrew@0: matchesFound.clear(); andrew@0: int startIndex = 0; andrew@10: andrew@0: if (recordedEventTimes.size() > 0){ andrew@0: andrew@0: //get to the right range of events to check in andrew@0: while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < startTime) andrew@0: startIndex++; andrew@0: andrew@0: } andrew@0: andrew@6: IntVector v; andrew@6: DoubleVector d; andrew@10: double tmpError = 100000.;//v high error andrew@6: andrew@5: double minimumConfidence = 0; andrew@0: while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < endTime){ andrew@0: if (recordedNoteOnMatrix[startIndex][1] == notePitch){ andrew@6: andrew@0: matchesFound.push_back(startIndex); andrew@6: v.push_back(startIndex); andrew@5: double eventConfidence = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[startIndex]); andrew@5: if (eventConfidence > minimumConfidence){ andrew@5: minimumConfidence = eventConfidence; andrew@5: bestMatchIndex = startIndex; andrew@5: } andrew@6: d.push_back(eventConfidence); andrew@5: andrew@6: double confidence = eventConfidence;//bayesStruct.posterior.getValueAtMillis(mouseX); andrew@1: // recordedEventTimes[startIndex]); andrew@1: matchString += "["+ofToString(startIndex)+"] = "+ofToString(confidence, 3)+" ."; andrew@10: andrew@10: if (abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate) < tmpError){ andrew@10: //record the error between expected and observed times andrew@10: tmpError = abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate); andrew@10: minimumMatchError = recordedEventTimes[startIndex] - bayesStruct.bestEstimate; andrew@10: } andrew@10: andrew@0: } andrew@0: startIndex++; andrew@0: } andrew@5: andrew@5: andrew@0: // printf("%i MATCHES TO Note %i found\n", (int)matchesFound.size(), notePitch); andrew@0: int size = matchesFound.size(); andrew@5: if (size > 0) andrew@5: noteOnMatches[bestMatchIndex] = true; andrew@5: andrew@6: v.insert(v.begin() , (int)size); andrew@6: d.insert(d.begin() , (double)size); andrew@6: andrew@6: //v.push_back(size); andrew@6: //d.push_back(size); andrew@6: //for (int i = 0;i < matchesFound.size()+1;i++){ andrew@6: // v.push_back(matchesFound[i]); andrew@6: // printf("match %i,[%i] is %i\n", startIndex, i, v[i]); andrew@6: //} andrew@6: andrew@0: andrew@0: matchMatrix.push_back(v); andrew@6: matchConfidence.push_back(d); andrew@0: andrew@0: return size; andrew@0: } andrew@0: andrew@0: bool midiEventHolder::checkIfMatchedNote(const int& tmpIndex){ andrew@0: for (int i = 0;i < matchesFound.size();i++){ andrew@0: if (matchesFound[i] == tmpIndex) andrew@0: return true; andrew@0: } andrew@0: return false; andrew@0: } andrew@0: andrew@0: andrew@0: andrew@0: void midiEventHolder::findLocalTempoPairs(){ andrew@6: andrew@0: int currentPlayedIndex = playedNoteOnMatrix.size()-1; andrew@6: // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); andrew@6: // printMatchesFound(); andrew@6: // printMatchMatrix(); andrew@6: // printf("possible notes \n"); andrew@9: bool needToUpdate = false; andrew@9: bayesStruct.setLikelihoodToConstant(); andrew@0: andrew@0: andrew@0: for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ andrew@6: //iterate through the recently matched events - even dodgy matches included andrew@6: //size, index of match0, index of match1, .... andrew@9: andrew@9: andrew@0: int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; andrew@0: andrew@0: int previousIndex = currentPlayedIndex-1; andrew@9: andrew@0: andrew@6: while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) { andrew@0: double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex]; andrew@6: andrew@0: for (int k = 0;k < matchMatrix[previousIndex][0];k++){ andrew@0: int recordedPreviousIndex = matchMatrix[previousIndex][k+1]; andrew@0: andrew@6: andrew@0: double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex]; andrew@6: andrew@0: andrew@0: //we want the speed of the recording relative to that of the playing live andrew@0: andrew@0: double speedRatio = recordedTimeDifference / playedTimeDifference; andrew@0: if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){ andrew@6: /* andrew@6: printf("(%i)", matchMatrix[currentPlayedIndex][i+1]); andrew@6: printf("[%i] :: ", recordedPreviousIndex); andrew@6: printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); andrew@6: printf("update on speed ratio %f\n", speedRatio); andrew@6: */ andrew@1: // matchString += " speed: "+ofToString(speedRatio, 3); andrew@6: // commented for debug andrew@2: andrew@9: //bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match andrew@9: double amount = (1-bayesStruct.speedLikelihoodNoise)/10; andrew@9: bayesStruct.updateTempoLikelihood(speedRatio, amount); andrew@9: needToUpdate = true; andrew@0: } andrew@6: // printf("\n"); andrew@0: } andrew@0: andrew@0: previousIndex--; andrew@0: }//end while previousindex countdown andrew@0: }//end for loop through possible current matches andrew@0: andrew@9: if (needToUpdate) andrew@9: bayesStruct.updateTempoDistribution(); andrew@9: andrew@2: //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); andrew@0: } andrew@0: andrew@0: andrew@6: void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){ andrew@9: bool needToUpdate = false; andrew@6: andrew@6: int currentPlayedIndex = playedNoteOnMatrix.size()-1; andrew@6: // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); andrew@6: // printMatchesFound(); andrew@6: // printMatchMatrix(); andrew@6: // printf("possible notes \n"); andrew@6: andrew@9: bayesStruct.setLikelihoodToConstant(); andrew@6: andrew@6: for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ andrew@6: //iterate through the recently matched events - even dodgy matches included andrew@6: //size, index of match0, index of match1, .... andrew@6: int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; andrew@6: andrew@6: double currentMatchConfidence = matchConfidence[currentPlayedIndex][i+1];//new confidence andrew@6: andrew@6: int previousIndex = currentPlayedIndex-1; andrew@6: andrew@6: while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) { andrew@6: double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex]; andrew@6: andrew@6: for (int k = 0;k < matchMatrix[previousIndex][0];k++){ andrew@6: int recordedPreviousIndex = matchMatrix[previousIndex][k+1]; andrew@6: andrew@6: double previousMatchConfidence = matchConfidence[previousIndex][k+1]; andrew@6: andrew@6: andrew@6: double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex]; andrew@6: andrew@6: andrew@6: //we want the speed of the recording relative to that of the playing live andrew@6: andrew@6: double speedRatio = recordedTimeDifference / playedTimeDifference; andrew@6: if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){ andrew@6: andrew@6: printf("(%i)", matchMatrix[currentPlayedIndex][i+1]); andrew@6: printf("[%i] :: ", recordedPreviousIndex); andrew@6: printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence); andrew@6: printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); andrew@6: printf("update on speed ratio %f\n", speedRatio); andrew@6: andrew@6: // matchString += " speed: "+ofToString(speedRatio, 3); andrew@6: // commented for debug andrew@9: double weighting = previousMatchConfidence * currentMatchConfidence ; andrew@9: double amount = (1-bayesStruct.speedLikelihoodNoise)*weighting/10; andrew@9: bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match andrew@9: needToUpdate = true; andrew@6: } andrew@6: // printf("\n"); andrew@6: } andrew@6: andrew@6: previousIndex--; andrew@6: }//end while previousindex countdown andrew@6: }//end for loop through possible current matches andrew@6: andrew@9: if (needToUpdate) andrew@9: bayesStruct.updateTempoDistribution(); andrew@6: //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); andrew@6: } andrew@6: andrew@6: andrew@6: andrew@0: void midiEventHolder::updatePlayPosition(){ andrew@0: andrew@0: //in actual fact if we are changing the speed of the play position andrew@0: //we will need to update this via the file andrew@0: andrew@0: double timeDifference = ofGetElapsedTimeMillis() - lastPeriodUpdateTime; andrew@0: //this is time diff in milliseconds andrew@0: //then we have andrew@0: double quarterNoteIntervals = (timeDifference / period); andrew@0: tickLocation = quarterNoteIntervals * pulsesPerQuarternote; andrew@0: andrew@0: playPositionInMillis = timeDifference;//based on updating from when we change period andrew@0: //this to be added andrew@0: andrew@0: bayesStruct.updateBestEstimate(); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@9: void midiEventHolder::drawMidiFile(){ andrew@9: andrew@0: //draws midi file on scrolling screen andrew@0: int size = recordedNoteOnMatrix.size(); andrew@0: if (size > 0){ andrew@0: andrew@0: numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in andrew@0: andrew@9: // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down andrew@0: timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen); andrew@0: andrew@0: while (noteArrayIndex < recordedNoteOnMatrix.size() && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] ) andrew@0: noteArrayIndex++; andrew@0: andrew@0: andrew@0: while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < recordedNoteOnMatrix[noteArrayIndex][0]) andrew@0: noteArrayIndex--; andrew@0: andrew@0: //need to start where we currently are in file andrew@0: int maxNoteIndexToPrint = noteArrayIndex; andrew@0: int minNoteIndexToPrint = noteArrayIndex; andrew@0: andrew@0: while (maxNoteIndexToPrint < recordedNoteOnMatrix.size() && recordedNoteOnMatrix[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen ) andrew@0: maxNoteIndexToPrint++; andrew@0: andrew@0: while (minNoteIndexToPrint > 0 && minNoteIndexToPrint < size && recordedNoteOnMatrix[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen) andrew@0: minNoteIndexToPrint--; andrew@0: andrew@0: for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){ andrew@0: andrew@0: if (checkIfMatchedNote(tmpIndex)) andrew@0: ofSetColor(0,0,255); andrew@5: else if(noteOnMatches[tmpIndex]){ andrew@9: ofSetColor(255,0,255); andrew@5: }else{ andrew@0: ofSetColor(255,255,255); andrew@5: } andrew@5: andrew@9: andrew@9: andrew@9: // XXX replace ofgetwidth below andrew@0: //if (tmpIndex >= 0 && tmpIndex < size) andrew@0: int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen; andrew@0: int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen; andrew@0: andrew@0: andrew@0: int yLocation = (*screenHeight) - ((recordedNoteOnMatrix[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum)); andrew@0: ofRect(xLocation,yLocation, duration, noteHeight); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: int xLocation;// = getLocationFromTicks(tickLocation); andrew@9: // ofLine(xLocation, 0, xLocation, (*screenHeight)); andrew@0: andrew@0: //orange line at best estimate andrew@0: xLocation = getLocationFromMillis(bayesStruct.bestEstimate); andrew@0: ofSetColor(250,100,0); andrew@0: ofLine(xLocation, 0, xLocation, (*screenHeight)); andrew@0: andrew@2: xLocation = getLocationFromMillis(bayesStruct.tmpBestEstimate); andrew@2: ofSetColor(250,100,0); andrew@2: ofLine(xLocation, 0, xLocation, (*screenHeight)); andrew@2: andrew@0: andrew@0: //lines where matching window start and end are andrew@0: ofSetColor(0,100,255); andrew@0: xLocation = getLocationFromMillis(windowStartTime); andrew@0: ofLine(xLocation, 0, xLocation, (*screenHeight)); andrew@0: xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth); andrew@0: ofLine(xLocation, 0, xLocation, (*screenHeight)); andrew@9: andrew@0: andrew@0: } andrew@0: andrew@0: ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); andrew@0: andrew@0: ofDrawBitmapString(timeString, 20, 60); andrew@0: andrew@9: andrew@9: } andrew@9: andrew@9: void midiEventHolder::drawFile(){ andrew@9: drawMidiFile(); andrew@9: andrew@9: andrew@0: // bayesStruct.drawArrays(); andrew@0: andrew@0: // ofSetColor(200,200,0); andrew@0: // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800); andrew@0: andrew@0: //need to draw arrays within correct timescope andrew@9: if (drawPhaseMode) andrew@0: bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen)); andrew@0: andrew@1: if (drawTempoMode) andrew@1: bayesStruct.drawTempoArrays(); andrew@0: andrew@1: andrew@1: ofSetColor(0, 0, 0); andrew@0: ofDrawBitmapString(matchString, 20, ofGetHeight() - 20); andrew@0: andrew@1: double confidence = bayesStruct.posterior.getValueAtMillis(mouseX); andrew@2: /* andrew@2: string mouseString = "mouseX "+ofToString(confidence, 3)+" ."; andrew@1: ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40); andrew@2: */ andrew@2: string mouseString = "updateCounter "+ofToString(bayesStruct.updateCounter); andrew@2: ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40); andrew@2: andrew@2: string infostring = "speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 3); andrew@2: ofDrawBitmapString(infostring, 20 , ofGetHeight() - 60); andrew@0: } andrew@0: andrew@0: int midiEventHolder::getLocationFromTicks(double tickPosition){ andrew@0: return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen); andrew@0: } andrew@0: andrew@0: int midiEventHolder::getLocationFromMillis(double millisPosition){ andrew@0: //(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen andrew@0: return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen); andrew@0: } andrew@0: andrew@0: andrew@0: void midiEventHolder::exampleCrossUpdate(){ andrew@0: andrew@0: bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200); andrew@0: andrew@0: } andrew@0: andrew@0: andrew@0: void midiEventHolder::setStartPlayingTimes(){ andrew@0: lastPeriodUpdateTime = ofGetElapsedTimeMillis(); andrew@0: startTime = lastPeriodUpdateTime; andrew@0: andrew@2: /* andrew@2: bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis(); andrew@2: bayesStruct.bestEstimate = 0; andrew@0: bayesStruct.resetArrays(); andrew@2: bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis(); andrew@2: */ andrew@2: bayesStruct.setStartPlaying(); andrew@0: matchString = ""; andrew@0: } andrew@0: andrew@0: andrew@0: void midiEventHolder::printMatchMatrix(){ andrew@0: printf("match matrix:\n"); andrew@0: for (int i = 0;i < matchMatrix.size();i++){ andrew@0: for (int k = 0;k < matchMatrix[i].size();k++){ andrew@0: printf("%i , ", matchMatrix[i][k]); andrew@0: } andrew@0: printf("\n"); andrew@0: } andrew@0: andrew@0: andrew@0: }