//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Mon Jul 18 11:23:42 PDT 2005
// Last Modified: Mon Jul 18 11:23:46 PDT 2005
// Last Modified: Sun Mar 2 18:58:48 PST 2008 Added -l and -i options
// Last Modified: Mon Mar 3 13:46:34 PST 2008 Added -r option
// Last Modified: Tue Apr 9 08:18:06 PDT 2013 Enabled multiple segment input
// Filename: ...sig/examples/all/thrux.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/thrux.cpp
// Syntax: C++; museinfo
//
// Description: C++ implementation of the Humdrum Toolkit thru command.
//
#include "humdrum.h"
#include <stdlib.h>
#include <string.h>
#ifndef OLDCPP
#include <iostream>
#else
#include <iostream.h>
#endif
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void processData(HumdrumFile& infile);
void usage(const char* command);
void getLabelSequence(Array<Array<char> >& labelsequence,
const char* string);
int getLabelIndex(Array<Array<char> >& labels, Array<char>& key);
void printLabelList(HumdrumFile& infile);
void printLabelInfo(HumdrumFile& infile);
int getBarline(HumdrumFile& infile, int line);
int adjustFirstBarline(HumdrumFile& infile);
// global variables
Options options; // database for command-line arguments
const char* variation = ""; // used with -v option
int listQ = 0; // used with -l option
int infoQ = 0; // used with -i option
int keepQ = 0; // used with -k option
const char* realization = ""; // used with -r option
///////////////////////////////////////////////////////////////////////////
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++) {
if (listQ) {
printLabelList(infiles[i]);
exit(0);
}
if (infoQ) {
printLabelInfo(infiles[i]);
exit(0);
}
// analyze the input file according to command-line options
infiles[i].printNonemptySegmentLabel(cout);
processData(infiles[i]);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// printLabelList -- print a list of the thru labels.
//
void printLabelList(HumdrumFile& infile) {
int i;
int j;
int length;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() != E_humrec_interpretation) {
continue;
}
if (strncmp(infile[i][0], "*>", 2) != 0) {
continue; // ignore non-labels
}
//if (strchr(infile[i][0], '[') != NULL) {
// continue; // ignore realizations
//}
length = strlen(infile[i][0]);
for (j=2; j<length; j++) {
if (infile[i][0][j] == '\0') {
break;
}
cout << infile[i][0][j];
}
cout << '\n';
}
}
//////////////////////////////
//
// printLabelInfo -- print a list of the thru labels.
//
void printLabelInfo(HumdrumFile& infile) {
int i;
int j;
int length;
infile.analyzeRhythm("4");
Array<int> labellines;
labellines.setSize(1000);
labellines.setGrowth(1000);
labellines.setSize(0);
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() != E_humrec_interpretation) {
continue;
}
if (strncmp(infile[i][0], "*>", 2) != 0) {
continue; // ignore non-labels
}
if (strchr(infile[i][0], '[') != NULL) {
cout << "!!>";
length = strlen(infile[i][0]);
for (j=2; j<length; j++) {
if (infile[i][0][j] == '\0') {
break;
}
cout << infile[i][0][j];
}
cout << '\n';
continue; // ignore realizations
}
labellines.append(i);
}
Array<int> barlines;
barlines.setSize(1000);
barlines.allowGrowth(0);
barlines.setAll(-1);
for (i=0; i<labellines.getSize(); i++) {
barlines[i] = getBarline(infile, labellines[i]);
}
if (barlines.getSize() > 0) {
barlines[0] = adjustFirstBarline(infile);
}
int startline;
int endline;
double startbeat;
double endbeat;
double duration;
cout << "**label\t**sline\t**eline\t**sbeat\t**ebeat\t**dur\t**bar\n";
for (i=0; i<labellines.getSize(); i++) {
startline = labellines[i];
if (i<labellines.getSize()-1) {
endline = labellines[i+1]-1;
} else {
endline = infile.getNumLines() - 1;
}
startbeat = infile[startline].getAbsBeat();
endbeat = infile[endline].getAbsBeat();
duration = endbeat - startbeat;
duration = int(duration * 10000.0 + 0.5) / 10000.0;
length = strlen(infile[startline][0]);
for (j=2; j<length; j++) {
if (infile[startline][0][j] == '\0') {
break;
}
cout << infile[startline][0][j];
}
cout << '\t';
cout << startline + 1;
cout << '\t';
cout << endline + 1;
cout << '\t';
cout << startbeat;
cout << '\t';
cout << endbeat;
cout << '\t';
cout << duration;
cout << '\t';
cout << barlines[i];
cout << '\n';
}
cout << "*-\t*-\t*-\t*-\t*-\t*-\t*-\n";
}
//////////////////////////////
//
// adjustFirstBarline --
//
int adjustFirstBarline(HumdrumFile& infile) {
int i;
int number = 0;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() != E_humrec_data_measure) {
continue;
}
if (infile[i].getAbsBeat() > 0) {
break;
}
sscanf(infile[i][0], "=%d", &number);
break;
}
return number;
}
//////////////////////////////
//
// getBarline --
//
int getBarline(HumdrumFile& infile, int line) {
if (infile[line].getAbsBeat() == 0) {
return 0;
}
int i;
int missingcount = 0;
int number = -1;
for (i=line; i>0; i--) {
if (infile[i].getType() != E_humrec_data_measure) {
continue;
}
if (sscanf(infile[i][0], "=%d", &number) == 1) {
break;
} else {
missingcount++;
}
if (missingcount > 1) {
break;
}
}
return number;
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("v|variation=s:", "Choose the expansion variation");
opts.define("l|list=b:", "Print list of labels in file");
opts.define("k|keep=b:", "Keep variation interpretations");
opts.define("i|info=b:", "Print info list of labels in file");
opts.define("r|realization=s:", "alternate relaization label sequence");
opts.define("d|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 1998" << 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);
}
variation = opts.getString("variation");
realization = opts.getString("realization");
listQ = opts.getBoolean("list");
infoQ = opts.getBoolean("info");
keepQ = opts.getBoolean("keep");
}
//////////////////////////////
//
// example -- example usage of the sonority program
//
void example(void) {
cout <<
" \n"
<< endl;
}
//////////////////////////////
//
// processData --
//
void processData(HumdrumFile& infile) {
Array<Array<char> > labelsequence;
labelsequence.setSize(1000);
labelsequence.setGrowth(1000);
labelsequence.setSize(0);
Array<Array<char> > labels;
labels.setSize(1000);
labels.setGrowth(1000);
labels.setSize(0);
Array<int> startline;
startline.setSize(1000);
startline.setGrowth(1000);
startline.setSize(0);
Array<int> stopline;
stopline.setSize(1000);
stopline.setGrowth(1000);
stopline.setSize(0);
int header = -1;
int footer = -1;
char labelsearch[1024] = {0};
strcpy(labelsearch, "*>");
strcat(labelsearch, variation);
strcat(labelsearch, "[");
int length = strlen(labelsearch);
// check for label to expand
int i;
int foundlabel = 0;
if (realization[0] == '\0') {
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() != E_humrec_interpretation) {
continue;
}
if (strncmp(labelsearch, infile[i][0], length) != 0) {
continue;
}
getLabelSequence(labelsequence, &(infile[i][0][length]));
foundlabel = 1;
break;
}
} else {
foundlabel = 1;
getLabelSequence(labelsequence, realization);
}
int j;
if (foundlabel == 0) {
// did not find the label to expand, so echo the data back
for (i=0; i<infile.getNumLines(); i++) {
if (strcmp(infile[i][0], "*thru") == 0) {
continue;
}
cout << infile[i] << "\n";
if (strncmp(infile[i][0], "**", 2) == 0) {
for (j=0; j<infile[i].getFieldCount(); j++) {
cout << "*thru";
if (j < infile[i].getFieldCount() - 1) {
cout << "\t";
}
}
cout << "\n";
}
}
return;
}
// for (i=0; i<labelsequence.getSize(); i++) {
// cout << i+1 << "\t=\t" << labelsequence[i].getBase() << endl;
// }
// search for the labeled sections in the music
const char* label;
int llen;
int location;
int index;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].getType() != E_humrec_interpretation) {
continue;
}
if (strcmp("*-", infile[i][0]) == 0) {
location = i-1;
footer = i;
stopline.append(location);
}
if (strncmp("*>", infile[i][0], 2) != 0) {
continue;
}
if (strchr(infile[i][0], '[') != NULL) {
continue;
}
if (strchr(infile[i][0], ']') != NULL) {
continue;
}
if (labels.getSize() == 0) {
header = i-1;
}
label = &(infile[i][0][2]);
llen = strlen(label);
index = labels.getSize();
location = i-1;
if (startline.getSize() > 0) {
stopline.append(location);
}
labels.setSize(index+1);
labels[index].setSize(llen+1);
strcpy(labels[index].getBase(), label);
startline.append(i);
}
// cout << "FOOTER = " << footer << endl;
// cout << "HEADER = " << header << endl;
// for (i=0; i<labels.getSize(); i++) {
// cout << "\t" << i << "\t=\t" << labels[i].getBase()
// << "\t" << startline[i] << "\t" << stopline[i]
// << endl;
// }
// now ready to copy the labeled segements into a final file.
// print header:
for (i=0; i<=header; i++) {
if (strcmp(infile[i][0], "*thru") == 0) {
continue;
}
if (!keepQ) {
if (infile[i].getType() == E_humrec_data_interpretation) {
if (strncmp(infile[i][0], "*>", 2) == 0) {
if (strchr(infile[i][0], '[') != NULL) {
continue;
}
}
}
}
cout << infile[i] << "\n";
if (strncmp(infile[i][0], "**", 2) == 0) {
for (j=0; j<infile[i].getFieldCount(); j++) {
cout << "*thru";
if (j < infile[i].getFieldCount() - 1) {
cout << "\t";
}
}
cout << "\n";
}
}
int start;
int stop;
for (i=0; i<labelsequence.getSize(); i++) {
index = getLabelIndex(labels, labelsequence[i]);
if (index < 0) {
cout << "!! THRU ERROR: label " << labelsequence[i].getBase()
<< " does not exist, skipping.\n";
}
start = startline[index];
stop = stopline[index];
for (j=start; j<=stop; j++) {
if (!keepQ) {
if (infile[j].getType() == E_humrec_data_interpretation) {
if (strncmp(infile[j][0], "*>", 2) == 0) {
if (strchr(infile[j][0], '[') != NULL) {
continue;
}
}
}
}
cout << infile[j] << "\n";
}
}
// print footer:
for (i=footer; i<infile.getNumLines(); i++) {
if (!keepQ) {
if (infile[i].getType() == E_humrec_data_interpretation) {
if (strncmp(infile[i][0], "*>", 2) == 0) {
if (strchr(infile[i][0], '[') != NULL) {
continue;
}
}
}
}
cout << infile[i] << "\n";
}
}
//////////////////////////////
//
// getLabelIndex --
//
int getLabelIndex(Array >& labels, Array& key) {
int i;
for (i=0; i<labels.getSize(); i++) {
if (strcmp(key.getBase(), labels[i].getBase()) == 0) {
return i;
}
}
return -1;
}
//////////////////////////////
//
// getLabelSequence --
//
void getLabelSequence(Array >& labelsequence, const char* string) {
int slength = strlen(string);
char* sdata = new char[slength+1];
strcpy(sdata, string);
const char* ignorecharacters = ", [] ";
int length = 0;
int index;
char* strptr = strtok(sdata, ignorecharacters);
while (strptr != NULL) {
length = strlen(strptr);
labelsequence.setSize(labelsequence.getSize() + 1);
index = labelsequence.getSize() - 1;
labelsequence[index].setSize(length+1);
strcpy(labelsequence[index].getBase(), strptr);
strptr = strtok(NULL, ignorecharacters);
}
delete [] sdata;
}
//////////////////////////////
//
// usage -- gives the usage statement for the sonority program
//
void usage(const char* command) {
cout <<
" \n"
<< endl;
}
// md5sum: 6f87e1d96ad34013dfe1d0f5c5abc58e thrux.cpp [20130420]