// // Programmer: Craig Stuart Sapp // Creation Date: Wed Apr 24 20:15:12 PDT 2002 // Last Modified: Sat Jan 24 09:27:33 PST 2004 // Filename: ...sig/examples/all/rism2kern2.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/rism2kern2.cpp // Syntax: C++; museinfo // // Description: Converts RISM II/A Plaine and Easie Code into **kern data. // // Todo: interpret beam groupings (e.g.: 6{ABCD} -> aLL b c dJJ // identify fermatas // interpret trills // handle tuplets // measure repeat indicator // repeat barlines // i,F repetitions // Figure out what ^! means (in RISM 1000117692) // natural sign indicator // clef changes (%F-4 ) // grace notes // acciaccatura notes (q and qq..r types) // // Done: key signature // ties // beam groupings // accidentals (except for naturals, and tied accidentals) // full measure rests (single and multiple) // time signature // // Fixed: initial octave (Sun Jan 25 10:46:10 PST 2004) // Fixed: initial rhythm 6 (Sun Jan 25 10:46:10 PST 2004) // #include "humdrum.h" #include #include #ifndef OLDCPP #include #include using namespace std; #else #include #include #endif typedef Array ArrayChar; ////////////////////////////////////////////////////////////////////////// class NoteObject { public: NoteObject(void) { clear(); }; void clear(void) { pitch = tie = beam = clef = clefnum = 0; wholerest = 0; measureduration = 0.0; duration = 0.0; }; int pitch; double duration; int tie; int beam; int clef; int clefnum; double measureduration; int wholerest; // number of whole rests to process }; ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void usage (const char* command); void convertRism112ToKern (HumdrumFile& hfile, int incipitnum); const char* getKeyInfo (Array& key, HumdrumFile& hfile, int incipitnum); const char* getTimeInfo (Array& timeinfo, HumdrumFile& hfile, int incipitnum); void printKeyInfo (ostream& out, Array& key, const char* keystring); void printTimeInfo (ostream& out, const char* timestring); void generateMusicData (Array& notes, HumdrumFile& infile, Array& key, int incipitnum, double measureduration); void printPitches (ostream& out, Array& notes); int getLineIndex (Array& pieces, const char* string); int getIncipitNumber (HumdrumFile& hfile); const char* getField (const char* field, HumdrumFile& hfile, int incipitnum); double getMeasureDur (Array& timeinfo); int getIncipitCount (HumdrumFile& hfile); const char* getKey (HumdrumFile& hfile, int incipitnum); // User interface variables: Options options; int debugQ = 0; // used with the --debug option ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); HumdrumFile hfile; hfile.read(options.getArg(1)); int incipitnum = getIncipitNumber(hfile); cout << hfile; convertRism112ToKern(hfile, incipitnum); return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // getKey -- // const char* getKey(HumdrumFile& hfile, int incipitnum) { int i; const char* keystring = NULL; for (i=0; i") == 0) { // 2,702 cases return "*B-:"; } else if (strcmp(ptr, "A") == 0) { // 2,634 cases return "*A:"; } else if (strcmp(ptr, "E>") == 0) { // 1,869 cases return "*E-:"; } else if (strcmp(ptr, "g") == 0) { // 1,807 cases return "*g:"; } else if (strcmp(ptr, "d") == 0) { // 1,711 cases return "*d:"; } else if (strcmp(ptr, "a") == 0) { // 1,492 cases return "*a:"; } else if (strcmp(ptr, "c") == 0) { // 797 cases return "*c:"; } else if (strcmp(ptr, "e") == 0) { // 689 cases return "*e:"; } else if (strcmp(ptr, "E") == 0) { // 598 cases return "*E:"; } else if (strcmp(ptr, "f") == 0) { // 253 cases return "*f:"; } else if (strcmp(ptr, "b") == 0) { // 206 cases return "*b:"; } else if (strcmp(ptr, "A>") == 0) { // 78 cases return "*A-:"; } else if (strcmp(ptr, "f#") == 0) { // 47 cases return "*f#:"; } else if (strcmp(ptr, "B") == 0) { // 18 cases return "*B:"; } else if (strcmp(ptr, "c#") == 0) { // 7 cases return "*c#:"; } else if (strcmp(ptr, "Bb") == 0) { // 7 cases return "*B-:"; } else if (strcmp(ptr, "Eb") == 0) { // 7 cases return "*E-:"; } else if (strcmp(ptr, "D>") == 0) { // 5 cases return "*D-:"; } else if (strcmp(ptr, "F#") == 0) { // 4 cases return "*F#:"; } else if (strcmp(ptr, "e>") == 0) { // 4 cases return "*e-:"; } else if (strcmp(ptr, "b>") == 0) { // 3 cases return "*b-:"; } else if (strcmp(ptr, "g#") == 0) { // 1 case return "*g#:"; } else if (strcmp(ptr, "G#") == 0) { // 1 case return "*G#:"; } else if (strcmp(ptr, "G>") == 0) { // 1 case return "*G-:"; } return "*X4:"; } ////////////////////////////// // // getIncipitNumber -- // int getIncipitNumber(HumdrumFile& hfile) { int i; int output = 0; int count = 0; const char* ptr = NULL; for (i=0; i notes; Array key(7); Array timeinfo(2); timeinfo.setAll(0); key.setAll(0); const char* keystring = getKeyInfo(key, hfile, incipitnum); const char* timestring = getTimeInfo(timeinfo, hfile, incipitnum); const char* a112 = getField("112A", hfile, incipitnum); int incipitcount = getIncipitCount(hfile); int length; int jj; if (incipitnum > 0) { cout << "**kern\n"; if (incipitcount > 1) { cout << "!! Incipit number: " << incipitnum << "/" << incipitcount << " ("; length = strlen(a112); for (jj=0; jj& timeinfo) { return timeinfo[0] * timeinfo[1]; } ////////////////////////////// // // generateMusicData -- // void generateMusicData(Array& notes, HumdrumFile& hfile, Array& key, int incipitnum, double measureduration) { notes.setSize(0); NoteObject tempnote; const char* musicdata = getField("112F", hfile, incipitnum); int length = strlen(musicdata); // measure octave at each position in the data string Array octave; octave.setSize(length); octave.setAll(0); int i; if (musicdata[0] == '\'') { octave[0] = 1; } else if (musicdata[0] == ',') { octave[0] = -1; } for (i=1; i acc; acc.setSize(length); acc.setAll(0); // measure accidentals at each position in the data string for (i=0; i=0) && (musicdata[i]-'A'<7)) { acc[i] = currentacc; currentacc = 0; } } // calculate slur information Array tempslur; tempslur.setSize(length); tempslur.setAll(0); int lasti = 0; int ii; for (i=0; i= 0) && (musicdata[i] - 'A' < 7)) { lasti = i; } else if (musicdata[i] == '+') { if (tempslur[lasti]) { tempslur[lasti] = 3; } else { tempslur[lasti] = 1; } for (ii=i; ii= 0) && (musicdata[ii]-'A'<7)) { tempslur[ii] = 2; i = ii; break; } } } } // calculate beam grouping information Array tempbeam; tempbeam.setSize(length); tempbeam.setAll(0); lasti = 0; for (i=0; i= 0) && (musicdata[i] - 'A' < 7)) { lasti = i; } else if (musicdata[i] == '}') { tempbeam[lasti] = 2; } else if (musicdata[i] == '{') { for (ii=i; ii= 0) && (musicdata[ii]-'A'<7)) { tempbeam[ii] = 1; i = ii; lasti = i; break; } } } } // calculate durations for all positions in data string Array duration; duration.setSize(length); duration.setAll(0.0); int dots = 0; double basedur = 0.0; for (i=0; i 0) { duration[i] = duration[i-1] + basedur * pow(2.0, -dots); } break; default: dots = 0; if (i > 0) { duration[i] = duration[i-1]; } break; } } // adjust for tuplet durations here... Array kkey; kkey.setSize(key.getSize()); for (i=0; i 0) { kkey[i] = +1; } else { kkey[i] = 0; } } int wholerestcount = 0; int accidental; Array mkey(7); mkey = kkey; int natural = 0; int pitch; for (i=0; i 5) { // accidental = 0; natural = 1; } pitch = 1000; switch (musicdata[i]) { case 'A': if (accidental != 0) { if (natural) { pitch = 31 + 40 * octave[i]; mkey[4] = 0; natural = 0; } else { pitch = 31 + 40 * octave[i] + accidental; mkey[4] = accidental; } } else { pitch = 31 + 40 * octave[i] + mkey[4]; } break; case 'B': if (accidental != 0) { if (natural) { pitch = 37 + 40 * octave[i]; mkey[6] = 0; natural = 0; } else { pitch = 37 + 40 * octave[i] + accidental; mkey[6] = accidental; } } else { pitch = 37 + 40 * octave[i] + mkey[6]; } break; case 'C': if (accidental != 0) { if (natural) { pitch = 2 + 40 * octave[i]; mkey[1] = 0; natural = 0; } else { pitch = 2 + 40 * octave[i] + accidental; mkey[1] = accidental; } } else { pitch = 2 + 40 * octave[i] + mkey[1]; } break; case 'D': if (accidental != 0) { if (natural) { pitch = 8 + 40 * octave[i]; mkey[3] = 0; natural = 0; } else { pitch = 8 + 40 * octave[i] + accidental; mkey[3] = accidental; } } else { pitch = 8 + 40 * octave[i] + mkey[3]; } break; case 'E': if (accidental != 0) { if (natural) { pitch = 14 + 40 * octave[i]; mkey[5] = 0; natural = 0; } else { pitch = 14 + 40 * octave[i] + accidental; mkey[5] = accidental; } } else { pitch = 14 + 40 * octave[i] + mkey[5]; } break; case 'F': if (accidental != 0) { if (natural) { pitch = 19 + 40 * octave[i]; mkey[0] = 0; natural = 0; } else { pitch = 19 + 40 * octave[i] + accidental; mkey[0] = accidental; } } else { pitch = 19 + 40 * octave[i] + mkey[0]; } break; case 'G': if (accidental != 0) { if (natural) { pitch = 25 + 40 * octave[i]; mkey[2] = 0; natural = 0; } else { pitch = 25 + 40 * octave[i] + accidental; mkey[2] = accidental; } } else { pitch = 25 + 40 * octave[i] + mkey[2]; } break; case '/': pitch = 0; break; case '-': pitch = -1000; break; case '=': pitch = -1000; wholerestcount = 1; if (isdigit(musicdata[i+1])) { sscanf(&(musicdata[i+1]), "%d", &wholerestcount); // warning: possible error -- maybe need to increment // pointer to the value after the whole rest count // incase there is no rhythm marker before the next pitch. } break; default: break; } if (pitch < 1000) { tempnote.pitch = pitch; tempnote.duration = duration[i]; tempnote.tie = tempslur[i]; tempnote.beam = tempbeam[i]; tempnote.wholerest = wholerestcount; tempnote.measureduration = measureduration; notes.append(tempnote); } } } ////////////////////////////// // // printPitches -- // void printPitches(ostream& out, Array& notes) { char buffer[1024] = {0}; int i, ii; for (i=0; i endindex; endindex.setSize(100); endindex.setSize(0); endindex.allowGrowth(); if (incipitnum == 0) { return ""; } int count = 0; int i; for (i=0; i=0; i--) { if (strncmp(hfile[i][0], "!!!RISM-112", 11) != 0) { break; } else if ((i < endindex[incipitnum-1]) && (strncmp(hfile[i][0], "!!!RISM-112F", 12) == 0)) { break; } else if (strncmp(hfile[i][0], searchstring, length) == 0) { output = hfile[i][1]; break; } } return output; } ////////////////////////////// // // getTimeInfo -- read the key signature. // const char* getTimeInfo(Array& timeinfo, HumdrumFile& hfile, int incipitnum) { const char* timeline = getField("112E", hfile, incipitnum); const char* output = "*M4/4"; if (strcmp(timeline, "&C;") == 0) { // 19,511 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0; output = "*M4/4\n*met(C)"; } else if (strcmp(timeline, "3/4;") == 0) { // 7,733 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0; output = "*M3/4"; } else if (strcmp(timeline, "2/4;") == 0) { // 6,873 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0; output = "*M2/4"; } else if (strcmp(timeline, "\"&alla\";") == 0) { // 6,865 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2\n*met(C|)"; } else if (strcmp(timeline, "\"&alla;\"") == 0) { // 6,865 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2\n*met(C|)"; } else if (strcmp(timeline, "\"&alla;\";") == 0) { // 6,865 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2\n*met(C|)"; } else if (strcmp(timeline, "6/8;") == 0) { // 3,855 cases timeinfo[0] = 6.0; timeinfo[1] = 4.0/8.0; output = "*M6/8"; } else if (strcmp(timeline, "3/8;") == 0) { // 2,789 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/8.0; output = "*M3/8"; } else if (strcmp(timeline, "[3/4];") == 0) { // 1,742 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0; output = "*M3/4\n!! inferred meter"; } else if (strcmp(timeline, "[&C];") == 0) { // 824 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0; output = "*M4/4\n*met(C)\n!! inferred meter"; } else if (strcmp(timeline, "[4/2];") == 0) { // 794 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/2.0; output = "*M4/2\n!! inferred meter"; } else if (strcmp(timeline, "[2/2];") == 0) { // 778 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2\n!! inferred meter"; } else if (strcmp(timeline, "3/2;") == 0) { // 689 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/2.0; output = "*M3/2"; } else if (strcmp(timeline, "12/8;") == 0) { // 482 cases timeinfo[0] = 12.0; timeinfo[1] = 4.0/8.0; output = "*M12/8"; } else if (strcmp(timeline, "\"[&alla;]\";") == 0) { // 417 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2\n*met(C|)\n!! inferred meter"; } else if (strcmp(timeline, "[3/2];") == 0) { // 374 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/2.0; output = "*M3/2\n!! inferred meter"; } else if (strcmp(timeline, "[2/2];") == 0) { // 272 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/4.0; output = "*M2/4\n!! inferred meter"; } else if (strcmp(timeline, "6/4;") == 0) { // 196 cases timeinfo[0] = 6.0; timeinfo[1] = 4.0/4.0; output = "*M6/4"; } else if (strcmp(timeline, "[6/8];") == 0) { // 169 cases timeinfo[0] = 6.0; timeinfo[1] = 4.0/8.0; output = "*M6/8\n!! inferred meter"; } else if (strcmp(timeline, "[6/4];") == 0) { // 157 cases timeinfo[0] = 6.0; timeinfo[1] = 4.0/4.0; output = "*M6/4\n!! inferred meter"; } else if (strcmp(timeline, "[3/8];") == 0) { // 123 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/8.0; output = "*M3/8\n!! inferred meter"; } else if (strcmp(timeline, "9/8;") == 0) { // 82 cases timeinfo[0] = 9.0; timeinfo[1] = 4.0/8.0; output = "*M9/8"; } else if (strcmp(timeline, "2/2;") == 0) { // 80 cases timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0; output = "*M2/2"; } else if (strcmp(timeline, "[6/2];") == 0) { // 42 cases timeinfo[0] = 6.0; timeinfo[1] = 4.0/2.0; output = "*M6/2\n!! inferred meter"; } else if (strcmp(timeline, "[3/1];") == 0) { // 36 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/1.0; output = "*M3/1\n!! inferred meter"; } else if (strcmp(timeline, "4/4;") == 0) { // 35 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0; output = "*M4/4"; } else if (strcmp(timeline, "3/1;") == 0) { // 33 cases timeinfo[0] = 3.0; timeinfo[1] = 4.0/1.0; output = "*M3/1"; } else if (strcmp(timeline, "[4/4];") == 0) { // 18 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0; output = "*M4/4\n!! inferred meter"; } else if (strcmp(timeline, "4/8;") == 0) { // 10 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/8.0; output = "*M4/8"; } else if (strcmp(timeline, "4/2;") == 0) { // 7 cases timeinfo[0] = 4.0; timeinfo[1] = 4.0/2.0; output = "*M4/2"; } else if (strcmp(timeline, "12/16;") == 0) { // 7 cases timeinfo[0] = 12.0; timeinfo[1] = 4.0/16.0; output = "*M12/16"; } else if (strcmp(timeline, "[12/8];") == 0) { // 6 cases timeinfo[0] = 12.0; timeinfo[1] = 4.0/8.0; output = "*M12/8\n!! inferred meter"; } else if (strcmp(timeline, "8/8;") == 0) { // 5 cases timeinfo[0] = 8.0; timeinfo[1] = 4.0/8.0; output = "*M8/8"; } else { timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0; output = "!! unknown meter"; } /* Other time signature cases not yet processed 4 &c; 3 [9/8]; 3 9/4; 3 6/16; 3 [4/8]; 3 [12/4]; 2 [&C/31]; 2 &C 2/4; 2 "&alla; [2/2]"; 2 9/16; 2 6/8-3/8; 2 [4/1]; 2 2/8; 2 24/16; 2 0; 2 [?]; 1 C6/8; 1 C6/4; 1 C/3/4; 1 &C,3/4; 1 C3/2; 1 &Alla.; 1 &alla.; 1 &alla; 1 &alla,; 1 "[&alla;?]"; 1 [9/4]; 1 [9/2]; 1 [6/8; 1 [6/16]; 1 5/4; 1 2/1; 1 [2/1]; 1 11/4; // weird time signatures 1 [?&C/3?]; 1 bB; 1 "&alla;/3i"; 1 2/3; 1 31; 1 [?3/1?]; 1 !3/4!; 1 3/8 [6/8]; 1 2 [2/4]; 1 2/4[3/4]; 8 &C 3/8; 3 &C/31; 3 [&C/3]; 5 03; 128 3; 37 \; 36 2; 18 &C/3; 15 [3]; 1 0/3; */ return output; } ////////////////////////////// // // getKeyInfo -- read the key signature. // const char* getKeyInfo(Array& key, HumdrumFile& hfile, int incipitnum) { const char* keyline = getField("112D", hfile, incipitnum); // at the key information line, extract data int type = 1; // 1 = sharps, 2 = flats int paren = 1; // 1 = normal, 2 = inside of square brackets int length = strlen(keyline); int i = 0; while (i < length) { switch (keyline[i]) { case 'b': type = -1; break; case 'x': type = 1; break; case '[': paren = 2; break; case ']': paren = 1; break; case 'F': key[0] = type * paren; break; case 'C': key[1] = type * paren; break; case 'G': key[2] = type * paren; break; case 'D': key[3] = type * paren; break; case 'A': key[4] = type * paren; break; case 'E': key[5] = type * paren; break; case 'B': key[6] = type * paren; break; case ' ': break; default: if (debugQ) { cout << "Error: unknown character: " << keyline[i] << endl; exit(1); } break; } i++; } return keyline; } ////////////////////////////// // // printTimeInfo -- // void printTimeInfo(ostream& out, const char* timestring) { out << timestring; int length = strlen(timestring); if (length > 0 && timestring[length-1] != '\n') { out << "\n"; } } ////////////////////////////// // // printKeyInfo -- not worrying about mixed sharp/flat key sigs // for now... // void printKeyInfo(ostream& out, Array& key, const char* keystr) { //if (keystr[0] != '\0') { // out << "!! Key signature: " << keystr << "\n"; //} out << "*k["; if (key[0] > 0) { if (key[0] > 0) out << "f#"; else if (key[0] < 0) out << "f-"; if (key[1] > 0) out << "c#"; else if (key[0] < 0) out << "c-"; if (key[2] > 0) out << "g#"; else if (key[0] < 0) out << "g-"; if (key[3] > 0) out << "d#"; else if (key[0] < 0) out << "d-"; if (key[4] > 0) out << "a#"; else if (key[0] < 0) out << "a-"; if (key[5] > 0) out << "e#"; else if (key[0] < 0) out << "e-"; if (key[6] > 0) out << "b#"; else if (key[0] < 0) out << "b-"; } else { if (key[6] < 0) out << "b-"; else if (key[0] > 0) out << "b#"; if (key[5] < 0) out << "e-"; else if (key[0] > 0) out << "e#"; if (key[4] < 0) out << "a-"; else if (key[0] > 0) out << "a#"; if (key[3] < 0) out << "d-"; else if (key[0] > 0) out << "d#"; if (key[2] < 0) out << "g-"; else if (key[0] > 0) out << "g#"; if (key[1] < 0) out << "c-"; else if (key[0] > 0) out << "c#"; if (key[0] < 0) out << "f-"; else if (key[0] > 0) out << "g#"; } out << "]" << endl; } ////////////////////////////// // // checkOptions -- // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("debug=b", "print debug information"); 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, April 2002" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 24 April 2002" << 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); } debugQ = opts.getBoolean("debug"); } ////////////////////////////// // // example -- // void example(void) { } ////////////////////////////// // // usage -- // void usage(const char* command) { } ////////////////////////////// // // getLineIndex -- get the index location of the given string. // int getLineIndex(Array& pieces, const char* string) { int index = -1; int i; for (i=0; i