// // Programmer: Craig Stuart Sapp // Creation Date: Mon Jun 24 20:05:15 PDT 2002 // Last Modified: Sun Aug 25 17:47:13 PDT 2002 // Last Modified: Sat Nov 30 15:46:46 PST 2002 (added triad spectrum display) // Filename: ...sig/examples/all/iwroot.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/iwroot.cpp // Syntax: C++; museinfo // // Description: Determine the root of a pitch set according to // different root-interval class sizes. // #define MYPI 3.141592653589793 #include "humdrum.h" #include #include // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void printScores (Array& rootscores); void printDistances (IntervalWeight& distances, int type); int analyzeChromatic (Array& rootscores, HumdrumFile& infile, IntervalWeight& distances, int startline, int stopline, int correct = -1, int debugQ = 0); double base40ToBase7 (int pitch); char base7pcToName (int value); void identifyErrorsChromatic (HumdrumFile& infile, int type, int debugQ); void generateDistances (IntervalWeight& distances, int type); void printNotes (int correct, Array& pitches); void printNotes (int correct, Array& pitches, Array& durations, Array& levels); int intcompare (const void* a, const void* b); int pdlcompare (const void* a, const void* b); int doublecompare (const void* a, const void* b); void setSortOrder (IntervalWeight& dist, Array& index); void getStartingWeights (IntervalWeight& weights, HumdrumFile& weightfile); double octavescaling (int pitch, double scaling); double durationscaling (double duration); double metricscaling (double metriclevel); // global variables Options options; // database for command-line arguments int debugQ = 0; // used with --debug option int appendQ = 0; // used with -a option int rootQ = 0; // used with -R option int errorsQ = 0; // used with -e option double theta1 = 51.0; // used with -t option double theta2 = 51.0; // used with -u option int invertQ = 0; // used with -i option int distanceQ = 0; // used with -d option int notesQ = 0; // used with -n option int transposeQ = 0; // used with -C option int singleQ = 0; // used with -s option int sortQ = 0; // used with -S option int locationQ = 0; // used with -l option int circularQ = 0; // used with -c option double power = 1.0; // used with -p option double circular = 0.0; // used with -c option double offset = 0.0; // used with -o option int weightQ = 0; // used with -w option string weightFile = ""; // used with -w option int verboseQ = 0; // used with -v option int octaveQ = 0; // used with -o option double octaveScale= 0.0; // used with -o option int rhythmQ = 0; // used with -r option double durationfactor=0.8; // used with --dfactor double metricfactor=0.5; // used with --mfactor int spectrumQ = 0; // used with --spectrum string CurrentFile = ""; // current file being processed int CurrentLine = 0; // current line in file being processed /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile infile; // process the command-line options checkOptions(options, argc, argv); int i; for (i=1; i<=options.getArgCount() || options.getArgCount()==0; i++) { infile.clear(); // if no command-line arguments read data file from standard input if (options.getArgCount() < 1) { infile.read(cin); } else { CurrentFile = options.getArg(i); infile.read(CurrentFile.c_str()); } if (errorsQ) { if (options.getBoolean("theta2")) { identifyErrorsChromatic(infile, 2, debugQ); } else if (circularQ) { identifyErrorsChromatic(infile, 4, debugQ); } else if (weightQ) { identifyErrorsChromatic(infile, 0, debugQ); } else { identifyErrorsChromatic(infile, 1, debugQ); } } else if (distanceQ) { IntervalWeight distances; if (options.getBoolean("theta2")) { generateDistances(distances, 2); printDistances(distances, 2); } else if (circularQ) { generateDistances(distances, 4); printDistances(distances, 4); } else if (weightQ) { generateDistances(distances, 0); printDistances(distances, 0); } else { generateDistances(distances, 1); printDistances(distances, 1); } } } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // generateDistances -- // void generateDistances(IntervalWeight& distances, int type) { switch (type) { case 0: // read weight file { HumdrumFile infile(weightFile.c_str()); getStartingWeights(distances, infile); } break; case 1: distances.setChromatic1(theta1); break; case 2: distances.setChromatic2(theta1, theta2); break; case 4: distances.setCircular(theta1, circular); break; default: cout << "Error: unknown type: " << type << endl; exit(1); } int i; if (power != 1.0) { for (i=0; i<40; i++) { distances[i] = pow(distances[i], power); } } if (offset != 0.0) { for (i=0; i<40; i++) { distances[i] += offset; } } } ////////////////////////////// // // identifyErrorsChromatic -- compare root scores value to root in // humdrum file and print out errors. // void identifyErrorsChromatic(HumdrumFile& infile, int type, int debugQ) { int oldline = 0; int init = 0; int best = 0; // best root according to algorithm int correct = 0; // correct base40 root int i; int j; // get interval distances: IntervalWeight distances; generateDistances(distances, type); // go though the file and compare all chords to **root info: Array rootscores(40); rootscores.setAll(0); for (i=0; i= 0) && (best+2 != correct)) { char zbuffer[128] = {0}; cout << "Error on line " << oldline + 1 << "\tcorrect=" << Convert::base40ToKern(zbuffer, correct+4*40); cout << "\tvalue=" << Convert::base40ToKern(zbuffer, best+2+4*40) << endl; } oldline = i; correct = Convert::kernToBase40(infile[i][j]) % 40; break; } } } best = analyzeChromatic(rootscores, infile, distances, oldline, i-1, correct, debugQ); if ((best >= 0) && (best+2 != correct)) { char zbuffer[128] = {0}; cout << "Error on line " << oldline + 1 << "\tcorrect=" << Convert::base40ToKern(zbuffer, correct+4*40); cout << "\tvalue=" << Convert::base40ToKern(zbuffer, best+2+4*40) << endl; } } ////////////////////////////// // // analyzeChromatic -- // int analyzeChromatic(Array& rootscores, HumdrumFile& infile, IntervalWeight& distances, int startline, int stopline, int correct, int debugQ) { // extract note data Array absbeat; Array pitches; Array durations; Array levels; infile.getNoteArray(absbeat, pitches, durations, levels, startline, stopline); if (pitches.getSize() == 0) { // give up if there are no notes in the specified region return -1; } if (notesQ) { if (rhythmQ) { printNotes(correct, pitches, durations, levels); } else { printNotes(correct, pitches); } } char buffer[64] = {0}; if (debugQ) { int i; cout << "====================" << endl; for (i=startline; i<=stopline; i++) { cout << infile[i] << "\n"; } cout << "--------------------" << endl; cout << "Start line=" << startline+1 << "\tEnd line=" << stopline+1 << endl; for (i=0; i& pitches, Array& durations, Array& levels) { Array pc = pitches; int i; for (i=0; i pitchinfo; pitchinfo.setSize(pc.getSize()); for (i=0; i& index) { Array used; used.setSize(40); used.allowGrowth(0); used.setAll(0); index.setSize(40); index.setAll(10000); int i, j; Array values; values.setSize(40); for (i=0; i<40; i++) { values[i] = dist[i]; } qsort(values.getBase(), values.getSize(), sizeof(double), doublecompare); for (i=0; i<35; i++) { for (j=0; j<40; j++) { if ((values[i] == dist[j]) && (used[j] == 0)) { used[j] = 1; index[i] = j; break; } } } } ////////////////////////////// // // printDistances -- // void printDistances(IntervalWeight& distances, int type) { int i; char buffer[64] = {0}; switch (type) { case 1: cout << "!! theta: " << theta1 << "\n"; break; case 2: cout << "!! theta1: " << theta1 << "\n"; cout << "!! theta2: " << theta2 << "\n"; break; case 4: cout << "!! theta: " << theta1 << "\n"; cout << "!! scaling: " << circular << "\n"; break; } cout << "**kern\t**weight\n"; if (sortQ) { Array sorter(40); setSortOrder(distances, sorter); for (i=0; i 40) { continue; } cout << Convert::base40ToKern(buffer, sorter[i]+4*40); cout << "\t" << distances[sorter[i]] << "\n"; } } else { for (i=0; i& rootscores) { int i; int findex; char buffer[64] = {0}; for (i=0; i *((int*)b)) { return 1; } else { return 0; } } ////////////////////////////// // // pdlcompare -- compare two pitches for ordering in PDL structure // int pdlcompare(const void* a, const void* b) { PDL& A = *((PDL*)a); PDL& B = *((PDL*)b); if (A.pitch < B.pitch) { return -1; } else if (A.pitch > B.pitch) { return +1; } // pitches are the same, so sort by duration if (A.duration < B.duration) { return -1; } else if (A.duration > B.duration) { return +1; } // durations are the same, so sort by metric level if (A.level < B.level) { return -1; } else if (A.level > B.level) { return +1; } // notes are identical return 0; } ////////////////////////////// // // doublecompare -- compare two doubles for ordering // int doublecompare(const void* a, const void* b) { if (*((double*)a) < *((double*)b)) { return -1; } else if (*((double*)a) > *((double*)b)) { return 1; } else { return 0; } } ////////////////////////////// // // getStartingWeights -- // void getStartingWeights(IntervalWeight& weights, HumdrumFile& weightfile) { weights.setAll(100000); int i, j; int root; double weight; for (i=0; i= 0) { weights[root] = weight; } } } // md5sum: 57e076dafa398fcaa7a7a612e2f3479f iwroot.cpp [20160320]