// // Programmer: Craig Stuart Sapp // Creation Date: Tue Apr 16 22:10:12 PDT 2002 // Last Modified: Fri Apr 19 13:03:58 PDT 2002 // Filename: ...sig/doc/examples/all/timeplay/timeplay.cpp // Syntax: C++ // // Description: Play **kern entries in a Humdrum file through MIDI // by following a **time spine. // #include "synthImprov.h" #include "humdrum.h" #include /*----------------- beginning of improvization algorithms ---------------*/ SigTimer timer; // for playing the humdrum file EventBuffer eventBuffer; // for storing note offs when playing notes HumdrumFile data; // humdrum file to play int linenum = 0; // for keeping track of current line in file int velocity = 64; // default velocity to play MIDI notes int echoTextQ = 1; // boolean for displaying input file int fileNumber = 1; // current file number being played int mine = 0; // used with the -m option int shortenQ = 0; // used with the -s option int shortenamount = 0; // used with the -s option int debugQ = 0; // used with the --debug option Array timings; // function declarations: void checkOptions (void); void inputNewFile (HumdrumFile& data, Array& timings); void playdata (HumdrumFile& data, int& linenum, SigTimer& timer, Array& timings); void printInputLine (HumdrumRecord& record); void processNotes (HumdrumFile& data, int line, Array& timings); double getDeltaTimeValue (HumdrumFile& data, int linenum, Array& timings); void getTimings (HumdrumFile& data, Array& timings); int getendline (HumdrumFile& data, int startline, double duration); /*--------------------- maintenance algorithms --------------------------*/ void description(void) { printboxtop(); psl(" TIMEPLAY -- by Craig Stuart Sapp " "-- 16 Apr 2002\n"); printboxbottom(); } void initialization(void) { checkOptions(); timer.setPeriod(500); timer.reset(); eventIdler.setPeriod(0); eventBuffer.setPollPeriod(10); } void finishup(void) { eventBuffer.off(); } /*-------------------- main loop algorithms -----------------------------*/ void mainloopalgorithms(void) { eventBuffer.checkPoll(); if (timer.expired()) { playdata(data, linenum, timer, timings); if (linenum >= data.getNumLines()) { inputNewFile(data, timings); } } } /*-------------------- triggered algorithms -----------------------------*/ void keyboardchar(int key) { switch (key) { case ' ': // toggle display of file while playing echoTextQ = !echoTextQ; if (echoTextQ) { cout << "!! FILE DISPLAY TURNED ON" << endl; } else { cout << "!! FILE DISPLAY TURNED OFF" << endl; } break; case 's': // silence notes eventBuffer.off(); break; } } /*------------------ end improvization algorithms -----------------------*/ ////////////////////////////// // // checkOptions -- process command-line options and setup the // humdrum data to play. // void checkOptions(void) { options.define("p|pause=d:1.0", "pause time in seconds between files"); options.define("q|quiet=b", "Turn off data echoing while playing"); options.define("v|velocity=i:64", "Default MIDI key velocity"); options.define("m|min=i:0", "minimum tick duration of notes"); options.define("s|shorten=i:0", "shortening tick value for note durations"); options.define("debug=b", "debug messages turned on"); options.process(); debugQ = options.getBoolean("debug"); velocity = options.getInteger("velocity"); if (options.getBoolean("quiet")) { echoTextQ = 0; } if (options.getArgCount() < 1) { data.read(cin); } else { inputNewFile(data, timings); } mine = options.getInteger("min"); if (mine < 0) { mine = 0; } shortenQ = options.getBoolean("shorten"); shortenamount = options.getInteger("shorten"); } ////////////////////////////// // // inputNewFile -- load in a new Humdrum file. // void inputNewFile(HumdrumFile& data, Array& timings) { data.clear(); linenum = 0; int count = options.getArgCount(); if (fileNumber > count) { finishup(); exit(0); } data.read(options.getArg(fileNumber)); data.analyzeRhythm("4"); getTimings(data, timings); if (fileNumber > 1) { millisleep((float)(1000 * options.getDouble("pause"))); } fileNumber++; } ////////////////////////////// // // getTimings -- get the absolute timing values from the humdrum file. // void getTimings(HumdrumFile& data, Array& timings) { int i, j; timings.setSize(data.getNumLines()); timings.allowGrowth(0); timings.setAll(-1.0); for (i=0; i=0; i--) { if (timings[i] == -1.0) { timings[i] = current; } else { current = timings[i]; } } // print timings if (debugQ) { for (int i=0; i& timings) { double duration = 0.0; // duration of the current line; while (linenum < data.getNumLines() && duration == 0.0) { duration = getDeltaTimeValue(data, linenum, timings); if (data[linenum].isData()) { processNotes(data, linenum, timings); } if (echoTextQ) { printInputLine(data[linenum]); } if (duration > 0.0) { timer.setPeriod(duration); timer.reset(); } linenum++; } } ////////////////////////////// // // printInputLine -- print the current line of the file, // omitting the duration field at the end of the line // void printInputLine(HumdrumRecord& record) { cout << record.getLine() << endl; } ////////////////////////////// // // processNotes -- play all kern notes in the current record and // return the shortest note duration. // void processNotes(HumdrumFile& data, int line, Array& timings) { HumdrumRecord& record = data[line]; NoteEvent note; int pitch = 0; double duration = 0.0; int staccatoQ = 0; int accentQ = 0; int sforzandoQ = 0; int i, j; int notecount = 0; int endline = 0; char buffer[128] = {0}; for (i=0; i= duration) { return i; } } return i; } ////////////////////////////// // // getDeltaTimeValue -- return the current absolute time minus // the previous absolute time. // double getDeltaTimeValue(HumdrumFile& data, int linenum, Array& timings) { if (linenum == timings.getSize()-1) { return 0.0; } return timings[linenum+1] - timings[linenum]; }