// // Programmer: Craig Stuart Sapp // Creation Date: Thu Oct 20 20:52:45 PDT 2011 // Last Modified: Thu Oct 20 20:52:48 PDT 2011 // Filename: ...sig/examples/all/staff.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/staff.cpp // Syntax: C++; museinfo // // Description: Extact music by staff indications. // #include "humdrum.h" #include "PerlRegularExpression.h" #ifndef OLDCPP using namespace std; #endif /////////////////////////////////////////////////////////////////////////// // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void processFile (HumdrumFile& infile, Array& field); void getStaves (Array > >& staves, HumdrumFile& infile); void setStaffAssignment (Array& states, const char* string); void printStaves (Array > >& staves); void fillFieldData (Array& field, Array& subfield, Array& model, string& fieldstring, HumdrumFile& infile); void processFieldEntry (Array& field, Array& subfield, Array& model, const char* string, HumdrumFile& infile); void removeDollarsFromString(Array& buffer, int maxtrack); int isMatch (int ss, Array& list); void printLineDuration (HumdrumFile& infile, int line); void getMeasureDurations (Array& measuredur, HumdrumFile& infile); void addStaffEntry (Array & states, double value); void getMeasureStates (Array >& measurestates, Array > >& staves, Array& mdur, HumdrumFile& infile); void printDuration (const RationalNumber& duration); // global variables Options options; // database for command-line arguments string fieldstring = ""; // used with -s option int debugQ = 0; // used with --debug option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile infile; // process the command-line options checkOptions(options, argc, argv); string 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(filename.c_str()); } infile.analyzeRhythm("4"); Array model; Array field; Array subfield; fillFieldData(field, subfield, model, fieldstring, infile); processFile(infile, field); } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // processFile -- // void processFile(HumdrumFile& infile, Array& field) { Array > > staves; getStaves(staves, infile); if (debugQ) { printStaves(staves); } Array measuredur; getMeasureDurations(measuredur, infile); Array > measurestates; getMeasureStates(measurestates, staves, measuredur, infile); PerlRegularExpression pre; int i, j, s, ss; int first = 0; int found = 0; int active; for (i=0; i 0) { // this is the first data element in the measure // place the rest here. printDuration(measuredur[i]); cout << "r"; } else { // not the first data element in measure so // just place a dot. cout << "."; } } } } cout << endl; } } ////////////////////////////// // // getMeasureStates -- return a list of staves which contain // data within the current measure. // void getMeasureStates(Array >& measurestates, Array > >& staves, Array& mdur, HumdrumFile& infile) { int i, ii, j, k; measurestates.setSize(mdur.getSize()); for (i=0; i 0) { continue; } if (measurestates[i-1].getSize() > 0) { measurestates[i] = measurestates[i-1]; } } if (debugQ) { cout << "STAVES BY MEASURE" << endl; for (i=0; i & states, double value) { int i; for (i=0; i& measuredur, HumdrumFile& infile) { measuredur.setSize(infile.getNumLines()); measuredur.setAll(0); RationalNumber rn; int i; int lastmi = -1; int mi = -1; int lastdatai = -1; int datai = -1; int datamark = 0; for (i=0; i 0) && (lastmi > 0)) { rn = infile[mi].getAbsBeatR() - infile[lastmi].getAbsBeatR(); if (lastdatai > 0) { measuredur[lastdatai] = rn; } } lastdatai = datai; } } } // process the last measure if (datamark) { datai = i; datamark = 0; if ((mi > 0) && (lastmi > 0)) { rn = infile[mi].getAbsBeatR() - infile[lastmi].getAbsBeatR(); if (lastdatai > 0) { measuredur[lastdatai] = rn; } } lastdatai = datai; } if (debugQ) { cout << "MEASURE DURATIONS" << endl; for (i=0; i& list) { int i; for (i=0; i > >& staves) { int i, j, k; for (i=0; i > >& staves, HumdrumFile& infile) { staves.setSize(infile.getNumLines()); int i, j; for (i=0; i firststaff; firststaff.setSize(infile.getMaxTracks()+1); firststaff.setAll(-1); Array > states; states.setSize(infile.getMaxTracks()+1); for (i=0; i=0; i--) { if (infile[i].isBibliographic()) { continue; } if (infile[i].isGlobalComment()) { continue; } if (infile[i].isEmpty()) { continue; } for (j=0; j& states, const char* string) { PerlRegularExpression pre; Array > pieces; pre.getTokens(pieces, "[^\\dX.]+", string); if (pieces.getSize() == 0) { states.setSize(0); states.allowGrowth(0); return; } int i; if (strncmp(pieces[0].getBase(), "X", 1) == 0) { states.setSize(0); states.allowGrowth(0); return; } states.setSize(pieces.getSize()); int number; for (i=0; i& field, Array& subfield, Array& model, string& fieldstring, HumdrumFile& infile) { int maxtrack = infile.getMaxTracks(); field.setSize(maxtrack); field.setGrowth(maxtrack); field.setSize(0); subfield.setSize(maxtrack); subfield.setGrowth(maxtrack); subfield.setSize(0); model.setSize(maxtrack); model.setGrowth(maxtrack); model.setSize(0); PerlRegularExpression pre; Array buffer; buffer.setSize(fieldstring.size()+1); strcpy(buffer.getBase(), fieldstring.c_str()); pre.sar(buffer, "\\s", "", "gs"); int start = 0; int value = 0; value = pre.search(buffer.getBase(), "^([^,]+,?)"); while (value != 0) { start += value - 1; start += strlen(pre.getSubmatch(1)); processFieldEntry(field, subfield, model, pre.getSubmatch(), infile); value = pre.search(buffer.getBase() + start, "^([^,]+,?)"); } } ////////////////////////////// // // processFieldEntry -- // 3-6 expands to 3 4 5 6 // $ expands to maximum spine track // $-1 expands to maximum spine track minus 1, etc. // void processFieldEntry(Array& field, Array& subfield, Array& model, const char* string, HumdrumFile& infile) { int maxtrack = infile.getMaxTracks(); int modletter; int subletter; PerlRegularExpression pre; Array 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"); // first remove $ symbols and replace with the correct values removeDollarsFromString(buffer, infile.getMaxTracks()); int zero = 0; if (pre.search(buffer.getBase(), "^(\\d+)-(\\d+)$")) { int firstone = strtol(pre.getSubmatch(1), NULL, 10); int lastone = strtol(pre.getSubmatch(2), NULL, 10); 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); } if (firstone > maxtrack) { cerr << "Error: range token: \"" << string << "\"" << " contains number too large at start: " << firstone << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } if (lastone > maxtrack) { cerr << "Error: range token: \"" << string << "\"" << " contains number too large at end: " << lastone << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } int i; if (firstone > lastone) { for (i=firstone; i>=lastone; i--) { field.append(i); subfield.append(zero); model.append(zero); } } else { for (i=firstone; i<=lastone; i++) { field.append(i); subfield.append(zero); model.append(zero); } } } else if (pre.search(buffer.getBase(), "^(\\d+)([a-z]*)")) { int value = strtol(pre.getSubmatch(1), NULL, 10); modletter = 0; subletter = 0; if (strchr(pre.getSubmatch(2), 'a') != NULL) { subletter = 'a'; } if (strchr(pre.getSubmatch(), 'b') != NULL) { subletter = 'b'; } if (strchr(pre.getSubmatch(), 'c') != NULL) { subletter = 'c'; } if (strchr(pre.getSubmatch(), 'd') != NULL) { modletter = 'd'; } if (strchr(pre.getSubmatch(), 'n') != NULL) { modletter = 'n'; } if (strchr(pre.getSubmatch(), 'r') != NULL) { modletter = 'r'; } 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 (value > maxtrack) { cerr << "Error: range token: \"" << string << "\"" << " contains number too large at start: " << value << endl; cerr << "Maximum number allowed is " << maxtrack << endl; exit(1); } field.append(value); if (value == 0) { subfield.append(zero); model.append(zero); } else { subfield.append(subletter); model.append(modletter); } } } ////////////////////////////// // // removeDollarsFromString -- substitute $ sign for maximum track count. // void removeDollarsFromString(Array& buffer, int maxtrack) { PerlRegularExpression pre; char buf2[128] = {0}; int value2; if (pre.search(buffer.getBase(), "\\$$")) { sprintf(buf2, "%d", maxtrack); pre.sar(buffer, "\\$$", buf2); } if (pre.search(buffer.getBase(), "\\$(?![\\d-])")) { // don't know how this case could happen, however... sprintf(buf2, "%d", maxtrack); pre.sar(buffer, "\\$(?![\\d-])", buf2, "g"); } if (pre.search(buffer.getBase(), "\\$0")) { // replace $0 with maxtrack (used for reverse orderings) sprintf(buf2, "%d", maxtrack); pre.sar(buffer, "\\$0", buf2, "g"); } while (pre.search(buffer.getBase(), "\\$(-?\\d+)")) { value2 = maxtrack - (int)fabs(strtol(pre.getSubmatch(1), NULL, 10)); sprintf(buf2, "%d", value2); pre.sar(buffer, "\\$-?\\d+", buf2); } } ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("s|staves=s:", "List of staves to extract"); 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 2011" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 20 Oct 2011" << endl; cout << "compiled: " << __DATE__ << endl; cout << MUSEINFO_VERSION << endl; exit(0); } else if (opts.getBoolean("help")) { usage(opts.getCommand().c_str()); exit(0); } else if (opts.getBoolean("example")) { example(); exit(0); } if (!opts.getBoolean("staves")) { cerr << "Error: you must specify the -s option" << endl; exit(1); } fieldstring = opts.getString("staves"); 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: d30163620ecea55295a3d6c330314091 staff.cpp [20160320]