//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Mon Nov 12 22:57:24 PST 2012
// Last Modified: Mon Nov 12 22:57:30 PST 2012
// Filename: ...sig/examples/all/menchop.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/menchop.cpp
// Syntax: C++; museinfo
//
// Description: Extract music with a specific mensurations from input.
//
// Limitations: Presumes no spine splits or subtracks.
//
#include "humdrum.h"
#include "PerlRegularExpression.h"
#include <fstream>
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void usage(const char* command);
void processFile(const char* filename);
void processTrack(HumdrumFile& infile, int track,
const char* basename);
char* getFileName(char* buffer, HumdrumFile& infile, int line,
const char* basename, int track);
char* buildFileName(char* buffer, const char* basename, int track,
int line, const char* met);
// global variables
Options options; // database for command-line arguments
int debugQ = 0; // used with the --debug option
int jrpQ = 0; // used with --jrp option
///////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
HumdrumFile infile;
// process the command-line options
checkOptions(options, argc, argv);
const char* filename = "";
int i;
for (i=1; i<=options.getArgCount(); i++) {
filename = options.getArg(i);
processFile(filename);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// processFile --
//
void processFile(const char* filename) {
Array<char> basename;
basename.setSize(strlen(filename)+1);
strcpy(basename.getBase(), filename);
PerlRegularExpression pre;
pre.sar(basename, ".*/", "");
pre.sar(basename, "\\....$", "");
Array<int> kerntracks;
HumdrumFile infile(filename);
infile.getTracksByExInterp(kerntracks, "**kern");
int i;
for (i=0; i<kerntracks.getSize(); i++) {
processTrack(infile, kerntracks[i], basename.getBase());
}
}
//////////////////////////////
//
// processTrack --
//
void processTrack(HumdrumFile& infile, int track, const char* basename) {
int i, j;
int ttrack;
int exinterpline = -1;
char buffer[1024] = {0};
int dataQ = 1;
int endQ = 0;
int notecount = 0;
fstream output;
Array<char> shortname;
shortname.setSize(strlen(basename)+1);
strcpy(shortname.getBase(), basename);
PerlRegularExpression pre;
if (jrpQ) {
pre.sar(shortname, "-.*", "");
}
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isGlobalComment()) {
continue;
}
if (infile[i].isBibliographic()) {
continue;
}
if (infile[i].isEmpty()) {
continue;
}
if (infile[i].isInterpretation() || infile[i].isLocalComment() ||
infile[i].isMeasure()) {
if (dataQ) {
getFileName(buffer, infile, i, shortname.getBase(), track);
if (strcmp(buffer, "") != 0) {
if ((endQ == 0) && (exinterpline >= 0)) {
output << "*-" << endl;
}
if (output.is_open()) {
output.close();
}
cout << "!!FILENAME: " << buffer << endl;
output.open(buffer, ios::out);
if (!output.is_open()) {
cerr << "ERROR: cannot write to " << buffer << endl;
exit(1);
}
output << "!!original-filename:\t"<< basename << ".krn" << endl;
if (exinterpline >= 0) {
output << "**kern" << endl;
if (notecount > 1) {
// how to deal with tied notes starting a segement
// will need to be considered. In this case the tied
// note will (probably) be ignored.
output << "!noff:" << track << ";" << notecount+1 << endl;
}
}
}
dataQ = 0;
}
}
if (infile[i].isData()) {
dataQ = 1;
}
if (strcmp(infile[i][0], "*-") == 0) {
endQ = 1;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
ttrack = infile[i].getPrimaryTrack(j);
if (ttrack != track) {
continue;
}
if (strcmp(infile[i][j], ".") == 0) {
continue;
}
if (strcmp(infile[i][j], "*") == 0) {
continue;
}
if (strcmp(infile[i][j], "!") == 0) {
continue;
}
if (strcmp(infile[i][j], "*^") == 0) {
// no spine changes allowed in output data
continue;
}
if (strcmp(infile[i][j], "*v") == 0) {
// no spine changes allowed in output data
continue;
}
if (strcmp(infile[i][j], "=-") == 0) {
continue;
}
if (strncmp(infile[i][j], "**", 2) == 0) {
exinterpline = i;
output << infile[i][j] << "\n";
output << "!noff:" << track << ";" << 1 << endl;
continue;
}
if (infile[i].isData()) {
if (pre.search(infile[i][j], "[a-z]", "i")) {
if (!((strchr(infile[i][j], ']') != NULL) ||
(strchr(infile[i][j], ']') != NULL) ||
(strchr(infile[i][j], 'r') != NULL))) {
// should consider what to do with rest counting.
notecount++;
}
}
}
output << infile[i][j] << "\n";
}
}
// cout << "\n\n";
if (output.is_open()) {
output.close();
}
}
///////////////////////////////
//
// getFileName --
//
char* getFileName(char* buffer, HumdrumFile& infile, int line,
const char* basename, int track) {
int i, j;
int ttrack;
PerlRegularExpression pre;
for (i=line; i<infile.getNumLines(); i++) {
if (infile[i].isData()) {
break;
}
if (!infile[i].isInterpretation()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
ttrack = infile[i].getPrimaryTrack(j);
if (ttrack != track) {
continue;
}
if (strncmp(infile[i][j], "*met(", 5) != 0) {
continue;
}
if (pre.search(infile[i][j], "^\\*met\\((.*?)\\)")) {
if (strcmp(pre.getSubmatch(1), "") == 0) {
buffer[0] = '\0';
return buffer;
}
return buildFileName(buffer, basename, track, i+1,
pre.getSubmatch());
}
}
}
buffer[0] = '\0';
return buffer;
}
//////////////////////////////
//
// buildFileName --
//
char* buildFileName(char* buffer, const char* basename, int track, int line,
const char* met) {
char voicenum[32] = {0};
strcpy(buffer, basename);
strcat(buffer, "-T");
sprintf(voicenum, "%d", track);
strcat(buffer, voicenum);
strcat(buffer, "L");
sprintf(voicenum, "%d", line);
strcat(buffer, voicenum);
strcat(buffer, "-");
if (strcmp(met, "C|") == 0) {
strcat(buffer, "MenCutC");
} else if (strcmp(met, "O") == 0) {
strcat(buffer, "MenCircle");
} else if (strcmp(met, "C3") == 0) {
strcat(buffer, "MenC3");
} else if (strcmp(met, "O/3") == 0) {
strcat(buffer, "MenOOver3");
} else if (strcmp(met, "C") == 0) {
strcat(buffer, "MenC");
} else if (strcmp(met, "O2") == 0) {
strcat(buffer, "MenCircle2");
} else if (strcmp(met, "O|") == 0) {
strcat(buffer, "MenCutCircle");
} else if (strcmp(met, "C|3") == 0) {
strcat(buffer, "MenCutC3");
} else if (strcmp(met, "O.") == 0) {
strcat(buffer, "MenCircleDot");
} else if (strcmp(met, "C2") == 0) {
strcat(buffer, "MenC2");
} else if (strcmp(met, "C|2") == 0) {
strcat(buffer, "MenCutC2");
} else if (strcmp(met, "2") == 0) {
strcat(buffer, "Men2");
} else if (strcmp(met, "3") == 0) {
strcat(buffer, "Men3");
} else if (strcmp(met, "Cr") == 0) {
strcat(buffer, "MenCReverse");
} else if (strcmp(met, "C.") == 0) {
strcat(buffer, "MenCDot");
} else if (strcmp(met, "3/2") == 0) {
strcat(buffer, "Men3Over2");
} else if (strcmp(met, "O|3") == 0) {
strcat(buffer, "MenCutCircle3");
} else if (strcmp(met, "O|3/2") == 0) {
strcat(buffer, "MenCutCircle3Over2");
} else if (strcmp(met, "O3") == 0) {
strcat(buffer, "MenCircle3");
} else if (strcmp(met, "C|/2") == 0) {
strcat(buffer, "MenCutCOver2");
} else if (strcmp(met, "C|/3") == 0) {
strcat(buffer, "MenCutCOver3");
} else if (strcmp(met, "O/3") == 0) {
strcat(buffer, "MenCircleOver3");
} else if (strcmp(met, "C.|") == 0) { // preferred
strcat(buffer, "MenCutCDot");
} else if (strcmp(met, "C|.") == 0) { // in case of alternates
strcat(buffer, "MenCutCDot");
} else {
strcat(buffer, "MenUnknown");
}
strcat(buffer, ".krn");
return buffer;
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("jrp=b", "JRP catalog extraction from filename");
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, Nov 2012" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 12 Nov 2012" << 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");
jrpQ = opts.getBoolean("jrp");
}
//////////////////////////////
//
// 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: d8db7c428a8274f9ffba82ae03efd376 menchop.cpp [20090419]