//
// 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]