// // Programmer: Craig Stuart Sapp // Creation Date: Mon Apr 6 13:54:09 PDT 2009 // Last Modified: Mon Apr 6 13:54:12 PDT 2009 // Filename: peep2midi.cpp // Syntax: C++; museinfo // // Description: Convert Performance Expression Extraction Program // output data into MIDI data. // #include "MidiFile.h" #include "humdrum.h" #include "Options.h" #include #include #include typedef unsigned char uchar; // user interface variables Options options; int debugQ = 0; // use with --debug option int maxcount = 100000; int mindyn = 30; // use with -r option int maxdyn = 120; // use with -r option double duration = 0.1; // use with -d option string filename = ""; // use with -o option // function declarations: void checkOptions (Options& opts, int argc, char** argv); void createMidiFile (MidiFile& midifile, HumdrumFile& infile); int getMIDIKeyNum (const char* string); int getTrackNumber (const char* string); void example (void); void usage (const char* command); ////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { checkOptions(options, argc, argv); HumdrumFile infile; infile.read(options.getArg(1)); MidiFile midifile; createMidiFile(midifile, infile); if (filename == "") { cout << midifile; } else { midifile.write(filename.c_str()); } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // createMidiFile -- // input humdrum file data should be in simple columns in this order: // // **data **data **data **data **data // 1.667 18.8 F3 -2 1 // 1.666 19 C4 -1 1 // 1.667 10.7 a4 -2 1 // 1.667 19.2 c5 -2 1 // 2.009 24 F3 +10 1 // 2.01 24.2 C4 +10 1 // // Column one is the time in seconds at which the note is started // Column two is a dynamic value (the range of which will be normalized) // Column three contains the pitch information. // void createMidiFile(MidiFile& midifile, HumdrumFile& infile) { vector millitimes; vector velocities; vector keynum; vector track; millitimes.reserve(infile.getNumLines()); velocities.reserve(infile.getNumLines()); keynum.reserve(infile.getNumLines()); track.reserve(infile.getNumLines()); int intval; double floatval; double dmax = -100000; double dmin = +100000; int i; for (i=0; i dmax) { dmax = floatval; } intval = getMIDIKeyNum(infile[i][2]); keynum.push_back(intval); intval = getTrackNumber(infile[i][2]); track.push_back(intval); } // normalize the dynamics data into the range from 0 to 1 double diff = dmax - dmin; for (i=0; i<(int)velocities.size(); 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.setMillisecondTicks(); // SMPTE 25 frames & 40 subframes midifile.absoluteTicks(); // Time values inserted are absolute midifile.addTrack(2); // Right and Left hands vector event; event.resize(3); int intdur = int(duration * 1000.0 + 0.5); int lasttime = 0; int dyndiff = maxdyn - mindyn; int vel; for (i=0; i<(int)millitimes.size(); 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; i0) { // 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).tick += 1500; } midifile.addEvent(i, lasttime+2000, event); } // add comments from header for (i=0; i maxdyn) { int temp = mindyn; mindyn = maxdyn; maxdyn = temp; } if (mindyn == maxdyn) { mindyn = 20; maxdyn = 120; } } ////////////////////////////// // // example -- // void example(void) { } ////////////////////////////// // // usage -- // void usage(const char* command) { cout << "Usage: " << command << " midifile" << endl; }