annotate src/CannamMidiFileLoader.cpp @ 14:3f103cf78148

Checking to allow offline version
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Thu, 10 Nov 2011 17:29:45 +0000
parents df9c838d0b8f
children f0abb0e414ec
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 myMidiEvents.pulsesPerQuarternote = fr.getTimingDivision();
andrew@2 53 } else {
andrew@2 54 int frames = 256 - (td >> 8);
andrew@2 55 int subframes = td & 0xff;
andrew@2 56 cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
andrew@2 57 }
andrew@2 58
andrew@2 59 for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
andrew@2 60
andrew@2 61 cout << "Start of track: " << i->first+1 << endl;
andrew@2 62
andrew@2 63 for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
andrew@2 64
andrew@2 65 unsigned int t = j->getTime();
andrew@2 66 int ch = j->getChannelNumber();
andrew@2 67
andrew@2 68 if (j->isMeta()) {
andrew@2 69 int code = j->getMetaEventCode();
andrew@2 70 string name;
andrew@2 71 bool printable = true;
andrew@2 72 switch (code) {
andrew@2 73
andrew@2 74 case MIDI_END_OF_TRACK:
andrew@2 75 cout << t << ": End of track" << endl;
andrew@2 76 break;
andrew@2 77
andrew@2 78 case MIDI_TEXT_EVENT: name = "Text"; break;
andrew@2 79 case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
andrew@2 80 case MIDI_TRACK_NAME: name = "Track name"; break;
andrew@2 81 case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
andrew@2 82 case MIDI_LYRIC: name = "Lyric"; break;
andrew@2 83 case MIDI_TEXT_MARKER: name = "Text marker"; break;
andrew@2 84 case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
andrew@2 85 case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
andrew@2 86 case MIDI_CUE_POINT: name = "Cue point"; break;
andrew@2 87 case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
andrew@2 88 case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
andrew@2 89 case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
andrew@2 90
andrew@2 91 case MIDI_SET_TEMPO:
andrew@2 92 {
andrew@2 93 int m0 = j->getMetaMessage()[0];
andrew@2 94 int m1 = j->getMetaMessage()[1];
andrew@2 95 int m2 = j->getMetaMessage()[2];
andrew@2 96 long tempo = (((m0 << 8) + m1) << 8) + m2;
andrew@2 97
andrew@2 98 cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
andrew@2 99 myMidiEvents.tempo = 60000000.0 / double(tempo);
andrew@2 100 myMidiEvents.period = double(tempo)/1000.0;
andrew@2 101
andrew@2 102 printf("period double is %f\n", myMidiEvents.period);
andrew@2 103 }
andrew@2 104 break;
andrew@2 105
andrew@2 106 case MIDI_TIME_SIGNATURE:
andrew@2 107 {
andrew@2 108 int numerator = j->getMetaMessage()[0];
andrew@2 109 int denominator = 1 << (int)j->getMetaMessage()[1];
andrew@2 110
andrew@2 111 cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
andrew@2 112 }
andrew@2 113
andrew@2 114 case MIDI_KEY_SIGNATURE:
andrew@2 115 {
andrew@2 116 int accidentals = j->getMetaMessage()[0];
andrew@2 117 int isMinor = j->getMetaMessage()[1];
andrew@2 118 bool isSharp = accidentals < 0 ? false : true;
andrew@2 119 accidentals = accidentals < 0 ? -accidentals : accidentals;
andrew@2 120 cout << t << ": Key signature: " << accidentals << " "
andrew@2 121 << (isSharp ?
andrew@2 122 (accidentals > 1 ? "sharps" : "sharp") :
andrew@2 123 (accidentals > 1 ? "flats" : "flat"))
andrew@2 124 << (isMinor ? ", minor" : ", major") << endl;
andrew@2 125 }
andrew@2 126
andrew@2 127 }
andrew@2 128
andrew@2 129
andrew@2 130 if (name != "") {
andrew@2 131 if (printable) {
andrew@2 132 cout << t << ": File meta event: code " << code
andrew@2 133 << ": " << name << ": \"" << j->getMetaMessage()
andrew@2 134 << "\"" << endl;
andrew@2 135 } else {
andrew@2 136 cout << t << ": File meta event: code " << code
andrew@2 137 << ": " << name << ": ";
andrew@2 138 for (int k = 0; k < j->getMetaMessage().length(); ++k) {
andrew@2 139 cout << (int)j->getMetaMessage()[k] << " ";
andrew@2 140 }
andrew@2 141 }
andrew@2 142 }
andrew@2 143 continue;
andrew@2 144 }
andrew@2 145
andrew@2 146 switch (j->getMessageType()) {
andrew@2 147
andrew@2 148 case MIDI_NOTE_ON:
andrew@14 149 cout << t << ": Note: channel " << ch
andrew@2 150 << " duration " << j->getDuration()
andrew@2 151 << " pitch " << j->getPitch()
andrew@2 152 << " velocity " << j->getVelocity()
andrew@2 153 << "event time " << myMidiEvents.getEventTimeMillis(t) << endl;
andrew@14 154
andrew@3 155
andrew@3 156 if (noteOnIndex == 0){
andrew@3 157 firstNoteTime = myMidiEvents.getEventTimeMillis(t);
andrew@3 158 firstTickTime = t;
andrew@3 159 }
andrew@3 160
andrew@3 161 noteOnIndex++;
andrew@3 162
andrew@2 163 v.clear();
andrew@3 164
andrew@3 165 if (!chopBeginning)
andrew@3 166 v.push_back(t);
andrew@3 167 else
andrew@3 168 v.push_back(t - firstTickTime);
andrew@3 169
andrew@2 170 v.push_back(j->getPitch());
andrew@2 171 v.push_back(j->getVelocity());
andrew@2 172 v.push_back(j->getDuration());
andrew@2 173 myMidiEvents.recordedNoteOnMatrix.push_back(v);
andrew@3 174
andrew@3 175 if (!chopBeginning)
andrew@2 176 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));
andrew@3 177 else {
andrew@3 178 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@4 179 // printf("chopping beginning %f \n", myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@3 180 }
andrew@5 181
andrew@5 182 myMidiEvents.noteOnMatches.push_back(false);
andrew@5 183
andrew@2 184 break;
andrew@2 185
andrew@2 186 case MIDI_POLY_AFTERTOUCH:
andrew@2 187 cout << t << ": Polyphonic aftertouch: channel " << ch
andrew@2 188 << " pitch " << j->getPitch()
andrew@2 189 << " pressure " << j->getData2() << endl;
andrew@2 190 break;
andrew@2 191
andrew@2 192 case MIDI_CTRL_CHANGE:
andrew@2 193 {
andrew@2 194 int controller = j->getData1();
andrew@2 195 string name;
andrew@2 196 switch (controller) {
andrew@2 197 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
andrew@2 198 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
andrew@2 199 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
andrew@2 200 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
andrew@2 201 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
andrew@2 202 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
andrew@2 203 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
andrew@2 204 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
andrew@2 205 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
andrew@2 206 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
andrew@2 207 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
andrew@2 208 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
andrew@2 209 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
andrew@2 210 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
andrew@2 211 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
andrew@2 212 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
andrew@2 213 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
andrew@2 214 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
andrew@2 215 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
andrew@2 216 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
andrew@2 217 }
andrew@2 218 cout << t << ": Controller change: channel " << ch
andrew@2 219 << " controller " << j->getData1();
andrew@2 220 if (name != "") cout << " (" << name << ")";
andrew@2 221 cout << " value " << j->getData2() << endl;
andrew@2 222 }
andrew@2 223 break;
andrew@2 224
andrew@2 225 case MIDI_PROG_CHANGE:
andrew@2 226 cout << t << ": Program change: channel " << ch
andrew@2 227 << " program " << j->getData1() << endl;
andrew@2 228 break;
andrew@2 229
andrew@2 230 case MIDI_CHNL_AFTERTOUCH:
andrew@2 231 cout << t << ": Channel aftertouch: channel " << ch
andrew@2 232 << " pressure " << j->getData1() << endl;
andrew@2 233 break;
andrew@2 234
andrew@2 235 case MIDI_PITCH_BEND:
andrew@2 236 cout << t << ": Pitch bend: channel " << ch
andrew@2 237 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
andrew@2 238 break;
andrew@2 239
andrew@2 240 case MIDI_SYSTEM_EXCLUSIVE:
andrew@2 241 cout << t << ": System exclusive: code "
andrew@2 242 << (int)j->getMessageType() << " message length " <<
andrew@2 243 j->getMetaMessage().length() << endl;
andrew@2 244 break;
andrew@2 245
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 }//end cannam midi main
andrew@2 259
andrew@2 260
andrew@2 261
andrew@2 262