//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Thu Nov 15 08:55:35 PST 2001
// Last Modified: Thu Nov 15 08:55:40 PST 2001
// Filename: ...sig/examples/all/spinemv.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/spinemv.cpp
// Syntax: C++; museinfo
//
// Description: For reorganizing spines in a humdrum file.
//
#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 getTransformation(HumdrumFile& hfile, Array<int>& transform);
void printTransformation(HumdrumFile& hfile, Array<int>& transform);
void printLine(HumdrumFile& hfile,Array<int>& transform,int line);
double getAveragePitch(HumdrumFile& hfile, int primaryTrack);
// User interface variables:
Options options;
int reverseQ = 0;
int determineQ = 0;
int normalQ = 0;
const char* primaryspine = "**kern";
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
HumdrumFile hfile;
checkOptions(options, argc, argv); // process the command-line options
// figure out the number of input files to process
int numinputs = options.getArgCount();
for (int i=0; i<numinputs || i==0; i++) {
hfile.clear();
// if no command-line arguments read data file from standard input
if (numinputs < 1) {
hfile.read(cin);
} else {
hfile.read(options.getArg(i+1));
}
// hfile.analyzeRhythm();
Array<int> transform;
getTransformation(hfile, transform);
if (!determineQ) {
printTransformation(hfile, transform);
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// printTransformation --
//
void printTransformation(HumdrumFile& hfile, Array& transform) {
int i;
for (i=0; i<hfile.getNumLines(); i++) {
switch (hfile[i].getType()) {
case E_humrec_none:
case E_humrec_empty:
case E_humrec_global_comment:
case E_humrec_bibliography:
cout << hfile[i] << "\n";
break;
case E_humrec_data_comment:
case E_humrec_data_kern_measure:
case E_humrec_interpretation:
case E_humrec_data:
printLine(hfile, transform, i);
break;
default:
cout << hfile[i] << "\n";
break;
}
}
}
//////////////////////////////
//
// printLine --
//
void printLine(HumdrumFile& hfile, Array& transform, int line) {
int i, j;
int target = 0;
int count = 0;
for (j=0; j<transform.getSize(); j++) {
target = transform[j];
for (i=0; i<hfile[line].getFieldCount(); i++) {
if (hfile[line].getPrimaryTrack(i) == target) {
if (count != 0) {
cout << "\t";
}
count++;
cout << hfile[line][i];
}
}
}
cout << "\n";
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("f|field-order=s", "reordering scheme of output");
opts.define("r|reverse=b", "reverse the order of the spines");
opts.define("n|normal=b", "convert score to normal order");
opts.define("p|primary=s:**kern", "main spine for group reversals");
opts.define("d|determine|detect=b", "determine score ordering only");
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, Nov 2001" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: Nov 2001" << 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);
}
reverseQ = opts.getBoolean("reverse");
normalQ = opts.getBoolean("normal");
determineQ = opts.getBoolean("determine");
if (determineQ) {
normalQ = 1;
}
primaryspine = options.getString("primary");
}
//////////////////////////////
//
// example --
//
void example(void) { }
//////////////////////////////
//
// getTransformation --
//
void getTransformation(HumdrumFile& hfile, Array& transform) {
transform.setSize(1000);
transform.setSize(0);
transform.allowGrowth(1);
int maxspine = hfile.getMaxTracks();
int i, j;
if (reverseQ) {
transform.setSize(maxspine);
for (i=0; i<maxspine; i++) {
transform[i] = maxspine - i;
}
return;
}
if (options.getBoolean("field-order")) {
// const char* order = options.getString("field-order");
cout << "Not yet written" << endl;
return;
}
if (normalQ) {
int findex = -1;
int lindex = -1;
int i;
for (i=0; i<hfile.getMaxTracks(); i++) {
if (strcmp(hfile.getTrackExInterp(i+1), "**kern") == 0) {
if (findex == -1) {
findex = i;
}
lindex = i;
}
}
double favg = 0.0;
double lavg = 0.0;
if (findex != lindex) {
favg = getAveragePitch(hfile, findex + 1);
lavg = getAveragePitch(hfile, lindex + 1);
}
if (favg > lavg) {
if (determineQ) {
cout << "Score is in reverse order.\tpitch avgs:"
<< favg << "\tcompared to " << lavg << endl;
return;
}
// reverse data by kern (or primary spine type) blocks
for (i=maxspine; i>0; i--) {
if (strcmp(hfile.getTrackExInterp(i), "**kern") == 0) {
transform.append(i);
j = i+1;
while ((j <= maxspine) &&
(strcmp(hfile.getTrackExInterp(j), "**kern") != 0)) {
transform.append(j);
j++;
}
}
}
transform.allowGrowth(0);
return;
} else {
// score is already in normal form
if (determineQ) {
cout << "Score is in normal order.\tpictch avgs.:"
<< favg << " compared to " << lavg << endl;
return;
}
for (i=1; i<=maxspine; i++) {
transform.append(i);
}
transform.allowGrowth(0);
return;
}
}
// reverse data by kern (or primary spine type) blocks
char buffer[1024] = {0};
if (strncmp(primaryspine, "**", 2) != 0) {
strcpy(buffer, "**");
strcat(buffer, primaryspine);
} else {
strcat(buffer, primaryspine);
}
for (i=maxspine; i>0; i--) {
if (strcmp(hfile.getTrackExInterp(i), buffer) == 0) {
transform.append(i);
j = i+1;
while ((j <= maxspine) &&
(strcmp(hfile.getTrackExInterp(j), buffer) != 0)) {
transform.append(j);
j++;
}
}
}
}
//////////////////////////////
//
// getAveragePitch -- get the base-12 pitch average.
//
double getAveragePitch(HumdrumFile& hfile, int primaryTrack) {
int i, j, k;
char buffer[1024] = {0};
double sum = 0.0;
int count = 0;
int tokencount = 0;
int pitch = 0;
for (i=0; i<hfile.getNumLines(); i++) {
if (hfile[i].getType() == E_humrec_data) {
for (j=0; j<hfile[i].getFieldCount(); j++) {
if (hfile[i].getPrimaryTrack(j) != primaryTrack) {
continue;
}
tokencount = hfile[i].getTokenCount(j);
for (k=0; k<tokencount; k++) {
hfile[i].getToken(buffer, j, k);
if (strcmp(buffer, ".") == 0) {
continue;
}
if (strcmp(buffer, ".") == 0) {
continue;
}
if (strchr(buffer, 'r') != NULL) {
continue;
}
if (strchr(buffer, '_') != NULL) {
// don't bother with tied notes
continue;
}
if (strchr(buffer, ']') != NULL) {
// don't bother with tied notes
continue;
}
pitch = Convert::kernToMidiNoteNumber(buffer);
if (pitch > 0) {
sum += pitch;
count++;
}
}
}
}
}
return sum/count;
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) { }
// md5sum: 8809beb49cafe8c95630fb2b8b5432ad mvspine.cpp [20050403]