// // Programmer: Craig Stuart Sapp // Creation Date: Sun Jul 28 21:48:39 PDT 2002 // Last Modified: Mon Jul 29 13:54:33 PDT 2002 // Filename: ...sig/examples/all/iwrange.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/iwrange.cpp // Syntax: C++; museinfo // // Description: Find the independent variation in interval weights // which yeild as good or better results than the current value. // #include "humdrum.h" #include #include #include #include #define MINIM 0.00000001 typedef Array ArrayDouble; typedef Array ArrayInt; /////////////////////////////////////////////////////////////////////////// // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void getStartingWeights (Array& weights, HumdrumFile& weightfile); void getChordInformation (Array& pitches, Array& root, Array& count, HumdrumFile& datafile); double getErrors (Array& weights, Array& pitches, Array& root, Array& count); void makeRandomWeights (Array& stepweights, double range); void printWeights (Array weights); double getDistance (Array& a, Array& b); void findRange (Array& pitches, Array& root, Array& count, Array& initialweights, int index, double& tune, double step); void printKern (Array& initialweights, Array& min, Array& max); void printPlot (Array& iw, Array& min, Array& max); double getMidRange (Array& min, Array& max, Array& pitches, Array& root, Array& count); // global variables Options options; // database for command-line arguments int debugQ = 0; // used with --debug option int verboseQ = 0; // used with -v option double decay = 0.5; // decay of range between each step double limit = 10.0; // maximum distance which can be searched double step = 1.0; // maximum distance which can be searched int plotQ = 0; // used with -p option int bestQ = 0; // used with the -b option double baseerror = 0; double minerror = -1; double miderror = 0; Array bestweights; /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile datafile; HumdrumFile weightfile; checkOptions(options, argc, argv); // process the command-line options datafile.read(options.getArg(1)); weightfile.read(options.getArg(2)); Array count; // the frequency of the chords occurence Array root; // the root of the chord Array pitches; // the pitch class set of the chord Array initialweights; // starting weights of the search getStartingWeights(initialweights, weightfile); getChordInformation(pitches, root, count, datafile); bestweights = initialweights; int i; Array min(initialweights.getSize()); Array max(initialweights.getSize()); for (i=0; i& min, Array& max, Array& pitches, Array& root, Array& count) { Array weights(40); weights.setAll(10000); int i; for (i=0; i<40; i++) { if (i==5||i==11||i==22||i==28||i==34) { continue; } weights[i] = (max[i] - min[i])/2.0 + min[i]; } return getErrors(weights, pitches, root, count); } ////////////////////////////// // // printPlot -- // void printPlot(Array& iw, Array& min, Array& max) { printKern(iw, min,max); cout << "@START: FIGURE\n\n"; int yvals[40] = { -14, -7, 0, 7, 14, // C 1000, -12, -5, 2, 9, 16, // D 1000, -10, -3, 4, 11, 18, // E -15, -8, -1, 6, 13, // F 1000, -13, -6, 1, 8, 15, // G 1000, -11, -4, 3, 10, 17, // A 1000, -9, -2, 5, 12, 19 // B }; double radius[40] = { -0.4, -0.4, -0.4, -0.4, -0.4, 0.0, 0.4, 0.4, 0.4, 0.4, 0.4, 0.0, -0.3, -0.3, -0.3, -0.3, -0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.0, -0.2, -0.2, -0.2, -0.2, -0.2, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, -0.1, -0.1, -0.1, -0.1, -0.1 }; int i; for (i=0; i<40; i++) { if (i==5||i==11||i==22||i==28||i==34) { continue; } cout << "@START: PLOTDATA\n"; cout << min[i] << "\t" << yvals[i] << "\n"; cout << max[i] << "\t" << yvals[i] << "\n"; cout << "@END: PLOTDATA\n\n"; } double curstyle = -1; double laststyle = -1; double currad = -1; cout << "@START: POINTS\n"; for (i=0; i<40; i++) { if (i==5||i==11||i==22||i==28||i==34) { continue; } if (currad != fabs(radius[i])) { currad = fabs(radius[i]); cout << "@RADIUS: " << currad << "\n"; } laststyle = curstyle; curstyle = radius[i] < 0 ? 0 : 1; if (curstyle != laststyle) { if (curstyle == 1) { cout << "@STYLE: circle\n"; } else { cout << "@STYLE: opencircle\n"; } } cout << iw[i] << "\t" << yvals[i] << "\n"; } cout <<"@END: FIGURE\n\n"; } ////////////////////////////// // // printKern -- // void printKern(Array& initialweights, Array& min, Array& max) { char buffer[1024] = {0}; cout << "!! Base Errors:\t" << baseerror << endl; cout << "!! Best Errors:\t" << minerror << endl; cout << "!! MidRange Errors:\t" << miderror << endl; cout << "**kern\t**weight\t**min\t**max\t**range\t**midrange\n"; int i; for (i=0; i& pitches, Array& root, Array& count, Array& initialweights, int index, double& tune, double step) { Array weights; weights = initialweights; baseerror = getErrors(weights, pitches, root, count); if (minerror < 0) { minerror = baseerror; } double starttune = tune; tune = weights[index]; double newerrors = 0.0; while ((fabs(step) > MINIM) && (fabs(tune - starttune) < limit*2)) { newerrors = getErrors(weights, pitches, root, count); if (newerrors < minerror) { minerror = newerrors; bestweights = weights; } if (newerrors <= baseerror) { tune += step; } else { tune -= step; step *= decay; if (verboseQ) { cerr << "Step set to " << step << endl; } } weights[index] = tune; if (verboseQ) { cerr << "weight = " << tune << endl; } } char buffer[32] = {0}; if (verboseQ) { cerr << Convert::base40ToKern(buffer, index+3*40) << "=====================================" << endl; } } ////////////////////////////// // // getErrors -- try all chords and count how many root errors occured. // double getErrors(Array& weights, Array& pitches, Array& root, Array& count) { Array rootscores; rootscores.setSize(40); rootscores.allowGrowth(0); int i, j, m; double errors = 0; int min; for (m=0; m rootscores[i]) { min = i; } } if (root[m] != min+2) { if (debugQ) { cout << "Error: root=" << root[m] << "\tbut measured: " << min << endl; } errors += count[m]; } } return errors; } ////////////////////////////// // // getDistance -- find the Euclidian distance between two vectors. // double getDistance(Array& a, Array& b) { Array c(40); int i; double sum = 0.0; for (i=0; i& stepweights, double range) { int i, j; double delta = 0.0; for (i=1; i& weights, HumdrumFile& weightfile) { weights.setSize(40); weights.setAll(100000); weights.allowGrowth(0); int i, j; int root; double weight; for (i=0; i= 0) { weights[root] = weight; } } if (debugQ) { printWeights(weights); } } ////////////////////////////// // // printWeights -- // void printWeights(Array weights) { char buffer[128] = {0}; cout << "**kern\t**weight\n"; int i; for (i=0; i& pitches, Array& root, Array& count, HumdrumFile& datafile) { count.setSize(datafile.getNumLines()); count.setSize(0); root.setSize(datafile.getNumLines()); root.setSize(0); pitches.setSize(datafile.getNumLines()); pitches.setSize(0); char buffer[1024] = {0}; int i, j, k; int troot = -1; int tpitch = -1; double tcount = 0.0; Array tpitches; tpitches.setSize(100); tpitches.setSize(0); for (i=0; i