// // Programmer: Craig Stuart Sapp // Creation Date: Tue Nov 14 09:18:07 PST 2000 // Last Modified: Fri Nov 17 12:02:24 PST 2000 // Filename: ...sig/examples/all/diametric.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/diametric.cpp // Syntax: C++; museinfo // // Description: Analyzes **kern sonorities for diatonic compactness // in various orderings of seconds, thirds, fifths // and their inversions. // #include "humdrum.h" #include #include #include #include #include #ifndef OLDCPP #include #else #include #endif // function declarations void checkOptions (Options& opts, int argc, char* argv[]); int countAttacks (HumdrumRecord& record); void displayAccentedBeatMetrics(Array& metposition, Array& ascores, const char* metermarker, int start, int stop); int doublecompare (const void* a, const void* b); void example (void); void generateAnalysis (HumdrumFile& infile, Array&analysis, int metric, Array& attacks); void generateSummary (HumdrumFile& infile, Array& metricana); void generateSubSummary (HumdrumFile& infile, Array& metricana, const char* metricmarker, int start, int stop); void getPitches (Array& pitches, HumdrumFile& infile, int line); double makeBeatScore (int totalbeats, double width, Array& metposition, Array&ascores); int makeMeasurement (Array&pitches, int metric); void printAnalysis (HumdrumFile& infile, Array&metric); void usage (const char* command); // global variables Options options; // database for command-line arguments int debugQ = 0; // used with the --debug option int metric = 1; // diatonic interleaving (1 = by thirds) int appendQ = 0; // used with the -a option int histogramQ = 0; // used with the -c option int summaryQ = 0; // used with the -c option int beatQ = 0; // used with the -b option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile infile; Array analysis; Array attacks; // 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 ordered by seconds, sevenths // metric == 1 --> ordered by thirds, sixths // metric == 2 --> ordered by fourths, fifths metric = opts.getInteger("metric") - 2; if (metric < 0) { metric = 1; } else if (metric == 3) { metric = 2; } else if (metric == 4) { metric = 1; } else if (metric == 5) { metric = 0; } else if (metric > 5) { metric = 1; } debugQ = opts.getBoolean("debug"); appendQ = opts.getBoolean("append"); histogramQ = opts.getBoolean("histogram"); if (opts.getBoolean("summary")) { summaryQ = 1; histogramQ = 0; appendQ = 0; } else { summaryQ = 0; } if (opts.getBoolean("beat")) { summaryQ = 1; beatQ = 1; histogramQ = 0; appendQ = 0; } } ////////////////////////////// // // example -- example usage of the quality program // void example(void) { cout << " \n" << endl; } ////////////////////////////// // // generateAnalysis -- // void generateAnalysis(HumdrumFile& infile, Array& analysis, int metric, Array& attacks) { Array pitches; pitches.setSize(100); pitches.setSize(0); pitches.allowGrowth(1); analysis.setSize(infile.getNumLines()); attacks.setSize(infile.getNumLines()); for (int i=0; i& pitches, HumdrumFile& infile, int line) { pitches.setSize(0); int diatonic; int j, k; int tokencount; char buffer[128] = {0}; for (j=0; j&pitches, int metric) { int compare[3][14] = {{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g'}, {'a', 'c', 'e', 'g', 'b', 'd', 'f', 'a', 'c', 'e', 'g', 'b', 'd', 'f'}, {'a', 'e', 'b', 'f', 'c', 'g', 'd', 'a', 'e', 'b', 'f', 'c', 'g', 'd'}}; int data[14] = {0}; int i; //cout << "Comparing to : "; //for (i=0; i<7; i++) { // cout << (char)compare[metric][i] << " "; //} //cout << " ... : " << endl; int j; for (i=0; i max) { max = count; } count = 0; } else { count++; } } if (count > max) { max = count; } //for (i=0; i& metricana) { int start = 0; int stop = 0; int i=0; int m=0; int datatrigger = 0; int metertrigger = 0; int summarytrigger = 0; int length; const char* metricmarker = ""; if (!beatQ) { cout << "**takt\t**avg\t**fract\t**ascore\n"; } while (i 2) && isdigit(infile[i][m][2]) && (strchr(infile[i][m], '/') != NULL)) { metertrigger = 1; metricmarker = infile[i][m]; if (datatrigger) { summarytrigger = 1; stop = i-1; } else { start = i; } break; } else if (strncmp(infile[i][m], "*MM", 3) == 0) { if (!beatQ) { cout << infile[i][m] << "\t"; cout << infile[i][m] << "\t"; cout << infile[i][m] << "\t"; cout << infile[i][m] << "\n"; break; } } } } } if (strcmp(infile[i][0], "*-") == 0) { summarytrigger = 1; stop = i; } if (datatrigger == 1 && metertrigger == 0) { generateSubSummary(infile, metricana, "*MX", 0, infile.getNumLines()); break; } if (summarytrigger) { generateSubSummary(infile, metricana, metricmarker, start, stop); summarytrigger = 0; datatrigger = 0; metricmarker = ""; start = stop + 1; } i++; } if (!beatQ) { cout << "*-\t*-\t*-\t*-\n"; } } ////////////////////////////// // // generateSubSummary -- // void generateSubSummary(HumdrumFile& infile, Array& metricana, const char* metricmarker, int start, int stop) { infile.analyzeRhythm(); Array metposition; metposition.setSize(0); metposition.allowGrowth(); Array count; count.setSize(0); count.allowGrowth(); Array data; data.setSize(0); data.allowGrowth(); double current; int one = 1; const char* metermarker = "*"; int sumcount = 0; int i; int j; int k; int sindex; for (i=start; i= 0) { count[sindex]++; data[sindex] += metricana[i]; sumcount++; } else { current = infile[i].getBeat(); metposition.append(current); count.append(one); data.append(metricana[i]); sumcount++; } } } Array sortmet = metposition; qsort(sortmet.getBase(), metposition.getSize(), sizeof(double), doublecompare); Array ascores; Array average; Array fraction; ascores.setSize(metposition.getSize()); average.setSize(metposition.getSize()); fraction.setSize(metposition.getSize()); double min = 99999999.0; for (i=0; i ascores[i]) { min = ascores[i]; } } // normalize ascore values if (min > 0.0) { for (i=0; i metposition.getSize()) { continue; } cout << sortmet[i] << "\t" << average[k] << "\t" << fraction[k] << "\t" << 1.0/ascores[k] << "\n"; } } else { displayAccentedBeatMetrics(metposition, ascores, metermarker, start, stop); } } ////////////////////////////// // // diaplyAccentedBeatMetrics -- generate a score for each possible // cyclical meter/beat combination. // void displayAccentedBeatMetrics(Array& metposition, Array& ascores, const char* metermarker, int start, int stop) { int beatcount = -1; int beatvalue = -1; sscanf(metermarker, "*M%d/%d", &beatcount, &beatvalue); int i; cout << "Start = " << start << "\tStop = " << stop << endl; cout << "Meter: " << metermarker << endl; cout << "beats: " << beatcount << endl; cout << "base: " << beatvalue << endl; double difference; double beatscore; double width; Array beatscores; beatscores.setSize(0); beatscores.allowGrowth(); Array widths; widths.setSize(0); widths.allowGrowth(); int candidate; for (i=1; i 0.999) { candidate = 1; } else { candidate = 0; } if (candidate) { beatscore = makeBeatScore(beatcount, width, metposition, ascores); beatscores.append(beatscore); widths.append(width); if (!summaryQ) { cout << "beat duration: " << metposition[i] - 1 << "\tscore: " << beatscore << endl; } } } if (summaryQ) { double max = beatscores[0]; int index = 0; for (i=1; i max) { max = beatscores[i]; index = i; } } cout << "Maximum Beat: " << widths[index] << "\tRating: " << beatscores[index] << endl; } } ////////////////////////////// // // makeBeatScore -- // double makeBeatScore(int totalbeats, double width, Array& metposition, Array&ascores) { int i; double product = 1.0; double difference; int count = 0; for (i=0; i 0.999) { count++; product *= 1.0/ascores[i]; } } int realcount = (int)(totalbeats/width + 0.5); for (i=0; i& metricana) { int i; if (summaryQ || beatQ) { generateSummary(infile, metricana); return; } if (appendQ) { for (i=0; i *((double*)b)) { return 1; } else { return 0; } } // md5sum: 8bbdfff24f2444c1601186e1e80857c9 diametric.cpp [20160320]