// // Programmer: Craig Stuart Sapp // Creation Date: Thu Jul 22 18:59:27 PDT 2010 // Last Modified: Thu Jul 22 18:59:30 PDT 2010 // Filename: ...sig/doc/examples/all/midiexcerpt/midiexcerpt.cpp // Syntax: C++ // // Description: Extracts a time region from a MIDI file. Notes // starting before the start time will be ignored. // Notes not ending before the end time of the file // will be turned off at the given end time. // #include "Options.h" #include "MidiFile.h" #include "PerlRegularExpression.h" #include using namespace std; // function declarations: void checkOptions (Options& opts); void example (void); void usage (const char* command); double getTimeInSeconds (const char* timestring); void extractMidi (MidiFile& outputfile, MidiFile& inputfile, double starttime, double endtime); int getStartIndex (MidiFile& midifile, int starttick); int getStopIndex (MidiFile& midifile, int startindex, int stoptick); // user interface variables: double starttime = 0.0; // used with -s option double endtime = 0.0; // used with -e option /////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { int status; MidiFile inputfile; MidiFile outputfile; Options options(argc, argv); checkOptions(options); status = inputfile.read(options.getArg(1)); if (status == 0) { cout << "Syntax error in file: " << options.getArg(1) << "\n"; } extractMidi(outputfile, inputfile, starttime, endtime); outputfile.write(options.getArg(2)); return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // extractMidi -- Extract a time range from a MIDI file. If the // endtime is negative, then that means through the end of the // original MIDI file. // // void extractMidi(MidiFile& outputfile, MidiFile& inputfile, double starttime, double endtime) { outputfile.absoluteTicks(); outputfile.setTicksPerQuarterNote(inputfile.getTicksPerQuarterNote()); if (inputfile.getTrackCount() > 1) { outputfile.addTrack(inputfile.getTrackCount()-1); } // outputfile.joinTracks(); int i, j; Array > > notestates; notestates.setSize(inputfile.getTrackCountAsType1()); for (i=0; i > timbres; timbres.setSize(notestates.getSize()); for (i=0; i= 0) { eventcopy.track = track; eventcopy[0] = 0xc0 | channel; eventcopy[1] = timbres[track][channel]; outputfile.addEvent(eventcopy); } } } MidiEvent *ptr; for (i=startindex; iisNoteOff()) { if (ptr->getCommandNibble() == 0x90) { offtype90++; } else if (ptr->getCommandNibble() == 0x80) { offtype80++; } track = ptr->track; channel = ptr->getChannelNibble(); pitch = (*ptr)[1]; if (notestates[track][channel][pitch] > 0) { notestates[track][channel][pitch]--; } else { // ignore the note off, since it is from a note // which was turned on before the selected time region. continue; } } else if (ptr->isNoteOn()) { track = ptr->track; pitch = (*ptr)[1]; notestates[track][channel][pitch]++; } eventcopy = *ptr; eventcopy.tick -= starttick; outputfile.addEvent(eventcopy); } // Turn off any notes which are still on... int k; eventcopy.resize(3); eventcopy.tick = stoptick - starttick; for (track=0; track offtype80) { eventcopy[0] = (uchar)(0x90 | channel); eventcopy[0] = 0; } else { eventcopy[0] = (uchar)(0x80 | channel); eventcopy[2] = 64; } outputfile.addEvent(eventcopy); } } } } outputfile.sortTracks(); } ////////////////////////////// // // getStartIndex -- // int getStartIndex(MidiFile& midifile, int starttick) { int i; for (i=0; i