// // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Creation Date: Wed Dec 3 11:13:50 PST 2008 // Last Modified: Wed Dec 3 11:13:55 PST 2008 // Filename: ...museinfo/examples/all/hokey2humdrum.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/hokey2humdrum.cpp // Syntax: C++ // // Description: Convert Hokey XML data files into Humdrum files. // #include "humdrum.h" #define TIXML_USE_STL #include "tinyxml.h" #include <iostream> #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 typedef const char* charstar; void printToHumdrum(ostream& out, const char* filename); void convertToHumdrum(HumdrumFile& outfile, TiXmlNode* node); void printHeaderInformation(ostream& out, TiXmlNode* node, double& offset, int& mtop, int& mbot, double& repeat, charstar& keyinfo); void printHumdrumPart(ostream& out, TiXmlNode* node, int stem); void printKernNote(ostream& out, TiXmlNode* node, int stem); void printKernRest(ostream& out, TiXmlNode* node, int stem); int getBase40FromHokeyPitch(const char* string); double printRhythm(ostream& out, int dtop, int dbot); void printbarline(ostream& out, int barcounter, int voices, const char* barstyle); void printKeyInfo(ostream& out, const char* keyinfo, int voices); void printAllSpines(ostream& out, int voices, const char* string); void addTies(HumdrumFile& outfile); void fillNullToken(HumdrumFile& outfile, int line, int spine); void makeNewToken(char* newstring, const char* oldstring, const char* rhythm, int tiestate); void addBeaming(HumdrumFile& outfile, int spine); #define STEMDEFAULT 0 #define STEMUP 1 #define STEMDOWN 2 #define TIENONE 0 #define TIESTART 1 #define TIEEND 2 /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { int i; for (i=1; i<argc; i++) { printToHumdrum(std::cout, argv[i]); } return 0; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////// // // printToHumdrum -- // void printToHumdrum(ostream& out, const char* filename) { TiXmlDocument doc(filename); int status = doc.LoadFile(); HumdrumFile outfile; if (status) { convertToHumdrum(outfile, &doc); } else { cout << "Failed to load file " << filename << "\n"; exit(1); } out << outfile; } ////////////////////////////// // // printHeaderInformation -- // void printHeaderInformation(ostream& out, TiXmlNode* node, double& offset, int& mtop, int& mbot, double& repeat, charstar& keyinfo) { node = node->FirstChild(); offset = 0; mtop = mbot = 0; const char* index = ""; const char* title = ""; const char* offsetT = ""; const char* repeatT = ""; int count; TiXmlText* textnode; while (node != NULL) { if (strcmp(node->Value(), "title") == 0) { textnode = node->FirstChild()->ToText(); title = textnode->Value(); } else if (strcmp(node->Value(), "index") == 0) { textnode = node->FirstChild()->ToText(); index = textnode->Value(); } else if (strcmp(node->Value(), "key") == 0) { textnode = node->FirstChild()->ToText(); keyinfo = textnode->Value(); } else if (strcmp(node->Value(), "start-time") == 0) { textnode = node->FirstChild()->ToText(); offsetT = textnode->Value(); } else if (strcmp(node->Value(), "repeat-time") == 0) { textnode = node->FirstChild()->ToText(); repeatT = textnode->Value(); } else if (strcmp(node->Value(), "meter") == 0) { textnode = node->FirstChild()->ToText(); count = sscanf(textnode->Value(), "%d/%d/", &mtop, &mbot); if (count != 2) { cerr << "ERROR in time signature " << textnode->Value() << endl; exit(1); } } node = node->NextSibling(); } if (title[0] != '\0') { out << "!!!COM:\t" << "Bach, Johann Sebastian" << "\n"; out << "!!!CDT:\t" << "1685/02/21/-1750/07/28/" << "\n"; out << "!!!OTL:\t" << title << "\n"; } if (index[0] != '\0') { out << "!!!ONM:\t" << index << "\n"; out << "!!!AGN:\t" << "chorale" << "\n"; } if (offsetT[0] != '\0') { int top = 0; int bot = 0; sscanf(offsetT, "%d/%d", &top, &bot); offset = (double)top / (double)bot * 4.0; } if (repeatT[0] != '\0') { int rtop = 0; int rbot = 0; sscanf(repeatT, "%d/%d", &rtop, &rbot); repeat = (double)rtop / (double)rbot * 4.0; } if ((mtop == 0) || (mbot == 0)) { cerr << "ERROR unspecified time signature" << endl; exit(1); } } ////////////////////////////// // // getHumdrumPart -- // void printHumdrumPart(ostream& out, TiXmlNode* node, int stem) { node = node->FirstChild(); out << "**kern\n"; while (node != NULL) { if (strcmp(node->Value(), "note") == 0) { printKernNote(out, node, stem); out << "\n"; } else if (strcmp(node->Value(), "rest") == 0) { printKernRest(out, node, stem); out << "\n"; } else { cerr << "Unknown ELEMENT <" << node->Value() << endl; exit(1); } node = node->NextSibling(); } out << "*-\n"; } /////////////////////////////// // // getBase40FromHokeyPitch -- // int getBase40FromHokeyPitch(const char* string) { int length = strlen(string); if (length == 0) { return 0; } int octave = 0; int count; int i; char string2[1024] = {0}; strcpy(string2, string); for (i=0; i<length; i++) { if (isdigit(string2[i])) { count = sscanf(string2 + i, "%d", &octave); if (count != 1) { cerr << "ERROR in pitch octave" << endl; exit(1); } string2[i] = '\0'; } } int diatonic; switch (string2[0]) { case 'A': case 'a': diatonic = 5; break; case 'B': case 'b': diatonic = 6; break; case 'C': case 'c': diatonic = 0; break; case 'D': case 'd': diatonic = 1; break; case 'E': case 'e': diatonic = 2; break; case 'F': case 'f': diatonic = 3; break; // careful: f is also a flat case 'G': case 'g': diatonic = 4; break; default: cerr << "ERROR IN DIATONIC PITCH NAME " << string2 << endl; exit(1); } int accidentals = 0; for (i=1; i<length; i++) { if (string[i] == 's') { accidentals++; } else if (string[i] == 'f') { accidentals--; } } int output = 0; switch (diatonic) { case 0: output = 0; break; case 1: output = 6; break; case 2: output = 12; break; case 3: output = 17; break; case 4: output = 23; break; case 5: output = 29; break; case 6: output = 35; break; } output = output + 2 + accidentals; return output + 40 * octave; } ////////////////////////////// // // printKernNote -- // void printKernNote(ostream& out, TiXmlNode* node, int stem) { TiXmlText* textnode; node = node->FirstChild(); int dtop = 0; int dbot = 0; int base40 = 0; int count; int fermata = 0; int tiestart = 0; int tiecontinue = 0; int tieend = 0; double duration; while (node != NULL) { // cout << "ELEMENT " << node->Value() << endl; if (strcmp(node->Value(), "fermata") == 0) { fermata = 1; } else if (strcmp(node->Value(), "tiestart") == 0) { tiestart = 1; } else if (strcmp(node->Value(), "tiecontinue") == 0) { tiecontinue = 1; } else if (strcmp(node->Value(), "tieend") == 0) { tieend = 1; } else if (strcmp(node->Value(), "duration") == 0) { textnode = node->FirstChild()->ToText(); count = sscanf(textnode->Value(), "%d/%d", &dtop, &dbot); if (count != 2) { cerr << "Error parsing rhythm: " << textnode->Value() << endl; exit(1); } } else if (strcmp(node->Value(), "pitch") == 0) { textnode = node->FirstChild()->ToText(); base40 = getBase40FromHokeyPitch(textnode->Value()); } node = node->NextSibling(); } if (dtop == 0 || dbot == 0 || base40 == 0) { cerr << "SOME SORT OF ERROR" << endl; cerr << "dtop =\t" << dtop << endl; cerr << "dbot =\t" << dbot << endl; cerr << "base40 =\t" << base40 << endl; exit(1); } if (tiestart) { out << "["; } duration = printRhythm(out, dtop, dbot); char buffer[1024] = {0}; out << Convert::base40ToKern(buffer, base40); if (fermata) { out << ";"; } if (tiecontinue) { out << "_"; } else if (tieend) { out << "]"; } if (duration < 4.0) { // only print stem info if less than whole note if (stem == STEMUP) { out << "/"; } else if (stem == STEMDOWN) { out << "\\"; } } } ////////////////////////////// // // printRhythm -- // double printRhythm(ostream& out, int dtop, int dbot) { double duration = (double)dtop / (double) dbot; duration *= 4.0; char buffer[1024] = {0}; out << Convert::durationToKernRhythm(buffer, duration); return duration; } ////////////////////////////// // // printKernRest -- // void printKernRest(ostream& out, TiXmlNode* node, int stem) { TiXmlText* textnode; node = node->FirstChild(); int dtop = 0; int dbot = 0; int base40 = 0; int count; int fermata = 0; double duration; while (node != NULL) { // cout << "ELEMENT " << node->Value() << endl; if (strcmp(node->Value(), "fermata") == 0) { fermata = 1; } else if (strcmp(node->Value(), "duration") == 0) { textnode = node->FirstChild()->ToText(); count = sscanf(textnode->Value(), "%d/%d", &dtop, &dbot); if (count != 2) { cerr << "Error parsing rhythm: " << textnode->Value() << endl; exit(1); } } else if (strcmp(node->Value(), "pitch") == 0) { textnode = node->FirstChild()->ToText(); base40 = getBase40FromHokeyPitch(textnode->Value()); } node = node->NextSibling(); } if (dtop == 0 || dbot == 0 || base40 != 0) { cerr << "SOME SORT OF ERROR 2" << endl; cerr << "dtop =\t" << dtop << endl; cerr << "dbot =\t" << dbot << endl; cerr << "base40 =\t" << base40 << endl; exit(1); } duration = printRhythm(out, dtop, dbot); out << "r"; if (fermata) { out << ";"; } } /////////////////////////////// // // convertToHumdrum -- // void convertToHumdrum(HumdrumFile& outfile, TiXmlNode* node) { SSTREAM headerstream; // deal with printing it out later SSTREAM sopranostream; SSTREAM altostream; SSTREAM tenorstream; SSTREAM bassstream; if (node->Type() != TiXmlNode::DOCUMENT) { cout << "ERROR not at start of document" << endl; exit(1); } node = node->FirstChild(); if ((strcmp(node->Value(), "chorale") != 0)) { cout << "ERROR did not find <chorale> marker" << endl; exit(1); } node = node->FirstChild(); if ((strcmp(node->Value(), "info") != 0)) { cout << "ERROR did not find <info> marker" << endl; exit(1); } double offset = 0; // for keeping track of pickup-measures int mtop = 0; // top of timesignature; int mbot = 0; // bottom of timesignature; const char* keyinfo = ""; double repeat = 0; printHeaderInformation(headerstream, node, offset, mtop, mbot, repeat, keyinfo); node = node->NextSibling(); if ((strcmp(node->Value(), "satb") != 0)) { cout << "ERROR did not find <satb> marker" << endl; exit(1); } node = node->FirstChild(); if ((strcmp(node->Value(), "soprano") != 0)) { cout << "ERROR did not find <soprano> marker" << endl; exit(1); } //printHumdrumPart(std::cout, node, STEMUP); printHumdrumPart(sopranostream, node, STEMUP); node = node->NextSibling(); if ((strcmp(node->Value(), "alto") != 0)) { cout << "ERROR did not find <satb> marker" << endl; exit(1); } printHumdrumPart(altostream, node, STEMDOWN); node = node->NextSibling(); if ((strcmp(node->Value(), "tenor") != 0)) { cout << "ERROR did not find <satb> marker" << endl; exit(1); } printHumdrumPart(tenorstream, node, STEMUP); node = node->NextSibling(); if ((strcmp(node->Value(), "bass") != 0)) { cout << "ERROR did not find <satb> marker" << endl; exit(1); } printHumdrumPart(bassstream, node, STEMDOWN); Array<HumdrumFile> parts; parts.setSize(4); parts.allowGrowth(0); headerstream << ends; sopranostream << ends; altostream << ends; tenorstream << ends; bassstream << ends; // change order when making single part to a spine // look for "check the next line of spine order changes" below as well parts[3].read(altostream); parts[2].read(sopranostream); parts[1].read(bassstream); parts[0].read(tenorstream); outfile.clear(); HumdrumFile::assemble(outfile, 4, parts.getBase()); outfile.analyzeRhythm("4"); SSTREAM newout; int repeatQ = 0; if (repeat > 0) { repeatQ = 1; } int barcounter = 1; double bardur = 4.0 * mtop / mbot; double nextbartime = bardur - offset; if (nextbartime >= bardur) { nextbartime = 0; barcounter = -1; } double absbeat; newout << headerstream.CSTRING; int i, j; int voices = outfile.getMaxTracks(); for (i=0; i<outfile.getNumLines(); i++) { switch (outfile[i].getType()) { case E_humrec_data_comment: newout << outfile[i] << "\n"; break; case E_humrec_data_kern_measure: newout << outfile[i] << "\n"; break; case E_humrec_interpretation: if (strncmp(outfile[i][0], "**", 2) == 0) { // (temporarily place two voices on each staff) newout << "**kern\t**kern\n"; newout << "*^\t*^\n"; newout << "*clefF4\t*clefF4\t*clefG2\t*clefG2\n"; // check the next line of spine order changes newout << "!tenor\t!bass\t!soprano\t!alto\n"; if (repeatQ) { printAllSpines(newout, voices, "*>[A,A,B]"); printAllSpines(newout, voices, "*>norep[A,A,B]"); printAllSpines(newout, voices, "*>A"); } printKeyInfo(newout, keyinfo, voices); // print meter: for (j=0; j<voices; j++) { newout << "*M" << mtop << "/" << mbot; if (j < voices - 1) { newout << "\t"; } } newout << "\n"; printAllSpines(newout, voices, "*MM100"); } else if (strcmp(outfile[i][0], "*-") == 0) { // (temporarily place two voices on each staff) newout << "*v\t*v\t*\t*\n"; newout << "*\t*v\t*v\n"; newout << "*-\t*-\n"; } else { newout << outfile[i] << "\n"; } break; case E_humrec_data: absbeat = outfile[i].getAbsBeat(); if (repeatQ && (repeat-offset <= absbeat)) { repeatQ = 0; if (nextbartime <= absbeat) { printbarline(newout, barcounter, voices, ":|!"); printAllSpines(newout, voices, "*>B"); barcounter = abs(barcounter); barcounter++; nextbartime += bardur; } else { printbarline(newout, -100, voices, ":|!"); printAllSpines(newout, voices, "*>B"); } } else if (nextbartime <= absbeat) { printbarline(newout, barcounter, voices, ""); barcounter = abs(barcounter); barcounter++; nextbartime += bardur; } newout << outfile[i] << "\n"; if (strcmp(outfile[i+1][0], "*-") == 0) { printbarline(newout, -100, voices, "="); } break; case E_humrec_none: case E_humrec_empty: case E_humrec_global_comment: case E_humrec_bibliography: default: newout << outfile[i] << "\n"; break; } } newout << "!!!hum2abc: -Q ''\n"; newout << "!!!title: @{ONM}. @{OTL}\n"; newout << ends; outfile.clear(); outfile.read(newout); outfile.analyzeRhythm("4"); addTies(outfile); outfile.analyzeRhythm("4"); addBeaming(outfile, 0); addBeaming(outfile, 1); addBeaming(outfile, 2); addBeaming(outfile, 3); } ////////////////////////////// // // addBeaming -- // void addBeaming(HumdrumFile& outfile, int spine) { Array<int> noterow; noterow.setSize(outfile.getNumLines()); noterow.setSize(0); Array<double> durs; durs.setSize(outfile.getNumLines()); durs.setSize(0); double duration; Array<int> beats; beats.setSize(outfile.getNumLines()); beats.setSize(0); int beat; int i; for (i=0; i<outfile.getNumLines(); i++) { if (outfile[i].getType() != E_humrec_data) { continue; } if (strcmp(outfile[i][spine], ".") == 0) { continue; } if (strchr(outfile[i][spine], 'r') != NULL) { continue; } duration = Convert::kernToDuration(outfile[i][spine]); if (fabs(duration - 0.5) < 0.001) { duration = 0.5; } if (fabs(duration - 0.25) < 0.001) { duration = 0.25; } if (duration <= 0.0) { continue; } beat = (int)(outfile[i].getAbsBeat() + 0.0001); beats.append(beat); durs.append(duration); noterow.append(i); } char buffer1[1024] = {0}; char buffer2[1024] = {0}; char buffer3[1024] = {0}; for (i=0; i<beats.getSize(); i++) { if (durs[i] >= 1.0) { continue; } if (i >= beats.getSize()-1) { continue; } if (beats[i] != beats[i+1]) { continue; } if (durs[i+1] >= 1.0) { continue; } if (strchr(outfile[noterow[i]][spine], 'L') != NULL) { continue; } if (strchr(outfile[noterow[i]][spine], 'J') != NULL) { continue; } if ((durs[i] == 0.5) && (durs[i+1] == 0.5)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcat(buffer1, "L"); strcat(buffer2, "J"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); continue; } if ((durs[i] == 0.75) && (durs[i+1] == 0.25)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcat(buffer1, "L"); strcat(buffer2, "Jk"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); continue; } if ((durs[i] == 0.25) && (durs[i+1] == 0.75)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcat(buffer1, "LK"); strcat(buffer2, "J"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); continue; } if (i >= beats.getSize()-2) { continue; } if ((beats[i] != beats[i+2]) || durs[i+2] >= 1.0) { if ((durs[i] == 0.25) && (durs[i+1] == 0.25)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcat(buffer1, "LL"); strcat(buffer2, "JJ"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); continue; } continue; } if ((durs[i] == 0.5) && (durs[i+1] == 0.25) && (durs[i+2] == 0.25)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcpy(buffer3, outfile[noterow[i+2]][spine]); strcat(buffer1, "L"); strcat(buffer2, "L"); strcat(buffer3, "JJ"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); outfile[noterow[i+2]].changeField(spine, buffer3); continue; } if ((durs[i] == 0.25) && (durs[i+1] == 0.25) && (durs[i+2] == 0.5)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+1]][spine]); strcpy(buffer3, outfile[noterow[i+2]][spine]); strcat(buffer1, "LL"); strcat(buffer2, "J"); strcat(buffer3, "J"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+1]].changeField(spine, buffer2); outfile[noterow[i+2]].changeField(spine, buffer3); continue; } if (i >= beats.getSize()-3) { continue; } if ((beats[i] != beats[i+3]) || durs[i+3] >= 1.0) { continue; } if ((durs[i] == 0.25) && (durs[i+1] == 0.25) && (durs[i+2] == 0.25) && (durs[i+3] == 0.25)) { strcpy(buffer1, outfile[noterow[i]][spine]); strcpy(buffer2, outfile[noterow[i+3]][spine]); strcat(buffer1, "LL"); strcat(buffer2, "JJ"); outfile[noterow[i]].changeField(spine, buffer1); outfile[noterow[i+3]].changeField(spine, buffer2); continue; } cout << "GOT HERE" << endl; } } ////////////////////////////// // // addTies -- // void addTies(HumdrumFile& outfile) { int i, j; int measureQ = 0; for (i=0; i<outfile.getNumLines(); i++) { if (outfile[i].getType() == E_humrec_data_measure) { measureQ = 1; } else if (measureQ && (outfile[i].getType() == E_humrec_data)) { for (j=0; j<outfile[i].getFieldCount(); j++) { if (strcmp(outfile[i][j], ".") == 0) { fillNullToken(outfile, i, j); } } measureQ = 0; } } } ////////////////////////////// // // fillNullToken -- // void fillNullToken(HumdrumFile& outfile, int line, int spine) { int row = outfile[line].getDotLine(spine); int col = outfile[line].getDotSpine(spine); double dur = Convert::kernToDuration(outfile[row][col]); double firstdur = outfile[line].getAbsBeat() - outfile[row].getAbsBeat(); double seconddur = dur - firstdur; char rhythm1[1024] = {0}; Convert::durationToKernRhythm(rhythm1, firstdur); char rhythm2[1024] = {0}; Convert::durationToKernRhythm(rhythm2, seconddur); char oldstring[1024] = {0}; strcpy(oldstring, outfile[row][col]); char newstring[1024] = {0}; makeNewToken(newstring, oldstring, rhythm1, TIESTART); outfile[row].changeField(col, newstring); makeNewToken(newstring, oldstring, rhythm2, TIEEND); outfile[line].changeField(spine, newstring); } ////////////////////////////// // // makeNewToken -- replace the old duration with a new one, and add // tie start/end marks as needed. Assumes that the token is not // a chord. // void makeNewToken(char* newstring, const char* oldstring, const char* rhythm, int tiestate) { char single[2] = {0}; single[1] = '\0'; newstring[0] = '\0'; int restQ = 0; if (strchr(oldstring, 'r') != NULL) { restQ = 1; } if (tiestate == TIESTART) { if (!restQ) { strcat(newstring, "["); } } int rhythmfound = 0; int i; int tieprinted = 0; int len = strlen(oldstring); for (i=0; i<len; i++) { if (isdigit(oldstring[i]) || (oldstring[i] == '.')) { if (rhythmfound == 0) { strcat(newstring, rhythm); rhythmfound = 1; } } else if ((tiestate == TIEEND) && ((oldstring[i] == '/') || (oldstring[i] == '\\'))) { if (!restQ) { strcat(newstring, "]"); } tieprinted = 1; } else if ((tiestate == TIESTART) && (oldstring[i] == ';')) { // don't do anything: suppress fermata on first of tied notes } else { single[0] = oldstring[i]; strcat(newstring, single); } } if ((tieprinted == 0) && (tiestate == TIEEND)) { if (!restQ) { strcat(newstring, "]"); } } } ////////////////////////////// // // printKeyInfo -- // void printKeyInfo(ostream& out, const char* keyinfo, int voices) { char buffer[1024] = {0}; strcpy(buffer, keyinfo); char* ptr1; char* ptr2; ptr1 = strtok(buffer, "-"); ptr2 = strtok(NULL, "-"); if ((ptr1 == NULL) || (ptr2 == NULL)) { cerr << "ERROR in key " << keyinfo << endl; exit(1); } int base40 = getBase40FromHokeyPitch(ptr1) % 40; int octave = 3; // major by default if (strcmp(ptr2, "Minor") == 0) { octave = 4; } else if (strcmp(ptr2, "Dorian") == 0) { octave = 4; } else if (strcmp(ptr2, "Phrygian") == 0) { octave = 4; } else if (strcmp(ptr2, "Locrian") == 0) { octave = 4; } base40 = base40 + octave * 40; char tempstring[1024] = {0}; char keyname[1024] = {0}; Convert::base40ToKern(tempstring, base40); strcpy(keyname, "*"); strcat(keyname, tempstring); strcat(keyname, ":"); int keynumber = 0; if (strcmp(keyname, "*C-:") == 0) { keynumber = -7; } else if (strcmp(keyname, "*G-:") == 0) { keynumber = -6; } else if (strcmp(keyname, "*D-:") == 0) { keynumber = -5; } else if (strcmp(keyname, "*A-:") == 0) { keynumber = -4; } else if (strcmp(keyname, "*E-:") == 0) { keynumber = -3; } else if (strcmp(keyname, "*B-:") == 0) { keynumber = -2; } else if (strcmp(keyname, "*F:") == 0) { keynumber = -1; } else if (strcmp(keyname, "*C:") == 0) { keynumber = 0; } else if (strcmp(keyname, "*G:") == 0) { keynumber = +1; } else if (strcmp(keyname, "*D:") == 0) { keynumber = +2; } else if (strcmp(keyname, "*A:") == 0) { keynumber = +3; } else if (strcmp(keyname, "*E:") == 0) { keynumber = +4; } else if (strcmp(keyname, "*B:") == 0) { keynumber = +5; } else if (strcmp(keyname, "*F#:") == 0) { keynumber = +6; } else if (strcmp(keyname, "*C#:") == 0) { keynumber = +7; } // minor keys else if (strcmp(keyname, "*a-:") == 0) { keynumber = -7; } else if (strcmp(keyname, "*e-:") == 0) { keynumber = -6; } else if (strcmp(keyname, "*b-:") == 0) { keynumber = -5; } else if (strcmp(keyname, "*f:") == 0) { keynumber = -4; } else if (strcmp(keyname, "*c:") == 0) { keynumber = -3; } else if (strcmp(keyname, "*g:") == 0) { keynumber = -2; } else if (strcmp(keyname, "*d:") == 0) { keynumber = -1; } else if (strcmp(keyname, "*a:") == 0) { keynumber = 0; } else if (strcmp(keyname, "*e:") == 0) { keynumber = +1; } else if (strcmp(keyname, "*b:") == 0) { keynumber = +2; } else if (strcmp(keyname, "*f#:") == 0) { keynumber = +3; } else if (strcmp(keyname, "*c#:") == 0) { keynumber = +4; } else if (strcmp(keyname, "*g#:") == 0) { keynumber = +5; } else if (strcmp(keyname, "*d#:") == 0) { keynumber = +6; } else if (strcmp(keyname, "*a#:") == 0) { keynumber = +7; } // adjust based on the mode if (strcmp(ptr2, "Dorian") == 0) { // add one sharp to the minor mode (e.g. one flat to natural for D Dorian) keynumber++; } else if (strcmp(ptr2, "Phrygian") == 0) { // subtract one (E minor has one sharp, E phrygian has no sharps) keynumber--; } else if (strcmp(ptr2, "Lydian") == 0) { // add a sharp keynumber++; } else if (strcmp(ptr2, "Mixolydian") == 0) { // subtract a sharp keynumber--; } else if (strcmp(ptr2, "Locrian") == 0) { // subtract 5 sharps keynumber-=5; } // cerr << "BASE-40 " << base40 << endl; // cerr << "KEY-NAME " << keyname << endl; // cerr << "KEY-NUMBER " << keynumber << endl; const char* keystring = Convert::keyNumberToKern(keynumber); int i; // first print the key signature for (i=0; i<voices; i++) { out << keystring; if (i < voices - 1) { out << "\t"; } } out << "\n"; // next print the key (major or minor part) for (i=0; i<voices; i++) { out << keyname; if (i < voices - 1) { out << "\t"; } } out << "\n"; if (strcmp(ptr2, "Dorian") == 0) { printAllSpines(out, voices, "*KDor"); } else if (strcmp(ptr2, "Phrygian") == 0) { printAllSpines(out, voices, "*KPhr"); } else if (strcmp(ptr2, "Lydian") == 0) { printAllSpines(out, voices, "*KLyd"); } else if (strcmp(ptr2, "Mixolydian") == 0) { printAllSpines(out, voices, "*KMix"); } else if (strcmp(ptr2, "Locrian") == 0) { printAllSpines(out, voices, "*KLoc"); } // finally print the mode if not major or minor } ////////////////////////////// // // printAllSpines -- // void printAllSpines(ostream& out, int voices, const char* string) { int i; for (i=0; i<voices; i++) { out << string; if (i < voices - 1) { out << "\t"; } } out << "\n"; } ////////////////////////////// // // printbarline -- // void printbarline(ostream& out, int barcounter, int voices, const char* barstyle) { char number[1024] = {0}; if (barcounter == -1) { strcat(number, "1-"); } else if (barcounter > 0) { sprintf(number, "%d", barcounter); } int i; for (i=0; i<voices; i++) { out << "=" << number << barstyle; if (i < voices - 1) { out << "\t"; } } out << "\n"; } // md5sum: de629c4e12fae751a17b0b52551a4a3e hokey2humdrum.cpp [20081221]