//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Fri May 10 12:40:06 PDT 2002
// Last Modified: Fri May 10 12:40:09 PDT 2002
// Last Modified: Tue Aug 26 01:37:37 PDT 2008 (allow multiple input files)
// Filename: ...sig/examples/all/pitchhist.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/pitchhist.cpp
// Syntax: C++; museinfo
//
// Description: Generate pitch histograms of **kern data in Humdrum files.
//
#include "humdrum.h"
#include <string.h>
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void usage(const char* command);
void printHistogram(Array<double>& histogram);
void getHistogram(Array<double>& histogram, HumdrumFile& infile,
double starttime, double stoptime);
// interface variables
Options options; // database for command-line arguments
double starttime = 0.0;
double stoptime = -1.0;
int verboseQ = 0; // used with -v option
int pcQ = 1; // used with -o option
int restQ = 0; // used with -r option
int base40Q = 0; // used with -b option
int fillQ = 0; // used with -f option
int countQ = 0; // used with -c option
int normalizeQ = 0; // used with -n option
int fifthsQ = 0; // used with -5 option
int cstyleQ = 0; // used with -C option
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
HumdrumFile infile;
// process the command-line options
checkOptions(options, argc, argv);
// figure out the number of input files to process
int numinputs = options.getArgCount();
Array<double> histogram(1001);
Array<double> temphistogram(1001);
histogram.zero();
temphistogram.zero();
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.analyzeRhythm();
// analyze the input file according to command-line options
getHistogram(temphistogram, infile, starttime, stoptime);
histogram += temphistogram;
}
double sum = 0.0;
int i;
if (normalizeQ) {
for (i=0; i<1000; i++) {
sum += histogram[i];
}
if (restQ) {
sum += histogram[1000];
}
if (sum > 0.0) {
for (i=0; i<1001; i++) {
histogram[i] /= sum;
}
}
}
printHistogram(histogram);
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// printHistogram --
//
void printHistogram(Array& histogram) {
int i;
char buffer[256] = {0};
int findex = 0;
if (verboseQ) {
for (i=0; i<histogram.getSize(); i++) {
if (base40Q && pcQ && i >39 && i<1000) {
continue;
}
if (!base40Q && pcQ && i >12 && i<1000) {
continue;
}
if (!base40Q && i>127 && i<1000) {
continue;
}
if (restQ == 0 && i >= 1000) {
continue;
}
if (!fillQ && histogram[i] == 0.0) {
continue;
}
if (base40Q) {
if (i < 1000) {
if (pcQ) {
if (fifthsQ) {
findex = (17 + i * 23) % 40;
Convert::base40ToKern(buffer, findex+4*40);
if (buffer[0] == '\0') {
continue;
}
} else {
Convert::base40ToKern(buffer, i+4*40);
if (buffer[0] == '\0') {
continue;
}
}
} else {
if (histogram[i] == 0.0) {
continue;
}
Convert::base40ToKern(buffer, i);
}
} else {
strcpy(buffer, "rest");
}
if (base40Q && pcQ && fifthsQ) {
cout << buffer << ":\t" << histogram[findex] << endl;
} else {
cout << buffer << ":\t" << histogram[i] << endl;
}
} else {
cout << i << ":\t" << histogram[i] << endl;
}
}
} else {
if (base40Q) {
} else {
if (cstyleQ) cout << "{";
for (i=0; i<12; i++) {
cout << histogram[i];
if (i < 11) {
if (cstyleQ) cout << ",";
cout << " ";
}
}
if (restQ) {
if (cstyleQ) cout << ",";
cout << " " << histogram[1000];
}
if (cstyleQ) cout << "};";
cout << endl;
}
}
}
//////////////////////////////
//
// getHistogram --
//
void getHistogram(Array<double>& histogram, HumdrumFile& infile,
double starttime, double stoptime) {
if (stoptime <= starttime) {
stoptime = infile.getTotalDuration();
}
histogram.zero();
int i, j, k;
double duration = 0.0;
int tokencount = 0;
int pitch = 0;
char buffer[1024] = {0};
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getAbsBeat() < starttime) {
continue;
} else if (infile[i].getAbsBeat() > stoptime) {
break;
}
if (!infile[i].isData()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
if (strcmp(infile[i].getExInterp(j), "**kern") != 0) {
continue;
}
tokencount = infile[i].getTokenCount(j);
for (k=0; k<tokencount; k++) {
infile[i].getToken(buffer, j, k);
if (strcmp(buffer, ".") == 0) {
continue;
}
if (countQ && (strchr(buffer, '_') != NULL)) {
continue;
}
if (countQ && (strchr(buffer, ']') != NULL)) {
continue;
}
if (base40Q) {
pitch = Convert::kernToBase40(buffer);
} else {
pitch = Convert::kernToMidiNoteNumber(buffer);
}
if (pitch < 0 || pitch == E_unknown) {
continue; // don't count weird notes
} else if (base40Q && pcQ) {
pitch = pitch % 40;
} else if (pcQ) {
pitch = pitch % 12;
}
duration = Convert::kernToDuration(buffer);
if (countQ) {
histogram[pitch] += 1;
} else {
histogram[pitch] += duration;
}
}
}
}
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("v|verbose=b", "display output in verbose style");
opts.define("o|octaves=b", "keep octave information");
opts.define("b|e|enharmonic|base40=b", "keep enharmonic information");
opts.define("r|rest=b", "display rest information");
opts.define("f|fill=b", "diplay entries with 0 values");
opts.define("c|count=b", "count attacks rather than durations");
opts.define("C|cstyle=b", "output data in C-style array");
opts.define("n|normalize=b","normalize to sum to 1.0");
opts.define("5|fifths=b", "display enharmonic pitch classes by fifths");
opts.define("debug=b", "determine bad input line num");
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, May 2002" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 10 May 2002" << 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);
}
verboseQ = opts.getBoolean("verbose");
pcQ = !opts.getBoolean("octaves");
base40Q = opts.getBoolean("base40");
restQ = opts.getBoolean("rest");
fillQ = opts.getBoolean("fill");
countQ = opts.getBoolean("count");
cstyleQ = opts.getBoolean("cstyle");
normalizeQ = opts.getBoolean("normalize");
fifthsQ = opts.getBoolean("fifths");
}
//////////////////////////////
//
// example -- example usage of the pitchhist program
//
void example(void) {
cout <<
" \n"
"# example usage of the sample program. \n"
" \n"
<< endl;
}
//////////////////////////////
//
// usage -- gives the usage statement for the pitchhist program
//
void usage(const char* command) {
cout <<
" To be written... \n"
<< endl;
}
// md5sum: 3a9ce567fdce91339b6a84aff70325f1 pitchhist.cpp [20101222]