annotate src/CannamMidiFileLoader.cpp @ 2:5581023e0de4

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