Mercurial > hg > midi-score-follower
view src/testApp.cpp @ 1:1a32ce016bb9
Changed bestEstimate timing to work via time sent from Max not the elapsed time. This had caused some problems, but this version now working surprisingly well on MIDI files with variable timing.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Thu, 18 Aug 2011 23:27:42 +0100 |
parents | b299a65a3ad0 |
children | 5581023e0de4 |
line wrap: on
line source
#include "testApp.h" //-------------------------------------------------------------- void testApp::setup(){ midiFileName = "../../../data/entertainer.mid"; int retVal = cannamMainFunction(); playing = false; /* bayesStruct.resetSize(1000); bayesStruct.resetSpeedSize(200); bayesStruct.setRelativeSpeedScalar(0.01); bayesStruct.simpleExample(); */ receiver.setup( PORT ); screenWidth = ofGetWidth(); screenHeight = ofGetHeight(); midiEvents.screenWidth = &screenWidth; midiEvents.screenHeight = &screenHeight; ofSetFrameRate(100); } //-------------------------------------------------------------- void testApp::update(){ if (playing){ midiEvents.updatePlayPosition(); midiEvents.bayesStruct.updateBestEstimate(); } // drawer.tickLocation+=20; // check for waiting messages while( receiver.hasWaitingMessages() ) { ofxOscMessage m; receiver.getNextMessage( &m ); if ( m.getAddress() == "/midinoteon" ) { int newMidiOnPitch = m.getArgAsInt32(0); int velocity = m.getArgAsInt32(1); double time = m.getArgAsFloat(2); if (velocity != 0) midiEvents.newNoteOnEvent(newMidiOnPitch, velocity, time); } if ( m.getAddress() == "/startplaying" ) { startPlaying(); } if ( m.getAddress() == "/stopplaying" ) { stopPlaying(); } }//end while osc } //-------------------------------------------------------------- void testApp::draw(){ midiEvents.drawFile(); } //-------------------------------------------------------------- void testApp::keyPressed(int key){ if (key == ' '){ startPlaying(); } if (key == 'c'){ double timenow = ofGetElapsedTimeMillis(); midiEvents.exampleCrossUpdate(); timenow *= -1; timenow += ofGetElapsedTimeMillis(); printf("CROSS UPDATE TOOK %f", timenow); } if (key == OF_KEY_RETURN) stopPlaying(); if (key == OF_KEY_UP){ if (midiEvents.ticksPerScreen >= 4000) midiEvents.ticksPerScreen += 2000; else midiEvents.ticksPerScreen += 500; } if (key == 'm'){ // midiEvents.findMatch(84, 0, 10000); } if (key == OF_KEY_DOWN){ if (midiEvents.ticksPerScreen >= 4000) midiEvents.ticksPerScreen -= 2000; else if (midiEvents.ticksPerScreen > 500) midiEvents.ticksPerScreen -= 500; } if (key == 'w') midiEvents.printMatchMatrix(); if (key == 'p'){ midiEvents.printNotes(); } if (key == 'l') midiEvents.bayesStruct.decaySpeedDistribution(100); if (key == 't') midiEvents.drawTempoMode = !midiEvents.drawTempoMode; if (key == 'o'){ //open audio file string *filePtr; filePtr = &midiFileName; if (getFilenameFromDialogBox(filePtr)){ printf("Midifile: Loaded name okay :\n'%s' \n", midiFileName.c_str()); cannamMainFunction(); } } } //-------------------------------------------------------------- void testApp::keyReleased(int key){ } //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y ){ midiEvents.mouseX = midiEvents.getEventTimeMillis((x * midiEvents.ticksPerScreen)/ screenWidth); } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::mouseReleased(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::windowResized(int w, int h){ screenWidth = w; screenHeight = h; midiEvents.noteHeight = screenHeight / (float)(midiEvents.noteMaximum - midiEvents.noteMinimum); } void testApp::startPlaying(){ playing = !playing; midiEvents.reset(); midiEvents.setStartPlayingTimes(); //this is where we stop and start playing } void testApp::stopPlaying(){ playing = false; } bool testApp::getFilenameFromDialogBox(string* fileNameToSave){ //this uses a pointer structure within the loader and returns true if the dialogue box was used successfully // first, create a string that will hold the URL string URL; // openFile(string& URL) returns 1 if a file was picked // returns 0 when something went wrong or the user pressed 'cancel' int response = ofxFileDialogOSX::openFile(URL); if(response){ // now you can use the URL *fileNameToSave = URL; //printf("\n filename is %s \n", soundFileName.c_str()); return true; } else { // soundFileName = "OPEN canceled. "; printf("\n open file cancelled \n"); return false; } } int testApp::cannamMainFunction(){ midiEvents.clearAllEvents(); //int main(int argc, char **argv) //{ // if (argc != 2) { // cerr << "Usage: midifile <file.mid>" << endl; // return 1; // } std::string filename = midiFileName;//argv[1]; MIDIFileReader fr(filename); if (!fr.isOK()) { std::cerr << "Error: " << fr.getError().c_str() << std::endl; return 1; } MIDIComposition c = fr.load(); switch (fr.getFormat()) { case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break; case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break; case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break; default: cout << "Format: Unknown MIDI file format?" << endl; break; } cout << "Tracks: " << c.size() << endl; int td = fr.getTimingDivision(); if (td < 32768) { cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl; midiEvents.pulsesPerQuarternote = fr.getTimingDivision(); } else { int frames = 256 - (td >> 8); int subframes = td & 0xff; cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl; } for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) { cout << "Start of track: " << i->first+1 << endl; for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { unsigned int t = j->getTime(); int ch = j->getChannelNumber(); if (j->isMeta()) { int code = j->getMetaEventCode(); string name; bool printable = true; switch (code) { case MIDI_END_OF_TRACK: cout << t << ": End of track" << endl; break; case MIDI_TEXT_EVENT: name = "Text"; break; case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break; case MIDI_TRACK_NAME: name = "Track name"; break; case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break; case MIDI_LYRIC: name = "Lyric"; break; case MIDI_TEXT_MARKER: name = "Text marker"; break; case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break; case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break; case MIDI_CUE_POINT: name = "Cue point"; break; case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break; case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break; case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break; case MIDI_SET_TEMPO: { int m0 = j->getMetaMessage()[0]; int m1 = j->getMetaMessage()[1]; int m2 = j->getMetaMessage()[2]; long tempo = (((m0 << 8) + m1) << 8) + m2; cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl; midiEvents.tempo = 60000000.0 / double(tempo); midiEvents.period = double(tempo)/1000.0; printf("period double is %f\n", midiEvents.period); } break; case MIDI_TIME_SIGNATURE: { int numerator = j->getMetaMessage()[0]; int denominator = 1 << (int)j->getMetaMessage()[1]; cout << t << ": Time signature: " << numerator << "/" << denominator << endl; } case MIDI_KEY_SIGNATURE: { int accidentals = j->getMetaMessage()[0]; int isMinor = j->getMetaMessage()[1]; bool isSharp = accidentals < 0 ? false : true; accidentals = accidentals < 0 ? -accidentals : accidentals; cout << t << ": Key signature: " << accidentals << " " << (isSharp ? (accidentals > 1 ? "sharps" : "sharp") : (accidentals > 1 ? "flats" : "flat")) << (isMinor ? ", minor" : ", major") << endl; } } if (name != "") { if (printable) { cout << t << ": File meta event: code " << code << ": " << name << ": \"" << j->getMetaMessage() << "\"" << endl; } else { cout << t << ": File meta event: code " << code << ": " << name << ": "; for (int k = 0; k < j->getMetaMessage().length(); ++k) { cout << (int)j->getMetaMessage()[k] << " "; } } } continue; } switch (j->getMessageType()) { case MIDI_NOTE_ON: cout << t << ": Note: channel " << ch << " duration " << j->getDuration() << " pitch " << j->getPitch() << " velocity " << j->getVelocity() << "event time " << midiEvents.getEventTimeMillis(t) << endl; v.clear(); v.push_back(t); v.push_back(j->getPitch()); v.push_back(j->getVelocity()); v.push_back(j->getDuration()); midiEvents.recordedNoteOnMatrix.push_back(v); midiEvents.recordedEventTimes.push_back(midiEvents.getEventTimeMillis(t)); break; case MIDI_POLY_AFTERTOUCH: cout << t << ": Polyphonic aftertouch: channel " << ch << " pitch " << j->getPitch() << " pressure " << j->getData2() << endl; break; case MIDI_CTRL_CHANGE: { int controller = j->getData1(); string name; switch (controller) { case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break; case MIDI_CONTROLLER_VOLUME: name = "Volume"; break; case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break; case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break; case MIDI_CONTROLLER_PAN: name = "Pan"; break; case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break; case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break; case MIDI_CONTROLLER_RELEASE: name = "Release"; break; case MIDI_CONTROLLER_ATTACK: name = "Attack"; break; case MIDI_CONTROLLER_FILTER: name = "Filter"; break; case MIDI_CONTROLLER_REVERB: name = "Reverb"; break; case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break; case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break; case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break; case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break; case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break; case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break; case MIDI_CONTROLLER_RESET: name = "Reset"; break; case MIDI_CONTROLLER_LOCAL: name = "Local"; break; case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break; } cout << t << ": Controller change: channel " << ch << " controller " << j->getData1(); if (name != "") cout << " (" << name << ")"; cout << " value " << j->getData2() << endl; } break; case MIDI_PROG_CHANGE: cout << t << ": Program change: channel " << ch << " program " << j->getData1() << endl; break; case MIDI_CHNL_AFTERTOUCH: cout << t << ": Channel aftertouch: channel " << ch << " pressure " << j->getData1() << endl; break; case MIDI_PITCH_BEND: cout << t << ": Pitch bend: channel " << ch << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl; break; case MIDI_SYSTEM_EXCLUSIVE: cout << t << ": System exclusive: code " << (int)j->getMessageType() << " message length " << j->getMetaMessage().length() << endl; break; } } } //} }//end cannam midi main