// // Programmer: Craig Stuart Sapp // Creation Date: Wed Apr 24 20:15:12 PDT 2002 // Last Modified: Wed Apr 24 20:15:15 PDT 2002 // Filename: ...sig/examples/all/rism2kern.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/rism2kern.cpp // Syntax: C++; museinfo // // Description: Converts RISM II/A Plaine and Easie Code into **kern data. // // Todo: expand beam groupings // identify fermatas // interpret trills // handle tuplets // measure repeat indicator // repeat barlines // !,F repetitions // natural sign indicator // clef changes (%F-4 ) // full measure rests (single and multiple) // time signature // grace notes // acciaccatura notes (q and qq..r types) // // Done: key signature // ties // beam groupings // accidentals (except for naturals, and tied accidentals) // #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; duration = 0.0; }; int pitch; double duration; int tie; int beam; int clef; int clefnum; }; ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void usage (const char* command); void convertRism789ToKern (HumdrumFile& hfile, const char* line789); void getPieces (Array& pieces, const char* line); void getKeyInfo (Array& key, Array& pieces); void printKeyInfo (ostream& out, Array& key, Array& pieces); void generateMusicData (Array& notes, Array& pieces, Array& key); void printPitches (ostream& out, Array& notes); int getLineIndex (Array& pieces, const char* string); // 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; #ifndef OLDCPP ifstream infile(options.getArg(1)); #else ifstream infile(options.getArg(1), ios::nocreate); #endif if (!infile.is_open()) { cout << "Error: cannot open file: " << options.getArg(1) << endl; exit(1); } char line[2048] = {0}; while (!infile.eof()) { while (!infile.eof() && strncmp(line, "!!!marc789:", 11) != 0) { infile.getline(line, 1024, '\n'); } if (strncmp(line, "!!!marc789:", 11) == 0) { convertRism789ToKern(hfile, line); } infile.getline(line, 1024, '\n'); } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // convertRism789ToKern -- // void convertRism789ToKern(HumdrumFile& hfile, const char* line789) { // cout << "LINE: " << line789 << endl; Array pieces; getPieces(pieces, line789); // cout << "There are " << pieces.getSize() << " subfields" << endl; // for (int i=0; i notes; Array key(7); key.setAll(0); getKeyInfo(key, pieces); generateMusicData(notes, pieces, key); cout << "**kern\n"; printKeyInfo(cout, key, pieces); printPitches(cout, notes); cout << "*-\n\n"; } ////////////////////////////// // // generateMusicData -- // void generateMusicData(Array& notes, Array& pieces, Array& key) { notes.setSize(0); NoteObject tempnote; int index = getLineIndex(pieces, "$h"); if (index == -1) { return; } cout << "PAEDATA: " << pieces[index].getBase() << endl; int length = strlen(pieces[index].getBase()); // measure octave at each position in the data string Array octave; octave.setSize(length); octave.setAll(0); int i; 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) && (pieces[index][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) && (pieces[index][i] - 'A' < 7)) { lasti = i; } else if (pieces[index][i] == '+') { if (tempslur[lasti]) { tempslur[lasti] = 3; } else { tempslur[lasti] = 1; } for (ii=i; ii= 0) && (pieces[index][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) && (pieces[index][i] - 'A' < 7)) { lasti = i; } else if (pieces[index][i] == '}') { tempbeam[lasti] = 2; } else if (pieces[index][i] == '{') { for (ii=i; ii= 0) && (pieces[index][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=1; i kkey; kkey.setSize(key.getSize()); for (i=0; i 0) { kkey[i] = +1; } else { kkey[i] = 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 (pieces[index][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; break; default: break; } if (pitch < 1000) { tempnote.pitch = pitch; tempnote.duration = duration[i]; tempnote.tie = tempslur[i]; tempnote.beam = tempbeam[i]; notes.append(tempnote); } } } ////////////////////////////// // // printPitches -- // void printPitches(ostream& out, Array& notes) { char buffer[1024] = {0}; int i; for (i=0; i& key, Array& pieces) { int i; for (i=0; i= pieces.getSize()) { return; } int line = i; int length = strlen(pieces[line].getBase()); for (i=0; i= length) { return; } // cout << "Key: " << &pieces[line][i] << "\t=\t"; // at the key information line, extract data int type = 1; // 1 = sharps, 2 = flats int paren = 1; // 1 = normal, 2 = inside of square brackets while (i < length) { switch (pieces[line][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: " << pieces[line][i] << endl; exit(1); } break; } i++; } } ////////////////////////////// // // printKeyInfo -- not worrying about mixed sharp/flat key sigs // for now... // void printKeyInfo(ostream& out, Array& key, Array& pieces) { int i; for (i=0; i 1) { out << "!! Key signature"; ptr = strchr(pieces[pline].getBase(), ':'); if (ptr != NULL) { out << ptr; } out << "\n"; break; } } } 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; } ////////////////////////////// // // getPieces -- // void getPieces(Array& pieces, const char* line) { // count the number of $ signs in line int count = 0; int i; int length = strlen(line); for (i=0; i& pieces, const char* string) { int index = -1; int i; for (i=0; i