// // Programmer: Craig Stuart Sapp // Creation Date: Thu Nov 30 16:41:05 PST 2000 // Last Modified: Wed Dec 6 20:06:55 PST 2000 // Last Modified: Tue Dec 19 11:15:53 PST 2000 (arbitrary part #s (L values)) // Filename: ...sig/examples/all/mustran2kern.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/mustran2kern.cpp // Syntax: C++; museinfo // // Description: Converts MUSTRAN musical data into Humdrum **kern data. // #include "humdrum.h" #include #include #include #ifndef OLDCPP #include #include #include #define SSTREAM stringstream #define CSTRING str().c_str() using namespace std; #else #include #include #ifdef VISUAL #include /* for Windows 95 */ #else #include #endif #define SSTREAM strstream #define CSTRING str() #endif void parseLine(void); void parseHeader(void); void parseData(void); void parseItem(char* data); void parseNoteData(char* data, char* notebuffer); void clearaccidentals(void); int checkforpart(void); void parseChord(char* data, char* chordbuffer); void printKern(int pitch, int octave, int clef, char* buffer); void printHfiles(Array& hfiles); void combineLines(Array& hfiles); void fixties(HumdrumFile& file); void getTiedPitches(Array& pitchcount, Array& tiedPitches, HumdrumRecord& record); void setTies(Array& pitchcount, Array& tiedPitches, HumdrumRecord& record); #define ACCIDENTAL_SIZE 7 int accidental[ACCIDENTAL_SIZE] = {0}; int tupletQ = 0; int tuplettype = 0; int tupletmatch = 0; int part = 0; int clef = 0; int chordQ = 0; int suppressQ = 0; char tbuffer[10000] = {0}; char notebuffer[10000] = {0}; char linebuffer[100000] = {0}; int length = 0; Array partindex; // interface variables: Options options; int combineQ = 1; // used with the -s option // function declarations: void checkOptions (Options& opts, int argc, char* argv[]); Array hfiles; HumdrumFile header; int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); if (options.getArgCount() != 1) { cout << "Usage: " << options.getCommand() << " inputfile " << endl; exit(1); } hfiles.setSize(1000); hfiles.setSize(0); partindex.setSize(1000); partindex.setSize(0); partindex.allowGrowth(1); #ifndef OLDCPP fstream infile(options.getArg(1), ios::in); #else fstream infile(options.getArg(1), ios::in | ios::nocreate); #endif if (!infile.is_open()) { cout << "Error: cannot open file for reading: " << options.getArg(1) << endl; exit(1); } char *buffer = linebuffer; while (infile.getline(buffer, 100000, '\n')) { if (buffer[0] != '\0') { parseLine(); } if (infile.eof()) { break; } // cout << "Line " << line++ << ":\t" << buffer << endl; } int i; for (i=0; igetNumLines() - 1][0], "*-") != 0) { hfiles[0]->appendLine("*-"); } if (hfiles.getSize() > 1 && combineQ) { combineLines(hfiles); } else { printHfiles(hfiles); } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("A|no-assemble=b"); // don't assemble analyses 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, December 2000" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 2 December 2000" << 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); } if (opts.getBoolean("no-assemble")) { combineQ = 0; } else { combineQ = 1; } } ////////////////////////////// // // fixties -- // void fixties(HumdrumFile& file) { Array pitchcount(1000); pitchcount.zero(); int i; int j = 0; Array tielines; tielines.setSize(file.getNumLines()); tielines.zero(); tielines.allowGrowth(0); // find the lines with ties, and how many there are on each line for (i=file.getNumLines()-1; i>=0; i--) { if (file[i].getType() != E_humrec_data) { continue; } if (strstr(file[i][0], "]") != NULL) { length = strlen(file[i][0]); for (j=0; j tiedPitches; int tieSearch = 0; // int tieLine = -1; for (i=file.getNumLines()-1; i>=0; i--) { if (file[i].getType() != E_humrec_data) { continue; } if (tieSearch) { // looking for ties, and this line does not have any new ties // there will be no continued ties. // all previous ties should be accounted for on this line. setTies(pitchcount, tiedPitches, file[i]); tieSearch = 0; } if (tieSearch == 0 && tielines[i] != 0) { // not previously looking for ties, but here is a line with them tieSearch = 1; // tieLine = i; getTiedPitches(pitchcount, tiedPitches, file[i]); continue; } if (tieSearch == 0 && tielines[i] == 0) { // prevent bugs in the data from propagating pitchcount.zero(); tiedPitches.zero(); } } } ////////////////////////////// // // setTies -- // void setTies(Array& pitchcount, Array& tiedPitches, HumdrumRecord& record) { static char buffer[10000] = {0}; char tbuffer[128] = {0}; buffer[0] = '\0'; int tokenCount = record.getTokenCount(0); int pitch; int match = 0; int m; int j; for (m=0; m& pitchcount, Array& tiedPitches, HumdrumRecord& record) { tiedPitches.setSize(0); tiedPitches.allowGrowth(1); char buffer[128] = {0}; int j; int pitch; int tokenCount = record.getTokenCount(0); for (j=0; j& hfiles) { HumdrumFile output; int i; for (i=0; ianalyzeSpines(); } HumdrumFile::assemble(output, hfiles.getSize(), hfiles.getBase()); cout << header; cout << output; } ////////////////////////////// // // printHfiles -- // void printHfiles(Array& hfiles) { cout << header; for (int i=0; i 1) { // cout << "==\n*-\n\n"; hfiles[part-2]->appendLine("=="); hfiles[part-2]->appendLine("*-"); } // cout << "**kern\n!part" << oldpart << endl; hfiles[part-1]->appendLine("**kern"); sprintf(tbuffer, "!part%d", oldpart); hfiles[part-1]->appendLine(tbuffer); } // cout << " measure = " << measure << "\tfor part " << part << endl; if (measure > 1) { // cout << "=" << measure << endl; sprintf(tbuffer, "=%d", measure); hfiles[part-1]->appendLine(tbuffer); } parseData(); } } ////////////////////////////// // // checkforpart -- // int checkforpart(void) { int i; for (i=0; i "; parseItem(data); if (!suppressQ) { // cout << endl; } suppressQ = 0; data = strtok(NULL, ","); } } ////////////////////////////// // // parseItem -- // void parseItem(char* data) { static char chordbuffer[10000] = {0}; if (toupper(data[0]) == 'L') { // sscanf(data, "L%d", &part); // cout << "part number = " << partindex[part-1] << endl; suppressQ = 1; return; } if (strchr(data, '(') != 0) { // cout << "start of tuplet"; tupletQ = 1; int flag = sscanf(data, "%d", &tuplettype); if (flag != 1) { cout << "Error no starting tuplet indicator" << endl; exit(1); } int i = data - linebuffer;; while (linebuffer[i] != ')' && i < length) { i++; } if (linebuffer[i] != ')') { cout << "\nError: no ending to tuplet " << endl; exit(1); } i--; if (!isdigit(linebuffer[i])) { cout << "\nError: no ending tuplet value" << endl; exit(1); } while (isdigit(linebuffer[i])) { i--; } i++; sscanf(&linebuffer[i], "%d", &tupletmatch); // cout << ": " << tuplettype << " in the time of " << tupletmatch; suppressQ = 1; return; } if (strchr(data, ')') != 0) { // cout << "end of tuplet"; tupletQ = 0; suppressQ = 1; return; } if (strcmp(data, "GS") == 0) { // cout << "treble clef"; // cout << "*clefG2"; hfiles[part-1]->appendLine("*clefG2"); clef = 0; return; } if (strcmp(data, "FS") == 0) { // cout << "bass clef"; // cout << "*clefF4"; hfiles[part-1]->appendLine("*clefF4"); clef = 1; return; } if (strchr(data, '=') != NULL) { int top; int bottom; sscanf(data, "%d=%d", &top, &bottom); // cout << "Time signature: " << top << '/' << bottom; // cout << "*M" << top << "/" << bottom; sprintf(tbuffer, "*M%d/%d", top, bottom); hfiles[part-1]->appendLine(tbuffer); return; } if (strcmp(data, "/") == 0 || strncmp(data, "/ ", 2) == 0) { // cout << "End of measure marker"; clearaccidentals(); suppressQ = 1; return; } if (strncmp(data, "//", 2) == 0) { // cout << "End of piece marker"; // cout << "==\n*-"; hfiles[part-1]->appendLine("=="); hfiles[part-1]->appendLine("*-"); clearaccidentals(); suppressQ = 1; return; } if (strncmp(data, "END", 3) == 0) { // cout << "End of piece assertion"; clearaccidentals(); suppressQ = 1; return; } if (strchr(data, 'Y') != 0) { chordQ = 1; parseChord(data, chordbuffer); hfiles[part-1]->appendLine(chordbuffer); chordQ = 0; return; } parseNoteData(data, notebuffer); hfiles[part-1]->appendLine(notebuffer); } ////////////////////////////// // // parseChord -- // void parseChord(char* data, char* chordbuffer) { char* note; chordbuffer[0] = '\0'; int tlen = strlen(data); int i = 0; int count = 1; int rcount = 0; for (i=0; i 0) { if (rcount == 1) { // cout << " (and " << rcount << " rest)"; } else { // cout << " (and " << rcount << " rests)"; } } // cout << endl; note = data; int xcount = 0; while (xcount < count) { i = 0; xcount++; // cout << "\t _"; // cout << note; // cout << "_\t chord "; parseNoteData(note, notebuffer); strcat(chordbuffer, notebuffer); if (count != xcount) { // cout << endl; // cout << " "; strcat(chordbuffer, " "); } while(note[i] != '\0') { i++; } i++; note += i; } } ////////////////////////////// // // clearaccidentals -- // void clearaccidentals(void) { for (int i=0; i