// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Fri Mar 4 07:02:41 PST 2011 // Last Modified: Fri Mar 4 07:02:43 PST 2011 // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/hexa.cpp // Syntax: C++; museinfo // // Description: Describe the hexachord position of notes. // #include <math.h> #include <time.h> /* for current time/date */ #ifndef OLDCPP #include <iostream> #include <fstream> #include <sstream> #define SSTREAM stringstream #define CSTRING str().c_str() using namespace std; #else #include <iostream.h> #include <fstream.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" #include "MuseDataSet.h" #include "CheckSum.h" #include "SigString.h" ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions(Options& opts, int argc, char** argv); void example(void); void usage(const char* command); void extractPitches(Array<Array<Array<int> > >& pitches, HumdrumFile& infile); void printData(Array<Array<Array<int> > >& pitches, HumdrumFile& infile); void printLine(HumdrumFile& infile, int line, Array<Array<Array<int> > >& pitches, int offset); void printDataToken(Array<Array<Array<int> > >& pitches, int line, int col, char prefix, int interval); void printKernTokenAndData(HumdrumFile& infile, int line, int col, Array<Array<Array<int> > >& pitches, int offset); char hexPos(int interval); void printSingleColumnLine(HumdrumRecord& arecord, int offset); // User interface variables: Options options; int debugQ = 0; // used with --debug option ////////////////////////////////////////////////////////////////////////// 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)); } infile.analyzeRhythm("4"); Array<Array<Array<int> > > pitches; extractPitches(pitches, infile); printData(pitches, infile); return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // printData -- // void printData(Array> >& pitches, HumdrumFile& infile) { int i; int offset = 75; for (i=0; i<infile.getNumLines(); i++) { if (infile[i].isData() || infile[i].isLocalComment() || infile[i].isInterpretation() || infile[i].isMeasure()) { printLine(infile, i, pitches, offset); } else { printSingleColumnLine(infile[i], offset); } } } ////////////////////////////// // // printSingleColumnLine -- add extract space between staves to allow // for printing of analysis data. // void printSingleColumnLine(HumdrumRecord& arecord, int offset) { PerlRegularExpression pre; pre.search(arecord[0], "(.*muse2ps.*)(v[0-9,]+)(.*)", ""); if (strlen(pre.getSubmatch(2)) == 0) { cout << arecord[0] << "\n"; return; } Array<char> pos; pos.setSize(strlen(pre.getSubmatch(2))+1); strcpy(pos.getBase(), pre.getSubmatch()); Array<Array<char> > tokens; PerlRegularExpression pre2; pre2.getTokens(tokens, "[v,\\s]+", pre.getSubmatch()); int value; cout << pre.getSubmatch(1); cout << "v"; int i; for (i=0; i<tokens.getSize(); i++) { value = atoi(tokens[i].getBase()); value += offset; cout << value; if (i<tokens.getSize()) { cout << ","; } } cout << pre.getSubmatch(3); cout << "\n"; } ////////////////////////////// // // printLine -- // void printLine(HumdrumFile& infile, int line, Array<Array<Array<int> > >& pitches, int offset) { int& i = line; int j; int started = 0; for (j=0; j<infile[i].getFieldCount(); j++) { if (!infile[i].isExInterp(j, "**kern")) { if (started) { cout << "\t"; } started = 1; cout << infile[i][j]; continue; } else { if (started) { cout << "\t"; } started = 1; printKernTokenAndData(infile, i, j, pitches, offset); } } cout << "\n"; } ////////////////////////////// // // printKernTokenAndData -- // void printKernTokenAndData(HumdrumFile& infile, int line, int col, Array<Array<Array<int> > >& pitches, int offset) { int& i = line; int& j = col; int m; PerlRegularExpression pre; Array<char> strang; strang.setSize(strlen(infile[i][j])+1); strcpy(strang.getBase(), infile[i][j]); if (pre.search(strang, "^(!LO:TX.*Y=)(\\d+)(.*)")) { // text printed below the staff, but need to drop it so that // it does not collide with the text (which cannot be adjsted // in muse2ps). cout << pre.getSubmatch(1); int value = atoi(pre.getSubmatch(2)); // value = -50; cout << value; cout << ":hide"; // just hide text so that it is not displayed cout << pre.getSubmatch(3); } else { cout << strang; } if (infile[i].isLocalComment()) { for (m=0; m<3; m++) { cout << "\t!"; } return; } if (infile[i].isMeasure()) { for (m=0; m<3; m++) { cout << "\t" << infile[i][j]; } return; } if (infile[i].isInterpretation()) { if (strncmp(infile[i][j], "**", 2) == 0) { for (m=0; m<3; m++) { cout << "\t**hexa"; } return; } if (strcmp(infile[i][j], "*-") == 0) { for (m=0; m<3; m++) { cout << "\t*-"; } return; } for (m=0; m<3; m++) { cout << "\t*"; } return; } char prefix[3] = {'f', 'c', 'g'}; int interval[3] = {17, 0, 23}; for (m=0; m<3; m++) { cout << "\t"; printDataToken(pitches, line, col, prefix[m], interval[m]); } } ////////////////////////////// // // printDataToken -- // void printDataToken(Array<Array<Array<int> > >& pitches, int line, int col, char prefix, int interval) { int& i = line; int& j = col; int k; char pos; if (pitches[i][j].getSize() == 0) { cout << "."; return; } for (k=0; k<pitches[i][j].getSize(); k++) { if (k > 0) { cout << " "; } pos = hexPos((pitches[line][col][k] - (2 + interval)) % 40); cout << prefix << pos; } } ////////////////////////////// // // hexPos -- // char hexPos(int interval) { switch (interval) { case 0: return '1'; case 6: return '2'; case 12: return '3'; case 17: return '4'; case 23: return '5'; case 29: return '6'; } return 'X'; } ////////////////////////////// // // extractPitches -- // void extractPitches(Array > >& pitches, HumdrumFile& infile) { pitches.setSize(infile.getNumLines()); PerlRegularExpression pre; int i, j, k; int value; int tokencount; char buffer[1024] = {0}; for (i=0; i<infile.getNumLines(); i++) { pitches[i].setSize(infile[i].getFieldCount()); for (j=0; j<pitches[i].getSize(); j++) { pitches[i][j].setSize(0); } if (!infile[i].isData()) { continue; } for (j=0; j<infile[i].getFieldCount(); j++) { if (!infile[i].isExInterp(j, "**kern")) { continue; } if (strcmp(infile[i][j], ".") == 0) { // ignore null tokens continue; } if (strchr(infile[i][j], 'r') != NULL) { // ignore rests continue; } if (strchr(infile[i][j], ']') != NULL) { // ignore endings of ties continue; } if (strchr(infile[i][j], '_') != NULL) { // ignore middle notes of ties continue; } tokencount = infile[i].getTokenCount(j); for (k=0; k<tokencount; k++) { infile[i].getToken(buffer, j, k); if (!pre.search(buffer, "[a-g]", "i")) { // ignore subtoken: missing a pitch name. continue; } value = Convert::kernToBase40(buffer); pitches[i][j].append(value); } } } } ////////////////////////////// // // checkOptions -- // void checkOptions(Options& opts, int argc, char** argv) { opts.define("d|debug=b", "Debugging information"); 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, March 2011" << "\n"; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 4 March 2011" << "\n"; cout << "compiled: " << __DATE__ << "\n"; cout << MUSEINFO_VERSION << "\n"; 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 function calls to the program. // void example(void) { } ////////////////////////////// // // usage -- command-line usage description and brief summary // void usage(const char* command) { } // md5sum: 8ac674bbee352e5eee29d3d12df21e8a hexa.cpp [20110308]