// // Programmer: Craig Stuart Sapp // Creation Date: Thu Mar 29 17:22:53 PST 2001 // Last Modified: Thu Mar 29 17:22:56 PST 2001 // Filename: ...sig/examples/all/rootcomp.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/rootcomp.cpp // Syntax: C++; museinfo // // Description: determine the root of chords in music according // to the timespan of a preexisting root analysis spine. // #include "humdrum.h" #include #include // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void generateAnalysis (HumdrumFile& hfile); void analyzeDataLine (HumdrumFile& hfile, int line); // global variables Options options; // database for command-line arguments int debugQ = 0; // used with the --debug option int rawQ = 0; // used with the --raw option int appendQ = 0; // used with the -a option double rval = 1.0; // used with the -r option double rlevel = 1.0; // used with the -r option double empirical1 = -4; // used with the -d option double empirical2 = -3; // used with the -l option double sx = 0.578; // used with the --sx option double sy = 1.0; // used with the --sx option int octave = -1; // used with the -o option int weightsQ = 0; // used with the -w option int algorithm = 0; // used with the --algorithm option int countQ = 0; // used with the -c option int errorQ = 0; // used with the -e option int errorcount = 0; // used with the -c option Array parameters(3); // for chord analysis parameters /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile hfile; // process the command-line options checkOptions(options, argc, argv); // figure out the number of input files to process int numinputs = options.getArgCount(); Array rootanalysis; // roots analysed at various times Array rootbeat; // absolute start beat of root Array rootscores; // score of best root for (int i=0; i& rootanalysis, Array& rootscores, double duration) { char buffer[1024] = {0}; errorcount = 0; int i; double fraction; int oldlocation = -1; int location; int n, m; if (rawQ) { for (i=0; i 0) { cout << "beat: " << i * duration << "\t= " << Convert::base40ToKern(buffer, rootanalysis[i]) << ",\tscore = " << rootscores[i] << endl; } else { cout << "beat: " << i * duration << "\t= " << "rest" << "\tscore = " << 0 << endl; } } } else { for (i=0; i 0.999) { fraction = 0.0; } if (location - oldlocation > 1 && oldlocation > 0) { for (n=1; n 0) { cout << Convert::base40ToKern(buffer, rootanalysis[oldlocation + n]); } else { cout << "r"; } if (weightsQ) { cout << "\t" << rootscores[oldlocation + n]; } cout << "\n"; } } oldlocation = location; cout << hfile[i].getLine(); cout << "\t"; if (fraction < 0.001) { cout << Convert::durationToKernRhythm(buffer, duration); if (rootanalysis[location] > 0) { cout << Convert::base40ToKern(buffer, rootanalysis[location]); } else { cout << "r"; } } else { cout << "."; } if (weightsQ && fraction < 0.001) { cout << "\t" << rootscores[location]; } else if (weightsQ) { cout << "\t."; } cout << "\n"; break; case E_humrec_data_measure: fraction = fabs(hfile[i].getAbsBeat()/duration); location = (int)fraction; fraction = fraction - (int)fraction; if (fraction > 0.999) { fraction = 0.0; } if (location - oldlocation > 1 && oldlocation > 0) { for (n=1; n 0) { cout << Convert::base40ToKern(buffer, rootanalysis[oldlocation + n]); } else { cout << "r"; } if (weightsQ) { cout << "\t" << rootscores[oldlocation + n]; } cout << "\n"; } } oldlocation = location - 1; cout << hfile[i].getLine(); cout << "\t" << hfile[i][0]; if (weightsQ) { cout << "\t" << hfile[i][0]; } cout << "\n"; break; case E_humrec_data_comment: cout << hfile[i].getLine(); if (hfile[i].equalFieldsQ()) { cout << "\t" << hfile[i][0]; } else { cout << "\t!"; } if (weightsQ && hfile[i].equalFieldsQ()) { cout << "\t" << hfile[i][0]; } else if (weightsQ) { cout << "\t!"; } cout << "\n"; break; case E_humrec_data_interpretation: cout << hfile[i].getLine(); if (strncmp(hfile[i][0], "**", 2) == 0) { cout << "\t**kern"; if (weightsQ) { cout << "\t**weight"; } cout << "\n"; } else { if (hfile[i].equalFieldsQ()) { cout << "\t" << hfile[i][0]; } else { cout << "\t*"; } if (weightsQ && hfile[i].equalFieldsQ()) { cout << "\t" << hfile[i][0]; } else if (weightsQ) { cout << "\t*"; } cout << "\n"; } break; case E_humrec_global_comment: case E_humrec_bibliography: case E_humrec_none: case E_humrec_empty: default: fraction = fabs(hfile[i].getAbsBeat()/duration); location = (int)fraction; fraction = fraction - (int)fraction; if (fraction > 0.999) { fraction = 0.0; } if (location - oldlocation > 1 && oldlocation > 0) { for (n=1; n 0) { cout << Convert::base40ToKern(buffer, rootanalysis[oldlocation + n]); } else { cout << "r"; } if (weightsQ) { cout << "\t" << rootscores[oldlocation + n]; } cout << "\n"; } } oldlocation = location - 1; cout << hfile[i].getLine() << "\n"; } } } } */ ////////////////////////////// // // generateAnalysis -- analyze the roots of the chords // void generateAnalysis(HumdrumFile& hfile) { hfile.analyzeRhythm(); int i; for (i=0; i values; values.setSize(0); double startbeat; double endbeat; int nextroot; int lastroot = -1; int most; int i; int rooti = -1; for (i=0; i= 0) { if (octave < 0) { nextroot = (most + 2) % 40 + 80; if (abs(nextroot + 40 - lastroot) < 13) { nextroot += 40; } else if (abs(nextroot - 40 - lastroot) < 13) { nextroot -= 40; } } else { nextroot = (most + 2) % 40 + 40 * octave; } Convert::base40ToKern(pitchbuffer, nextroot); lastroot = nextroot; } else { nextroot = 0; pitchbuffer[0] = 'r'; pitchbuffer[1] = '\0'; } if (!countQ) { cout << hfile[line] << "\t" << durstring << pitchbuffer << endl; } else { if ((pitch % 40) != (nextroot % 40)) { errorcount++; } if (errorQ && ((pitch % 40) != (nextroot % 40))) { Convert::base40ToKern(pitchbuffer, pitch); cout << "Wanted: " << pitchbuffer; Convert::base40ToKern(pitchbuffer, nextroot); cout << "\tbut got: " << pitchbuffer; cout << "\ton line: " << line+1 << endl; } } } ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|append=b", "append analysis to data in output"); opts.define("raw=b", "raw display of output"); opts.define("c|count=b", "count the numbers of errors only"); opts.define("e|error=b", "display pitch errors"); opts.define("r|rhythm=i:4", "rhythm to measure root at"); opts.define("d|delta=d:-4.0", "rhythm scaling value 1"); opts.define("l|lambda=d:-3.0", "metric scaling factor value 2"); opts.define("sx=d:0.578", "scale factor for the x-pitch space axis"); opts.define("sy=d:1.0", "scale factor for the y-pitch space axis"); opts.define("o|octave=i:-1", "octave number of bass line"); opts.define("w|weights=b", "display parallel spine of scores next to roots"); opts.define("algorithm=i:0", "analysis algorithm to use"); opts.define("debug=b", "trace input parsing"); opts.define("author=b", "author of the program"); opts.define("version=b", "compilation information"); opts.define("example=b", "example usage"); 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 2000" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 21 Mar 2001" << 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); } debugQ = opts.getBoolean("debug"); appendQ = opts.getBoolean("append"); rawQ = opts.getBoolean("raw"); countQ = opts.getBoolean("count"); errorQ = opts.getBoolean("error"); if (errorQ) { countQ = 1; } empirical1 = opts.getDouble("delta"); empirical2 = opts.getDouble("lambda"); sx = opts.getDouble("sx"); sy = opts.getDouble("sy"); algorithm = opts.getInteger("algorithm"); octave = opts.getInteger("octave"); weightsQ = opts.getBoolean("weights"); parameters.setSize(3); parameters[0] = sx; parameters[1] = empirical1; parameters[2] = empirical2; } ////////////////////////////// // // example -- example usage of the maxent program // void example(void) { cout << " \n" << endl; } ////////////////////////////// // // usage -- gives the usage statement for the quality program // void usage(const char* command) { cout << " \n" << endl; }