//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Wed Jan 10 12:32:52 PST 2001
// Last Modified: Mon Jan 29 10:39:20 PST 2001
// Filename: ...sig/examples/all/ccheck.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/ccheck.cpp
// Syntax: C++; museinfo
//
// Description: determine the chord information for the given region
//
#include "humdrum.h"
#include <string.h>
#include <math.h>
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void printAnalysis(HumdrumFile& infile, Array<int>& rhylev);
void usage(const char* command);
int findMinimum(Array<double>& values);
int findBestMode(Array<double>& values, int bestroot);
int findBestTonic(Array<double>& values);
// global variables
Options options; // database for command-line arguments
int debugQ = 0; // used with the --debug option
int appendQ = 0; // used with the -a option
int compoundQ = 1; // used with the -c option
double e1; // used with the --e1 option
double e2; // used with the --e2 option
double sx; // used with the --sx option
double sy; // used with the --sy option
double neighbornorm[40] = {
0.0000000000000, // C C 0 0 0
1.4142135623731, // C C# 1 1 -1
2.8284271247462, // C C## 2 2 -2
100000.0, // invalid 3
3.0000000000000, // C D-- 4 -3 0
2.2360679774998, // C D- 5 -2 -1
2.2360679774998, // C D 6 -1 -2
3.0000000000000, // C D# 7 0 -3
4.0000000000000, // C D## 8 4 0
100000.0, // invalid 9
2.2360679774998, // C E-- 10 -1 2
1.0000000000000, // C E- 11 0 1
1.0000000000000, // C E 12 1 0
2.2360679774998, // C E# 13 2 -1
3.6055512754640, // C E## 14 3 -2
3.1622776601684, // C F-- 15 -3 1
2.0000000000000, // C F- 16 -2 0
1.4142135623731, // C F 17 -1 -1
2.0000000000000, // C F# 18 0 -2
3.1622776601684, // C F## 19 1 -3
100000.0, // invalid 20
3.1622776601684, // C G-- 21 -1 3
2.0000000000000, // C G- 22 0 2
1.4142135623731, // C G 23 1 1
2.0000000000000, // C G# 24 2 0
3.1622776601684, // C G## 25 3 -1
100000.0, // invalid 26
2.2360679774998, // C A-- 27 -2 1
1.0000000000000, // C A- 28 -1 0
1.0000000000000, // C A 29 0 -1
2.2360679774998, // C A# 30 1 -2
3.6055512754640, // C A## 31 2 -3
100000.0, // invalid 32
3.0000000000000, // C B-- 33 0 3
2.2360679774998, // C B- 34 1 2
2.2360679774998, // C B 35 2 1
3.0000000000000, // C B# 36 3 0
4.1231056256176, // C B## 37 4 -1
2.8284271247462, // C C-- -2 -2 2
1.4142135623731, // C C- -1 -1 1
};
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
HumdrumFile infile;
Array<int> rhylev;
// process the command-line options
checkOptions(options, argc, argv);
// figure out the number of input files to process
int numinputs = options.getArgCount();
int most = 0;
Array<double> values;
values.setSize(0);
char buffer[128] = {0};
Array<double> tonicscores;
for (int i=0; i<numinputs || i==0; i++) {
infile.clear();
// if no command-line arguments read data file from standard input
if (numinputs < 1) {
infile.read(cin);
} else {
infile.read(options.getArg(i+1));
}
infile.analyzeMetricLevel(rhylev);
most = infile.analyzeChordProbability(values, 0,
infile.getNumLines()-1, rhylev, e1, e2, sx, sy);
int bestroot = findBestTonic(values);
int bestmode = findBestMode(values, bestroot);
bestroot += 2;
Convert::base40ToKern(buffer, bestroot + 160);
if (options.getBoolean("numeric")) {
cout << bestroot - 2 << "\t" << bestmode << endl;
} else {
cout << "best key: ";
if (bestmode == 0) {
cout << buffer << " major " << endl;
} else {
cout << buffer << " minor " << endl;
}
}
if (options.getBoolean("scores")) {
for (i=0; i<values.getSize(); i++) {
cout << " root " << i << ":\t" << values[i] << endl;
}
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// findBestMode -- choose whether a major or minor key is a better fit to
// the data. The test mode which has the best third scale degree score
// will determine the mode.
//
//
int findBestMode(Array& values, int majorbest) {
int majindexnatu = (12 + majorbest) % 40;
int majindexflat = (11 + majorbest) % 40;
cout << "tonic " << majorbest << "\t= " << values[majorbest] << endl;
cout << "values " << majindexnatu << "\t= " << values[majindexnatu] << endl;
cout << "values " << majindexflat << "\t= " << values[majindexflat] << endl;
cout << "Diff = " << values[majindexflat]-values[majorbest] << endl;
if (values[majindexnatu] < values[majindexflat]) {
return 0;
} else {
return 1;
}
}
//////////////////////////////
//
// findMinimum --
//
int findMinimum(Array& values) {
int i;
int min = 0;
for (i=1; i<values.getSize(); i++) {
if (values[i] < values[min]) {
min = i;
}
}
return min;
}
//////////////////////////////
//
// findBestTonic --
//
int findBestTonic(Array& values) {
int i;
int best = 0;
for (i=1; i<values.getSize(); i++) {
if (values[i] < values[best]) {
best = i;
}
}
return best;
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("a|append=b", "append analysis to data in output");
opts.define("C|compound=b", "don't try to use compound meters");
opts.define("e1=d:-4.0", "first rhythm scalar");
opts.define("e2=d:-3.0", "second rhythm scalar");
opts.define("sx=d:0.578", "first pitch scalar");
opts.define("sy=d:1", "second pitch scalar");
opts.define("s|scores=b", "show scores");
opts.define("n|numeric=b", "show result in numeric root/mode");
opts.define("debug=b", "trace input parsing");
opts.define("author=b", "author of the program");
opts.define("version=b", "compilation information");
opts.define("example=b", "example usage");
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, Dec 2000" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 6 Dec 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);
}
debugQ = opts.getBoolean("debug");
appendQ = opts.getBoolean("append");
if (opts.getBoolean("compound")) {
compoundQ = 0;
} else {
compoundQ = 0;
}
e1 = opts.getDouble("e1");
e2 = opts.getDouble("e2");
sx = opts.getDouble("sx");
sy = opts.getDouble("sy");
}
//////////////////////////////
//
// example -- example usage of the maxent program
//
void example(void) {
cout <<
" \n"
<< endl;
}
//////////////////////////////
//
// printAnalysis --
//
void printAnalysis(HumdrumFile& infile, Array& rhylev) {
int i;
if (appendQ) {
for (i=0; i<infile.getNumLines(); i++) {
switch (infile[i].getType()) {
case E_humrec_global_comment:
case E_humrec_bibliography:
case E_humrec_none:
case E_humrec_empty:
cout << infile[i].getLine() << "\n";
break;
case E_humrec_data:
cout << infile[i].getLine() << "\t";
cout << rhylev[i] << "\n";
break;
case E_humrec_data_comment:
if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i].getLine() << "\t"
<< infile[i][0] << "\n";
} else {
cout << infile[i].getLine() << "\t!\n";
}
break;
case E_humrec_data_measure:
if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i].getLine() << "\t"
<< infile[i][0] << "\n";
} else {
cout << infile[i].getLine() << "\t=\n";
}
break;
case E_humrec_data_interpretation:
if (strncmp(infile[i][0], "**", 2) == 0) {
cout << infile[i].getLine() << "\t";
cout << "**rhylev" << "\n";
} else if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i].getLine() << "\t"
<< infile[i][0] << "\n";
} else {
cout << infile[i].getLine() << "\t*\n";
}
break;
}
}
} else {
for (i=0; i<infile.getNumLines(); i++) {
switch (infile[i].getType()) {
case E_humrec_global_comment:
case E_humrec_bibliography:
case E_humrec_none:
case E_humrec_empty:
cout << infile[i].getLine() << "\n";
break;
case E_humrec_data:
cout << rhylev[i] << "\n";
break;
case E_humrec_data_comment:
if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i][0] << "\n";
} else {
// do nothing
}
break;
case E_humrec_data_measure:
if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i][0] << "\n";
} else {
cout << "\t=\n";
}
break;
case E_humrec_data_interpretation:
if (strncmp(infile[i][0], "**", 2) == 0) {
cout << "**rhylev" << "\n";
} else if (infile[i].equalFieldsQ("**kern")) {
cout << infile[i][0] << "\n";
} else {
// do nothing
}
break;
}
}
}
}
//////////////////////////////
//
// usage -- gives the usage statement for the quality program
//
void usage(const char* command) {
cout <<
" \n"
<< endl;
}
// md5sum: 3fc1c34a7d66d25ebf7dc49609e07cf2 ckey.cpp [20050403]