annotate src/CannamMidiFileLoader.cpp @ 3:de86d77f2612

added speed prior setting. needs some cleaning
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 19 Aug 2011 02:36:34 +0100
parents 5581023e0de4
children 4a8e6a6cd224
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@2 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@3 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@3 180 printf("chopping beginning %f \n", myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@3 181 }
andrew@3 182
andrew@2 183 break;
andrew@2 184
andrew@2 185 case MIDI_POLY_AFTERTOUCH:
andrew@2 186 cout << t << ": Polyphonic aftertouch: channel " << ch
andrew@2 187 << " pitch " << j->getPitch()
andrew@2 188 << " pressure " << j->getData2() << endl;
andrew@2 189 break;
andrew@2 190
andrew@2 191 case MIDI_CTRL_CHANGE:
andrew@2 192 {
andrew@2 193 int controller = j->getData1();
andrew@2 194 string name;
andrew@2 195 switch (controller) {
andrew@2 196 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
andrew@2 197 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
andrew@2 198 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
andrew@2 199 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
andrew@2 200 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
andrew@2 201 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
andrew@2 202 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
andrew@2 203 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
andrew@2 204 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
andrew@2 205 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
andrew@2 206 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
andrew@2 207 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
andrew@2 208 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
andrew@2 209 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
andrew@2 210 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
andrew@2 211 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
andrew@2 212 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
andrew@2 213 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
andrew@2 214 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
andrew@2 215 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
andrew@2 216 }
andrew@2 217 cout << t << ": Controller change: channel " << ch
andrew@2 218 << " controller " << j->getData1();
andrew@2 219 if (name != "") cout << " (" << name << ")";
andrew@2 220 cout << " value " << j->getData2() << endl;
andrew@2 221 }
andrew@2 222 break;
andrew@2 223
andrew@2 224 case MIDI_PROG_CHANGE:
andrew@2 225 cout << t << ": Program change: channel " << ch
andrew@2 226 << " program " << j->getData1() << endl;
andrew@2 227 break;
andrew@2 228
andrew@2 229 case MIDI_CHNL_AFTERTOUCH:
andrew@2 230 cout << t << ": Channel aftertouch: channel " << ch
andrew@2 231 << " pressure " << j->getData1() << endl;
andrew@2 232 break;
andrew@2 233
andrew@2 234 case MIDI_PITCH_BEND:
andrew@2 235 cout << t << ": Pitch bend: channel " << ch
andrew@2 236 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
andrew@2 237 break;
andrew@2 238
andrew@2 239 case MIDI_SYSTEM_EXCLUSIVE:
andrew@2 240 cout << t << ": System exclusive: code "
andrew@2 241 << (int)j->getMessageType() << " message length " <<
andrew@2 242 j->getMetaMessage().length() << endl;
andrew@2 243 break;
andrew@2 244
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 }//end cannam midi main
andrew@2 258
andrew@2 259
andrew@2 260
andrew@2 261