// // Programmer: Craig Stuart Sapp // Creation Date: Sun Aug 17 19:08:36 PDT 2014 // Last Modified: Sun Aug 17 19:08:39 PDT 2014 // Filename: ...sig/examples/all/barline.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/barline.cpp // Syntax: C++; museinfo // // Description: Add or remove barlines from music. Grace notes not // handled. // #include #include #include #include #include #include "humdrum.h" using namespace std; // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const string& command); void processFileAuto (HumdrumFile& file); void processFileConvert (HumdrumFile& infile); void cutNotesAcrossBarline(HumdrumFile& infile, int line, int trackline, int fieldcount, RationalNumber& barabsbeat); void getTrackInfo (HumdrumFile& infile, int trackline, vector& trackcount, vector& subtrackcount); void generateDataLine (HumdrumFile& infile, int line, vector& trackcount, vector& subtrackcount); void getAddress (int& tline, int& tcol, HumdrumFile& infile, int barline, int track, int subtrack); int setNewDuration (HumdrumFile& infile, int line, int col, RationalNumber& newdur, int order, int tiestate); // global variables Options options; // database for command-line arguments int autoQ = 0; // used with -a option int convertQ = 0; // used with -c option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { checkOptions(options, argc, argv); HumdrumStream streamer(options); HumdrumFile infile; while (streamer.read(infile)) { if (autoQ) { processFileAuto(infile); } else if (convertQ) { processFileConvert(infile); } } return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // processFileConvert -- // void processFileConvert(HumdrumFile& infile) { infile.analyzeRhythm("4"); PerlRegularExpression pre; RationalNumber absbeat; int fieldcount = 0; int i, j; char buffer[1024] = {0}; int trackline = 0; int dashQ = 0; for (i=0; i 0) && (strcmp(infile[i][j], "*v") == 0)) { if (strcmp(infile[i][j-1], "*v") == 0) { fieldcount--; trackline = i; } } // should check for *+, but not very common. } continue; } if (!infile[i].isGlobalComment()) { continue; } if (pre.search(infile[i][0], "^!!barline:.*absbeat\\s*=\\s*(\\d+)/(\\d+)")) { absbeat = atoi(pre.getSubmatch(1)); absbeat /= atoi(pre.getSubmatch(2)); if (pre.search(infile[i][0], "dash", "i")) { dashQ = 1; } else { dashQ = 0; } } else if (pre.search(infile[i][0], "^!!barline:.*absbeat\\s*=\\s*(\\d+)")) { absbeat = atoi(pre.getSubmatch(1)); if (pre.search(infile[i][0], "dash", "i")) { dashQ = 1; } else { dashQ = 0; } } else { continue; } buffer[0] = '\0'; for (j=0; j tracknum; vector subtracknum; int i; getTrackInfo(infile, trackline, tracknum, subtracknum); PerlRegularExpression pre; int dataline = -1; for (i=barline+1; i 0) { // Ending note. If tiestate == 1, then this note should // continue a tie. If tiestate == -1, then this note should // terminate a tie. pre.sar(token, "[_\\][]", "", "g"); if (tiestate == 1) { // continue tie pre.sar(token, " ", "_ ", "g"); pre.sar(token, "$", "_", ""); infile[line].setToken(col, token.c_str()); return 0; } else if (tiestate == -1) { // end tie pre.sar(token, " ", "] ", "g"); pre.sar(token, "$", "]", ""); infile[line].setToken(col, token.c_str()); return 0; } else { cerr << "Error: should not get here" << endl; exit(1); } } cerr << "Error: should not get here 2" << endl; return 0; } ////////////////////////////// // // getAddress -- // void getAddress(int& tline, int& tcol, HumdrumFile& infile, int barline, int track, int subtrack) { int ptrack; int ptrackcount; for (int i=barline-1; i>=0; i--) { if (infile[i].isBarline()) { break; } if (!infile[i].isData()) { continue; } ptrackcount = 0; for (int j=0; j& tracknum, vector& subtracknum) { char buffer[1024] = {0}; for (int j=0; j<(int)tracknum.size(); j++) { strcat(buffer, "."); if (j < (int)tracknum.size() - 1) { strcat(buffer, "\t"); } } infile[line].setLine(buffer); } ////////////////////////////// // // getTrackInfo -- // void getTrackInfo(HumdrumFile& infile, int trackline, vector& trackcount, vector& subtrackcount) { trackcount.reserve(1000); trackcount.resize(0); subtrackcount.reserve(1000); subtrackcount.resize(0); vector ptrackcounter(infile.getMaxTracks()+1, 0); int ptrack; if (!infile[trackline].isInterpretation()) { for (int j=0; j0) && (strcmp(infile[trackline][j], "*v") == 0)) { if (strcmp(infile[trackline][j-1], "*v") == 0) { continue; } ptrack = infile[trackline].getPrimaryTrack(j); trackcount.push_back(ptrack); } } for (int j=0; j<(int)trackcount.size(); j++) { subtrackcount.push_back(ptrackcounter[trackcount[j]]); ptrackcounter[trackcount[j]]++; } } ////////////////////////////// // // processFileAuto -- Look for fractional barline directives in the file, // such as: // !!BARLINES: 1/2 // which will be used to add a barline 1/2 of the way through all // subsequent bars. This will add a marker: // !!barline: absbeat=41/2 // at the appropriate place in the music, where the absbeat parameter // is the time position of the barline that will be placed. // void processFileAuto(HumdrumFile& infile) { infile.analyzeRhythm("4"); PerlRegularExpression pre; RationalNumber fraction = 1; int barcounter = 0; RationalNumber barstarttime; RationalNumber barduration; RationalNumber nextbarmessage; int dashQ = 0; for (int i=0; i 0) && (infile[i].getAbsBeatR() >= nextbarmessage)) { cout << "!!barline: absbeat=" << nextbarmessage; if (dashQ) { cout << " dash"; } cout << endl; if (infile[i].getAbsBeatR() > nextbarmessage) { cout << "!!barline: dataline" << endl; } barcounter++; if (barcounter+1 == fraction.getDenominator()) { nextbarmessage = -1; } else { nextbarmessage = barstarttime + barduration * fraction * (barcounter + 1); } } if (infile[i].isGlobalComment()) { if (pre.search(infile[i][0], "!!BARLINES:\\s*(\\d+)/(\\d+)")) { fraction = atoi(pre.getSubmatch(1)); fraction /= atoi(pre.getSubmatch(2)); if (pre.search(infile[i][0], "dash", "i")) { dashQ = 1; } else { dashQ = 0; } continue; } } if (fraction == 1) { cout << infile[i] << endl; continue; } if (infile[i].isBarline()) { barcounter = 0; barstarttime = infile[i].getAbsBeatR(); barduration = infile[i].getMeasureDuration(); if (barduration <= 0) { nextbarmessage = -1; } else { nextbarmessage = barstarttime + barduration * fraction; } cout << infile[i] << endl; continue; } cout << infile[i] << endl; } } ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|auto=b", "auto-mark measure subdivisions"); opts.define("c|convert=b", "convert auto-mark output"); opts.define("debug=b"); // print debug info 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, Aug 2014" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 18 Aug 2014" << 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); } autoQ = opts.getBoolean("auto"); convertQ = opts.getBoolean("convert"); } ////////////////////////////// // // example -- example usage of the quality program // void example(void) { cout << " \n" << endl; } ////////////////////////////// // // usage -- gives the usage statement for the meter program // void usage(const string& command) { cout << " \n" << endl; }