// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Thu Jul 9 13:20:28 PDT 1998 // Last Modified: Tue Dec 5 15:11:50 PST 2000 (enable polyphonic sampling) // Filename: ...sig/examples/all/sample.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/sample.cpp // Syntax: C++; museinfo // // Description: Samples pitches according to the given pattern // #include "humdrum.h" #include "CircularBuffer.h" #include <math.h> #include <string.h> #include <ctype.h> // function declarations void checkOptions(Options& opts, int argc, char* argv[]); void createDataLine(char* buffer, HumdrumFile& infile, int line, double duration, int style); void example(void); void processRecords(HumdrumFile& infile, HumdrumFile& outfile); void usage(const char* command); // interface variables Options options; // database for command-line arguments CircularBuffer<double> durations(1000); CircularBuffer<int> styles(1000); /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile infile, outfile; // process the command-line options checkOptions(options, argc, argv); // figure out the number of input files to process int numinputs = options.getArgCount(); for (int i=0; i<numinputs || i==0; i++) { infile.clear(); outfile.clear(); // if no command-line arguments read data file from standard input if (numinputs < 1) { infile.read(cin); } else { infile.read(options.getArg(i+1)); } // analyze the input file according to command-line options processRecords(infile, outfile); outfile.write(cout); } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("r|rhythm|rhythm-cycle|=s:4"); // rhythm to sample notes at opts.define("m|metric=s"); // metric cycle to sample opts.define("d|divide=b"); // determine if to split input notes opts.define("debug=b"); // determine bad input line num opts.define("author=b"); // author of program opts.define("version=b"); // compilation info opts.define("example=b"); // example usages opts.define("h|help=b"); // short description opts.process(argc, argv); // handle basic options: if (opts.getBoolean("author")) { cout << "Written by Craig Stuart Sapp, " << "craig@ccrma.stanford.edu, July 1998" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 5 December 2000" << endl; cout << "compiled: " << __DATE__ << endl; cout << MUSEINFO_VERSION << endl; exit(0); } else if (opts.getBoolean("help")) { usage(opts.getCommand()); exit(0); } else if (opts.getBoolean("example")) { example(); exit(0); } double duration = 0.0; int style = 0; int length; length = strlen(opts.getString("rhythm")); char buffer[length + 1]; strcpy(buffer, opts.getString("rhythm")); durations.reset(); styles.reset(); char *durstr; durstr = strtok(buffer, " ,:\t\n;"); while (durstr != NULL) { duration = Convert::kernToDuration(durstr); if (strchr(durstr, 'r') != 0) { style = 'r'; } else if (strchr(durstr, 'x') != 0) { style = 'x'; } else { style = 0; } durations.insert(duration); styles.insert(style); durstr = strtok(NULL, " ,:\t\n;"); } } ////////////////////////////// // // example -- example usage of the sample program // void example(void) { cout << " \n" "# example usage of the sample program. \n" " \n" << endl; } ////////////////////////////// // // processRecords -- // void processRecords(HumdrumFile& infile, HumdrumFile& outfile) { infile.analyzeRhythm(); char buffer[10000] = {0}; int style; double duration; style = styles.extract(); duration = durations.extract(); double currbeat = 0; double targetbeat = 0; int lastline = 0; double currdur; int state = 0; for (int i=0; i<infile.getNumLines(); i++) { if (options.getBoolean("debug")) { cout << "processing line " << (i+1) << " of input ..." << endl; } if (infile[i].getType() != E_humrec_data) { outfile.appendLine(infile[i]); continue; } state = 0; currbeat = infile[i].getAbsBeat(); currdur = infile[i].getDuration(); while ((currbeat+currdur > targetbeat) || (fabs(currbeat-targetbeat) < 0.001)) { if (fabs(currbeat - targetbeat) < 0.0001) { createDataLine(buffer, infile, i, duration, style); outfile.appendLine(buffer); styles.insert(style); durations.insert(duration); style = styles.extract(); duration = durations.extract(); targetbeat += duration; } else if (currbeat+currdur > targetbeat) { if (state == 1) { createDataLine(buffer, infile, lastline, duration, style); } else { createDataLine(buffer, infile, i, duration, style); } outfile.appendLine(buffer); styles.insert(style); durations.insert(duration); style = styles.extract(); duration = durations.extract(); targetbeat += duration; } else { break; } } lastline = i; } } ////////////////////////////// // // createDataLine -- // void createDataLine(char* buffer, HumdrumFile& infile, int line, double duration, int style) { buffer[0] = '\0'; if (style == 'x') { return; } char dstring[100] = {0}; char pbuffer[100] = {0}; char tbuffer[100] = {0}; int tokencount; Convert::durationToKernRhythm(dstring, duration); int pitch; int i, k; for (i=0; i<infile[line].getFieldCount(); i++) { if (infile[line].getExInterpNum(i) == E_KERN_EXINT) { if (strcmp(infile[line][i], ".") == 0) { int dotline = infile[line].getDotLine(i); int dotspine = infile[line].getDotSpine(i); tokencount = infile[dotline].getTokenCount(dotspine); for (k=0; k<tokencount; k++) { infile[dotline].getToken(tbuffer, dotspine, k); pitch = Convert::kernToBase40(tbuffer); Convert::base40ToKern(pbuffer, pitch); strcat(buffer, dstring); if (style == 'r') { strcat(buffer, "r"); } else { strcat(buffer, pbuffer); } if (k < tokencount - 1) { strcat(buffer, " "); } } } else { tokencount = infile[line].getTokenCount(i); for (k=0; k<tokencount; k++) { infile[line].getToken(tbuffer, i, k); pitch = Convert::kernToBase40(tbuffer); Convert::base40ToKern(pbuffer, pitch); strcat(buffer, dstring); if (style == 'r') { strcat(buffer, "r"); } else { strcat(buffer, pbuffer); } if (k < tokencount - 1) { strcat(buffer, " "); } } } strcat(buffer, "\t"); } else { continue; } } // remove any extra tab character that might have been added. int length = strlen(buffer); if (buffer[length-1] == '\t') { buffer[length-1] = '\0'; } } ////////////////////////////// // // usage -- gives the usage statement for the sample program // void usage(const char* command) { cout << " \n" "Analyzes **kern data and generates a rhythmic analysis which gives \n" "the beat location of **kern data records in the measure. Currently, \n" "input spines cannot split or join. \n" " \n" "Usage: " << command << " [-a][-b base-rhythm][-s|-d][input1 [input2 ...]]\n" " \n" "Options: \n" " -b = set the base rhythm for analysis to specified kern rhythm value. \n" " -d = gives the duration of each kern record in beat measurements. \n" " -s = sum the beat count in each measure. \n" " --options = list of all options, aliases and default values \n" " \n" << endl; } // md5sum: 6e41ca61d5e538864e16c6c86db90137 sample.cpp [20050403]