//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Dec 26 17:03:54 PST 2010
// Last Modified: Fri Jan 14 17:06:32 PST 2011 (added --mark and --mdsep)
// Last Midified: Wed Feb 2 12:13:11 PST 2011 (added *met extraction)
// Filename: ...sig/examples/all/myank.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/myank.cpp
// Syntax: C++; museinfo
//
// Description: Extract measures from input data.
//
#include <math.h>
#ifndef OLDCPP
#include <iostream>
#include <sstream>
#define SSTREAM stringstream
#define CSTRING str().c_str()
using namespace std;
#else
#include <iostream.h>
#ifdef VISUAL
#include <strstrea.h>
#else
#include <strstream.h>
#endif
#define SSTREAM strstream
#define CSTRING str()
#endif
#include "string.h"
#include "humdrum.h"
#include "PerlRegularExpression.h"
#include "MuseData.h"
class Coord {
public:
Coord(void) { clear(); }
void clear(void) { x = y = -1; }
int x;
int y;
};
class MeasureInfo {
public:
MeasureInfo(void) { clear(); }
void clear(void) { num = seg = start = stop = -1;
sclef.setSize(0); skeysig.setSize(0); skey.setSize(0);
stimesig.setSize(0); smet.setSize(0); stempo.setSize(0);
eclef.setSize(0); ekeysig.setSize(0); ekey.setSize(0);
etimesig.setSize(0); emet.setSize(0); etempo.setSize(0);
}
int num; // measure number
int seg; // measure segment
int start; // starting line of segment
int stop; // ending line of segment
// musical settings at start of measure
Array<Coord> sclef; // starting clef of segment
Array<Coord> skeysig; // starting keysig of segment
Array<Coord> skey; // starting key of segment
Array<Coord> stimesig; // starting timesig of segment
Array<Coord> smet; // starting met of segment
Array<Coord> stempo; // starting tempo of segment
// musical settings at start of measure
Array<Coord> eclef; // ending clef of segment
Array<Coord> ekeysig; // ending keysig of segment
Array<Coord> ekey; // ending key of segment
Array<Coord> etimesig; // ending timesig of segment
Array<Coord> emet; // ending met of segment
Array<Coord> etempo; // ending tempo of segment
};
//////////////////////////////////////////////////////////////////////////
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void myank(HumdrumFile& infile,
Array<MeasureInfo>& outmeasure);
void removeDollarsFromString(Array<char>& buffer, int maxx);
void processFieldEntry(Array<MeasureInfo>& field, const char* string,
HumdrumFile& infile, int maxmeasure,
Array<MeasureInfo>& inmeasures,
Array<int>& inmap);
void expandMeasureOutList(Array<MeasureInfo>& measureout,
Array<MeasureInfo>& measurein,
HumdrumFile& infile, const char* optionstring);
void getMeasureStartStop(Array<MeasureInfo>& measurelist,
HumdrumFile& infile);
void printEnding(HumdrumFile& infile, int lastline, int adjlin);
void printStarting(HumdrumFile& infile);
void reconcileSpineBoundary(HumdrumFile& infile, int index1, int index2);
void reconcileStartingPosition(HumdrumFile& infile, int index2);
void printJoinLine(Array<int>& splits, int index, int count);
void printInvisibleMeasure(HumdrumFile& infile, int line);
void fillGlobalDefaults(HumdrumFile& infile,
Array<MeasureInfo>& measurein,
Array<int>& inmap);
void adjustGlobalInterpretations(HumdrumFile& infile, int ii,
Array<MeasureInfo>& outmeasures, int index);
void adjustGlobalInterpretationsStart(HumdrumFile& infile, int ii,
Array<MeasureInfo>& outmeasures, int index);
void getMarkString(ostream& out, HumdrumFile& infile);
void printDoubleBarline(HumdrumFile& infile, int line);
void insertZerothMeasure(Array<MeasureInfo>& measurelist,
HumdrumFile& infile);
void getMetStates(Array<Array<Coord> >& metstates,
HumdrumFile& infile);
Coord getLocalMetInfo(HumdrumFile& infile, int row, int track);
// User interface variables:
Options options;
int debugQ = 0; // used with --debug option
int verboseQ = 0; // used with -v option
int invisibleQ = 1; // used with --visible option
int maxQ = 0; // used with --max option
int minQ = 0; // used with --min option
int instrumentQ= 0; // used with -I option
int nolastbarQ = 0; // used with -B option
int markQ = 0; // used with --mark option
int doubleQ = 0; // used with --mdsep option
Array<MeasureInfo> MeasureOutList; // used with -m option
Array<MeasureInfo> MeasureInList; // used with -m option
Array<Array<Coord> > metstates;
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
HumdrumFile infile;
// initial processing of the command-line options
checkOptions(options, argc, argv);
if (options.getArgCount() < 1) {
infile.read(cin);
} else {
infile.read(options.getArg(1));
}
getMetStates(metstates, infile);
getMeasureStartStop(MeasureInList, infile);
Array<char> measurestring;
measurestring.setSize(strlen(options.getString("measure"))+1);
strcpy(measurestring.getBase(), options.getString("measure"));
SSTREAM mstring;
if (markQ) {
getMarkString(mstring, infile);
mstring << ends;
measurestring.setSize(strlen(mstring.CSTRING)+1);
strcpy(measurestring.getBase(), mstring.CSTRING);
if (debugQ) {
cout << "MARK STRING: " << mstring.CSTRING << endl;
}
}
if (debugQ) {
cout << "MARK MEASURES: " << measurestring << endl;
}
// expand to multiple measures later.
expandMeasureOutList(MeasureOutList, MeasureInList, infile,
measurestring.getBase());
if (debugQ) {
cout << "INPUT MEASURE MAP: " << endl;
for (int i=0; i<MeasureInList.getSize(); i++) {
cout << "\tm:" << MeasureInList[i].num
<< "\tstart:" << MeasureInList[i].start;
if (MeasureInList[i].start < 10) {
cout << " ";
}
cout << "\tstop:" << MeasureInList[i].stop
<< "\tclef:";
for (int j=1; j<MeasureInList[i].sclef.getSize(); j++) {
cout << MeasureInList[i].sclef[j].x << ","
<< MeasureInList[i].sclef[j].x << ":";
cout << MeasureInList[i].eclef[j].x << ","
<< MeasureInList[i].eclef[j].x << " ";
}
cout << "\tkeysig:";
for (int j=1; j<MeasureInList[i].skeysig.getSize(); j++) {
cout << MeasureInList[i].skeysig[j].x << ","
<< MeasureInList[i].skeysig[j].x << ":";
cout << MeasureInList[i].ekeysig[j].x << ","
<< MeasureInList[i].ekeysig[j].x << " ";
}
cout << "\ttempo:";
for (int j=1; j<MeasureInList[i].stempo.getSize(); j++) {
cout << MeasureInList[i].stempo[j].x << ","
<< MeasureInList[i].stempo[j].x << ":";
cout << MeasureInList[i].etempo[j].x << ","
<< MeasureInList[i].etempo[j].x << " ";
}
cout << endl;
}
}
if (debugQ) {
cout << "OUTPUT MEASURE MAP: " << endl;
for (int i=0; i<MeasureOutList.getSize(); i++) {
cout << "\tm: " << MeasureOutList[i].num
<< "\tstart: " << MeasureOutList[i].start;
if (MeasureOutList[i].start < 10) {
cout << " ";
}
cout << "\tstop: " << MeasureOutList[i].stop
<< "\tclef:";
for (int j=1; j<MeasureOutList[i].sclef.getSize(); j++) {
cout << MeasureOutList[i].sclef[j].x << ","
<< MeasureOutList[i].sclef[j].x << ":";
cout << MeasureOutList[i].eclef[j].x << ","
<< MeasureOutList[i].eclef[j].x << " ";
}
cout << "\tkeysig:";
for (int j=1; j<MeasureOutList[i].skeysig.getSize(); j++) {
cout << MeasureOutList[i].skeysig[j].x << ","
<< MeasureOutList[i].skeysig[j].x << ":";
cout << MeasureOutList[i].ekeysig[j].x << ","
<< MeasureOutList[i].ekeysig[j].x << " ";
}
cout << "\ttempo:";
for (int j=1; j<MeasureOutList[i].stempo.getSize(); j++) {
cout << MeasureOutList[i].stempo[j].x << ","
<< MeasureOutList[i].stempo[j].x << ":";
cout << MeasureOutList[i].etempo[j].x << ","
<< MeasureOutList[i].etempo[j].x << " ";
}
cout << endl;
}
}
myank(infile, MeasureOutList);
return 0;
}
//////////////////////////////////////////////////////////////////////////
////////////////////////
//
// getMetStates -- Store the current *met for every token
// in the score, keeping track of meter without metric symbols.
//
void getMetStates(Array >& metstates, HumdrumFile& infile) {
Array<Coord> current;
current.setSize(infile.getMaxTracks()+1);
metstates.setSize(infile.getNumLines());
PerlRegularExpression pre;
int i, j, track;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isInterpretation()) {
for (j=0; j<infile[i].getFieldCount(); j++) {
track = infile[i].getPrimaryTrack(j);
if (pre.search(infile[i][j], "^\\*met\\([^\\)]+\\)", "")) {
current[track].x = i;
current[track].y = j;
} else if (pre.search(infile[i][j], "^\\*M\\d+\\d+", "")) {
current[track] = getLocalMetInfo(infile, i, track);
}
}
}
// metstates[i].setSize(infile[i].getFieldCount());
// for (j=0; j<infile[i].getFieldCount(); j++) {
// track = infile[i].getPrimaryTrack(j);
// metstates[i][j] = current[track];
// }
metstates[i].setSize(infile.getMaxTracks()+1);
for (j=1; j<=infile.getMaxTracks(); j++) {
metstates[i][j] = current[j];
}
}
if (debugQ) {
for (i=0; i<infile.getNumLines(); i++) {
for (j=1; j<metstates[i].getSize(); j++) {
if (metstates[i][j].x < 0) {
cout << ".";
} else {
cout << infile[metstates[i][j].x][metstates[i][j].y];
}
cout << "\t";
}
cout << infile[i] << endl;
}
}
}
//////////////////////////////
//
// getLocalMetInfo -- search in the non-data region indicated by the
// input row for a *met entry in the input track. Return empty
// value if none found.
//
Coord getLocalMetInfo(HumdrumFile& infile, int row, int track) {
Coord output;
int startline = -1;
int stopline = -1;
int i = row;
int j;
int xtrac;
PerlRegularExpression pre;
while (i>=0) {
if (infile[i].isData()) {
startline = i+1;
break;
}
i--;
}
if (startline < 0) {
startline = 0;
}
i = row;
while (i<infile.getNumLines()){
if (infile[i].isData()) {
stopline = i-1;
break;
}
i++;
}
if (stopline >= infile.getNumLines()) {
stopline = infile.getNumLines()-1;
}
for (i=startline; i<=stopline; i++) {
if (!infile[i].isInterpretation()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
xtrac = infile[i].getPrimaryTrack(j);
if (track != xtrac) {
continue;
}
if (pre.search(infile[i][j], "^\\*met\\([^\\)]+\\)", "")) {
output.x = i;
output.x = j;
}
}
}
return output;
}
//////////////////////////////
//
// getMarkString -- return a list of measures which contain marked
// notes (primarily from search matches).
// This function scans for reference records in this form:
// !!!RDF**kern: @= matched note
// or
// !!!RDF**kern: i= marked note
// If it finds any lines like that, it will extract the character before
// the equals sign, and scan for it in the **kern data in the file.
// any measure which contains such a mark will be stored in the output
// string.
//
void getMarkString(ostream& out, HumdrumFile& infile) {
Array<char> mchar; // list of characters which are marks
mchar.setSize(0);
int i, j, k, m;
char target;
PerlRegularExpression pre;
for (i=0; i<infile.getNumLines(); i++) {
if (!infile[i].isBibliographic()) {
continue;
}
if (pre.search(infile[i][0],
"!!!RDF\\*\\*kern\\s*:\\s*([^=])\\s*=\\s*match", "i")) {
target = pre.getSubmatch(1)[0];
mchar.append(target);
} else if (pre.search(infile[i][0],
"!!!RDF\\*\\*kern\\s*:\\s*([^=])\\s*=\\s*mark", "i")) {
target = pre.getSubmatch(1)[0];
mchar.append(target);
}
}
if (debugQ) {
for (i=0; i<mchar.getSize(); i++) {
cout << "\tMARK CHARCTER: " << mchar[i] << endl;
}
}
if (mchar.getSize() == 0) {
return;
}
// now search for measures which contains any of those character
// in **kern data:
int curmeasure = 0;
int inserted = 0;
int hasmark = 0;
const char* str;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isMeasure()) {
if (pre.search(infile[i][0], "^=.*?(\\d+)", "")) {
curmeasure = atoi(pre.getSubmatch(1));
hasmark = 0;
}
}
if (hasmark) {
continue;
}
if (!infile[i].isData()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
if (infile[i].isExInterp(j, "**kern")) {
k=0;
str = infile[i][j];
while (str[k] != '\0') {
for (m=0; m<mchar.getSize(); m++) {
if (str[k] == mchar[m]) {
if (inserted) {
out << ',';
} else {
inserted++;
}
out << curmeasure;
hasmark = 1;
goto outerforloop;
}
}
k++;
}
}
outerforloop: ;
}
}
}
//////////////////////////////
//
// myank -- yank the specified measures.
//
void myank(HumdrumFile& infile, Array& outmeasures) {
if (outmeasures.getSize() > 0) {
printStarting(infile);
}
int lastline = -1;
int h, i, j;
int counter;
int printed = 0;
int mcount = 0;
int measurestart = 1;
int datastart = 0;
for (h=0; h<outmeasures.getSize(); h++) {
measurestart = 1;
printed = 0;
counter = 0;
if (debugQ) {
cout << "!! =====================================\n";
}
if (h > 0) {
reconcileSpineBoundary(infile, outmeasures[h-1].stop,
outmeasures[h].start);
} else {
reconcileStartingPosition(infile, outmeasures[0].start);
}
for (i=outmeasures[h].start; i<outmeasures[h].stop; i++) {
counter++;
if ((!printed) && ((mcount == 0) || (counter == 2))) {
if ((datastart == 0) && outmeasures[h].num == 0) {
// not ideal setup...
datastart = 1;
} else{
adjustGlobalInterpretations(infile, i, outmeasures, h);
printed = 1;
}
}
if (infile[i].isData() && (mcount == 0)) {
mcount++;
}
if (infile[i].isMeasure()) {
mcount++;
}
if ((mcount == 1) && invisibleQ && infile[i].isMeasure()) {
printInvisibleMeasure(infile, i);
measurestart = 0;
} else if (doubleQ && measurestart) {
printDoubleBarline(infile, i);
measurestart = 0;
} else {
cout << infile[i] << "\n";
}
lastline = i;
}
}
PerlRegularExpression pre;
Array<char> token;
int lasti = outmeasures.last().stop;
if ((!nolastbarQ) && infile[lasti].isMeasure()) {
for (j=0; j<infile[lasti].getFieldCount(); j++) {
token.setSize(strlen(infile[lasti][j])+1);
strcpy(token.getBase(), infile[lasti][j]);
pre.sar(token, "\\d+", "", "");
if (doubleQ) {
if (pre.search(token, "=(.+)")) {
// don't add double barline, there is already
// some style on the barline
} else {
// add a double barline
pre.sar(token, "$", "||", "");
}
}
cout << token;
if (j < infile[lasti].getFieldCount() - 1) {
cout << '\t';
}
}
cout << '\n';
}
if (debugQ) {
cout << "PROCESSING ENDING" << endl;
}
if (lastline >= 0) {
//printEnding(infile, lastline);
printEnding(infile, outmeasures.last().stop, lasti);
}
}
//////////////////////////////
//
// adjustGlobalInterpretations --
//
void adjustGlobalInterpretations(HumdrumFile& infile, int ii,
Array<MeasureInfo>& outmeasures, int index) {
if (index <= 0) {
adjustGlobalInterpretationsStart(infile, ii, outmeasures, index);
return;
}
int i;
int clefQ = 0;
int keysigQ = 0;
int keyQ = 0;
int timesigQ = 0;
int metQ = 0;
int tempoQ = 0;
int x, y;
int xo, yo;
int tracks = infile.getMaxTracks();
// these lines may cause bugs, but they get rid of zeroth measure
// problem.
// ggg
// if ((outmeasures.getSize() > 1) && (outmeasures[index-1].num == 0)) {
// return;
// }
// if ((outmeasures.getSize() > 0) && (outmeasures[index].num == 0)) {
// return;
// }
for (i=1; i<=tracks; i++) {
if (!clefQ) {
x = outmeasures[index].sclef[i].x;
y = outmeasures[index].sclef[i].y;
xo = outmeasures[index-1].eclef[i].x;
yo = outmeasures[index-1].eclef[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
clefQ = 1;
}
}
}
if (!keysigQ) {
x = outmeasures[index].skeysig[i].x;
y = outmeasures[index].skeysig[i].y;
xo = outmeasures[index-1].ekeysig[i].x;
yo = outmeasures[index-1].ekeysig[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
keysigQ = 1;
}
}
}
if (!keyQ) {
x = outmeasures[index].skey[i].x;
y = outmeasures[index].skey[i].y;
xo = outmeasures[index-1].ekey[i].x;
yo = outmeasures[index-1].ekey[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
keyQ = 1;
}
}
}
if (!timesigQ) {
x = outmeasures[index].stimesig[i].x;
y = outmeasures[index].stimesig[i].y;
xo = outmeasures[index-1].etimesig[i].x;
yo = outmeasures[index-1].etimesig[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
timesigQ = 1;
}
}
}
if (!metQ) {
x = outmeasures[index].smet[i].x;
y = outmeasures[index].smet[i].y;
xo = outmeasures[index-1].emet[i].x;
yo = outmeasures[index-1].emet[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
metQ = 1;
}
}
}
if (!tempoQ) {
x = outmeasures[index].stempo[i].x;
y = outmeasures[index].stempo[i].y;
xo = outmeasures[index-1].etempo[i].x;
yo = outmeasures[index-1].etempo[i].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
tempoQ = 1;
}
}
}
}
int track;
if (clefQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].sclef[track].x;
y = outmeasures[index].sclef[track].y;
xo = outmeasures[index-1].eclef[track].x;
yo = outmeasures[index-1].eclef[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (keysigQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].skeysig[track].x;
y = outmeasures[index].skeysig[track].y;
xo = outmeasures[index-1].ekeysig[track].x;
yo = outmeasures[index-1].ekeysig[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (keyQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].skey[track].x;
y = outmeasures[index].skey[track].y;
xo = outmeasures[index-1].ekey[track].x;
yo = outmeasures[index-1].ekey[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (timesigQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].stimesig[track].x;
y = outmeasures[index].stimesig[track].y;
xo = outmeasures[index-1].etimesig[track].x;
yo = outmeasures[index-1].etimesig[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (metQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].smet[track].x;
y = outmeasures[index].smet[track].y;
xo = outmeasures[index-1].emet[track].x;
yo = outmeasures[index-1].emet[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (tempoQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
track = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].stempo[track].x;
y = outmeasures[index].stempo[track].y;
xo = outmeasures[index-1].etempo[track].x;
yo = outmeasures[index-1].etempo[track].y;
if ((x>=0)&&(y>=0)&&(xo>=0)&&(yo>=0)) {
if (strcmp(infile[x][y], infile[xo][yo]) != 0) {
cout << infile[x][y];
} else {
cout << "*";
}
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
}
//////////////////////////////
//
// adjustGlobalInterpretationsStart --
//
void adjustGlobalInterpretationsStart(HumdrumFile& infile, int ii,
Array<MeasureInfo>& outmeasures, int index) {
if (index != 0) {
cerr << "Error in adjustGlobalInterpetationsStart" << endl;
exit(1);
}
int i;
int clefQ = 0;
int keysigQ = 0;
int keyQ = 0;
int timesigQ = 0;
int metQ = 0;
int tempoQ = 0;
int x, y;
// ignore the zeroth measure
// (may not be proper).
// ggg
if (outmeasures[index].num == 0) {
return;
}
int tracks = infile.getMaxTracks();
for (i=1; i<=tracks; i++) {
if (!clefQ) {
x = outmeasures[index].sclef[i].x;
y = outmeasures[index].sclef[i].y;
if ((x>=0)&&(y>=0)) {
clefQ = 1;
}
}
if (!keysigQ) {
x = outmeasures[index].skeysig[i].x;
y = outmeasures[index].skeysig[i].y;
if ((x>=0)&&(y>=0)) {
keysigQ = 1;
}
}
if (!keyQ) {
x = outmeasures[index].skey[i].x;
y = outmeasures[index].skey[i].y;
if ((x>=0)&&(y>=0)) {
keyQ = 1;
}
}
if (!timesigQ) {
x = outmeasures[index].stimesig[i].x;
y = outmeasures[index].stimesig[i].y;
if ((x>=0)&&(y>=0)) {
timesigQ = 1;
}
}
if (!metQ) {
x = outmeasures[index].smet[i].x;
y = outmeasures[index].smet[i].y;
if ((x>=0)&&(y>=0)) {
metQ = 1;
}
}
if (!tempoQ) {
x = outmeasures[index].stempo[i].x;
y = outmeasures[index].stempo[i].y;
if ((x>=0)&&(y>=0)) {
tempoQ = 1;
}
}
}
int ptrack;
if (clefQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].sclef[ptrack].x;
y = outmeasures[index].sclef[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (keysigQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].skeysig[ptrack].x;
y = outmeasures[index].skeysig[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (keyQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].skey[ptrack].x;
y = outmeasures[index].skey[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (timesigQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].stimesig[ptrack].x;
y = outmeasures[index].stimesig[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (metQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].smet[ptrack].x;
y = outmeasures[index].smet[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
if (tempoQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile[ii].getPrimaryTrack(i);
x = outmeasures[index].stempo[ptrack].x;
y = outmeasures[index].stempo[ptrack].y;
if ((x>=0)&&(y>=0)) {
cout << infile[x][y];
} else {
cout << "*";
}
if (i < infile[ii].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
}
//////////////////////////////
//
// printDoubleBarline --
//
void printDoubleBarline(HumdrumFile& infile, int line) {
if (!infile[line].isMeasure()) {
cout << infile[line] << "\n";
return;
}
PerlRegularExpression pre;
int j;
for (j=0; j<infile[line].getFieldCount(); j++) {
if (pre.search(infile[line][j], "(=\\d*)(.*)", "")) {
cout << pre.getSubmatch(1);
cout << "||";
} else {
cout << "=||";
}
if (j < infile[line].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
//////////////////////////////
//
// printInvisibleMeasure --
//
void printInvisibleMeasure(HumdrumFile& infile, int line) {
if (!infile[line].isMeasure()) {
cout << infile[line] << "\n";
return;
}
PerlRegularExpression pre;
int j;
for (j=0; j<infile[line].getFieldCount(); j++) {
if (strchr(infile[line][j], '-') != NULL) {
cout << infile[line][j];
if (j < infile[line].getFieldCount()-1) {
cout << "\t";
}
continue;
}
if (pre.search(infile[line][j], "(=\\d*)(.*)", "")) {
cout << pre.getSubmatch(1);
cout << "-";
cout << pre.getSubmatch(2);
} else {
cout << infile[line][j];
}
if (j < infile[line].getFieldCount()-1) {
cout << "\t";
}
}
cout << "\n";
}
//////////////////////////////
//
// reconcileSpineBoundary -- merge spines correctly between segments.
// will not be able to handle all permutations of spine manipulators.
// So don't expect exotic manipulators to work...
//
void reconcileSpineBoundary(HumdrumFile& infile, int index1, int index2) {
if (debugQ) {
cout << "RECONCILING LINES " << index1+1 << " and " << index2+1 << endl;
cout << "FIELD COUNT OF " << index1+1 << " is "
<< infile[index1].getFieldCount() << endl;
cout << "FIELD COUNT OF " << index2+1 << " is "
<< infile[index2].getFieldCount() << endl;
}
// check to see if any changes need reconciling; otherwise, exit function
int i, j;
if (infile[index1].getFieldCount() == infile[index2].getFieldCount()) {
int same = 1;
for (i=0; i<infile[index1].getFieldCount(); i++) {
if (strcmp(infile[index1].getSpineInfo(i),
infile[index2].getSpineInfo(i)) != 0) {
same = 0;
}
}
if (same != 0) {
return;
}
}
// handle splits all at once
char buff1[1024] = {0};
char buff2[1024] = {0};
Array<int> splits(infile[index1].getFieldCount());
splits.setAll(0);
int hassplit = 0;
for (i=0; i<infile[index1].getFieldCount(); i++) {
strcpy(buff1, "(");
strcat(buff1, infile[index1].getSpineInfo(i));
strcat(buff1, ")");
strcpy(buff2, buff1);
strcat(buff1, "a");
strcat(buff2, "b");
for (j=0; j<infile[index2].getFieldCount()-1; j++) {
if ((strcmp(buff1, infile[index2].getSpineInfo(j)) == 0)
&& (strcmp(buff2, infile[index2].getSpineInfo(j+1)) == 0)) {
splits[i] = 1;
hassplit++;
}
}
}
if (hassplit) {
for (i=0; i<splits.getSize(); i++) {
if (splits[i]) {
cout << "*^";
} else {
cout << '*';
}
if (i < splits.getSize()-1) {
cout << '\t';
}
}
cout << '\n';
}
// make splits cumulative;
//for (i=1; i<splits.getSize(); i++) {
// splits[i] += splits[i-1];
//}
PerlRegularExpression pre1;
PerlRegularExpression pre2;
// handle joins one at a time, only look for binary joins at the moment.
// assuming that no *x has been used to mix the voices up.
for (i=0; i<infile[index1].getFieldCount()-1; i++) {
if (!pre1.search(infile[index1].getSpineInfo(i), "\\((.*)\\)a")) {
continue;
}
if (!pre2.search(infile[index1].getSpineInfo(i+1), "\\((.*)\\)b")) {
continue;
}
if (strcmp(pre1.getSubmatch(1), pre2.getSubmatch(1)) != 0) {
// spines are not split from same source
continue;
}
// found an "a" and "b" portion of a spine split, now search
// through the target line for a joint of those two sub-spines
for (j=0; j<infile[index2].getFieldCount(); j++) {
if (strcmp(infile[index2].getSpineInfo(j), pre1.getSubmatch()) != 0) {
continue;
}
// found a simple binary spine join: emmit a spine manipulator line
printJoinLine(splits, i, 2);
}
}
// handle *x switches, not perfect since ordering might need to be
// handled between manipulators...
}
//////////////////////////////
//
// printJoinLine -- count is currently ignored, but may in the future
// allow for more than two spines to join at the same time.
//
void printJoinLine(Array& splits, int index, int count) {
int i;
for (i=0; i<splits.getSize(); i++) {
if (i == index) {
cout << "*v\t*v";
i+=count-1;
} else {
cout << "*";
}
if (i<splits.getSize()-1) {
cout << "\t";
}
}
cout << "\n";
// merge splits by one element
for (i=index+1; i<splits.getSize()-1; i++) {
splits[i] = splits[i+1];
}
splits.setSize(splits.getSize()-1);
}
//////////////////////////////
//
// reconcileStartingPosition -- merge spines from start of data and
// first measure in output.
//
void reconcileStartingPosition(HumdrumFile& infile, int index2) {
int i;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isInterpretation()) {
reconcileSpineBoundary(infile, i, index2);
break;
}
}
}
//////////////////////////////
//
// printStarting -- print header information before start of data.
//
void printStarting(HumdrumFile& infile) {
int i, j;
int exi = -1;
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isInterpretation()) {
// the first interpretation is the exclusive one
cout << infile[i] << "\n";
exi = i;
break;
}
cout << infile[i] << "\n";
}
int hasI = 0;
if (instrumentQ) {
// print any tandem interpretations which start with *I found
// at the start of the data before measures, notes, or any
// spine manipulator lines
for (i=exi+1; i<infile.getNumLines(); i++) {
if (infile[i].isData()) {
break;
}
if (infile[i].isMeasure()) {
break;
}
if (!infile[i].isInterpretation()) {
continue;
}
if (infile[i].isSpineManipulator()) {
break;
}
hasI = 0;
for (j=0; j<infile[i].getFieldCount(); j++) {
if (strncmp(infile[i][j], "*I", 2) == 0) {
hasI = 1;
break;
}
}
if (hasI) {
for (j=0; j<infile[i].getFieldCount(); j++) {
if (strncmp(infile[i][j], "*I", 2) == 0) {
cout << infile[i][j];
} else {
cout << "*";
}
if (j < infile[i].getFieldCount() - 1) {
cout << "\t";
}
}
cout << "\n";
}
}
}
}
//////////////////////////////
//
// printEnding -- print the measure
//
void printEnding(HumdrumFile& infile, int lastline, int adjlin) {
if (debugQ) {
cout << "IN printEnding" << endl;
}
int ending = -1;
int marker = -1;
int i;
for (i=infile.getNumLines()-1; i>=0; i--) {
if (infile[i].isInterpretation() && (ending <0)
&& (strcmp(infile[i][0], "*-") == 0)) {
ending = i;
}
if (infile[i].isData()) {
marker = i+1;
break;
}
if (infile[i].isMeasure()) {
marker = i+1;
break;
}
}
if (ending >= 0) {
reconcileSpineBoundary(infile, adjlin, ending);
}
int startline = ending;
if (marker >= 0) {
// capture any comment which occur after the last measure
// line in the data.
startline = marker;
}
// reconcileSpineBoundary(infile, lastline, startline);
if (startline >= 0) {
for (i=startline; i<infile.getNumLines(); i++) {
cout << infile[i] << "\n";
}
}
}
//////////////////////////////
//
// getMeasureStartStop -- Get a list of the (numbered) measures in the
// input file, and store the start/stop lines for those measures.
// All data before the first numbered measure is in measure 0.
// although, if the first measure is not labeled, then ...
//
void getMeasureStartStop(Array& measurelist, HumdrumFile& infile) {
measurelist.setSize(infile.getNumLines());
measurelist.setSize(0);
MeasureInfo current;
int i, ii;
int lastend = -1;
int dataend = -1;
int barnum1 = -1;
int barnum2 = -1;
insertZerothMeasure(measurelist, infile);
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isInterpretation()) {
if (strcmp(infile[i][0], "*-") == 0) {
dataend = i;
break;
}
}
if (!infile[i].isMeasure()) {
continue;
}
if (!sscanf(infile[i][0], "=%d", &barnum1)) {
continue;
}
current.clear();
current.start = i;
current.num = barnum1;
for (ii=i+1; ii<infile.getNumLines(); ii++) {
if (!infile[ii].isMeasure()) {
continue;
}
if (sscanf(infile[ii][0], "=%d", &barnum2)) {
current.stop = ii;
lastend = ii;
i = ii - 1;
measurelist.append(current);
break;
}
}
}
int lastdata = -1; // last line in file with data
int lastmeasure = -1; // last line in file with measure
for (i=infile.getNumLines()-1; i>=0; i--) {
if ((lastdata < 0) && infile[i].isData()) {
lastdata = i;
}
if ((lastmeasure < 0) && infile[i].isMeasure()) {
lastmeasure = i;
}
if ((lastmeasure >= 0) && (lastdata >= 0)) {
break;
}
}
if (lastmeasure < lastdata) {
// no final barline, so set to ignore
lastmeasure = -1;
lastdata = -1;
}
if ((barnum2 >= 0) && (lastend >= 0) && (dataend >= 0)) {
current.clear();
current.num = barnum2;
current.start = lastend;
current.stop = dataend;
if (lastmeasure > lastdata) {
current.stop = lastmeasure;
}
measurelist.append(current);
}
}
//////////////////////////////
//
// insertZerothMeasure --
//
void insertZerothMeasure(Array<MeasureInfo>& measurelist,
HumdrumFile& infile) {
PerlRegularExpression pre;
int exinterpline = -1;
int startline = -1;
int stopline = -1;
int i;
for (i=9; i<infile.getNumLines(); i++) {
if ((exinterpline < 0) && infile[i].isInterpretation()) {
exinterpline = i;
}
if ((startline < 0) && (infile[i].isData())) {
startline = i;
}
if (infile[i].isMeasure() && pre.search(infile[i][0], "^=.*\\d+", "")) {
stopline = i;
break;
}
}
if (exinterpline < 0) {
// somethind weird happend, just return
return;
}
if (startline < 0) {
// no zeroth measure;
return;
}
if (stopline < 0) {
// strange situation, no measure numbers
// consider what to do later...
return;
}
MeasureInfo current;
current.clear();
current.num = 0;
// current.start = startline;
current.start = exinterpline+1;
current.stop = stopline;
measurelist.append(current);
}
//////////////////////////////
//
// expandMeasureOutList -- read the measure list for the sequence of measures
// to extract.
//
void expandMeasureOutList(Array<MeasureInfo>& measureout,
Array<MeasureInfo>& measurein, HumdrumFile& infile,
const char* optionstring) {
PerlRegularExpression pre;
// find the largest measure number in the score
int maxmeasure = -1;
int minmeasure = -1;
int i;
for (i=0; i<measurein.getSize(); i++) {
if (maxmeasure < measurein[i].num) {
maxmeasure = measurein[i].num;
}
if ((minmeasure == -1) || (minmeasure > measurein[i].num)) {
minmeasure = measurein[i].num;
}
}
if (maxmeasure <= 0) {
cerr << "Error: There are no measure numbers present in the data" << endl;
exit(1);
}
if (maxmeasure > 1123123) {
cerr << "Error: ridiculusly large measure number: " << maxmeasure << endl;
exit(1);
}
if (maxQ) {
if (measurein.getSize() == 0) {
cout << 0 << endl;
} else {
cout << maxmeasure << endl;
}
exit(0);
} else if (minQ) {
int ii;
for (ii=0; ii<infile.getNumLines(); ii++) {
if (infile[ii].isMeasure()) {
if (pre.search(infile[ii][0], "=\\d", "")) {
break;
} else {
cout << 0 << endl;
exit(0);
}
}
if (infile[ii].isData()) {
cout << 0 << endl;
exit(0);
}
}
if (measurein.getSize() == 0) {
cout << 0 << endl;
} else {
cout << minmeasure << endl;
}
exit(0);
}
// create reverse-lookup list
Array<int> inmap(maxmeasure+1);
inmap.setAll(-1);
for (i=0; i<measurein.getSize(); i++) {
inmap[measurein[i].num] = i;
}
fillGlobalDefaults(infile, measurein, inmap);
Array <char> ostring;
ostring.setSize(strlen(optionstring)+1);
strcpy(ostring.getBase(), optionstring);
removeDollarsFromString(ostring, maxmeasure);
if (debugQ) {
cout << "Option string expanded: " << ostring << endl;
}
pre.sar(ostring, "\\s+", "", "g"); // remove any spaces between items.
pre.sar(ostring, "--+", "-", "g"); // remove extra dashes
int value = 0;
int start = 0;
Array<MeasureInfo>& range = measureout;
range.setSize(10000);
range.setSize(0);
range.setGrowth(5123123);
value = pre.search(ostring.getBase(), "^([^,]+,?)");
while (value != 0) {
start += value - 1;
start += strlen(pre.getSubmatch(1));
processFieldEntry(range, pre.getSubmatch(), infile, maxmeasure,
measurein, inmap);
value = pre.search(ostring.getBase() + start, "^([^,]+,?)");
}
}
//////////////////////////////
//
// fillGlobalDefaults -- keep track of the clef, key signature, key
//
void fillGlobalDefaults(HumdrumFile& infile, Array<MeasureInfo>& measurein,
Array<int>& inmap) {
int i, j;
PerlRegularExpression pre;
int tracks = infile.getMaxTracks();
Array<Coord> currclef(tracks+1);
Array<Coord> currkeysig(tracks+1);
Array<Coord> currkey(tracks+1);
Array<Coord> currtimesig(tracks+1);
Array<Coord> currmet(tracks+1);
Array<Coord> currtempo(tracks+1);
Coord undefCoord;
undefCoord.x = -1;
undefCoord.y = -1;
currclef.setAll(undefCoord);
currkeysig.setAll(undefCoord);
currkey.setAll(undefCoord);
currtimesig.setAll(undefCoord);
currmet.setAll(undefCoord);
currtempo.setAll(undefCoord);
int currmeasure = -1;
int lastmeasure = -1;
int datafound = 0;
int track;
int thingy = 0;
for (i=0; i<infile.getNumLines(); i++) {
if ((currmeasure == -1) && (thingy == 0) && infile[i].isData()) {
currmeasure = 0;
}
if (infile[i].isMeasure()) {
if (!pre.search(infile[i][0], "(\\d+)", "")) {
continue;
}
thingy = 1;
// store state of global music values at end of measure
if (currmeasure >= 0) {
measurein[inmap[currmeasure]].eclef = currclef;
measurein[inmap[currmeasure]].ekeysig = currkeysig;
measurein[inmap[currmeasure]].ekey = currkey;
measurein[inmap[currmeasure]].etimesig = currtimesig;
measurein[inmap[currmeasure]].emet = currmet;
measurein[inmap[currmeasure]].etempo = currtempo;
}
lastmeasure = currmeasure;
currmeasure = atoi(pre.getSubmatch(1));
measurein[inmap[currmeasure]].sclef = currclef;
measurein[inmap[currmeasure]].skeysig = currkeysig;
measurein[inmap[currmeasure]].skey = currkey;
measurein[inmap[currmeasure]].stimesig = currtimesig;
measurein[inmap[currmeasure]].smet = metstates[i];
measurein[inmap[currmeasure]].stempo = currtempo;
datafound = 0;
continue;
}
if (infile[i].isInterpretation()) {
for (j=0; j<infile[i].getFieldCount(); j++) {
if (!infile[i].isExInterp(j, "**kern")) {
continue;
}
track = infile[i].getPrimaryTrack(j);
if ((datafound == 0) && (lastmeasure >= 0)) {
if (strncmp(infile[i][j], "*clef", 5) == 0) {
measurein[inmap[currmeasure]].sclef[track].x = -1;
measurein[inmap[currmeasure]].sclef[track].y = -1;
} else if (pre.search(infile[i][j], "^\\*k\\[.*\\]", "")) {
measurein[inmap[currmeasure]].skeysig[track].x = -1;
measurein[inmap[currmeasure]].skeysig[track].y = -1;
} else if (pre.search(infile[i][j], "^\\*[A-G][#-]?:", "i")) {
measurein[inmap[currmeasure]].skey[track].x = -1;
measurein[inmap[currmeasure]].skey[track].y = -1;
} else if (pre.search(infile[i][j], "^\\*M\\d+/\\d+", "i")) {
measurein[inmap[currmeasure]].stimesig[track].x = -1;
measurein[inmap[currmeasure]].stimesig[track].y = -1;
measurein[inmap[currmeasure]].smet[track].x = -1;
measurein[inmap[currmeasure]].smet[track].y = -1;
} else if (pre.search(infile[i][j], "^\\*MM\\d+", "i")) {
measurein[inmap[currmeasure]].stempo[track].x = -1;
measurein[inmap[currmeasure]].stempo[track].y = -1;
}
}
if (strncmp(infile[i][j], "*clef", 5) == 0) {
currclef[track].x = i;
currclef[track].y = j;
continue;
}
if (pre.search(infile[i][j], "^\\*k\\[.*\\]", "")) {
currkeysig[track].x = i;
currkeysig[track].y = j;
continue;
}
if (pre.search(infile[i][j], "^\\*[A-G][#-]?:", "i")) {
currkey[track].x = i;
currkey[track].y = j;
continue;
}
if (pre.search(infile[i][j], "^\\*M\\d+/\\d+", "i")) {
currtimesig[track].x = i;
currtimesig[track].y = j;
continue;
}
if (pre.search(infile[i][j], "^\\*MM[\\d.]+", "i")) {
currtempo[track].x = i;
currtempo[track].y = j;
continue;
}
}
}
if (infile[i].isData()) {
datafound = 1;
}
}
// store state of global music values at end of music
if (currmeasure >= 0) {
measurein[inmap[currmeasure]].eclef = currclef;
measurein[inmap[currmeasure]].ekeysig = currkeysig;
measurein[inmap[currmeasure]].ekey = currkey;
measurein[inmap[currmeasure]].etimesig = currtimesig;
measurein[inmap[currmeasure]].emet = currmet;
measurein[inmap[currmeasure]].etempo = currtempo;
}
}
//////////////////////////////
//
// processFieldEntry --
// 3-6 expands to 3 4 5 6
// $ expands to maximum spine track
// $0 expands to maximum spine track
// $1 expands to maximum spine track minus 1, etc.
// 2-$1 expands to 2 through the maximum minus one.
// 6-3 expands to 6 5 4 3
// $2-5 expands to the maximum minus 2 down through 5.
// Ignore negative values and values which exceed the maximum value.
//
void processFieldEntry(Array<MeasureInfo>& field, const char* string,
HumdrumFile& infile, int maxmeasure, Array<MeasureInfo>& inmeasures,
Array<int>& inmap) {
MeasureInfo current;
PerlRegularExpression pre;
Array<char> buffer;
buffer.setSize(strlen(string)+1);
strcpy(buffer.getBase(), string);
// remove any comma left at end of input string (or anywhere else)
pre.sar(buffer, ",", "", "g");
if (pre.search(buffer.getBase(), "^(\\d+)[a-z]?-(\\d+)[a-z]?$")) {
int firstone = strtol(pre.getSubmatch(1), NULL, 10);
int lastone = strtol(pre.getSubmatch(2), NULL, 10);
// limit the range to 0 to maxmeasure
if (firstone > maxmeasure) { firstone = maxmeasure; }
if (lastone > maxmeasure) { lastone = maxmeasure; }
if (firstone < 0 ) { firstone = 0 ; }
if (lastone < 0 ) { lastone = 0 ; }
if ((firstone < 1) && (firstone != 0)) {
cerr << "Error: range token: \"" << string << "\""
<< " contains too small a number at start: " << firstone << endl;
cerr << "Minimum number allowed is " << 1 << endl;
exit(1);
}
if ((lastone < 1) && (lastone != 0)) {
cerr << "Error: range token: \"" << string << "\""
<< " contains too small a number at end: " << lastone << endl;
cerr << "Minimum number allowed is " << 1 << endl;
exit(1);
}
int i;
if (firstone > lastone) {
for (i=firstone; i>=lastone; i--) {
if (inmap[i] >= 0) {
if ((field.getSize() > 0) &&
(field.last().stop == inmeasures[inmap[i]].start)) {
field.last().stop = inmeasures[inmap[i]].stop;
} else {
current.clear();
current.num = i;
current.start = inmeasures[inmap[i]].start;
current.stop = inmeasures[inmap[i]].stop;
current.sclef = inmeasures[inmap[i]].sclef;
current.skeysig = inmeasures[inmap[i]].skeysig;
current.skey = inmeasures[inmap[i]].skey;
current.stimesig = inmeasures[inmap[i]].stimesig;
current.smet = inmeasures[inmap[i]].smet;
current.stempo = inmeasures[inmap[i]].stempo;
current.eclef = inmeasures[inmap[i]].eclef;
current.ekeysig = inmeasures[inmap[i]].ekeysig;
current.ekey = inmeasures[inmap[i]].ekey;
current.etimesig = inmeasures[inmap[i]].etimesig;
current.emet = inmeasures[inmap[i]].emet;
current.etempo = inmeasures[inmap[i]].etempo;
field.append(current);
}
}
}
} else {
for (i=firstone; i<=lastone; i++) {
if (inmap[i] >= 0) {
if ((field.getSize() > 0) &&
(field.last().stop == inmeasures[inmap[i]].start)) {
field.last().stop = inmeasures[inmap[i]].stop;
} else {
current.clear();
current.num = i;
current.start = inmeasures[inmap[i]].start;
current.stop = inmeasures[inmap[i]].stop;
current.sclef = inmeasures[inmap[i]].sclef;
current.skeysig = inmeasures[inmap[i]].skeysig;
current.skey = inmeasures[inmap[i]].skey;
current.stimesig = inmeasures[inmap[i]].stimesig;
current.smet = inmeasures[inmap[i]].smet;
current.stempo = inmeasures[inmap[i]].stempo;
current.eclef = inmeasures[inmap[i]].eclef;
current.ekeysig = inmeasures[inmap[i]].ekeysig;
current.ekey = inmeasures[inmap[i]].ekey;
current.etimesig = inmeasures[inmap[i]].etimesig;
current.emet = inmeasures[inmap[i]].emet;
current.etempo = inmeasures[inmap[i]].etempo;
field.append(current);
}
}
}
}
} else if (pre.search(buffer.getBase(), "^(\\d+)([a-z]*)")) {
int value = strtol(pre.getSubmatch(1), NULL, 10);
// do something with letter later...
if ((value < 1) && (value != 0)) {
cerr << "Error: range token: \"" << string << "\""
<< " contains too small a number at end: " << value << endl;
cerr << "Minimum number allowed is " << 1 << endl;
exit(1);
}
if (inmap[value] >= 0) {
if ((field.getSize() > 0) &&
(field.last().stop == inmeasures[inmap[value]].start)) {
field.last().stop = inmeasures[inmap[value]].stop;
} else {
current.clear();
current.num = value;
current.start = inmeasures[inmap[value]].start;
current.stop = inmeasures[inmap[value]].stop;
current.sclef = inmeasures[inmap[value]].sclef;
current.skeysig = inmeasures[inmap[value]].skeysig;
current.skey = inmeasures[inmap[value]].skey;
current.stimesig = inmeasures[inmap[value]].stimesig;
current.smet = inmeasures[inmap[value]].smet;
current.stempo = inmeasures[inmap[value]].stempo;
current.eclef = inmeasures[inmap[value]].eclef;
current.ekeysig = inmeasures[inmap[value]].ekeysig;
current.ekey = inmeasures[inmap[value]].ekey;
current.etimesig = inmeasures[inmap[value]].etimesig;
current.emet = inmeasures[inmap[value]].emet;
current.etempo = inmeasures[inmap[value]].etempo;
field.append(current);
}
}
}
}
//////////////////////////////
//
// removeDollarsFromString -- substitute $ sign for maximum track count.
//
void removeDollarsFromString(Array& buffer, int maxx) {
PerlRegularExpression pre;
PerlRegularExpression pre2;
char tbuf[1024] = {0};
char obuf[1024] = {0};
int outval;
int value;
if (debugQ) {
cout << "MEASURE STRING BEFORE DOLLAR REMOVAL: " << buffer << endl;
}
while (pre.search(buffer, "(\\$\\d*)", "")) {
strcpy(tbuf, pre.getSubmatch(1));
if (pre2.search(tbuf, "(\\$\\d+)")) {
sscanf(pre2.getSubmatch(1), "$%d", &value);
outval = maxx - value;
} else {
outval = maxx;
}
if (outval < 0) {
outval = 0;
}
sprintf(tbuf, "%d", outval);
strcpy(obuf, "\\");
strcat(obuf, pre.getSubmatch());
pre.sar(buffer, obuf, tbuf, "");
}
if (debugQ) {
cout << "DOLLAR EXPAND: " << buffer << endl;
}
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char** argv) {
opts.define("v|verbose=b", "Verbose output of data");
opts.define("d|debug=b", "Debugging information");
opts.define("mark|marks=b", "Yank measure with marked notes");
opts.define("double|dm|md|mdsep|mdseparator=b", "Put double barline between non-consecutive measure segments");
opts.define("m|b|measures|bars|measure|bar=s", "Measures to yank");
opts.define("I|i|instrument=b", "Include instrument codes from start of data");
opts.define("visible|not-invisible=b", "Do not make initial measure invisible");
opts.define("B|noendbar=b", "Do not print barline at end of data");
opts.define("max=b", "print maximum measure number");
opts.define("min=b", "print minimum measure number");
opts.define("author=b", "Program author");
opts.define("version=b", "Program version");
opts.define("example=b", "Program examples");
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, December 2010" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 26 December 2010" << 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");
verboseQ = opts.getBoolean("verbose");
maxQ = opts.getBoolean("max");
minQ = opts.getBoolean("min");
invisibleQ = !opts.getBoolean("not-invisible");
instrumentQ = opts.getBoolean("instrument");
nolastbarQ = opts.getBoolean("noendbar");
markQ = opts.getBoolean("mark");
doubleQ = opts.getBoolean("mdsep");
if (!(opts.getBoolean("measures") || markQ)) {
// if -m option is not given, then --mark option presumed
markQ = 1;
// cerr << "Error: the -m option is required" << endl;
// exit(1);
}
}
//////////////////////////////
//
// example -- example function calls to the program.
//
void example(void) {
}
//////////////////////////////
//
// usage -- command-line usage description and brief summary
//
void usage(const char* command) {
}
// md5sum: bd3850e7b81f41c49ace22d69b3e2d49 myank.cpp [20110427]