annotate 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
rev   line source
andrew@0 1 #include "testApp.h"
andrew@0 2
andrew@0 3 //--------------------------------------------------------------
andrew@0 4 void testApp::setup(){
andrew@0 5 midiFileName = "../../../data/entertainer.mid";
andrew@0 6 int retVal = cannamMainFunction();
andrew@0 7
andrew@0 8 playing = false;
andrew@0 9 /*
andrew@0 10 bayesStruct.resetSize(1000);
andrew@0 11 bayesStruct.resetSpeedSize(200);
andrew@0 12 bayesStruct.setRelativeSpeedScalar(0.01);
andrew@0 13 bayesStruct.simpleExample();
andrew@0 14 */
andrew@0 15
andrew@0 16 receiver.setup( PORT );
andrew@0 17
andrew@0 18 screenWidth = ofGetWidth();
andrew@0 19 screenHeight = ofGetHeight();
andrew@0 20 midiEvents.screenWidth = &screenWidth;
andrew@0 21 midiEvents.screenHeight = &screenHeight;
andrew@0 22 ofSetFrameRate(100);
andrew@0 23 }
andrew@0 24
andrew@0 25 //--------------------------------------------------------------
andrew@0 26 void testApp::update(){
andrew@0 27 if (playing){
andrew@0 28 midiEvents.updatePlayPosition();
andrew@0 29 midiEvents.bayesStruct.updateBestEstimate();
andrew@0 30 }
andrew@0 31 // drawer.tickLocation+=20;
andrew@0 32
andrew@0 33 // check for waiting messages
andrew@0 34 while( receiver.hasWaitingMessages() )
andrew@0 35 {
andrew@0 36 ofxOscMessage m;
andrew@0 37 receiver.getNextMessage( &m );
andrew@0 38
andrew@0 39 if ( m.getAddress() == "/midinoteon" )
andrew@0 40 {
andrew@0 41 int newMidiOnPitch = m.getArgAsInt32(0);
andrew@0 42 int velocity = m.getArgAsInt32(1);
andrew@0 43 double time = m.getArgAsFloat(2);
andrew@0 44
andrew@0 45 if (velocity != 0)
andrew@0 46 midiEvents.newNoteOnEvent(newMidiOnPitch, velocity, time);
andrew@0 47
andrew@0 48 }
andrew@0 49
andrew@0 50 if ( m.getAddress() == "/startplaying" )
andrew@0 51 {
andrew@0 52 startPlaying();
andrew@0 53 }
andrew@0 54
andrew@0 55 if ( m.getAddress() == "/stopplaying" )
andrew@0 56 {
andrew@0 57 stopPlaying();
andrew@0 58 }
andrew@0 59 }//end while osc
andrew@0 60
andrew@0 61 }
andrew@0 62
andrew@0 63 //--------------------------------------------------------------
andrew@0 64 void testApp::draw(){
andrew@0 65
andrew@0 66 midiEvents.drawFile();
andrew@0 67
andrew@0 68 }
andrew@0 69
andrew@0 70 //--------------------------------------------------------------
andrew@0 71 void testApp::keyPressed(int key){
andrew@0 72
andrew@0 73
andrew@0 74 if (key == ' '){
andrew@0 75 startPlaying();
andrew@0 76 }
andrew@0 77
andrew@0 78 if (key == 'c'){
andrew@0 79 double timenow = ofGetElapsedTimeMillis();
andrew@0 80 midiEvents.exampleCrossUpdate();
andrew@0 81 timenow *= -1;
andrew@0 82 timenow += ofGetElapsedTimeMillis();
andrew@0 83 printf("CROSS UPDATE TOOK %f", timenow);
andrew@0 84 }
andrew@0 85
andrew@0 86 if (key == OF_KEY_RETURN)
andrew@0 87 stopPlaying();
andrew@0 88
andrew@0 89 if (key == OF_KEY_UP){
andrew@0 90 if (midiEvents.ticksPerScreen >= 4000)
andrew@0 91 midiEvents.ticksPerScreen += 2000;
andrew@0 92 else
andrew@0 93 midiEvents.ticksPerScreen += 500;
andrew@0 94 }
andrew@0 95
andrew@0 96 if (key == 'm'){
andrew@0 97 // midiEvents.findMatch(84, 0, 10000);
andrew@0 98 }
andrew@0 99
andrew@0 100 if (key == OF_KEY_DOWN){
andrew@0 101 if (midiEvents.ticksPerScreen >= 4000)
andrew@0 102 midiEvents.ticksPerScreen -= 2000;
andrew@0 103 else if (midiEvents.ticksPerScreen > 500)
andrew@0 104 midiEvents.ticksPerScreen -= 500;
andrew@0 105 }
andrew@0 106
andrew@0 107 if (key == 'w')
andrew@0 108 midiEvents.printMatchMatrix();
andrew@0 109
andrew@0 110 if (key == 'p'){
andrew@0 111 midiEvents.printNotes();
andrew@0 112 }
andrew@0 113
andrew@0 114 if (key == 'l')
andrew@0 115 midiEvents.bayesStruct.decaySpeedDistribution(100);
andrew@0 116
andrew@1 117 if (key == 't')
andrew@1 118 midiEvents.drawTempoMode = !midiEvents.drawTempoMode;
andrew@1 119
andrew@0 120 if (key == 'o'){
andrew@0 121 //open audio file
andrew@0 122 string *filePtr;
andrew@0 123 filePtr = &midiFileName;
andrew@0 124
andrew@0 125 if (getFilenameFromDialogBox(filePtr)){
andrew@0 126 printf("Midifile: Loaded name okay :\n'%s' \n", midiFileName.c_str());
andrew@0 127 cannamMainFunction();
andrew@0 128 }
andrew@0 129
andrew@0 130 }
andrew@0 131 }
andrew@0 132
andrew@0 133 //--------------------------------------------------------------
andrew@0 134 void testApp::keyReleased(int key){
andrew@0 135
andrew@0 136 }
andrew@0 137
andrew@0 138 //--------------------------------------------------------------
andrew@0 139 void testApp::mouseMoved(int x, int y ){
andrew@1 140 midiEvents.mouseX = midiEvents.getEventTimeMillis((x * midiEvents.ticksPerScreen)/ screenWidth);
andrew@0 141 }
andrew@0 142
andrew@0 143 //--------------------------------------------------------------
andrew@0 144 void testApp::mouseDragged(int x, int y, int button){
andrew@0 145
andrew@0 146 }
andrew@0 147
andrew@0 148 //--------------------------------------------------------------
andrew@0 149 void testApp::mousePressed(int x, int y, int button){
andrew@0 150
andrew@0 151 }
andrew@0 152
andrew@0 153 //--------------------------------------------------------------
andrew@0 154 void testApp::mouseReleased(int x, int y, int button){
andrew@0 155
andrew@0 156 }
andrew@0 157
andrew@0 158 //--------------------------------------------------------------
andrew@0 159 void testApp::windowResized(int w, int h){
andrew@0 160 screenWidth = w;
andrew@0 161 screenHeight = h;
andrew@0 162 midiEvents.noteHeight = screenHeight / (float)(midiEvents.noteMaximum - midiEvents.noteMinimum);
andrew@0 163
andrew@0 164 }
andrew@0 165
andrew@0 166
andrew@0 167
andrew@0 168 void testApp::startPlaying(){
andrew@0 169 playing = !playing;
andrew@0 170 midiEvents.reset();
andrew@0 171 midiEvents.setStartPlayingTimes();
andrew@0 172 //this is where we stop and start playing
andrew@0 173 }
andrew@0 174
andrew@0 175 void testApp::stopPlaying(){
andrew@0 176 playing = false;
andrew@0 177 }
andrew@0 178
andrew@0 179 bool testApp::getFilenameFromDialogBox(string* fileNameToSave){
andrew@0 180 //this uses a pointer structure within the loader and returns true if the dialogue box was used successfully
andrew@0 181 // first, create a string that will hold the URL
andrew@0 182 string URL;
andrew@0 183
andrew@0 184 // openFile(string& URL) returns 1 if a file was picked
andrew@0 185 // returns 0 when something went wrong or the user pressed 'cancel'
andrew@0 186 int response = ofxFileDialogOSX::openFile(URL);
andrew@0 187 if(response){
andrew@0 188 // now you can use the URL
andrew@0 189 *fileNameToSave = URL;
andrew@0 190 //printf("\n filename is %s \n", soundFileName.c_str());
andrew@0 191 return true;
andrew@0 192 }
andrew@0 193 else {
andrew@0 194 // soundFileName = "OPEN canceled. ";
andrew@0 195 printf("\n open file cancelled \n");
andrew@0 196 return false;
andrew@0 197 }
andrew@0 198
andrew@0 199
andrew@0 200
andrew@0 201 }
andrew@0 202
andrew@0 203
andrew@0 204
andrew@0 205
andrew@0 206 int testApp::cannamMainFunction(){
andrew@0 207
andrew@0 208
andrew@1 209 midiEvents.clearAllEvents();
andrew@0 210
andrew@0 211 //int main(int argc, char **argv)
andrew@0 212 //{
andrew@0 213 // if (argc != 2) {
andrew@0 214 // cerr << "Usage: midifile <file.mid>" << endl;
andrew@0 215 // return 1;
andrew@0 216 // }
andrew@0 217
andrew@0 218 std::string filename = midiFileName;//argv[1];
andrew@0 219
andrew@0 220 MIDIFileReader fr(filename);
andrew@0 221 if (!fr.isOK()) {
andrew@0 222 std::cerr << "Error: " << fr.getError().c_str() << std::endl;
andrew@0 223 return 1;
andrew@0 224 }
andrew@0 225
andrew@0 226 MIDIComposition c = fr.load();
andrew@0 227
andrew@0 228 switch (fr.getFormat()) {
andrew@0 229 case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break;
andrew@0 230 case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break;
andrew@0 231 case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break;
andrew@0 232 default: cout << "Format: Unknown MIDI file format?" << endl; break;
andrew@0 233 }
andrew@0 234
andrew@0 235 cout << "Tracks: " << c.size() << endl;
andrew@0 236
andrew@0 237 int td = fr.getTimingDivision();
andrew@0 238 if (td < 32768) {
andrew@0 239 cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
andrew@0 240
andrew@0 241 midiEvents.pulsesPerQuarternote = fr.getTimingDivision();
andrew@0 242 } else {
andrew@0 243 int frames = 256 - (td >> 8);
andrew@0 244 int subframes = td & 0xff;
andrew@0 245 cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
andrew@0 246 }
andrew@0 247
andrew@0 248 for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
andrew@0 249
andrew@0 250 cout << "Start of track: " << i->first+1 << endl;
andrew@0 251
andrew@0 252 for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
andrew@0 253
andrew@0 254 unsigned int t = j->getTime();
andrew@0 255 int ch = j->getChannelNumber();
andrew@0 256
andrew@0 257 if (j->isMeta()) {
andrew@0 258 int code = j->getMetaEventCode();
andrew@0 259 string name;
andrew@0 260 bool printable = true;
andrew@0 261 switch (code) {
andrew@0 262
andrew@0 263 case MIDI_END_OF_TRACK:
andrew@0 264 cout << t << ": End of track" << endl;
andrew@0 265 break;
andrew@0 266
andrew@0 267 case MIDI_TEXT_EVENT: name = "Text"; break;
andrew@0 268 case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
andrew@0 269 case MIDI_TRACK_NAME: name = "Track name"; break;
andrew@0 270 case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
andrew@0 271 case MIDI_LYRIC: name = "Lyric"; break;
andrew@0 272 case MIDI_TEXT_MARKER: name = "Text marker"; break;
andrew@0 273 case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
andrew@0 274 case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
andrew@0 275 case MIDI_CUE_POINT: name = "Cue point"; break;
andrew@0 276 case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
andrew@0 277 case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
andrew@0 278 case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
andrew@0 279
andrew@0 280 case MIDI_SET_TEMPO:
andrew@0 281 {
andrew@0 282 int m0 = j->getMetaMessage()[0];
andrew@0 283 int m1 = j->getMetaMessage()[1];
andrew@0 284 int m2 = j->getMetaMessage()[2];
andrew@0 285 long tempo = (((m0 << 8) + m1) << 8) + m2;
andrew@0 286
andrew@0 287 cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
andrew@0 288 midiEvents.tempo = 60000000.0 / double(tempo);
andrew@0 289 midiEvents.period = double(tempo)/1000.0;
andrew@0 290
andrew@0 291 printf("period double is %f\n", midiEvents.period);
andrew@0 292 }
andrew@0 293 break;
andrew@0 294
andrew@0 295 case MIDI_TIME_SIGNATURE:
andrew@0 296 {
andrew@0 297 int numerator = j->getMetaMessage()[0];
andrew@0 298 int denominator = 1 << (int)j->getMetaMessage()[1];
andrew@0 299
andrew@0 300 cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
andrew@0 301 }
andrew@0 302
andrew@0 303 case MIDI_KEY_SIGNATURE:
andrew@0 304 {
andrew@0 305 int accidentals = j->getMetaMessage()[0];
andrew@0 306 int isMinor = j->getMetaMessage()[1];
andrew@0 307 bool isSharp = accidentals < 0 ? false : true;
andrew@0 308 accidentals = accidentals < 0 ? -accidentals : accidentals;
andrew@0 309 cout << t << ": Key signature: " << accidentals << " "
andrew@0 310 << (isSharp ?
andrew@0 311 (accidentals > 1 ? "sharps" : "sharp") :
andrew@0 312 (accidentals > 1 ? "flats" : "flat"))
andrew@0 313 << (isMinor ? ", minor" : ", major") << endl;
andrew@0 314 }
andrew@0 315
andrew@0 316 }
andrew@0 317
andrew@0 318
andrew@0 319 if (name != "") {
andrew@0 320 if (printable) {
andrew@0 321 cout << t << ": File meta event: code " << code
andrew@0 322 << ": " << name << ": \"" << j->getMetaMessage()
andrew@0 323 << "\"" << endl;
andrew@0 324 } else {
andrew@0 325 cout << t << ": File meta event: code " << code
andrew@0 326 << ": " << name << ": ";
andrew@0 327 for (int k = 0; k < j->getMetaMessage().length(); ++k) {
andrew@0 328 cout << (int)j->getMetaMessage()[k] << " ";
andrew@0 329 }
andrew@0 330 }
andrew@0 331 }
andrew@0 332 continue;
andrew@0 333 }
andrew@0 334
andrew@0 335 switch (j->getMessageType()) {
andrew@0 336
andrew@0 337 case MIDI_NOTE_ON:
andrew@0 338 cout << t << ": Note: channel " << ch
andrew@0 339 << " duration " << j->getDuration()
andrew@0 340 << " pitch " << j->getPitch()
andrew@0 341 << " velocity " << j->getVelocity()
andrew@0 342 << "event time " << midiEvents.getEventTimeMillis(t) << endl;
andrew@0 343 v.clear();
andrew@0 344 v.push_back(t);
andrew@0 345 v.push_back(j->getPitch());
andrew@0 346 v.push_back(j->getVelocity());
andrew@0 347 v.push_back(j->getDuration());
andrew@0 348 midiEvents.recordedNoteOnMatrix.push_back(v);
andrew@0 349 midiEvents.recordedEventTimes.push_back(midiEvents.getEventTimeMillis(t));
andrew@0 350 break;
andrew@0 351
andrew@0 352 case MIDI_POLY_AFTERTOUCH:
andrew@0 353 cout << t << ": Polyphonic aftertouch: channel " << ch
andrew@0 354 << " pitch " << j->getPitch()
andrew@0 355 << " pressure " << j->getData2() << endl;
andrew@0 356 break;
andrew@0 357
andrew@0 358 case MIDI_CTRL_CHANGE:
andrew@0 359 {
andrew@0 360 int controller = j->getData1();
andrew@0 361 string name;
andrew@0 362 switch (controller) {
andrew@0 363 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
andrew@0 364 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
andrew@0 365 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
andrew@0 366 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
andrew@0 367 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
andrew@0 368 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
andrew@0 369 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
andrew@0 370 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
andrew@0 371 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
andrew@0 372 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
andrew@0 373 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
andrew@0 374 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
andrew@0 375 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
andrew@0 376 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
andrew@0 377 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
andrew@0 378 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
andrew@0 379 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
andrew@0 380 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
andrew@0 381 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
andrew@0 382 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
andrew@0 383 }
andrew@0 384 cout << t << ": Controller change: channel " << ch
andrew@0 385 << " controller " << j->getData1();
andrew@0 386 if (name != "") cout << " (" << name << ")";
andrew@0 387 cout << " value " << j->getData2() << endl;
andrew@0 388 }
andrew@0 389 break;
andrew@0 390
andrew@0 391 case MIDI_PROG_CHANGE:
andrew@0 392 cout << t << ": Program change: channel " << ch
andrew@0 393 << " program " << j->getData1() << endl;
andrew@0 394 break;
andrew@0 395
andrew@0 396 case MIDI_CHNL_AFTERTOUCH:
andrew@0 397 cout << t << ": Channel aftertouch: channel " << ch
andrew@0 398 << " pressure " << j->getData1() << endl;
andrew@0 399 break;
andrew@0 400
andrew@0 401 case MIDI_PITCH_BEND:
andrew@0 402 cout << t << ": Pitch bend: channel " << ch
andrew@0 403 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
andrew@0 404 break;
andrew@0 405
andrew@0 406 case MIDI_SYSTEM_EXCLUSIVE:
andrew@0 407 cout << t << ": System exclusive: code "
andrew@0 408 << (int)j->getMessageType() << " message length " <<
andrew@0 409 j->getMetaMessage().length() << endl;
andrew@0 410 break;
andrew@0 411
andrew@0 412
andrew@0 413 }
andrew@0 414
andrew@0 415
andrew@0 416 }
andrew@0 417
andrew@0 418
andrew@0 419 }
andrew@0 420
andrew@0 421 //}
andrew@0 422
andrew@0 423
andrew@0 424
andrew@0 425
andrew@0 426 }//end cannam midi main
andrew@0 427