// // Programmer: Craig Stuart Sapp // Creation Date: Mon Oct 27 10:42:08 PST 2008 // Last Modified: Thu Nov 13 15:32:17 PST 2008 // Filename: ...museinfo/examples/all/themax.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/themax.cpp // Syntax: C++; museinfo // // Description: searches index created by themebuilderx. Themax // is a C++ implementation of the original thema command // which was written by David Huron in 1996/1998, and // modified with a few bug fixes during the implementation // of Themefinder.org by Craig Sapp (1999-2001). // // Classical themebuilder entry order: // fileid [Zz] { # : % } j J M // Additional rhythmic marks: // ~ ^ ! & @ ` ' // // Meaning of the tracer symbols: // [Zz] = major/minor key // { = 12-tone interval // # = pitch refined contour // : = pitch gross contour // % = scale degree // } = musical interval // j = 12-tone pitch // J = absolute pitch // M = metric description // Added rhythmic markers: // ~ = duration gross contour // ^ = duration refined contour // ! = duration (IOI) // & = beat level // @ = metric gross contour // ` = metric refined contour // ' = metric level // // Options: // -a anchor to start (implemented) // -M major keys (implemented) // -m minor keys (implemented) // -t mode (implemented) // -T meter (implemented) // // -i { 12-tone interval (implemented) // -c # refined contour (implemented) // -C : gross contour (implemented) // -d % scale degree (implemented) // -I } musical interval (implemented) // -P j 12-tone pitch class (implemented) // -p J pitch-class name (implamented) // // do assign an option letter: // ~ duration gross contour // ^ duration refined contour // ! duration (IOI) // & beat level // @ metric gross contour // ` metric refined contour // ' metric level // #include "humdrum.h" #ifndef OLDCPP #include #include using namespace std; #else #include #include #endif // character markers in index file: #define PITCH_TWELVE_TONE_INTERVAL_MARKER '{' #define PITCH_REFINED_CONTOUR_MARKER '#' #define PITCH_GROSS_CONTOUR_MARKER ':' #define PITCH_SCALE_DEGREE_MARKER '%' #define PITCH_MUSICAL_INTERVAL_MARKER '}' #define PITCH_TWELVE_TONE_MARKER 'j' #define PITCH_CLASS_MARKER 'J' #define DURATION_GROSS_CONTOUR_MARKER '~' #define DURATION_REFINED_CONTOUR_MARKER '^' #define DURATION_IOI '!' #define BEAT_LEVEL '&' #define METRIC_GROSS_CONTOUR '@' #define METRIC_REFINED_CONTOUR '`' #define METRIC_LEVEL '\'' // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void usage (const string& command); void appendString (string& ss, const string& string); void appendToSearchString (string& ss, const string& string, char marker, int anchor); // User interface variables: Options options; int anchoredQ = 0; // used with -a option int keyfilterQ = 0; // used with -m -M and -t options int minorQ = 0; // used with -m option int majorQ = 0; // used with -M option int debugQ = 0; // used with --debug option int tonicQ = 0; // used with -t option string tonicstring = ""; // used with -t option int meterQ = 0; // used with -T option string meterstring = ""; // used with -T option // classical searches int P12toneintervalQ = 0; // used with -i option int PgrosscontourQ = 0; // used with -c option int PrefinedcontourQ = 0; // used with -C option int PscaledegreeQ = 0; // used with -d option int PmusicalintervalQ = 0; // used with -I option int P12tonepitchclassQ = 0; // used with -P option int PpitchclassQ = 0; // used with -p option string P12toneinterval = ""; // used with -i option string Pgrosscontour = ""; // used with -c option string Prefinedcontour = ""; // used with -C option string Pscaledegree = ""; // used with -d option string Pmusicalinterval = ""; // used with -I option string P12tonepitchclass = ""; // used with -P option string Ppitchclass = ""; // used with -p option // extended rhythm searches int RgrosscontourQ = 0; // used with -R option int RrefinedcontourQ = 0; // used with -r option int RdurationQ = 0; // used with -D option int RbeatlevelQ = 0; // used with -b option int RmetriclevelQ = 0; // used with -L option int RmetricrefinedcontourQ = 0; // used with -e option int RmetricgrosscontourQ = 0; // used with -E option string Rgrosscontour = ""; // used with -R option string Rrefinedcontour = ""; // used with -r option string Rduration = ""; // used with -D option string Rbeatlevel = ""; // used with -b option string Rmetriclevel = ""; // used with -L option string Rmetricrefinedcontour = ""; // used with -e option string Rmetricgrosscontour = ""; // used with -E option ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { checkOptions(options, argc, argv); // process the command-line options string searchstring; string& ss = searchstring; ss.reserve(1000); appendString(ss, "egrep "); // start regular expression string appendString(ss, "'"); // order of data in index file: // [Zz] = major/minor key ////////////////////////////////////////////////// if (keyfilterQ) { if (majorQ && !minorQ) { appendString(ss, "Z"); } else if (minorQ && !majorQ) { appendString(ss, "z"); } else { appendString(ss, "[Zz]"); } // place the tonic search next if given if (tonicQ) { appendString(ss, tonicstring); } else { appendString(ss, "[^=]*"); } // place the end of key information marker: appendString(ss, "=.*"); } // { = 12-tone interval ////////////////////////////////////////////////// if (P12toneintervalQ) { appendToSearchString(ss, P12toneinterval, PITCH_TWELVE_TONE_INTERVAL_MARKER, anchoredQ); } // # = pitch refined contour ///////////////////////////////////////////// if (PrefinedcontourQ) { appendToSearchString(ss, Prefinedcontour, PITCH_REFINED_CONTOUR_MARKER, anchoredQ); } // : = pitch gross contour /////////////////////////////////////////////// if (PgrosscontourQ) { appendToSearchString(ss, Pgrosscontour, PITCH_GROSS_CONTOUR_MARKER, anchoredQ); } // % = scale degree ////////////////////////////////////////////////////// if (PscaledegreeQ) { appendToSearchString(ss, Pscaledegree, PITCH_SCALE_DEGREE_MARKER, anchoredQ); } // } = musical interval ////////////////////////////////////////////////// if (PmusicalintervalQ) { appendToSearchString(ss, Pmusicalinterval, PITCH_MUSICAL_INTERVAL_MARKER, anchoredQ); } // j = 12-tone pitch class /////////////////////////////////////////////// if (P12tonepitchclassQ) { appendToSearchString(ss, P12tonepitchclass, PITCH_TWELVE_TONE_MARKER, anchoredQ); } // J = pitch class name ////////////////////////////////////////////////// if (PpitchclassQ) { appendToSearchString(ss, Ppitchclass, PITCH_CLASS_MARKER, anchoredQ); } // M = metric description //////////////////////////////////////////////// if (meterQ) { appendString(ss, "M"); if (!isdigit(meterstring[0])) { appendString(ss, "[^\t]*"); } appendString(ss, meterstring); appendString(ss, ".*"); } // Added rhythmic markers: // ~ = duration gross contour /////////////////////////////////////////// if (RgrosscontourQ) { appendToSearchString(ss, Rgrosscontour, DURATION_GROSS_CONTOUR_MARKER, anchoredQ); } // ^ = duration refined contour ///////////////////////////////////////// if (RrefinedcontourQ) { appendToSearchString(ss, Rrefinedcontour, DURATION_REFINED_CONTOUR_MARKER, anchoredQ); } // ! = duration (IOI) /////////////////////////////////////////////////// if (RdurationQ) { appendToSearchString(ss, Rduration, DURATION_IOI, anchoredQ); } // & = beat level /////////////////////////////////////////////////////// if (RbeatlevelQ) { appendToSearchString(ss, Rbeatlevel, BEAT_LEVEL, anchoredQ); } // @ = metric gross contour ///////////////////////////////////////////// if (RmetriclevelQ) { appendToSearchString(ss, Rmetriclevel, METRIC_LEVEL, anchoredQ); } // ` = metric refined contour /////////////////////////////////////////// if (RmetricrefinedcontourQ) { appendToSearchString(ss, Rmetricrefinedcontour, METRIC_REFINED_CONTOUR, anchoredQ); } // ' = metric level ///////////////////////////////////////////////////// if (RmetricgrosscontourQ) { appendToSearchString(ss, Rmetricgrosscontour, METRIC_GROSS_CONTOUR, anchoredQ); } ////////////////////////////////////////////////////////////////////////////// // terminate regular expression string appendString(ss, "'"); // add index filename to search appendString(ss, " "); appendString(ss, options.getArgument(1)); if (debugQ) { cout << "### Search string: " << ss << endl; } if (system(NULL)) { if (system(ss.c_str()) == -1) { exit(-1); } } else { cerr << "No command processor available\n"; exit(1); } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // appendToSearchString // void appendToSearchString(string& ss, const string& astring, char marker, int anchor) { char ch; // add back quote for certain markers switch (marker) { case '{': case '}': case '^': ch = '\\'; ss.push_back(ch); } ss.push_back(marker); // add [^\t]* if not anchored: if (!anchor) { appendString(ss, "[^\t]*"); } appendString(ss, astring); // for pitch-class names, the next character after the search // string must be a space or a tab to prevent accidentals // from matching on natural-note search endings. if (marker == PITCH_CLASS_MARKER) { appendString(ss, "[ \t]"); } appendString(ss, ".*"); } ////////////////////////////// // // appendString -- // void appendString(string& ss, const string& astring) { int i; char ch; int length = astring.size(); for (i=0; i=]\n" " -R incipit : identify according to long/short/medium rhythm [LSM]\n" " -s : limit search to structural tones only\n" " -t tonic : limit search to themes in key of \"tonic\" (major or minor)\n" "\n" " Refer to reference manual for further details." <