// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Thu Jan 20 15:21:48 PST 2011 // Last Modified: Thu Jan 20 15:21:50 PST 2011 // Filename: ...sig/examples/all/chordmark.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/chordmark.cpp // Syntax: C++; museinfo // // Description: Add marks to notes according to their triadic position // in a chord. // #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 "humdrum.h" #include "PerlRegularExpression.h" ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions(Options& opts, int argc, char** argv); void example(void); void usage(const char* command); void chordmark(HumdrumFile& infile); void printHexColor(double color); void printChordMarkInfo(Array<char>& marklevel, Array<Array<double> >& levelcolor, Array<int>& markused); int getRootTrack(HumdrumFile& infile); void markToken(HumdrumFile& infile, int line, int col, int root); void printSubToken(ostream& out, const char* token, int root); int updateRoot(HumdrumFile& infile, int line, int root, int track); // User interface variables: Options options; int debugQ = 0; // used with --debug option Array<char> marklevel; Array<int> markused; Array<Array<double> > levelcolor; ////////////////////////////////////////////////////////////////////////// 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)); } chordmark(infile); cout << infile; printChordMarkInfo(marklevel, levelcolor, markused); return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // printChordMarkInfo -- // void printChordMarkInfo(Array<char>& marklevel, Array<Array<double> >& levelcolor, Array<int>& markused) { int i; for (i=0; i<marklevel.getSize(); i++) { if (marklevel[i] && markused[i]) { cout << "!!!RDF**kern: " << marklevel[i] << "= mark color=\"#"; printHexColor(levelcolor[i][0]); printHexColor(levelcolor[i][1]); printHexColor(levelcolor[i][2]); cout << "\""; switch (i) { case 0: cout << ", root"; break; case 2: cout << ", third"; break; case 4: cout << ", fifth"; break; case 6: cout << ", seventh"; break; case 1: cout << ", ninth/second"; break; case 3: cout << ", eleventh/fourth"; break; case 5: cout << ", thirteenth/sixth"; break; } cout << endl; } } } ////////////////////////////// // // printHexColor -- // void printHexColor(double color) { if (color > 1.0) { color = 1.0; } if (color < 0.0) { color = 0.0; } int icol = (int)(255 * color); int digit1 = icol / 16; int digit2 = icol % 16; char buffer[32] = {0}; sprintf(buffer, "%x%x", digit1, digit2); cout << buffer; } ////////////////////////////// // // chordmark -- add an up/down stem on notes in **kern data which do not // already have stem information. // void chordmark(HumdrumFile& infile) { int roottrack = getRootTrack(infile); int curroot = -1; int i, j; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isData()) { continue; } curroot = updateRoot(infile, i, curroot, roottrack); if (curroot < 0) { // current root is inactive, so don't try to mark notes continue; } for (j=0; j<infile[i].getFieldCount(); j++) { if (!infile[i].isExInterp(j, "**kern")) { continue; } markToken(infile, i, j, curroot); } } } ////////////////////////////// // // markToken -- // void markToken(HumdrumFile& infile, int line, int col, int root) { int& i = line; int& j = col; if (strcmp(infile[i][j], ".") == 0) { // don't mark null tokens return; } if (strchr(infile[i][j], 'r') != NULL) { // don't mark rests return; } if (root < 0) { // root is invalid return; } SSTREAM newmark; int k; char buffer[128] = {0}; int tcount = infile[i].getTokenCount(j); for (k=0; k<tcount; k++) { infile[i].getToken(buffer, j, k, 100); printSubToken(newmark, buffer, root); if (k < tcount - 1) { newmark << ' '; } } infile[i].changeField(j, newmark.CSTRING); } ////////////////////////////// // // printSubToken -- // void printSubToken(ostream& out, const char* token, int root) { int diatonic = Convert::kernToDiatonicPitch(token) % 7; int position = ((diatonic + 70) - root) % 7; out << token; if (marklevel[position]) { markused[position]++; out << marklevel[position]; } } ////////////////////////////// // // updateRoot -- // int updateRoot(HumdrumFile& infile, int line, int root, int track) { int& i = line; int j; for (j=0; j<infile[i].getFieldCount(); j++) { if (track != infile[i].getPrimaryTrack(j)) { continue; } if (strcmp(infile[i][j], ".") == 0) { // nothing to update with return root; } if (strchr(infile[i][j], 'R') != NULL) { // rest, return root off marker return -1; } return Convert::kernToDiatonicPitch(infile[i][j]) % 7; } return root; } ////////////////////////////// // // getRootTrack -- // int getRootTrack(HumdrumFile& infile) { int i, j; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isInterpretation()) { continue; } for (j=0; j<infile[i].getFieldCount(); j++) { if (infile[i].isExInterp(j, "**root")) { return infile[i].getPrimaryTrack(j); } } } cerr << "Could not find root spine\n" << endl; exit(1); } ////////////////////////////// // // 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, 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"); marklevel.setSize(7); marklevel.allowGrowth(0); marklevel.setAll(0); markused.setSize(7); markused.allowGrowth(0); markused.setAll(0); levelcolor.setSize(7); levelcolor.allowGrowth(0); int i; for (i=0; i<levelcolor.getSize(); i++) { levelcolor[i].setSize(3); levelcolor[i].allowGrowth(0); levelcolor[i].setAll(0); } // default coloring: marklevel[0] = 'N'; marklevel[2] = 'U'; marklevel[4] = 'Z'; // Root = red levelcolor[0][0] = 1.0; levelcolor[0][1] = 0.0; levelcolor[0][2] = 0.0; // third = green levelcolor[2][0] = 0.0; levelcolor[2][1] = 0.7; levelcolor[2][2] = 0.0; // fifth = blue levelcolor[4][0] = 0.0; levelcolor[4][1] = 0.7; levelcolor[4][2] = 0.0; // seventh = fuchsia levelcolor[6][0] = 1.0; levelcolor[6][1] = 0.0; levelcolor[6][2] = 1.0; // ninth/second = orange levelcolor[1][0] = 1.0; levelcolor[1][1] = 0.4; levelcolor[1][2] = 0.0; // eleventh/fourth = light blue levelcolor[3][0] = 0.0; levelcolor[3][1] = 1.0; levelcolor[3][2] = 1.0; // thirteenth/sixth = purple levelcolor[5][0] = 0.5; levelcolor[5][1] = 0.0; levelcolor[5][2] = 0.6; } ////////////////////////////// // // example -- example function calls to the program. // void example(void) { } ////////////////////////////// // // usage -- command-line usage description and brief summary // void usage(const char* command) { } // md5sum: c8dee3aebc50cc0e6bf41b03d4397fad chordmark.cpp [20110206]