#include "music.h" //event times & durations are absolute integer milliseconds note::note(int n,int v,int d){ num=n; velocity=v; duration=d; } void musicscore::parseMidi(string filename){ // millis = 60000 / (BPM * PPQ) // BPM = 60000000 / MQPN (last 3 bytes of midi tempoSet) // http://www.lastrayofhope.com/2009/12/23/midi-delta-time-ticks-to-seconds/ // presume no change in time signature? //2 passes:: extract notes & set abs times, then scan for float wt=ofGetElapsedTimef(); float BPM=120.0f; //input:: MPQN :: default 500000 float MPQN=60000000.0f/BPM; //unknown:: ticks per quarter note int TPQN=96; //want:: seconds per tick in float float SPT =(MPQN/1000000.0f)/TPQN; float time=0; //counts up in float seconds but converts to millis for map index map events; if( !XML.loadFile(filename) ){ printf("unable to load %s check data/ folder\n",filename.c_str()); }else{ if(XML.pushTag("MidiFile")) { for (int i=0;i::iterator iter1; map::iterator iter2; for (iter1 = events.begin(); iter1 != events.end(); ++iter1) { if (iter1->second->duration==144) { iter1->second->duration=0; iter2=iter1; while (++iter2 != events.end()) { if ((iter1->second->num==iter2->second->num)&&(iter2->second->duration==128)) { iter1->second->duration=iter2->first-iter1->first; notes[iter1->first]=iter1->second; //printf("%i: noteon %i %i\n",iter1->first,iter1->second->num,iter1->second->duration); break; } } } } printf("processed %s: %i notes in %f seconds\n",filename.c_str(),notes.size(),ofGetElapsedTimef()-wt); } song::song(string backfile,string melfile,string notefile) { backing.loadSound(backfile); melody.loadSound(melfile); notes.parseMidi(notefile); bpm=bpm; //can be used to set tempo eventually? keeps everything simple to do it this way }