annotate src/CannamMidiFileLoader.cpp @ 5:195907bb8bb7

added purple where notes have been seen - lets you see what updates have been used. Also the chopping of midi files to the beginning was introduced recently, so when they load, you chop any white space at the beginning, then use first note to launch.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 19 Aug 2011 16:38:30 +0100
parents 4a8e6a6cd224
children df9c838d0b8f
rev   line source
andrew@2 1 /*
andrew@2 2 * CannamMidiFileLoader.cpp
andrew@2 3 * midi-score-follower
andrew@2 4 *
andrew@2 5 * Created by Andrew on 19/08/2011.
andrew@2 6 * Copyright 2011 QMUL. All rights reserved.
andrew@2 7 *
andrew@2 8 */
andrew@2 9
andrew@2 10 #include "MIDIFileReader.h"
andrew@2 11 #include "CannamMidiFileLoader.h"
andrew@2 12
andrew@3 13 CannamMidiFileLoader::CannamMidiFileLoader(){
andrew@3 14 chopBeginning = true;
andrew@3 15 }
andrew@3 16
andrew@2 17 int CannamMidiFileLoader::loadFile(std::string& filename, midiEventHolder& myMidiEvents){
andrew@2 18
andrew@3 19 noteOnIndex = 0;
andrew@2 20 myMidiEvents.clearAllEvents();
andrew@2 21
andrew@2 22 //int main(int argc, char **argv)
andrew@2 23 //{
andrew@2 24 // if (argc != 2) {
andrew@2 25 // cerr << "Usage: midifile <file.mid>" << endl;
andrew@2 26 // return 1;
andrew@2 27 // }
andrew@2 28
andrew@2 29 // std::string filename = midiFileName;//argv[1];
andrew@2 30
andrew@2 31 MIDIFileReader fr(filename);
andrew@2 32
andrew@2 33 if (!fr.isOK()) {
andrew@2 34 std::cerr << "Error: " << fr.getError().c_str() << std::endl;
andrew@2 35 return 1;
andrew@2 36 }
andrew@2 37
andrew@2 38 MIDIComposition c = fr.load();
andrew@2 39
andrew@2 40 switch (fr.getFormat()) {
andrew@2 41 case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break;
andrew@2 42 case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break;
andrew@2 43 case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break;
andrew@2 44 default: cout << "Format: Unknown MIDI file format?" << endl; break;
andrew@2 45 }
andrew@2 46
andrew@2 47 cout << "Tracks: " << c.size() << endl;
andrew@2 48
andrew@2 49 int td = fr.getTimingDivision();
andrew@2 50 if (td < 32768) {
andrew@2 51 cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
andrew@2 52
andrew@2 53 myMidiEvents.pulsesPerQuarternote = fr.getTimingDivision();
andrew@2 54 } else {
andrew@2 55 int frames = 256 - (td >> 8);
andrew@2 56 int subframes = td & 0xff;
andrew@2 57 cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
andrew@2 58 }
andrew@2 59
andrew@2 60 for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
andrew@2 61
andrew@2 62 cout << "Start of track: " << i->first+1 << endl;
andrew@2 63
andrew@2 64 for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
andrew@2 65
andrew@2 66 unsigned int t = j->getTime();
andrew@2 67 int ch = j->getChannelNumber();
andrew@2 68
andrew@2 69 if (j->isMeta()) {
andrew@2 70 int code = j->getMetaEventCode();
andrew@2 71 string name;
andrew@2 72 bool printable = true;
andrew@2 73 switch (code) {
andrew@2 74
andrew@2 75 case MIDI_END_OF_TRACK:
andrew@2 76 cout << t << ": End of track" << endl;
andrew@2 77 break;
andrew@2 78
andrew@2 79 case MIDI_TEXT_EVENT: name = "Text"; break;
andrew@2 80 case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
andrew@2 81 case MIDI_TRACK_NAME: name = "Track name"; break;
andrew@2 82 case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
andrew@2 83 case MIDI_LYRIC: name = "Lyric"; break;
andrew@2 84 case MIDI_TEXT_MARKER: name = "Text marker"; break;
andrew@2 85 case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
andrew@2 86 case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
andrew@2 87 case MIDI_CUE_POINT: name = "Cue point"; break;
andrew@2 88 case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
andrew@2 89 case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
andrew@2 90 case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
andrew@2 91
andrew@2 92 case MIDI_SET_TEMPO:
andrew@2 93 {
andrew@2 94 int m0 = j->getMetaMessage()[0];
andrew@2 95 int m1 = j->getMetaMessage()[1];
andrew@2 96 int m2 = j->getMetaMessage()[2];
andrew@2 97 long tempo = (((m0 << 8) + m1) << 8) + m2;
andrew@2 98
andrew@2 99 cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
andrew@2 100 myMidiEvents.tempo = 60000000.0 / double(tempo);
andrew@2 101 myMidiEvents.period = double(tempo)/1000.0;
andrew@2 102
andrew@2 103 printf("period double is %f\n", myMidiEvents.period);
andrew@2 104 }
andrew@2 105 break;
andrew@2 106
andrew@2 107 case MIDI_TIME_SIGNATURE:
andrew@2 108 {
andrew@2 109 int numerator = j->getMetaMessage()[0];
andrew@2 110 int denominator = 1 << (int)j->getMetaMessage()[1];
andrew@2 111
andrew@2 112 cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
andrew@2 113 }
andrew@2 114
andrew@2 115 case MIDI_KEY_SIGNATURE:
andrew@2 116 {
andrew@2 117 int accidentals = j->getMetaMessage()[0];
andrew@2 118 int isMinor = j->getMetaMessage()[1];
andrew@2 119 bool isSharp = accidentals < 0 ? false : true;
andrew@2 120 accidentals = accidentals < 0 ? -accidentals : accidentals;
andrew@2 121 cout << t << ": Key signature: " << accidentals << " "
andrew@2 122 << (isSharp ?
andrew@2 123 (accidentals > 1 ? "sharps" : "sharp") :
andrew@2 124 (accidentals > 1 ? "flats" : "flat"))
andrew@2 125 << (isMinor ? ", minor" : ", major") << endl;
andrew@2 126 }
andrew@2 127
andrew@2 128 }
andrew@2 129
andrew@2 130
andrew@2 131 if (name != "") {
andrew@2 132 if (printable) {
andrew@2 133 cout << t << ": File meta event: code " << code
andrew@2 134 << ": " << name << ": \"" << j->getMetaMessage()
andrew@2 135 << "\"" << endl;
andrew@2 136 } else {
andrew@2 137 cout << t << ": File meta event: code " << code
andrew@2 138 << ": " << name << ": ";
andrew@2 139 for (int k = 0; k < j->getMetaMessage().length(); ++k) {
andrew@2 140 cout << (int)j->getMetaMessage()[k] << " ";
andrew@2 141 }
andrew@2 142 }
andrew@2 143 }
andrew@2 144 continue;
andrew@2 145 }
andrew@2 146
andrew@2 147 switch (j->getMessageType()) {
andrew@2 148
andrew@2 149 case MIDI_NOTE_ON:
andrew@4 150 /* cout << t << ": Note: channel " << ch
andrew@2 151 << " duration " << j->getDuration()
andrew@2 152 << " pitch " << j->getPitch()
andrew@2 153 << " velocity " << j->getVelocity()
andrew@2 154 << "event time " << myMidiEvents.getEventTimeMillis(t) << endl;
andrew@4 155 */
andrew@3 156
andrew@3 157 if (noteOnIndex == 0){
andrew@3 158 firstNoteTime = myMidiEvents.getEventTimeMillis(t);
andrew@3 159 firstTickTime = t;
andrew@3 160 }
andrew@3 161
andrew@3 162 noteOnIndex++;
andrew@3 163
andrew@2 164 v.clear();
andrew@3 165
andrew@3 166 if (!chopBeginning)
andrew@3 167 v.push_back(t);
andrew@3 168 else
andrew@3 169 v.push_back(t - firstTickTime);
andrew@3 170
andrew@2 171 v.push_back(j->getPitch());
andrew@2 172 v.push_back(j->getVelocity());
andrew@2 173 v.push_back(j->getDuration());
andrew@2 174 myMidiEvents.recordedNoteOnMatrix.push_back(v);
andrew@3 175
andrew@3 176 if (!chopBeginning)
andrew@2 177 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));
andrew@3 178 else {
andrew@3 179 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@4 180 // printf("chopping beginning %f \n", myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@3 181 }
andrew@5 182
andrew@5 183 myMidiEvents.noteOnMatches.push_back(false);
andrew@5 184
andrew@2 185 break;
andrew@2 186
andrew@2 187 case MIDI_POLY_AFTERTOUCH:
andrew@2 188 cout << t << ": Polyphonic aftertouch: channel " << ch
andrew@2 189 << " pitch " << j->getPitch()
andrew@2 190 << " pressure " << j->getData2() << endl;
andrew@2 191 break;
andrew@2 192
andrew@2 193 case MIDI_CTRL_CHANGE:
andrew@2 194 {
andrew@2 195 int controller = j->getData1();
andrew@2 196 string name;
andrew@2 197 switch (controller) {
andrew@2 198 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
andrew@2 199 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
andrew@2 200 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
andrew@2 201 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
andrew@2 202 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
andrew@2 203 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
andrew@2 204 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
andrew@2 205 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
andrew@2 206 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
andrew@2 207 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
andrew@2 208 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
andrew@2 209 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
andrew@2 210 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
andrew@2 211 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
andrew@2 212 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
andrew@2 213 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
andrew@2 214 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
andrew@2 215 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
andrew@2 216 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
andrew@2 217 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
andrew@2 218 }
andrew@2 219 cout << t << ": Controller change: channel " << ch
andrew@2 220 << " controller " << j->getData1();
andrew@2 221 if (name != "") cout << " (" << name << ")";
andrew@2 222 cout << " value " << j->getData2() << endl;
andrew@2 223 }
andrew@2 224 break;
andrew@2 225
andrew@2 226 case MIDI_PROG_CHANGE:
andrew@2 227 cout << t << ": Program change: channel " << ch
andrew@2 228 << " program " << j->getData1() << endl;
andrew@2 229 break;
andrew@2 230
andrew@2 231 case MIDI_CHNL_AFTERTOUCH:
andrew@2 232 cout << t << ": Channel aftertouch: channel " << ch
andrew@2 233 << " pressure " << j->getData1() << endl;
andrew@2 234 break;
andrew@2 235
andrew@2 236 case MIDI_PITCH_BEND:
andrew@2 237 cout << t << ": Pitch bend: channel " << ch
andrew@2 238 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
andrew@2 239 break;
andrew@2 240
andrew@2 241 case MIDI_SYSTEM_EXCLUSIVE:
andrew@2 242 cout << t << ": System exclusive: code "
andrew@2 243 << (int)j->getMessageType() << " message length " <<
andrew@2 244 j->getMetaMessage().length() << endl;
andrew@2 245 break;
andrew@2 246
andrew@2 247
andrew@2 248 }
andrew@2 249
andrew@2 250
andrew@2 251 }
andrew@2 252
andrew@2 253
andrew@2 254 }
andrew@2 255
andrew@2 256
andrew@2 257
andrew@2 258
andrew@2 259 }//end cannam midi main
andrew@2 260
andrew@2 261
andrew@2 262
andrew@2 263