annotate src/CannamMidiFileLoader.cpp @ 52:13194a9dca77 tip

Added exporting of image and text data
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 17 Jul 2012 22:13:10 +0100
parents d75d16c57eac
children
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@17 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 firstTickTime = t;
andrew@3 158 }
andrew@3 159
andrew@3 160 noteOnIndex++;
andrew@3 161
andrew@2 162 v.clear();
andrew@3 163
andrew@3 164 if (!chopBeginning)
andrew@3 165 v.push_back(t);
andrew@3 166 else
andrew@3 167 v.push_back(t - firstTickTime);
andrew@3 168
andrew@2 169 v.push_back(j->getPitch());
andrew@2 170 v.push_back(j->getVelocity());
andrew@2 171 v.push_back(j->getDuration());
andrew@2 172 myMidiEvents.recordedNoteOnMatrix.push_back(v);
andrew@3 173
andrew@5 174 myMidiEvents.noteOnMatches.push_back(false);
andrew@5 175
andrew@2 176 break;
andrew@2 177
andrew@2 178 case MIDI_POLY_AFTERTOUCH:
andrew@2 179 cout << t << ": Polyphonic aftertouch: channel " << ch
andrew@2 180 << " pitch " << j->getPitch()
andrew@2 181 << " pressure " << j->getData2() << endl;
andrew@2 182 break;
andrew@2 183
andrew@2 184 case MIDI_CTRL_CHANGE:
andrew@2 185 {
andrew@2 186 int controller = j->getData1();
andrew@2 187 string name;
andrew@2 188 switch (controller) {
andrew@2 189 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
andrew@2 190 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
andrew@2 191 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
andrew@2 192 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
andrew@2 193 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
andrew@2 194 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
andrew@2 195 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
andrew@2 196 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
andrew@2 197 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
andrew@2 198 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
andrew@2 199 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
andrew@2 200 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
andrew@2 201 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
andrew@2 202 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
andrew@2 203 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
andrew@2 204 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
andrew@2 205 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
andrew@2 206 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
andrew@2 207 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
andrew@2 208 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
andrew@2 209 }
andrew@2 210 cout << t << ": Controller change: channel " << ch
andrew@2 211 << " controller " << j->getData1();
andrew@2 212 if (name != "") cout << " (" << name << ")";
andrew@2 213 cout << " value " << j->getData2() << endl;
andrew@2 214 }
andrew@2 215 break;
andrew@2 216
andrew@2 217 case MIDI_PROG_CHANGE:
andrew@2 218 cout << t << ": Program change: channel " << ch
andrew@2 219 << " program " << j->getData1() << endl;
andrew@2 220 break;
andrew@2 221
andrew@2 222 case MIDI_CHNL_AFTERTOUCH:
andrew@2 223 cout << t << ": Channel aftertouch: channel " << ch
andrew@2 224 << " pressure " << j->getData1() << endl;
andrew@2 225 break;
andrew@2 226
andrew@2 227 case MIDI_PITCH_BEND:
andrew@2 228 cout << t << ": Pitch bend: channel " << ch
andrew@2 229 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
andrew@2 230 break;
andrew@2 231
andrew@2 232 case MIDI_SYSTEM_EXCLUSIVE:
andrew@2 233 cout << t << ": System exclusive: code "
andrew@2 234 << (int)j->getMessageType() << " message length " <<
andrew@2 235 j->getMetaMessage().length() << endl;
andrew@2 236 break;
andrew@2 237
andrew@2 238
andrew@2 239 }
andrew@2 240
andrew@2 241
andrew@2 242 }
andrew@2 243
andrew@2 244
andrew@2 245 }
andrew@16 246
andrew@17 247 myMidiEvents.printRecordedEvents();
andrew@16 248 printf("|||||||||||||||||||||| \n\n\n\n\n\n\n");
andrew@16 249 myMidiEvents.reorderMatrixFromNoteTimes(myMidiEvents.recordedNoteOnMatrix);
andrew@16 250 myMidiEvents.correctTiming(myMidiEvents.recordedNoteOnMatrix);
andrew@17 251 myMidiEvents.doublecheckOrder(myMidiEvents.recordedNoteOnMatrix);
andrew@16 252
andrew@17 253 createEventTiming(myMidiEvents);
andrew@17 254
andrew@17 255 myMidiEvents.printRecordedEvents();
andrew@17 256
andrew@17 257 }//end cannam midi main
andrew@17 258
andrew@17 259
andrew@17 260 void CannamMidiFileLoader::createEventTiming( midiEventHolder& myMidiEvents){
andrew@16 261
andrew@16 262 long t;
andrew@16 263 t = myMidiEvents.recordedNoteOnMatrix[0][0];
andrew@16 264 firstNoteTime = myMidiEvents.getEventTimeMillis(t);
andrew@16 265
andrew@16 266 for (int i = 0; i < myMidiEvents.recordedNoteOnMatrix.size();i++){
andrew@16 267 t = myMidiEvents.recordedNoteOnMatrix[i][0];
andrew@2 268
andrew@16 269 if (!chopBeginning)
andrew@16 270 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));
andrew@16 271 else {
andrew@16 272 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t) - firstNoteTime);
andrew@17 273
andrew@16 274 }
andrew@16 275 }
andrew@16 276
andrew@17 277 }
andrew@2 278
andrew@2 279
andrew@2 280