//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Tue Feb 15 17:09:16 PST 2011
// Last Modified: Tue Feb 15 17:09:23 PST 2011
// Filename: ...sig/examples/all/fixdyna.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/lazydynam.cpp
// Syntax: C++; museinfo
//
// Description: Fix crescendo and decrescendo symbols (wedges, hairpins).
//
#include "humdrum.h"
#include "PerlRegularExpression.h"
#ifndef OLDCPP
using namespace std;
#endif
class Coord {
public:
int i, j;
Coord(void) { }
~Coord() { }
void clear(void) { i = j = -1; }
};
///////////////////////////////////////////////////////////////////////////
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void usage(const char* command);
void processFile(HumdrumFile& infile);
void processDynamicSpine(HumdrumFile& infile, int track);
void storeDynamSpine(Array<Array<Coord> >& data, HumdrumFile& infile,
int track);
// global variables
Options options; // database for command-line arguments
int debugQ = 0; // used with --debug option
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
HumdrumFile infile;
// process the command-line options
checkOptions(options, argc, argv);
const char* filename;
infile.clear();
// if no command-line arguments read data file from standard input
int numinputs = options.getArgCount();
if (numinputs < 1) {
infile.read(cin);
} else {
filename = options.getArg(1);
infile.read(options.getArg(1));
}
processFile(infile);
cout << infile;
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// processFile --
//
void processFile(HumdrumFile& infile) {
int i, j;
for (i=0; i<infile.getNumLines(); i++) {
if (!infile[i].isInterpretation()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
if (!infile[i].isExInterp(j, "**dynam")) {
continue;
}
processDynamicSpine(infile, infile[i].getPrimaryTrack(j));
}
break; // just procesing the first exclusive interpretation line.
}
}
//////////////////////////////
//
// processDynamicSpine -- Only looking at first layer of spine.
//
void processDynamicSpine(HumdrumFile& infile, int track) {
Array<Array<Coord> > data;
storeDynamSpine(data, infile, track);
int i;
int ii, jj;
int crescX = 0; // interpreted crescendo (cresc. word)
int decrescX = 0; // interpreted decrescendo (decresc. word)
int crescy = 0; // hidden crescendo
int decrescy = 0; // hidden decrescendo
int crescState = 0; // active crescendo
int decrescState = 0; // active decrescendo
char buffer[1024] = {0};
Array<char> buf;
PerlRegularExpression pre;
int xx, yy;
if (debugQ) {
cerr << "DATA SIZE = " << data.getSize() << endl;
}
for (i=0; i<data.getSize(); i++) {
ii = data[i][0].i;
jj = data[i][0].j;
if (debugQ) {
cerr << "PROCESSING I = " << i << " " << infile[ii][jj] << endl;
}
if (crescState) {
if (debugQ) {
cerr << "\tACTIVE CRESC" << endl;
}
// if currently a crescendo, then either continue or end
if (strcmp(infile[ii][jj], ".") == 0) {
// convert "." to "(" to continue the crescendo
if (debugQ) {
cerr << "\tChanging . to (" << endl;
}
strcpy(buffer, "(");
if (crescX) {
strcat(buffer, "X");
}
if (crescy) {
strcat(buffer, "yy");
}
infile[ii].changeField(jj, buffer);
} else {
// end the crescendo
xx = data[i-1][0].i;
yy = data[i-1][0].j;
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
if ((xx < 0) || (yy < 0)) {
continue;
}
// this is a dynamic object of some sort so terminate
// the crescendo on the previous item
if (strchr(infile[xx][yy], '(') != NULL) {
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
// replace the '(' found on the previous data line
buf.setSize(strlen(infile[xx][yy])+1);
strcpy(buf.getBase(), infile[xx][yy]);
pre.sar(buf, "\\(", "[", ""); // should only apply to last
if (crescX) {
pre.sar(buf, "\\[", "[", "");
crescX = 0;
}
if (crescy) {
pre.sar(buf, "\\[", "[", "");
crescy = 0;
}
infile[xx].changeField(yy, buf.getBase());
crescState = 0;
if (debugQ) {
cerr << "DEACTIVATING CRESC 1" << endl;
}
} else {
// there is something other than ( on the last line:
// append " ["
strcpy(buffer, infile[xx][yy]);
strcat(buffer, " [");
//if (crescy) {
// strcat(buffer, "yy");
// crescy = 0;
//} if (crescX) {
// strcat(buffer, "X");
// crescX = 0;
//}
infile[xx].changeField(yy, buffer);
crescState = 0;
if (debugQ) {
cerr << "DEACTIVATING CRESC 2" << endl;
}
}
}
} else if (decrescState) {
// if currently a decrescendo, then either continue or end
if (strcmp(infile[ii][jj], ".") == 0) {
// convert "." to "(" to continue the decrescendo
strcpy(buffer, ")");
if (decrescX) {
strcat(buffer, "X");
}
if (decrescy) {
strcat(buffer, "yy");
}
infile[ii].changeField(jj, buffer);
} else {
// end the decrescendo
xx = data[i-1][0].i;
yy = data[i-1][0].j;
if ((xx < 0) || (yy < 0)) {
continue;
}
// this is a dynamic object of some sort so terminate
// the decrescendo on the previous item
if (strchr(infile[xx][yy], ')') != NULL) {
// replace the '(' found on the previous data line
buf.setSize(strlen(infile[xx][yy])+1);
strcpy(buf.getBase(), infile[xx][yy]);
pre.sar(buf, "\\)", "]", ""); // should only apply to last
//if (decrescX) {
// pre.sar(buf, "\\]", "]X", "");
// decrescX = 0;
//}
//if (decrescy) {
// pre.sar(buf, "\\]", "]y", "");
// decrescy = 0;
//}
infile[xx].changeField(yy, buf.getBase());
decrescState = 0;
} else {
// there is something other than ( on the last line:
// append " ["
strcpy(buffer, infile[xx][yy]);
strcat(buffer, " ]");
if (decrescy) {
strcat(buffer, "yy");
decrescy = 0;
} if (decrescX) {
strcat(buffer, "X");
decrescX = 0;
}
infile[xx].changeField(yy, buffer);
decrescState = 0;
}
}
}
// search for < or > marker to initiate de/cresc.
if (strchr(infile[ii][jj], '<') != NULL) { crescState = 1; }
if (strchr(infile[ii][jj], '>') != NULL) { decrescState = 1; }
if (strstr(infile[ii][jj], "<X") != NULL) { crescX = 1; }
if (strstr(infile[ii][jj], ">X") != NULL) { decrescX = 1; }
if (strstr(infile[ii][jj], "<yy") != NULL) { crescy = 1; }
if (strstr(infile[ii][jj], ">yy") != NULL) { decrescy = 1; }
}
// handle case where cresc/decresc ends data with nothing after it.
if (crescState) {
// end the crescendo
xx = data.last()[0].i;
yy = data.last()[0].j;
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
if ((xx < 0) || (yy < 0)) {
return;
}
// this is a dynamic object of some sort so terminate
// the crescendo on the previous item
if (strchr(infile[xx][yy], '(') != NULL) {
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
// replace the '(' found on the previous data line
buf.setSize(strlen(infile[xx][yy])+1);
strcpy(buf.getBase(), infile[xx][yy]);
pre.sar(buf, "\\(", "[", ""); // should only apply to last
if (crescX) {
pre.sar(buf, "\\[", "[", "");
crescX = 0;
}
if (crescy) {
pre.sar(buf, "\\[", "[", "");
crescy = 0;
}
infile[xx].changeField(yy, buf.getBase());
crescState = 0;
if (debugQ) {
cerr << "DEACTIVATING CRESC 1" << endl;
}
}
} else if (decrescState) {
// end the decrescendo
xx = data.last()[0].i;
yy = data.last()[0].j;
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
if ((xx < 0) || (yy < 0)) {
return;
}
// this is a dynamic object of some sort so terminate
// the decrescendo on the previous item
if (strchr(infile[xx][yy], ')') != NULL) {
if (debugQ) {
cerr << "GOT HERE " << infile[xx][yy] << endl;
}
// replace the '(' found on the previous data line
buf.setSize(strlen(infile[xx][yy])+1);
strcpy(buf.getBase(), infile[xx][yy]);
pre.sar(buf, "\\)", "]", ""); // should only apply to last
if (decrescX) {
pre.sar(buf, "\\]", "]", "");
decrescX = 0;
}
if (decrescy) {
pre.sar(buf, "\\]", "]", "");
decrescy = 0;
}
infile[xx].changeField(yy, buf.getBase());
decrescState = 0;
if (debugQ) {
cerr << "DEACTIVATING DECRESC 1" << endl;
}
}
}
}
//////////////////////////////
//
// storeDynamSpine -- make a list of the data spines for the given track
//
void storeDynamSpine(Array<Array<Coord> >& data, HumdrumFile& infile,
int track) {
data.setSize(infile.getNumLines());
data.setSize(0);
Coord coord;
int i, j;
for (i=0; i<infile.getNumLines(); i++){
if (!infile[i].isData()) {
continue;
}
data.increase(1);
data.last().setSize(0);
for (j=0; j<infile[i].getFieldCount(); j++) {
if (track != infile[i].getPrimaryTrack(j)) {
continue;
}
coord.i = i;
coord.j = j;
data.last().append(coord);
}
}
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
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, Oct 2004" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 25 Oct 2004" << 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");
}
//////////////////////////////
//
// example -- example usage of the program
//
void example(void) {
cout <<
" \n"
<< endl;
}
//////////////////////////////
//
// usage -- gives the usage statement for the program
//
void usage(const char* command) {
cout <<
" \n"
<< endl;
}
// md5sum: 75c005000c7e41eba457053aac3847a3 autodynam.cpp [20110220]