void appendMidi(MidiFile& outfile, const char* filename, double seconds, int initQ) { MidiFile infile(filename); infile.joinTracks(); infile.deltaTicks(); int i; int tpq; int count; MidiEvent anevent; if (initQ == 0) { outfile.joinTracks(); count = infile.getEventCount(0); // don't include end-of-track meta event count--; tpq = infile.getTicksPerQuarterNote(); outfile.setTicksPerQuarterNote(tpq); for (i=0; i<count; i++) { anevent = infile.getEvent(0,i); // storing as a type-0 file, so remove track information anevent.track = 0; outfile.addEvent(anevent); } return; } // presuming constant tpq for different files. tpq = outfile.getTicksPerQuarterNote(); if (seconds > 0.0) { // insert a tempo marking of 120, and then a pause related to how // long in second to wait until next MIDI file contents. // micro-seconds per quarter note is last three bytes of meta message // If quarter note is 120 bpm, that is 0.5 seconds or 500000 usec. // In hex 500000 is 07 a1 20 // Tempo meta event: ff 51 03 07 a1 20 vector<uchar> bpm120; bpm120.resize(3); bpm120[0] = 0x07; bpm120[1] = 0xa1; bpm120[2] = 0x20; outfile.addMetaEvent(0, 0, 0x51, bpm120); infile.getEvent(0,0).tick = int(seconds * 2 * tpq + 0.5); } count = infile.getEventCount(0); // don't include end-of-track meta event count--; for (i=0; i<count; i++) { anevent = infile.getEvent(0,i); anevent.track = 0; outfile.addEvent(anevent); } }
int main(int argc, char** argv) { MidiFile outputfile; // create an empty MIDI file with one track outputfile.absoluteTicks(); // time information stored as absolute time // (will be coverted to delta time when written) outputfile.addTrack(2); // Add another two tracks to the MIDI file vector<uchar> midievent; // temporary storage for MIDI events midievent.resize(3); // set the size of the array to 3 bytes int tpq = 120; // default value in MIDI file is 48 outputfile.setTicksPerQuarterNote(tpq); // data to write to MIDI file: (60 = middle C) // C5 C G G A A G- F F E E D D C- int melody[50] = {72,72,79,79,81,81,79,77,77,76,76,74,74,72,-1}; int mrhythm[50] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2,-1}; // C3 C4 E C F C E C D B3 C4 A3 F G C- int bass[50] = {48,60,64,60,65,60,64,60,62,59,60,57,53,55,48,-1}; int brhythm[50]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,-1}; // store a melody line in track 1 (track 0 left empty for conductor info) int i=0; int actiontime = 0; // temporary storage for MIDI event time midievent[2] = 64; // store attack/release velocity for note command while (melody[i] >= 0) { midievent[0] = 0x90; // store a note on command (MIDI channel 1) midievent[1] = melody[i]; outputfile.addEvent(1, actiontime, midievent); actiontime += tpq * mrhythm[i]; midievent[0] = 0x80; // store a note on command (MIDI channel 1) outputfile.addEvent(1, actiontime, midievent); i++; } // store a base line in track 2 i=0; actiontime = 0; // reset time for beginning of file midievent[2] = 64; while (bass[i] >= 0) { midievent[0] = 0x90; midievent[1] = bass[i]; outputfile.addEvent(2, actiontime, midievent); actiontime += tpq * brhythm[i]; midievent[0] = 0x80; outputfile.addEvent(2, actiontime, midievent); i++; } outputfile.sortTracks(); // make sure data is in correct order outputfile.write("twinkle.mid"); // write Standard MIDI File twinkle.mid return 0; }
void createMidiFile(const char* filename, vector<vector<int> >& sequence) { MidiFile midifile; midifile.absoluteTicks(); midifile.addTrack(1); int tpq = 120; double beat = 0.0; midifile.setTicksPerQuarterNote(tpq); MidiEvent tempo; tempo.setMetaTempo(60.0); tempo.track = 0; tempo.tick = 0; midifile.addEvent(tempo); int maxlen = 0; int i, j; for (i=0; i<(int)sequence.size(); i++) { if ((int)sequence[i].size() > maxlen) { maxlen = sequence[i].size(); } } vector<int> notelist; MidiEvent noteon(0x90, 0, 64); MidiEvent noteoff(0x80, 0, 64); noteon.track = 1; noteoff.track = 1; for (i=0; i<maxlen; i++) { notelist.clear(); for (j=0; j<(int)sequence.size(); j++) { if (i<(int)sequence[j].size()) { notelist.push_back(sequence[j][i]); } } for (j=0; j<(int)notelist.size(); j++) { noteon[1] = 0x7f & notelist[j]; noteoff[1] = 0x7f & notelist[j]; noteon.tick = (int)(beat * tpq + 0.5); noteoff.tick = (int)(beat * tpq + 1 * tpq + 0.5); midifile.addEvent(noteon); midifile.addEvent(noteoff); } beat += 1.0; } midifile.sortTracks(); midifile.write(filename); }
void AddDrumTrack(MidiFile& midifile, int* data, int instrument, int ticks) { vector<uchar> midievent; // temporary storage for MIDI events midievent.resize(3); // set the size of the array to 3 bytes midievent[2] = 64; // set the loudness to a constant value int notestate = 0; // 0 = off, 1 = on int i = 0; int actiontime; int track = midifile.addTrack(); // Add a track to the MIDI file while (data[i] >= 0) { switch (data[i]) { case 'x': case 'X': if (notestate) { // turn off previous note midievent[0] = 0x89; midievent[1] = instrument; actiontime = ticks * i - 1; midifile.addEvent(track, actiontime, midievent); } // turn on current note midievent[0] = 0x99; midievent[1] = instrument; actiontime = ticks * i; midifile.addEvent(track, actiontime, midievent); notestate = 1; break; case '0': case 'o': case 'O': // turn off previous note if (notestate) { midievent[0] = 0x89; midievent[1] = instrument; actiontime = ticks * i - 1; midifile.addEvent(track, actiontime, midievent); notestate = 0; } break; } i++; } if (notestate) { // turn off last note midievent[0] = 0x89; midievent[1] = instrument; actiontime = ticks * i; midifile.addEvent(track, actiontime, midievent); } }
int main(int argc, char* argv[]) { checkOptions(options, argc, argv); MidiFile outfile; outfile.joinTracks(); outfile.deltaTicks(); int i; int initQ = 0; for (i=1; i<=options.getArgCount(); i++) { appendMidi(outfile, options.getArg(i).data(), seconds, initQ++); } // insert an end-of track Meta Event int tpq = outfile.getTicksPerQuarterNote(); MidiEvent mfevent; mfevent.tick = tpq; mfevent.track = 0; mfevent.resize(3); mfevent[0] = 0xff; mfevent[1] = 0x2f; mfevent[2] = 0; outfile.addEvent(mfevent); if (binaryQ) { outfile.write(cout); } else { cout << outfile; } return 0; }
void midiProcessing::generateMidiFile(const char *filePath, int size) { srand (time(NULL)); MidiFile outputFile; outputFile.absoluteTime(); outputFile.addTrack(1); outputFile.setTicksPerQuarterNote(tpq); Array<uchar> midiEvent; midiEvent.setSize(3); int actionTime = 0; int tempVectorIndex = 0; std::vector<note> tempNote; int tempIndex; for (int i = 0; i < size; i++) { tempNote = midiProcessing::markovList.at(tempVectorIndex); tempIndex = (rand() % (midiProcessing::markovList.at(tempVectorIndex).size()-1)) + 1; midiEvent[0] = 0x90; midiEvent[1] = tempNote.at(tempIndex).getNumber(); midiEvent[2] = tempNote.at(tempIndex).getVelocity(); outputFile.addEvent(1, actionTime, midiEvent); midiEvent[0] = 0x80; outputFile.addEvent(1, (tempNote.at(tempIndex).getDuration())+actionTime, midiEvent); actionTime += tempNote.at(tempIndex).getRest(); for (int j = 0; j < midiProcessing::markovList.size(); j++) { if (midiProcessing::markovList.at(j).at(0).getNumber() == tempNote.at(tempIndex).getNumber()) { tempVectorIndex = j; break; } } } outputFile.sortTracks(); outputFile.write(filePath); }
void createMidiFile(MidiFile& midifile, HumdrumFile& infile) { Array<int> millitimes; Array<double> velocities; Array<int> keynum; Array<int> track; millitimes.setSize(infile.getNumLines()); velocities.setSize(infile.getNumLines()); keynum.setSize(infile.getNumLines()); track.setSize(infile.getNumLines()); millitimes.setSize(0); velocities.setSize(0); keynum.setSize(0); track.setSize(0); int intval; double floatval; double dmax = -100000; double dmin = +100000; int i; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isData()) { continue; } sscanf(infile[i][0], "%lf", &floatval); intval = int(floatval * 1000.0 + 0.5); millitimes.append(intval); sscanf(infile[i][1], "%lf", &floatval); velocities.append(floatval); if (floatval < dmin) { dmin = floatval; } if (floatval > dmax) { dmax = floatval; } intval = getMIDIKeyNum(infile[i][2]); keynum.append(intval); intval = getTrackNumber(infile[i][2]); track.append(intval); } millitimes.allowGrowth(0); velocities.allowGrowth(0); keynum.allowGrowth(0); track.allowGrowth(0); // normalize the dynamics data into the range from 0 to 1 double diff = dmax - dmin; for (i=0; i<velocities.getSize(); i++) { if (diff > 0.0) { velocities[i] = (velocities[i] - dmin) / diff; } else { velocities[i] = 0.5; } } // now ready to write the data to the MIDI file: midifile.setMillisecondDelta(); // SMPTE 25 frames & 40 subframes midifile.absoluteTime(); // Time values inserted are absolute midifile.addTrack(2); // Right and Left hands Array<uchar> event; event.setSize(3); int intdur = int(duration * 1000.0 + 0.5); int lasttime = 0; int dyndiff = maxdyn - mindyn; int vel; for (i=0; i<millitimes.getSize(); i++) { if ((keynum[i] <= 10) || (keynum[i] > 127)) { continue; } vel = int(velocities[i] * dyndiff + mindyn + 0.5); if (vel < 1) { vel = 1; } if (vel > 127) { vel = 127; } event[0] = 0x90; // note-on event[1] = keynum[i]; event[2] = vel; midifile.addEvent(track[i], millitimes[i], event); event[2] = 0; lasttime = millitimes[i] + intdur; midifile.addEvent(track[i], lasttime, event); } // write the end of track marker event[0] = 0xff; event[1] = 0x2f; event[2] = 0; for (i=0; i<midifile.getTrackCount(); i++) { if (i>0) { // have to lengthen the last note in track due to bugs // in various MIDI playback programs which clip // the last chord of a file midifile.getEvent(i, midifile.getNumEvents(i)-1).time += 1500; } midifile.addEvent(i, lasttime+2000, event); } // add comments from header for (i=0; i<infile.getNumLines() && i<lasttime; i++) { if (infile[i].isBibliographic() || infile[i].isGlobalComment()) { // 0x01 is a text event midifile.addMetaEvent(0, i, 0x01, infile[i].getLine()); } } // sort the ontimes and offtimes so they are in correct time order: midifile.sortTracks(); }