// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Mon Dec 18 03:41:53 PST 2006 // Last Modified: Mon Dec 18 03:42:01 PST 2006 // Filename: ...sig/examples/all/onsetbeats.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/onsetbeats.cpp // Syntax: C++; museinfo // // Description: Identifies absolute beat location of note onset // events in the score (or lack thereof). // #include "humdrum.h" // function declarations void checkOptions(Options& opts, int argc, char* argv[]); void example(void); void usage(const char* command); int isOnset(HumdrumFile& infile, int line); void printOutput(HumdrumFile& file); // global variables Options options; // database for command-line arguments int appendQ = 0; // used with -a option int prependQ = 0; // used with -p option int beatsQ = 0; // only check the main beat locations int zero = 0; // offset control int invertQ = 0; // not yet implemented /////////////////////////////////////////////////////////////////////////// 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 infile.analyzeRhythm(); printOutput(infile); } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // printOutput -- // void printOutput(HumdrumFile& file) { int lastmeasureline = -1; double absbeatval; int foundOnset; for (int i=0; i<file.getNumLines(); i++) { switch (file[i].getType()) { case E_humrec_data_comment: if (appendQ) { cout << file[i] << "\t" << "!" << "\n"; } else if (prependQ) { cout << "!\t" << file[i] << "\n"; } else { cout << file[i] << "\n"; } break; case E_humrec_data_kern_measure: if (prependQ) { cout << file[i][0] << "\t"; cout << file[i] << "\n"; } else if (appendQ) { cout << file[i] << "\t"; cout << file[i][0] << "\n"; } else { cout << file[i][0] << "\n"; } lastmeasureline = i; break; case E_humrec_interpretation: if (appendQ) { cout << file[i] << "\t"; } if (strncmp(file[i][0], "**", 2) == 0) { cout << "**absbeat"; if (!(appendQ || prependQ)) { cout << "\n"; } } else if (strcmp(file[i][0], "*-") == 0) { cout << "*-"; } else { if (appendQ || prependQ) { cout << "*"; } } if (prependQ) { cout << "\t" << file[i]; } if (appendQ || prependQ) { cout << "\n"; } break; case E_humrec_data: if (appendQ) { cout << file[i] << "\t"; } absbeatval = file[i].getAbsBeat(); foundOnset = isOnset(file, i); if (invertQ) { foundOnset = !foundOnset; } if (foundOnset) { if (beatsQ) { if ((absbeatval+0.005) - (int)absbeatval < 0.01) { cout << absbeatval; } else { cout << "."; } } else { cout << absbeatval; } } else { cout << "."; } if (prependQ) { cout << "\t" << file[i]; } cout << "\n"; break; case E_humrec_none: case E_humrec_empty: case E_humrec_global_comment: case E_humrec_bibliography: default: cout << file[i] << "\n"; break; } } } ////////////////////////////// // // isOnset -- returns true of there is a note on the current line // which is starting to play. // int isOnset(HumdrumFile& infile, int line) { int i; int k; char buffer[1024] = {0}; int count; for (i=0; i<infile[line].getFieldCount(); i++) { if (strcmp(infile[line].getExInterp(i), "**kern") != 0) { continue; } if (strcmp(infile[line][i], ".") == 0) { continue; } count = infile[line].getTokenCount(i); for (k=0; k<count; k++) { infile[line].getToken(buffer, i, k); if (strchr(buffer, ']') != NULL) { // igmore tie endings continue; } if (strchr(buffer, '_') != NULL) { // ignore tie continuations continue; } if (strcmp(buffer, ".") == 0) { // igmore null tokens continue; } if (strchr(buffer, 'r') != NULL) { // ignore rests continue; } if (strchr(buffer, 'A') != NULL) { return 1; } if (strchr(buffer, 'B') != NULL) { return 1; } if (strchr(buffer, 'C') != NULL) { return 1; } if (strchr(buffer, 'D') != NULL) { return 1; } if (strchr(buffer, 'E') != NULL) { return 1; } if (strchr(buffer, 'F') != NULL) { return 1; } if (strchr(buffer, 'G') != NULL) { return 1; } if (strchr(buffer, 'a') != NULL) { return 1; } if (strchr(buffer, 'b') != NULL) { return 1; } if (strchr(buffer, 'c') != NULL) { return 1; } if (strchr(buffer, 'd') != NULL) { return 1; } if (strchr(buffer, 'e') != NULL) { return 1; } if (strchr(buffer, 'f') != NULL) { return 1; } if (strchr(buffer, 'g') != NULL) { return 1; } } } return 0; } ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|append=b"); // append analysis to input opts.define("p|prepend=b"); // prepend analysis to input opts.define("b|beats=b"); // only check beat locations opts.define("z|zero|zero-offset=b"); // first beat is represented by a 0 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, Dec 2006" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 18 Dec 2006" << 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); } zero = 0; appendQ = opts.getBoolean("append"); prependQ = opts.getBoolean("prepend"); beatsQ = opts.getBoolean("beats"); } ////////////////////////////// // // example -- example usage of the quality program // void example(void) { cout << " \n" "# example usage of the meter program. \n" "# analyze a Bach chorale for meter position: \n" " meter chor217.krn \n" " \n" "# display the metrical location spine with original data: \n" " meter -a chor217.krn \n" " \n" << endl; } ////////////////////////////// // // usage -- gives the usage statement for the meter 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" " -a = assemble the analysis spine with the input data. \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: 605a0baaf888b392e8a0c3b4165039a5 onsetbeats.cpp [20061218]