// // Programmer: Craig Stuart Sapp // Creation Date: Fri Jun 26 23:44:15 PDT 1998 // Last Modified: Fri Jun 26 23:44:19 PDT 1998 // Filename: ...sig/examples/all/harmanal.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/harmanal.cpp // Syntax: C++; museinfo // // Description: Analyzes **kern data and generates a functional // harmony analysis of timeslices (no melodic harmony). // #include "humdrum.h" #include #include #include #ifndef OLDCPP #include #else #include #endif // function declarations void checkOptions(Options& opts, int argc, char* argv[]); ChordQuality determineChordQuality(const HumdrumRecord& aRecord); void example(void); void processRecords(HumdrumFile& infile, HumdrumFile& outfile); void usage(const char* command); // global variables Options options; // database for command-line arguments char unknown[256] = {0}; // space for unknown chord simplification int chordinit; // for initializing chord detection function int key = E_root_C; // base pitch of key to analyze in int mode = E_mode_major; // mode of the key /////////////////////////////////////////////////////////////////////////// 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 lastnotes; // for keeping track of null record notes int i; if (chordinit) { chordinit = 0; lastnotes.setSize(aRecord.getFieldCount()); for (i=0; i currentNotes(lastnotes.getSize()); int count = 0; for (i=0; i chordNotes; Collection scaleDegrees; chordNotes = Convert::chordQualityToNoteSet(aQuality); scaleDegrees = Convert::keyToScaleDegrees(aKey, aMode); // question: is root in key? int i; for (i=0; i 1) { if (chordNotes[0] < chordNotes[1]) { chordThird = chordNotes[1] - chordNotes[0]; } else { chordThird = chordNotes[0] - chordNotes[1]; } } else { strncpy(output, "X", strlen); return; } if (chordNotes.getSize() > 2) { if (chordNotes[0] < chordNotes[2]) { chordFifth = chordNotes[2] - chordNotes[0]; } else { chordFifth = chordNotes[0] - chordNotes[2]; } } // can now build a chord in the key switch (degreeLocation) { case 0: strcpy(output, "I"); break; case 1: strcpy(output, "II"); break; case 2: strcpy(output, "III"); break; case 3: strcpy(output, "IV"); break; case 4: strcpy(output, "V"); break; case 5: strcpy(output, "VI"); break; case 6: strcpy(output, "VII"); break; default: strncpy(output, "X", strlen); return; } // adjust for major/minor third i = 0; while (output[i] != '\0') { output[i] = tolower(output[i]); } if (chordFifth == E_base40_dim5 || (chordFifth == 0 && aQuality.getType() == E_chord_incmin)) { strcat(output, "o"); } else if (chordFifth == E_base40_aug5) { strcat(output, "+"); } if (chordNotes.getSize() == 4) { if (degreeLocation == 6) { strcat(output, "0"); } strcat(output, "7"); } switch (aQuality.getInversion()) { case 0: break; case 1: strcat(output, "a"); break; case 2: strcat(output, "b"); break; case 3: strcat(output, "c"); break; case 4: strcat(output, "d"); break; default: strcat(output, "x"); } return; } else { strncpy(output, "X", strlen); return; } } ////////////////////////////// // // example -- example usage of the quality program // void example(void) { cout << " \n" "# example usage of the quality program. \n" "# analyze a Bach chorale for chord qualities: \n" " quality chor217.krn \n" " \n" "# display only the chord analysis: \n" " quality -x chor217.krn \n" " \n" "# display only the roots of chords: \n" " quality -r chor217.krn \n" " \n" << endl; } ////////////////////////////// // // processRecords -- looks at humdrum records and determines chord // quality // void processRecords(HumdrumFile& infile, HumdrumFile& outfile) { ChordQuality quality; char aString[256] = {0}; HumdrumRecord currRecord; for (int i=0; i