// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Thu Mar 17 07:46:28 PDT 2011 // Last Modified: Thu Mar 17 07:46:35 PDT 2011 // Last Modified: Mon Apr 1 12:06:53 PDT 2013 Enabled multiple segment input // Last Modified: Mon Apr 15 18:24:31 PDT 2013 Added subset forms // Last Modified: Tue Apr 16 23:04:00 PDT 2013 Added attack-only analysis // Filename: ...sig/examples/all/tntype.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/tntype.cpp // Syntax: C++; museinfo // // Description: Analyzes **kern data with serial descriptions. // Reference: http://solomonsmusic.net/pcsets.htm // #include "humdrum.h" #include "PerlRegularExpression.h" #include <stdlib.h> #include <string.h> #ifndef OLDCPP #include <iostream> #else #include <iostream.h> #endif #define NORM_OPEN "[" #define NORM_CLOSE "]" #define PRIME_OPEN "(" #define PRIME_CLOSE ")" #define TN_OPEN "{" #define TN_CLOSE "}" #define IV_OPEN "<" #define IV_CLOSE ">" // function declarations void checkOptions(Options& opts, int argc, char* argv[]); void example(void); void processRecords(HumdrumFile& infile); void usage(const char* command); void fillStringWithNotes(char* string, ChordQuality& quality, HumdrumFile& infile, int line); int identifyBassNote(SigCollection<int>& notes, HumdrumFile& infile, int line, Array<int>& sounding); int transitionalSonority(ChordQuality& quality, HumdrumFile& infile, int line); double getMeasureSize(HumdrumFile& infile, int width); void printAttackMarker(HumdrumFile& infile, int line); void printRotation(HumdrumFile& infile, int line); const char* getDescription(const char* tntype); // 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 notesQ = 0; // used with --notes option int suppressQ = 0; // used with -s option int transQ = 0; // used with -T option int parenQ = 1; // used with -P option int ivQ = 0; // used with --iv option int infoQ = 0; // used with -D option int forteQ = 0; // used with --forte option int tnQ = 0; // used with --tn option int normQ = 0; // used with -n option int subsetQ = 0; // used with -k option int attackQ = 0; // used with -A option int tnormQ = 0; // used with -t option int verboseQ = 0; // used with -v option int tniQ = 0; // used with --tni option int rotationQ = 0; // used with -r option int xsattackQ = 0; // used with -x option int appendQ = 0; // used with -a option const char* notesep = " "; // used with -N option const char* colorindex[26]; /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFileSet infiles; // process the command-line options checkOptions(options, argc, argv); // figure out the number of input files to process int numinputs = options.getArgCount(); int i; if (numinputs < 1) { infiles.read(cin); } else { for (i=0; i<numinputs; i++) { infiles.readAppend(options.getArg(i+1)); } } for (i=0; i<infiles.getCount(); i++) { chordinit = 1; processRecords(infiles[i]); } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|assemble|append=b", "append analysis to input data"); opts.define("debug=b", "determine bad input line num"); opts.define("d|notes=b", "display pitch classes in sonority"); opts.define("n|norm=b", "display normal form of pitch sets"); opts.define("D|description=b", "display musical Description of Tn type"); opts.define("k|combinations|subsets=b", "display all subset forms"); opts.define("A|attacks|attack=b", "consider only note attaks"); opts.define("f|form|tnorm=b", "display transposed normal form of pitch sets"); opts.define("i|iv|ic=b", "print interval vector"); opts.define("x|sonor|suspension=b", "print marker if not all start attacks"); opts.define("F|forte=b", "print forte interval vector set name"); opts.define("r|rotation=b", "mark which note is in the bass"); opts.define("t|transpose=b", "indicate the tranposition value for Tn form"); opts.define("Tn|tn=b", "print forte set with subsets"); opts.define("Tni|tni=b", "print forte set with subsets/inversion"); opts.define("v|verbose=b", "print verbose label with extra info"); opts.define("s|suppress=b", "suppress data if overlapping sonority"); opts.define("S|paren-off=b","suppress parentheses for overlapping"); opts.define("author=b", "author of program"); opts.define("version=b", "compilation info"); opts.define("example=b", "example usages"); 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, Mar 2011" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: Nov 2000" << 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); } ivQ = opts.getBoolean("iv"); transQ = opts.getBoolean("transpose"); xsattackQ = opts.getBoolean("suspension"); infoQ = opts.getBoolean("description"); forteQ = opts.getBoolean("forte"); rotationQ = opts.getBoolean("rotation"); tnQ = opts.getBoolean("Tn"); subsetQ = opts.getBoolean("combinations"); attackQ = opts.getBoolean("attacks"); verboseQ = opts.getBoolean("verbose"); if (tnQ) { forteQ = 1; } tniQ = opts.getBoolean("Tni"); if (tniQ) { tnQ = 1; forteQ = 1; } normQ = opts.getBoolean("norm"); tnormQ = opts.getBoolean("tnorm"); notesQ = opts.getBoolean("notes"); suppressQ = opts.getBoolean("suppress"); parenQ = !opts.getBoolean("paren-off"); appendQ = opts.getBoolean("append"); } ////////////////////////////// // // example -- example usage of the sonority program // void example(void) { cout << " \n" "# example usage of the sonority program. \n" "# analyze a Bach chorale for chord qualities: \n" " sonority chor217.krn \n" " \n" "# display the chord analysis with original data: \n" " sonority -a chor217.krn \n" " \n" "# display only the roots of chords: \n" " sonority -r chor217.krn \n" " \n" << endl; } ////////////////////////////// // // processRecords -- looks at humdrum records and determines pitch-class sets // from sonorities made of simultaneously sounding notes. // void processRecords(HumdrumFile& infile) { Array<ChordQuality> cq; infile.analyzeSonorityQuality(cq); ChordQuality quality; Array<char> data; PerlRegularExpression pre; int foundstart = 0; char aString[512] = {0}; infile.printNonemptySegmentLabel(cout); for (int i=0; i<infile.getNumLines(); i++) { if (options.getBoolean("debug")) { cout << "processing line " << (i+1) << " of input ..." << endl; cout << "LINE IS: " << infile[i] << endl; } switch (infile[i].getType()) { case E_humrec_none: case E_humrec_empty: case E_humrec_bibliography: case E_humrec_global_comment: cout << infile[i] << endl; break; case E_humrec_data_comment: if (appendQ) { cout << infile[i] << "\t"; } if (infile[i].equalFieldsQ("**kern")) { cout << infile[i][0]; } else { cout << "!"; } cout << endl; break; case E_humrec_data_interpretation: if (appendQ) { cout << infile[i] << "\t"; } if (!foundstart && infile[i].hasExclusiveQ()) { foundstart = 1; if (tniQ) { cout << "**Tni"; } else if (tnQ) { cout << "**Tn"; } else if (forteQ) { cout << "**forte"; } else if (tnormQ) { cout << "**tnf"; } else if (notesQ) { cout << "**dpc"; } else if (normQ) { cout << "**nf"; } else if (ivQ) { cout << "**iv"; } else if (infoQ) { cout << "**description"; } else { cout << "**tnt"; } } else { if (infile[i].equalFieldsQ("**kern") && (!infile[i].isSpineManipulator(0))) { cout << infile[i][0]; } else { cout << "*"; } } cout << endl; break; case E_humrec_data_kern_measure: if (appendQ) { cout << infile[i] << "\t"; } cout << infile[i][0]; cout << endl; break; case E_humrec_data: if (appendQ) { cout << infile[i] << "\t"; } // handle null fields if (infile[i].equalFieldsQ("**kern", ".")) { cout << "." << endl; break; } if (ivQ) { Array<int> iv; infile.getIntervalVector(iv, i); cout << IV_OPEN; for (int ii=0; ii<iv.getSize(); ii++) { if (iv[ii] < 9) { cout << iv[ii]; continue; } if (iv[ii] < 36) { cout << char(iv[ii]-10+'A'); continue; } if (ii > 0) { cout << ","; } cout << iv[ii]; if (ii < 5) { cout << ","; } } cout << IV_CLOSE << endl; } else if (forteQ) { const char* name = infile.getForteSetName(i); cout << name; if (tnQ) { if (strcmp(name, "3-11") == 0) { if (strcmp(cq[i].getTypeName(), "min") == 0) { cout << "A"; } else if (strcmp(cq[i].getTypeName(), "maj") == 0) { cout << "B"; } } } if (tniQ) { int inversion = -1; if (strcmp(name, "3-11") == 0) { if ((strcmp(cq[i].getTypeName(), "min") == 0) || (strcmp(cq[i].getTypeName(), "maj") == 0)) { inversion = cq[i].getInversion(); } if (inversion >= 0) { cout << char('a'+inversion); } } } if (xsattackQ) { printAttackMarker(infile, i); } cout << endl; } else if (normQ) { Array<int> norm; infile.getNormalForm(norm, i); cout << NORM_OPEN; for (int ii=0; ii<norm.getSize(); ii++) { if (norm[ii] < 10) { cout << norm[ii]; } else { cout << char('A' + norm[ii] - 10); } } cout << NORM_CLOSE; if (rotationQ) { printRotation(infile, i); } if (xsattackQ) { printAttackMarker(infile, i); } cout << endl; } else if (tnormQ) { Array<int> norm; infile.getNormalForm(norm, i); cout << TN_OPEN; int value; for (int ii=0; ii<norm.getSize(); ii++) { value = (norm[ii] - norm[0] + 144) % 12; if (value < 10) { cout << value; } else { cout << char('A' + value - 10); } } cout << TN_CLOSE; if (rotationQ) { printRotation(infile, i); } if (xsattackQ) { printAttackMarker(infile, i); } if (transQ) { if (norm.getSize() > 0) { cout << "T"; if (norm[0] < 10) { cout << "0"; } cout << norm[0]; } } cout << endl; } else if (notesQ) { quality = cq[i]; fillStringWithNotes(aString, quality, infile, i); cout << aString << endl; } else if (infoQ) { const char* tnname; tnname = infile.getTnSetName(i, attackQ); data.setSize(strlen(tnname)+1); strcpy(data.getBase(), tnname); pre.sar(data, "Z", "", "g"); if (pre.search(data, "^(\\d+-\\d+[AB]?)", "")) { cout << getDescription(pre.getSubmatch(1)); } else { cout << "."; } cout << endl; } else if (subsetQ) { Array<int> tnnames; infile.getTnSetNameAllSubsets(tnnames, i, attackQ); int cardinality; int enumeration; int inversion; // int transpose; for (int ii=tnnames.getSize()-1; ii>=0; ii--) { // tntypes are sorted from smallest subset to largest // but want to print from largest to smallest // 302200 --> 3-2B cardinality = (tnnames[ii] % 10000000) / 100000; enumeration = (tnnames[ii] % 100000 ) / 1000; inversion = (tnnames[ii] % 1000 ) / 100; // transpose = (tnnames[ii] % 100); cout << cardinality << "-" << enumeration; switch (inversion) { case 1: cout << "A"; break; case 2: cout << "B"; break; } // if (transQ) ... if (ii > 0) { cout << " "; } } // if (rotationQ) { // printRotation(infile, i); // } // if (xsattackQ) { // printAttackMarker(infile, i); // } // if (transQ) { // Array<int> norm; // infile.getNormalForm(norm, i); // if (norm.getSize() > 0) { // cout << "T"; // if (norm[0] < 10) { // cout << "0"; // } // cout << norm[0]; // } // } cout << endl; } else { const char* tnname; tnname = infile.getTnSetName(i, attackQ); if (verboseQ) { cout << tnname; } else { data.setSize(strlen(tnname)+1); strcpy(data.getBase(), tnname); if (pre.search(data, "^(\\d+-\\d+[AB]?)", "")) { cout << pre.getSubmatch(1); } else if (pre.search(data, "^(\\d+-)Z(\\d+[AB]?)", "")) { cout << pre.getSubmatch(1); cout << pre.getSubmatch(2); } else { cout << tnname; } } if (rotationQ) { printRotation(infile, i); } if (xsattackQ) { printAttackMarker(infile, i); } if (transQ) { Array<int> norm; infile.getNormalForm(norm, i); if (norm.getSize() > 0) { cout << "T"; if (norm[0] < 10) { cout << "0"; } cout << norm[0]; } } cout << endl; } break; default: cerr << "Error on line " << (i+1) << " of input" << endl; cerr << "record type = " << infile[i].getType() << endl; exit(1); } } } ////////////////////////////// // // printRotation -- // void printRotation(HumdrumFile& infile, int line) { Array<int> base12; infile.getBase12PitchList(base12, line); int i; if (base12.getSize() == 0) { return; } int min = base12[0]; for (i=1; i<base12.getSize(); i++) { if (base12[i] < min) { min = base12[i]; } } min = min % 12; Array<int> norm; infile.getNormalForm(norm, line); for (i=0; i<norm.getSize(); i++) { if (norm[i] == min) { cout << char('a' + i); return; } } cout << '?'; } ////////////////////////////// // // printAttackMarker -- print an "s" if the there is any note at // the start of the region which is not attacked (i.e., suspended // from a previous sonority; otherwise, print an "x" which means // that all notes in the sonority are attacked at the start of the // region. // void printAttackMarker(HumdrumFile& infile, int line) { int j, ii, jj; int& i = line; int dotQ; for (j=0; j<infile[i].getFieldCount(); j++) { if (!infile[i].isExInterp(j, "**kern")) { continue; } if (strcmp(infile[i][j], ".") == 0) { ii = infile[i].getDotLine(j); jj = infile[i].getDotSpine(j); if (ii < 0 || jj < 0) { continue; } dotQ = 1; } else { ii = i; jj = j; dotQ = 0; } if (strchr(infile[ii][jj], 'r') != NULL) { continue; } else if (dotQ) { cout << "s"; return; } if (strchr(infile[ii][jj], '_') != NULL) { cout << "s"; return; } if (strchr(infile[ii][jj], ']') != NULL) { cout << "s"; return; } } cout << "x"; } ////////////////////////////// // // transitionalSonority -- // int transitionalSonority(ChordQuality& quality, HumdrumFile& infile, int line) { SigCollection<int> notes; quality.getNotesInChord(notes); Array<int> octave; octave.setSize(notes.getSize()); octave.allowGrowth(0); octave.setAll(0); Array<int> sounding; sounding.setSize(notes.getSize()); sounding.allowGrowth(0); sounding.setAll(0); // int bassindex = identifyBassNote(notes, infile, line, sounding); int i; for (i=0; i<sounding.getSize(); i++) { if (sounding[i] == 0) { return 1; } } return 0; } ////////////////////////////// // // fillStringWithNotes -- // void fillStringWithNotes(char* string, ChordQuality& quality, HumdrumFile& infile, int line) { string[0] = '\0'; SigCollection<int> notes; quality.getNotesInChord(notes); Array<int> octave; octave.setSize(notes.getSize()); octave.allowGrowth(0); octave.setAll(4); Array<int> sounding; sounding.setSize(notes.getSize()); sounding.allowGrowth(0); sounding.setAll(0); int bassindex = identifyBassNote(notes, infile, line, sounding); if (bassindex >= 0) { octave[bassindex] = 3; //if (notes[bassindex] >= 40) { // octave[bassindex] += -2; //} } int i; if (suppressQ) { for (i=0; i<sounding.getSize(); i++) { if (sounding[i] == 0) { strcpy(string, "."); return; } } } string[0] = '\0'; char buffer[32] = {0}; for (i=0; i<notes.getSize(); i++) { //if (octaveVal >= 0) { // Convert::base40ToKern(buffer, (notes[i]%40) + octaveVal * 40); //} else { // Convert::base40ToKern(buffer, notes[i] + ((octave[i]+4) * 40)); //} Convert::base40ToKern(buffer, notes[i]%40 + (octave[i] * 40)); if (parenQ && (sounding[i] == 0)) { strcat(string, "("); } strcat(string, buffer); if (parenQ && (sounding[i] == 0)) { strcat(string, ")"); } if (i < notes.getSize() - 1) { strcat(string, notesep); } } } ////////////////////////////// // // identifyBassnote -- // int identifyBassNote(SigCollection<int>& notes, HumdrumFile& infile, int line, Array<int>& sounding) { int j, k; int output = -1; int minval = 1000000; int value; int tcount; char buffer[128] = {0}; Array<int> soundQ(40); soundQ.setAll(0); sounding.setSize(notes.getSize()); sounding.setAll(0); int pline; int pspine; int dotQ = 0; if (notes.getSize() == 0) { return -1; } for (j=0; j<infile[line].getFieldCount(); j++) { if (!infile[line].isExInterp(j, "**kern")) { continue; } dotQ = 0; if (strcmp(infile[line][j], ".") == 0) { pline = infile[line].getDotLine(j); pspine = infile[line].getDotSpine(j); if (pline < 0 || pspine < 0) { continue; } dotQ = 1; } else { pline = line; pspine = j; } tcount = infile[pline].getTokenCount(pspine); for (k=0; k<tcount; k++) { infile[pline].getToken(buffer, pspine, k); if (strchr(buffer, 'r') != NULL) { continue; } if (strcmp(buffer, ".") == 0) { // shouldn't get here... continue; } value = Convert::kernToMidiNoteNumber(buffer); if (value < 0) { continue; } if (value < minval) { minval = value; } if (dotQ) { continue; } if (strchr(buffer, '_') != NULL) { continue; } if (strchr(buffer, ']') != NULL) { continue; } value = Convert::kernToBase40(buffer); if (value < 0) { continue; } soundQ[value % 40] = 1; } } if (minval > 100000) { return -1; } minval = minval % 12; int i; int tval; for (i=0; i<notes.getSize(); i++) { if (notes[i] >= 0) { if (soundQ[notes[i]%40]) { sounding[i] = 1; } } tval = Convert::base40ToMidiNoteNumber(notes[i]); if (tval < 0) { continue; } tval = tval % 12; if (tval == minval) { output = i; // break; need to supress this because of sounding tests } } return output; } ////////////////////////////// // // getDescription -- return a rough musical description of the Tn type // const char* getDescription(const char* tntype) { int cardinality = 0; if (!sscanf(tntype, "%d", &cardinality)) { return "."; } switch (cardinality) { case 0: if (strcmp(tntype, "0-1") == 0) return "Rest"; break; case 1: if (strcmp(tntype, "1-1") == 0) return "Unison"; break; case 2: if (strcmp(tntype, "2-1") == 0) return "Semitone"; if (strcmp(tntype, "2-2") == 0) return "Whole-tone"; if (strcmp(tntype, "2-3") == 0) return "Minor Third"; if (strcmp(tntype, "2-4") == 0) return "Major Third"; if (strcmp(tntype, "2-5") == 0) return "Perfect Fourth"; if (strcmp(tntype, "2-6") == 0) return "Tritone"; break; case 3: if (strcmp(tntype, "3-1") == 0) return "BACH /Chromatic Trimirror"; if (strcmp(tntype, "3-2A") == 0) return "Phrygian Trichord"; if (strcmp(tntype, "3-2B") == 0) return "Minor Trichord"; if (strcmp(tntype, "3-3A") == 0) return "Major-minor Trichord.1"; if (strcmp(tntype, "3-3B") == 0) return "Major-minor Trichord.2"; if (strcmp(tntype, "3-4A") == 0) return "Incomplete Major-seventh Chord.1"; if (strcmp(tntype, "3-4B") == 0) return "Incomplete Major-seventh Chord.2"; if (strcmp(tntype, "3-5A") == 0) return "Rite chord.2, Tritone-fourth.1"; if (strcmp(tntype, "3-5B") == 0) return "Rite chord.1, Tritone-fourth.2"; if (strcmp(tntype, "3-6") == 0) return "Whole-tone Trichord"; if (strcmp(tntype, "3-7A") == 0) return "Incomplete Minor-seventh Chord"; if (strcmp(tntype, "3-7B") == 0) return "Incomplete Dominant-seventh Chord.2"; if (strcmp(tntype, "3-8A") == 0) return "Incomplete Dominant-seventh Chord.1/Italian-sixth"; if (strcmp(tntype, "3-8B") == 0) return "Incomplete Half-dim-seventh Chord"; if (strcmp(tntype, "3-9") == 0) return "Quartal Trichord"; if (strcmp(tntype, "3-10") == 0) return "Diminished Chord"; if (strcmp(tntype, "3-11A") == 0) return "Minor Chord"; if (strcmp(tntype, "3-11B") == 0) return "Major Chord"; if (strcmp(tntype, "3-12") == 0) return "Augmented Chord"; break; case 4: if (strcmp(tntype, "4-1") == 0) return "BACH /Chromatic Tetramirror"; if (strcmp(tntype, "4-2A") == 0) return "Major-second Tetracluster.2"; if (strcmp(tntype, "4-2B") == 0) return "Major-second Tetracluster.1"; if (strcmp(tntype, "4-3") == 0) return "Alternating Tetramirror"; if (strcmp(tntype, "4-4A") == 0) return "Minor Third Tetracluster.2"; if (strcmp(tntype, "4-4B") == 0) return "Minor Third Tetracluster.1"; if (strcmp(tntype, "4-5A") == 0) return "Major Third Tetracluster.2"; if (strcmp(tntype, "4-5B") == 0) return "Major Third Tetracluster.1"; if (strcmp(tntype, "4-6") == 0) return "Perfect Fourth Tetramirror"; if (strcmp(tntype, "4-7") == 0) return "Arabian Tetramirror"; if (strcmp(tntype, "4-8") == 0) return "Double Fourth Tetramirror"; if (strcmp(tntype, "4-9") == 0) return "Double Tritone Tetramirror"; if (strcmp(tntype, "4-10") == 0) return "Minor Tetramirror"; if (strcmp(tntype, "4-11A") == 0) return "Phrygian Tetrachord"; if (strcmp(tntype, "4-11B") == 0) return "Major Tetrachord"; if (strcmp(tntype, "4-12A") == 0) return "Harmonic-minor Tetrachord"; if (strcmp(tntype, "4-12B") == 0) return "Major-third Diminished Tetrachord"; if (strcmp(tntype, "4-13A") == 0) return "Minor-second Diminished Tetrachord"; if (strcmp(tntype, "4-13B") == 0) return "Perfect-fourth Diminished Tetrachord"; if (strcmp(tntype, "4-14A") == 0) return "Major-second Minor Tetrachord"; if (strcmp(tntype, "4-14B") == 0) return "Perfect-fourth Major Tetrachord"; if (strcmp(tntype, "4-15A") == 0) return "All-interval Tetrachord.1"; if (strcmp(tntype, "4-15B") == 0) return "All-interval Tetrachord.2"; if (strcmp(tntype, "4-16A") == 0) return "Minor-second Quartal Tetrachord"; if (strcmp(tntype, "4-16B") == 0) return "Tritone Quartal Tetrachord"; if (strcmp(tntype, "4-17") == 0) return "Major-minor Tetramirror"; if (strcmp(tntype, "4-18A") == 0) return "Major-diminished Tetrachord"; if (strcmp(tntype, "4-18B") == 0) return "Minor-diminished Tetrachord"; if (strcmp(tntype, "4-19A") == 0) return "Minor-augmented Tetrachord"; if (strcmp(tntype, "4-19B") == 0) return "Augmented-major Tetrachord"; if (strcmp(tntype, "4-20") == 0) return "Major-seventh Chord"; if (strcmp(tntype, "4-21") == 0) return "Whole-tone Tetramirror"; if (strcmp(tntype, "4-22A") == 0) return "Major-second Major Tetrachord"; if (strcmp(tntype, "4-22B") == 0) return "Perfect-fourth Minor Tetrachord"; if (strcmp(tntype, "4-23") == 0) return "Quartal Tetramirror"; if (strcmp(tntype, "4-24") == 0) return "Augmented Seventh Chord"; if (strcmp(tntype, "4-25") == 0) return "French-sixth Chord"; if (strcmp(tntype, "4-26") == 0) return "Minor-seventh Chord"; if (strcmp(tntype, "4-27A") == 0) return "Half-diminished Seventh Chord/Tristan Chord"; if (strcmp(tntype, "4-27B") == 0) return "Dominant-seventh/German-sixth Chord"; if (strcmp(tntype, "4-28") == 0) return "Diminished-seventh Chord"; if (strcmp(tntype, "4-29A") == 0) return "All-interval Tetrachord.3"; if (strcmp(tntype, "4-29B") == 0) return "All-interval Tetrachord.4"; break; case 5: if (strcmp(tntype, "5-1") == 0) return "Chromatic Pentamirror"; if (strcmp(tntype, "5-2A") == 0) return "Major-second Pentacluster.2"; if (strcmp(tntype, "5-2B") == 0) return "Major-second Pentacluster.1"; if (strcmp(tntype, "5-3A") == 0) return "Minor-second Major Pentachord"; if (strcmp(tntype, "5-3B") == 0) return "Spanish Pentacluster"; if (strcmp(tntype, "5-4A") == 0) return "Blues Pentacluster"; if (strcmp(tntype, "5-4B") == 0) return "Minor-third Pentacluster"; if (strcmp(tntype, "5-5A") == 0) return "Major-third Pentacluster.2"; if (strcmp(tntype, "5-5B") == 0) return "Major-third Pentacluster.1"; if (strcmp(tntype, "5-6A") == 0) return "Oriental Pentacluster.1, Raga Megharanji (13161)"; if (strcmp(tntype, "5-6B") == 0) return "Oriental Pentacluster.2"; if (strcmp(tntype, "5-7A") == 0) return "DoublePentacluster.1, Raga Nabhomani (11415)"; if (strcmp(tntype, "5-7B") == 0) return "Double Pentacluster.2"; if (strcmp(tntype, "5-8") == 0) return "Tritone-Symmetric Pentamirror"; if (strcmp(tntype, "5-9A") == 0) return "Tritone-Expanding Pentachord"; if (strcmp(tntype, "5-9B") == 0) return "Tritone-Contracting Pentachord"; if (strcmp(tntype, "5-10A") == 0) return "Alternating Pentachord.1"; if (strcmp(tntype, "5-10B") == 0) return "Alternating Pentachord.2"; if (strcmp(tntype, "5-11A") == 0) return "Center-cluster Pentachord.1"; if (strcmp(tntype, "5-11B") == 0) return "Center-cluster Pentachord.2"; if (strcmp(tntype, "5-12") == 0) return "Locrian Pentamirror"; if (strcmp(tntype, "5-13A") == 0) return "Augmented Pentacluster.1"; if (strcmp(tntype, "5-13B") == 0) return "Augmented Pentacluster.2"; if (strcmp(tntype, "5-14A") == 0) return "Double-seconds Triple-fourth Pentachord.1"; if (strcmp(tntype, "5-14B") == 0) return "Double-seconds Triple-fourth Pentachord.2"; if (strcmp(tntype, "5-15") == 0) return "Assymetric Pentamirror"; if (strcmp(tntype, "5-16A") == 0) return "Major-minor-dim Pentachord.1"; if (strcmp(tntype, "5-16B") == 0) return "Major-minor-dim Pentachord.2"; if (strcmp(tntype, "5-17") == 0) return "Minor-major Ninth Chord"; if (strcmp(tntype, "5-18A") == 0) return "Gypsy Pentachord.1"; if (strcmp(tntype, "5-18B") == 0) return "Gypsy Pentachord.2"; if (strcmp(tntype, "5-19A") == 0) return "Javanese Pentachord"; if (strcmp(tntype, "5-19B") == 0) return "Balinese Pentachord"; if (strcmp(tntype, "5-20A") == 0) return "Balinese Pelog Pentatonic (12414), Raga Bhupala, Raga Bibhas"; if (strcmp(tntype, "5-20B") == 0) return "Hirajoshi Pentatonic (21414), Iwato (14142), Sakura/Raga Saveri (14214)"; if (strcmp(tntype, "5-21A") == 0) return "Syrian Pentatonic/Major-augmented Ninth Chord, Raga Megharanji (13134)"; if (strcmp(tntype, "5-21B") == 0) return "Lebanese Pentachord/Augmented-minor Chord"; if (strcmp(tntype, "5-22") == 0) return "Persian Pentamirror, Raga reva/Ramkali (13314)"; if (strcmp(tntype, "5-23A") == 0) return "Minor Pentachord"; if (strcmp(tntype, "5-23B") == 0) return "Major Pentachord"; if (strcmp(tntype, "5-24A") == 0) return "Phrygian Pentachord"; if (strcmp(tntype, "5-24B") == 0) return "Lydian Pentachord"; if (strcmp(tntype, "5-25A") == 0) return "Diminished-major Ninth Chord"; if (strcmp(tntype, "5-25B") == 0) return "Minor-diminished Ninth Chord"; if (strcmp(tntype, "5-26A") == 0) return "Diminished-augmented Ninth Chord"; if (strcmp(tntype, "5-26B") == 0) return "Augmented-diminished Ninth Chord"; if (strcmp(tntype, "5-27A") == 0) return "Major-Ninth Chord"; if (strcmp(tntype, "5-27B") == 0) return "Minor-Ninth Chord"; if (strcmp(tntype, "5-28A") == 0) return "Augmented-sixth Pentachord.1"; if (strcmp(tntype, "5-28B") == 0) return "Augmented-sixth Pentachord.2"; if (strcmp(tntype, "5-29A") == 0) return "Kumoi Pentachord.2"; if (strcmp(tntype, "5-29B") == 0) return "Kumoi Pentachord.1"; if (strcmp(tntype, "5-30A") == 0) return "Enigmatic Pentachord.1"; if (strcmp(tntype, "5-30B") == 0) return "Enigmatic Pentachord.2, Altered Pentatonic (14223)"; if (strcmp(tntype, "5-31A") == 0) return "Diminished Minor-Ninth Chord"; if (strcmp(tntype, "5-31B") == 0) return "Ranjaniraga/Flat-Ninth Pentachord"; if (strcmp(tntype, "5-32A") == 0) return "Neapolitan Pentachord.1"; if (strcmp(tntype, "5-32B") == 0) return "Neapolitan Pentachord.2"; if (strcmp(tntype, "5-33") == 0) return "Whole-tone Pentamirror"; if (strcmp(tntype, "5-34") == 0) return "Dominant-ninth/major-minor/Prometheus Pentamirror, Dominant Pentatonic (22332)"; if (strcmp(tntype, "5-35") == 0) return "'Black Key' Pentatonic/Slendro/Bilahariraga/Quartal Pentamirror, Yo (23232)"; if (strcmp(tntype, "5-36A") == 0) return "Major-seventh Pentacluster.2"; if (strcmp(tntype, "5-36B") == 0) return "Minor-seventh Pentacluster.1"; if (strcmp(tntype, "5-37") == 0) return "Center-cluster Pentamirror"; if (strcmp(tntype, "5-38A") == 0) return "Diminished Pentacluster.1"; if (strcmp(tntype, "5-38B") == 0) return "Diminished Pentacluster.2"; break; case 6: if (strcmp(tntype, "6-1") == 0) return "Chromatic Hexamirror/1st ord. all-comb (P6, Ib, RI5)"; if (strcmp(tntype, "6-2A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-2B") == 0) return "comb I (1)"; if (strcmp(tntype, "6-4") == 0) return "comb RI (6)"; if (strcmp(tntype, "6-5A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-5B") == 0) return "comb I (3)"; if (strcmp(tntype, "6-6") == 0) return "Double-cluster Hexamirror"; if (strcmp(tntype, "6-7") == 0) return "Messiaen's mode 5 (114114), 2nd ord.all-comb(P3+9,I5,Ib,R6,RI2+8)"; if (strcmp(tntype, "6-8") == 0) return "1st ord.all-comb (P6, I1, RI7)"; if (strcmp(tntype, "6-9A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-9B") == 0) return "comb I (3)"; if (strcmp(tntype, "6-13") == 0) return "Alternating Hexamirror/comb RI7)"; if (strcmp(tntype, "6-14A") == 0) return "comb P (6)"; if (strcmp(tntype, "6-14B") == 0) return "comb P (6)"; if (strcmp(tntype, "6-15A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-15B") == 0) return "comb I (5)"; if (strcmp(tntype, "6-16A") == 0) return "comb I (3)"; if (strcmp(tntype, "6-16B") == 0) return "Megha or 'Cloud' Raga/comb.I (1)"; if (strcmp(tntype, "6-18A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-18B") == 0) return "comb I (5)"; if (strcmp(tntype, "6-20") == 0) return "Augmented scale, Genus tertium, 3rd ord. all-comb (P2+6+10, I3+7+b, R4+8, RI1+5+9)"; if (strcmp(tntype, "6-21A") == 0) return "comb I (1)"; if (strcmp(tntype, "6-21B") == 0) return "comb I (3)"; if (strcmp(tntype, "6-22A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-22B") == 0) return "comb I (5)"; if (strcmp(tntype, "6-23") == 0) return "Super-Locrian Hexamirror/comb RI (8)"; if (strcmp(tntype, "6-24B") == 0) return "Melodic-minor Hexachord"; if (strcmp(tntype, "6-25A") == 0) return "Locrian Hexachord/Suddha Saveriraga"; if (strcmp(tntype, "6-25B") == 0) return "Minor Hexachord"; if (strcmp(tntype, "6-26") == 0) return "Phrygian Hexamirror/comb RI (8)"; if (strcmp(tntype, "6-27A") == 0) return "comb I (b)"; if (strcmp(tntype, "6-27B") == 0) return "Pyramid Hexachord/comb I (1)"; if (strcmp(tntype, "6-28") == 0) return "Double-Phrygian Hexachord/comb RI (6)"; if (strcmp(tntype, "6-29") == 0) return "comb RI (9)"; if (strcmp(tntype, "6-30A") == 0) return "Minor-bitonal Hexachord/comb R (6), I (5,b)"; if (strcmp(tntype, "6-30B") == 0) return "Petrushka chord, Major-bitonal Hexachord, comb R (6), I (1,7)"; if (strcmp(tntype, "6-31A") == 0) return "comb I (7)"; if (strcmp(tntype, "6-31B") == 0) return "comb I (b)"; if (strcmp(tntype, "6-32") == 0) return "Arezzo major Diatonic (221223), major hexamirror, quartal hexamirror, 1st ord.all-comb P (6), I (3), RI (9)"; if (strcmp(tntype, "6-33A") == 0) return "Dorian Hexachord/comb I (1)"; if (strcmp(tntype, "6-33B") == 0) return "Dominant-11th/Lydian Hexachord/comb I (5)"; if (strcmp(tntype, "6-34A") == 0) return "Mystic Chord or Prometheus Hexachord/comb I (B)"; if (strcmp(tntype, "6-34B") == 0) return "Harmonic Hexachord/Augmented-11th/comb I (7)"; if (strcmp(tntype, "6-35") == 0) return "Wholetone scale/6th ord.all-comb.(P+IoddT, R+RIevenT)"; if (strcmp(tntype, "6-37") == 0) return "comb RI (4)"; if (strcmp(tntype, "6-38") == 0) return "comb RI (3)"; if (strcmp(tntype, "6-42") == 0) return "comb RI (3)"; if (strcmp(tntype, "6-44A") == 0) return "Schoenberg Anagram Hexachord"; if (strcmp(tntype, "6-44B") == 0) return "Bauli raga (133131)"; if (strcmp(tntype, "6-45") == 0) return "comb RI (6)"; if (strcmp(tntype, "6-47B") == 0) return "Blues mode.1 (321132)"; if (strcmp(tntype, "6-48") == 0) return "comb RI (2)"; if (strcmp(tntype, "6-49") == 0) return "Prometheus Neapolitan mode (132312), comb RI (4)"; if (strcmp(tntype, "6-50") == 0) return "comb RI (1)"; break; case 7: if (strcmp(tntype, "7-1") == 0) return "Chromatic Heptamirror"; if (strcmp(tntype, "7-20A") == 0) return "Chromatic Phrygian inverse (1123113)"; if (strcmp(tntype, "7-20B") == 0) return "Pantuvarali Raga (1321131), Chromatic Mixolydian (1131132), Chromatic Dorian/Mela Kanakangi (1132113)"; if (strcmp(tntype, "7-21B") == 0) return "Gypsy hexatonic (1312113)"; if (strcmp(tntype, "7-22") == 0) return "Persian, Major Gypsy, Hungarian Minor, Double Harmonic scale, Bhairav That, Mayamdavagaula Raga (all: 1312131), Oriental (1311312)"; if (strcmp(tntype, "7-23B") == 0) return "Tritone Major Heptachord"; if (strcmp(tntype, "7-24B") == 0) return "Enigmatic Heptatonic (1322211)"; if (strcmp(tntype, "7-27B") == 0) return "Modified Blues mode (2121132)"; if (strcmp(tntype, "7-30A") == 0) return "Neapolitan-Minor mode (1222131), Mela Dhenuka"; if (strcmp(tntype, "7-31A") == 0) return "Alternating Heptachord.1/Hungarian Major mode (3121212)"; if (strcmp(tntype, "7-31B") == 0) return "Alternating Heptachord.2"; if (strcmp(tntype, "7-32A") == 0) return "Harmonic-Minor mode (2122131), Spanish Gypsy, Mela Kiravani, Pilu That"; if (strcmp(tntype, "7-32B") == 0) return "Dharmavati Scale (2131221), Harmonic minor inverse (1312212), Mela Cakravana, Raga Ahir Bhairav"; if (strcmp(tntype, "7-33") == 0) return "Neapolitan-major mode (1222221)/Leading-Whole-tone mode (222211)"; if (strcmp(tntype, "7-34") == 0) return "Harmonic/Super-Locrian, Melodic minor ascending (1212222)/Aug.13th Heptamirror, Jazz Minor"; if (strcmp(tntype, "7-35") == 0) return "Major Diatonic Heptachord/Dominant-13th, Locrian (1221222), Phrygian (1222122), Major inverse"; break; case 8: if (strcmp(tntype, "8-1") == 0) return "Chromatic Octamirror"; if (strcmp(tntype, "8-9") == 0) return "Messiaen's mode 4 (11131113)"; if (strcmp(tntype, "8-22B") == 0) return "Spanish Octatonic Scale (r9) (12111222)"; if (strcmp(tntype, "8-23") == 0) return "Quartal Octachord, Diatonic Octad"; if (strcmp(tntype, "8-25") == 0) return "Messiaen mode 6 (11221122)"; if (strcmp(tntype, "8-26") == 0) return "Spanish Phrygian (r9) (12112122)/ Blues mode.2 (21211212)"; if (strcmp(tntype, "8-28") == 0) return "Alternating Octatonic or Diminished scale (12121212)"; break; case 9: if (strcmp(tntype, "9-1") == 0) return "Chromatic Nonamirror"; if (strcmp(tntype, "9-7A") == 0) return "Nonatonic Blues Scale (211111212)"; if (strcmp(tntype, "9-9") == 0) return "Raga Ramdasi Malhar (r2) (211122111)"; if (strcmp(tntype, "9-11B") == 0) return "Diminishing Nonachord"; if (strcmp(tntype, "9-12") == 0) return "Tsjerepnin/Messiaen mode 3 (112112112)"; break; case 10: if (strcmp(tntype, "10-1") == 0) return "Chromatic Decamirror"; if (strcmp(tntype, "10-5") == 0) return "Major-minor mixed (r7)"; if (strcmp(tntype, "10-6") == 0) return "Messiaen mode 7 (1111211112)"; break; case 11: if (strcmp(tntype, "11-1") == 0) return "Chromatic Undecamirror"; break; case 12: if (strcmp(tntype, "12-1") == 0) return "Chromatic Scale/Dodecamirror (111111111111)"; break; } // no musical desciption of the Tn type return "."; } ////////////////////////////// // // usage -- gives the usage statement for the sonority program // void usage(const char* command) { cout << " \n" << endl; } // md5sum: 6745642f50b60d70467597a03c9dd764 tntype.cpp [20130420]