// // Programmer: Craig Stuart Sapp // Creation Date: Tue Jun 5 13:48:27 PDT 2001 // Last Modified: Tue Jun 5 13:48:29 PDT 2001 // Last Modified: Fri Feb 25 00:09:19 PST 2005 Balanced markers // Last Modified: Tue Dec 12 20:23:42 PST 2006 Handling > and < as text // Last Modified: Tue Nov 22 07:08:10 PST 2011 Fixed grace noteshapes // Last Modified: Tue Jun 26 15:13:50 PDT 2012 Added time-modification f/tuplets // Last Modified: Tue Jun 26 17:06:38 PDT 2012 Bug fixes f/multi-voice treatment // Last Modified: Fri Jul 3 14:41:16 PDT 2015 Added colored marker export // Filename: ...sig/examples/all/hum2xml.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/hum2xml.cpp // Syntax: C++; museinfo // // Description: Converts a Humdrum file into MusicXML. // #include "humdrum.h" #include "PerlRegularExpression.h" #include "RationalNumber.h" #include #include #include #include #include #include #include // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void convertToMusicXML (HumdrumFile& infile); int makePartList (HumdrumFile& infile); void makePart (HumdrumFile& infile, int start, int col, int count); void generatePartInfo (HumdrumFile& infile, int start, int col, int count); void convertDataToMusicXML (HumdrumFile& infile, int line, int col, int voice); void convertMeasureToXML (HumdrumFile& infile, int line, int col, int voice); void convertAttributeToXML (HumdrumFile& infile, int line, int col, int voice); void convertNoteToXML (HumdrumFile& infile, int line, int col, int voice); void pline (int level, const char* string, ostream& out = cout); void usage (const char* command); double convertNoteEntryToXML (HumdrumFile& infile, int line, int col, const char* buffer, int chord, int vlevel, int voice); void checkMeasure (void); void printDurationType (const string& durstring); void printDots (const char* durstring); void adjustKey (int keyinfo); void checkAccidentals (int diatonic, int alter, int chord); void updateAccidentals (void); void printGlobalComments (HumdrumFile& infile, int direction); void printGlobalComment (HumdrumFile& infile, int line); void printBibliography (HumdrumFile& infile, int line); void checkbackup (int currenttick, int targettick); void processTextUnderlay (HumdrumFile& infile, int line, int col); void displayUnknownTextType(HumdrumFile& infile, int line, int col, int verse); void displayLyrics (HumdrumFile& infile, int line, int col, int verse); void displayHTMLText (const char* buffer); void processBeams (HumdrumFile& infile, int line, int col, const char* buffer, int vlevel); void setLineTicks (vector& LineTick, HumdrumFile& infile, int divisions); void getBarlines (vector& barlines, HumdrumFile& infile); void convertMeasureToMusicXML(HumdrumFile& infile, int track, int startbar, int endbar); int getMaxVoice (HumdrumFile& infile, int track, int startline, int endline); void convertVoice (HumdrumFile& infile, int track, int startbar, int endbar, int voice); void printMode (int lev, HumdrumFile& infile, int line, int col, int voice); int adjustKeyInfo (HumdrumFile& infile, int line, int col, int voice); void setColorCharacters (HumdrumFile& infile, string& colorchar, vector& colorout); string checkColor (const char* note, string& colorchar, vector& colorout); void convertBnumForNote (ostream& out, HumdrumFile& infile, int line, int col); void convertBassoContinuoFigureGroup(ostream& out, HumdrumFile& infile, int line, int col); void convertBassoContinuoFigure(ostream& out, HumdrumFile& infile, int line, int col); void convertBassoContinuoFigureSingle(ostream& out, const char* figure); int checkForAnotherFigure (ostream& out, HumdrumFile& infile, int oline, int line, int ktrack, int btrack); // User interface variables: Options options; int debugQ = 0; // used with the --debug option int cautionaryQ = 1; // used with the --nocaution option int reverseQ = 0; // reverse the ordering of the parts int lev = 0; // indentation level in output text int minit = 0; // at start of each part: if measure is active double smallestdur = 1.0; // smallest durational component in the music int divisions = 1; // number of divisions per beat int measurestate = 0; // 0 = measure is not open, 1 = measure open int v1lastmeasure[7] = {0}; // for explicit accidentals ABCDEFG int v1states[7] = {0}; // for explicit accidentals ABCDEFG int v1key[7] = {0}; // for explicit accidentals ABCDEFG int v1chord[7] = {0}; // for explicit accidentals ABCDEFG int v1prechordstates[7] = {0}; // for explicit accidentals ABCDEFG int AbsTick = 0; // for commands vector LineTick; // for and commands int beamlevel[128] = {0}; // for beaming information int musicstart = 0; // for suppressing bars before music starts // int attributes = 0; // for suppressing multiple attributes entries vector Barlines; int ClefOctaveTranspose = 0; // used to fix bug in MusicXML vocal tenor clef notes string Colorchar; // charcter in **kern data which causes color vector Colorcode; // color code that the marker indicates ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); // figure out the number of input files to process int numinputs = options.getArgCount(); HumdrumFile infile; for (int i=0; i& barlines, HumdrumFile& infile) { barlines.clear(); barlines.reserve(infile.getNumLines()); int i; int datafoundQ = 0; // int exinterpline = 0; for (i=0; i& LineTick, HumdrumFile& infile, int divisions) { LineTick.resize(infile.getNumLines()); RationalNumber rat; int i; for (i=0; i // // // MusicXML 0.3 (alpha) header: // // // // void convertToMusicXML(HumdrumFile& infile) { pline (lev, "\n"); pline (lev, "\n"); // previous xml declaration: // pline(lev, "\n"); // pline(lev, "\n"); printGlobalComments(infile, 1); // pline(lev, "\n"); pline(lev, "\n"); vector kerntracks; infile.getTracksByExInterp(kerntracks, "**kern"); int count = makePartList(infile); int start = 0; // should be the start of exclusive interpretation line // (but setting to zero). int gcount = 0; int i; if (!reverseQ) { // print parts in reverse order because Humdrum scores are printed lowest // part first going towards highest, but MusicXML is from highest to lowest. for (i=(int)kerntracks.size()-1; i>=0 ;i--) { makePart(infile, start, kerntracks[i], ++gcount); } } else { // print reverse because Humdrum score is probably reversed for (i=0; i<(int)kerntracks.size(); i++) { makePart(infile, start, kerntracks[i], ++gcount); } } lev = 0; pline(lev, "\n"); printGlobalComments(infile, -1); if (count != (int)kerntracks.size()) { cerr << "Error in generating parts: number of parts has changed: " << count << endl; } } ////////////////////////////// // // printGlobalComments -- // void printGlobalComments(HumdrumFile& infile, int direction) { int start = 0; int stop = infile.getNumLines(); int i; if (direction == 1) { start = 0; i = 0; while (i < infile.getNumLines()) { if (strncmp(infile[i][0], "**", 2) == 0) { stop = i; break; } i++; } } else { stop = infile.getNumLines() - 1; i = stop; while (i >= 0) { if (strcmp(infile[i][0], "*-") == 0) { start = i; break; } i--; } } for (i=start; i<=stop; i++) { switch (infile[i].getType()) { case E_humrec_global_comment: printGlobalComment(infile, i); break; case E_humrec_bibliography: printBibliography(infile, i); break; } } } ////////////////////////////// // // printGlobalComment -- // void printGlobalComment(HumdrumFile& infile, int line) { pline(lev, "\n"; } ////////////////////////////// // // printBibliography -- // void printBibliography(HumdrumFile& infile, int line) { char buffer[1024] = {0}; strcpy(buffer, infile[line][0]); int i = 0; while (buffer[i] != '\0') { if (buffer[i] == ':') { buffer[i] = '\0'; i++; if (buffer[i] == ' ') { buffer[i] = '\0'; i++; } break; } i++; } if (i == 0) return; // Handle stupid XML parsers which find "--" within a comment and choke: string newvalue = &buffer[i]; PerlRegularExpression pre; pre.sar(newvalue, "--", "--", "g"); pline(lev, "\n"; } ////////////////////////////// // // makePart -- ggg // void makePart(HumdrumFile& infile, int start, int track, int count) { // spine == track ? cout << "\n"; pline(lev, "\n"; lev++; minit = 0; musicstart = 0; AbsTick = 0; ClefOctaveTranspose = 0; // reset any clef transposition from previous part checkMeasure(); lev++; pline(lev, "\n"); // attributes = 1; lev++; pline(lev, ""); cout << divisions << "\n"; lev--; pline(lev, "\n"); // att lev--; // att int i; for (i=0; i<(int)Barlines.size()-1; i++) { convertMeasureToMusicXML(infile, track, Barlines[i], Barlines[i+1]); } /* int i; int j; int testtrack; for (i=start+1; i\n"); measurestate = 0; } lev--; pline(lev, "\n"); } ////////////////////////////// // // convertMeasureToMusicXML -- // void convertMeasureToMusicXML(HumdrumFile& infile, int track, int startbar, int endbar) { int maxVoice = getMaxVoice(infile, track, startbar, endbar); //cout << "" << endl; int voice; for (voice=1; voice<=maxVoice; voice++) { convertVoice(infile, track, startbar, endbar, voice); } } ////////////////////////////// // // convertVoice -- // void convertVoice(HumdrumFile& infile, int track, int startbar, int endbar, int voice) { // off by one for some reason endbar = endbar - 1; int i, j, t, v; int start = startbar; if (voice > 1) { // don't print measure information for secondary voices start++; } for (i=start; i<=endbar; i++) { v = 0; for (j=0; j maxv) { maxv = count; } } return maxv; } ////////////////////////////// // // convertDataToMusicXML -- // void convertDataToMusicXML(HumdrumFile& infile, int line, int col, int voice) { if (debugQ) { cout << "\n"; } switch(infile[line].getType()) { case E_humrec_none: case E_humrec_empty: case E_humrec_global_comment: case E_humrec_bibliography: case E_humrec_data_comment: break; case E_humrec_data_kern_measure: convertMeasureToXML(infile, line, col, voice); break; case E_humrec_interpretation: convertAttributeToXML(infile, line, col, voice); break; case E_humrec_data: musicstart = 1; convertNoteToXML(infile, line, col, voice); break; default: break; } } ////////////////////////////// // // updateAccidentals -- restore accidentals at a measure boundary. // void updateAccidentals(void) { // copy v1states to v1lastmeasure // and fill v1states with v1key int i; for (i=0; i<7; i++) { v1lastmeasure[i] = v1states[i]; v1states[i] = v1key[i]; } } ////////////////////////////// // // convertMeasureToXML -- // void convertMeasureToXML(HumdrumFile& infile, int line, int col, int voice) { int measureno = -1; if (!musicstart) { return; } updateAccidentals(); const char *ptr; /* int nextline = -1; int nextcol = -1; int track = infile[line].getPrimaryTrack(col); // locate the next barline int i, j; for (i=line+1; i 0) { for (j=0; j= 0) && (nextcol >= 0)) { nextbar = infile[nextline][nextcol]; } */ if ((strncmp(infile[line][col], "==", 2) == 0) || (strcmp(infile[line][col], "*-") == 0)) { checkbackup(AbsTick, LineTick[line]); lev++; pline(lev, "\n"); lev++; pline(lev, "light-heavy\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); measurestate = 0; } else if ((ptr = strchr(infile[line][col], ':')) != NULL) { if ((ptr+1)[0] == '|' || (ptr+1)[0] == '!') { lev++; pline(lev, "\n"); lev++; if (strstr(infile[line][col], ":|!") != NULL) { pline(lev, "light-heavy\n"); } else if (strstr(infile[line][col], ":||") != NULL) { pline(lev, "light-light\n"); } else if (strstr(infile[line][col], ":!") != NULL) { pline(lev, "heavy\n"); } else if (strstr(infile[line][col], ":|") != NULL) { pline(lev, "light\n"); } pline(lev, "\n"); lev--; pline(lev, "\n"); lev--; } } else if (strstr(infile[line][col], "||") != NULL) { checkbackup(AbsTick, LineTick[line]); lev++; pline(lev, "\n"); lev++; pline(lev, "light-light\n"); lev--; pline(lev, "\n"); lev--; } if (strcmp(infile[line+1][0], "*-") == 0) { return; } checkbackup(AbsTick, LineTick[line]); if (minit != 0) { if (measurestate != 0) { pline(lev, "\n"); measurestate = 0; } } minit++; if (sscanf(infile[line][col], "=%d", &measureno)) { pline(lev, "\n"; measurestate = 1; } else if (strncmp(infile[line][col], "=", 1) == 0) { if (infile.getTotalDuration() > infile[line].getAbsBeat()) { // don't start a new measure if we are at the end of the music pline(lev, "\n"; measurestate = 1; } } if ((ptr = strchr(infile[line][col], ':')) != NULL) { if ((ptr-1)[0] == '|' || (ptr-1)[0] == '!') { lev++; pline(lev, "\n"); lev++; if (strstr(infile[line][col], ":|!") != NULL) { pline(lev, "light-heavy\n"); } else if (strstr(infile[line][col], ":||") != NULL) { pline(lev, "light-light\n"); } else if (strstr(infile[line][col], ":!") != NULL) { pline(lev, "heavy\n"); } else if (strstr(infile[line][col], ":|") != NULL) { pline(lev, "light\n"); } pline(lev, "\n"); lev--; pline(lev, "\n"); lev--; } } } ////////////////////////////// // // checkMeasure -- // void checkMeasure(void) { if (minit == 0) { minit++; pline(lev, "\n"; measurestate = 1; } } ////////////////////////////// // // adjustKey -- replace the old key signature with a new one // void adjustKey(int keyinfo) { int i; for (i=0; i<7; i++) { v1key[i] = 0; } if (keyinfo < 0) { v1key['B' - 'A'] = -1; if (keyinfo < -1) v1key['E' - 'A'] = -1; if (keyinfo < -2) v1key['A' - 'A'] = -1; if (keyinfo < -3) v1key['D' - 'A'] = -1; if (keyinfo < -4) v1key['G' - 'A'] = -1; if (keyinfo < -5) v1key['C' - 'A'] = -1; if (keyinfo < -6) v1key['F' - 'A'] = -1; } if (keyinfo > 0) { v1key['F' - 'A'] = 1; if (keyinfo > 1) v1key['C' - 'A'] = 1; if (keyinfo > 2) v1key['G' - 'A'] = 1; if (keyinfo > 3) v1key['D' - 'A'] = 1; if (keyinfo > 4) v1key['A' - 'A'] = 1; if (keyinfo > 5) v1key['E' - 'A'] = 1; if (keyinfo > 6) v1key['B' - 'A'] = 1; } // erase previous measure accidentals: for (i=0; i<7; i++) { v1lastmeasure[i] = v1key[i]; v1states[i] = v1key[i]; } } ////////////////////////////// // // convertAttributeToXML -- // void convertAttributeToXML(HumdrumFile& infile, int line, int col, int voice) { int length = strlen(infile[line][col]); if (strncmp(infile[line][col], "*M", 2) == 0 && strchr(infile[line][col], '/') != NULL) { // meter marking int top = 0; int bottom = 0; int flag = sscanf(infile[line][col], "*M%d/%d", &top, &bottom); if (flag == 2) { checkMeasure(); lev++; // if (!attributes) { pline(lev, "\n"); lev++; // attributes = 1; // } pline(lev, "\n"); lev--; pline(lev, "\n"); // att lev--; // att } } else if (strncmp(infile[line][col], "*k[", 3) == 0 && infile[line][col][length-1] == ']') { // key signature int pitch = 0; if (length > 4) { pitch = Convert::kernToBase40(&infile[line][col][length-3]); pitch = pitch % 40; } else { pitch = E_muse_c; } int keyinfo = 0; switch (pitch) { case E_muse_c: keyinfo = 0; break; case E_muse_fs: keyinfo = 1; break; case E_muse_cs: keyinfo = 2; break; case E_muse_gs: keyinfo = 3; break; case E_muse_ds: keyinfo = 4; break; case E_muse_as: keyinfo = 5; break; case E_muse_es: keyinfo = 6; break; case E_muse_bs: keyinfo = 7; break; case E_muse_bf: keyinfo = -1; break; case E_muse_ef: keyinfo = -2; break; case E_muse_af: keyinfo = -3; break; case E_muse_df: keyinfo = -4; break; case E_muse_cf: keyinfo = -5; break; case E_muse_gf: keyinfo = -6; break; case E_muse_ff: keyinfo = -7; break; } adjustKey(keyinfo); checkMeasure(); lev++; // if (!attributes) { pline(lev, "\n"); lev++; // attributes = 1; // } pline(lev, "\n"); lev++; pline(lev, ""); // keyinfo += adjustKeyInfo(infile, line, col, voice); cout << keyinfo << "\n"; printMode(lev, infile, line, col, voice); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); // att lev--; // att } else if (strcmp(infile[line][col], "*clefF4") == 0) { checkMeasure(); lev++; // if (!attributes) { pline(lev, "\n"); lev++; // attributes = 1; // } pline(lev, "\n"); lev++; pline(lev, "F\n"); pline(lev, "4\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); // att lev--; // att ClefOctaveTranspose = 0; } else if (strcmp(infile[line][col], "*clefG2") == 0) { checkMeasure(); lev++; // if (!attributes) { pline(lev, "\n"); lev++; // attributes = 1; // } pline(lev, "\n"); lev++; pline(lev, "G\n"); pline(lev, "2\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); // att lev--; // att ClefOctaveTranspose = 0; } else if (strcmp(infile[line][col], "*clefGv2") == 0) { checkMeasure(); lev++; // if (!attributes) { pline(lev, "\n"); lev++; // attributes = 1; // } pline(lev, "\n"); lev++; pline(lev, "G\n"); pline(lev, "2\n"); pline(lev, "-1\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); // att lev--; // att ClefOctaveTranspose = -1; } } ////////////////////////////// // // adjustKeyInfo -- account for modal keys: // ionian = 0 (to get to major) // dorian = -1 (to get to minor) // phrygian = +1 (to get to minor) // lydian = -1 (to get to major) // mixolydian = +1 (to get to major) // aeolean = 0 (to get to minor) // mixolydian = +2 (to get to minor) // int adjustKeyInfo(HumdrumFile& infile, int line, int col, int voice) { int startline = line; int endline = line; int i, j; int track = infile[line].getPrimaryTrack(col); PerlRegularExpression pre; for (i=line; i>=0; i--) { if (infile[i].isData()) { startline = i+1; break; } else { startline = i; } } for (i=line; i=0; i--) { if (infile[i].isData()) { startline = i+1; break; } else { startline = i; } } for (i=line; idorian\n"); return; } if (strstr(infile[i][j], ":phr") != NULL) { pline(lev, "phrygian\n"); return; } if (strstr(infile[i][j], ":lyd") != NULL) { pline(lev, "lydian\n"); return; } if (strstr(infile[i][j], ":mix") != NULL) { pline(lev, "mixolydian\n"); return; } if (strstr(infile[i][j], ":aeo") != NULL) { pline(lev, "aeolean\n"); return; } if (strstr(infile[i][j], ":loc") != NULL) { pline(lev, "locrian\n"); return; } if (std::islower(pre.getSubmatch(1)[0])) { pline(lev, "minor\n"); return; } else { pline(lev, "major\n"); return; } } } } } ////////////////////////////// // // convertNoteToXML -- // void convertNoteToXML(HumdrumFile& infile, int line, int col, int voice) { static char buffer[128] = {0}; int i; if (!infile[line].isExInterp(col, "**kern")) { return; } musicstart = 1; // copy current accidentals into chord buffer for (i=0; i<7; i++) { v1chord[i] = v1lastmeasure[i]; v1prechordstates[i] = v1states[i]; } lev++; if (strcmp(infile[line][col], ".") != 0) { convertBnumForNote(cout, infile, line, col); } // double cdur = 0; // int xdur = 0; int tokencount = infile[line].getTokenCount(col); for (i=0; i 0) { pline(lev, "\n", out); out << firstout.str(); lev++; pline(lev, "", out); out << ticks << "\n"; lev--; pline(lev, "\n", out); } if (secondout.str().size() > 0) { out << secondout.str(); } } ////////////////////////////// // // checkForAnotherFigure -- // int checkForAnotherFigure(ostream& out, HumdrumFile& infile, int oline, int line, int ktrack, int btrack) { int i, j; RationalNumber starttime = infile[oline].getAbsBeat(); RationalNumber endtime; int ticks = 0; int tline = -1; for (i=line; i marker. RationalNumber time1 = infile[oline].getAbsBeat(); RationalNumber time2 = infile[tline].getAbsBeat(); RationalNumber dur = time2 - time1; ticks = divisions * dur.getNumerator() / dur.getDenominator(); convertBnumForNote(out, infile, tline, kcol); } stringstream tempout; int dur = checkForAnotherFigure(tempout, infile, tline, tline+1, ktrack, btrack); if (tempout.str().size() > 0) { out << tempout.str(); pline(lev, "", out); out << dur << "\n"; pline(lev--, "", out); } // This needs to be fixed: the return value should be "ticks" and // "dur" should be printed in this group instead. return ticks; } ////////////////////////////// // // convertBassoContinuoFigureGroup -- // void convertBassoContinuoFigureGroup(ostream& out, HumdrumFile& infile, int line, int col) { char buffer[1024] = {0}; int tcount = infile[line].getTokenCount(col); int k; for (k=0; k\n", out); lev++; if (strlen(prefix) > 0) { if (strchr(prefix, '#') != NULL) { pline(lev, "sharp\n", out); } else if (strchr(prefix, 'b') != NULL) { pline(lev, "flat\n", out); } else if (strchr(prefix, '-') != NULL) { pline(lev, "flat\n", out); } else if (strchr(prefix, 'f') != NULL) { pline(lev, "flat\n", out); } } if (strlen(number)) { pline(lev, "", out); out << number << "\n"; } if (strlen(suffix) > 0) { if (strchr(suffix, '#') != NULL) { pline(lev, "sharp\n", out); } else if (strchr(suffix, 'b') != NULL) { pline(lev, "flat\n", out); } else if (strchr(suffix, '-') != NULL) { pline(lev, "flat\n", out); } else if (strchr(suffix, 'f') != NULL) { pline(lev, "flat\n", out); } else if (strchr(suffix, '+') != NULL) { pline(lev, "cross\n", out); } else if (strchr(suffix, 'n') != NULL) { pline(lev, "natural\n", out); } else if (strchr(suffix, '/') != NULL) { pline(lev, "slash\n", out); } else if (strchr(suffix, '\\') != NULL) { pline(lev, "backslash\n", out); } } lev--; pline(lev, "\n", out); } ////////////////////////////// // // checkbackup -- // void checkbackup (int currenttick, int targettick) { int direction = currenttick - targettick; if (direction > 0) { // backwards pline(lev, "\n"); lev++; pline(lev, ""); cout << direction << "\n"; lev--; pline(lev, "\n"); } else if (direction < 0) { // forwards pline(lev, "\n"); lev++; pline(lev, ""); cout << -direction << "\n"; lev--; pline(lev, "\n"); } AbsTick = targettick; } ////////////////////////////// // // convertNoteEntryToXML -- // double convertNoteEntryToXML(HumdrumFile& infile, int line, int col, const char* buffer, int chord, int vlevel, int voice) { RationalNumber durationR = Convert::kernToDurationR(buffer); if (strcmp(buffer, ".") == 0) { // nothing to do return 0.0; } if ((strstr(buffer, "yy") != NULL) && (strchr(buffer, 'r') != NULL)) { if (!chord) { checkbackup(AbsTick, LineTick[line]); } // invisible rest: generate a direction RationalNumber rduration = durationR * divisions; int tickdur = (int)rduration.getFloat(); AbsTick += tickdur; pline(lev, "\n"); pline(lev+1, ""); cout << tickdur << "\n"; pline(lev, "\n"); return durationR.getFloat(); } double output = 0; // int explicitz = 0; int altered = 0; int pitch = Convert::kernToBase40(buffer); // Sibelius interprets vocal tenor clef improperly, uncomment to fix: // pitch = pitch - 40 * ClefOctaveTranspose; char buff2[64] = {0}; if (pitch > 0) { Convert::base40ToKern(buff2, pitch); } else { strcpy(buff2, "r"); } if (strstr(buff2, "--") != NULL) { } else if (strstr(buff2, "--") != NULL) { altered = -2; } else if (strstr(buff2, "##") != NULL) { altered = 2; } else if (strstr(buff2, "-") != NULL) { altered = -1; } else if (strstr(buff2, "#") != NULL) { altered = 1; } else if (strstr(buffer, "n") != NULL) { altered = 0; // explicitz = 1; } else { altered = 0; // explicitz = 0; } char diapitch = toupper(buff2[0]); int octave = 0; if (pitch > 0) { octave = pitch / 40; } if (debugQ) { cout << "+++ processing note token: " << buffer << endl; } // if (attributes) { // lev--; // pline(lev, "\n"); // lev--; // att // attributes = 0; // } if (!chord) { checkbackup(AbsTick, LineTick[line]); } pline(lev, "\n"); lev++; int slash = 0; int grace = 0; if (strchr(buffer, 'q') != NULL || strchr(buffer, 'Q') != NULL) { grace = 1; slash = 1; if (strstr(buffer, "qq") != NULL) { slash = 0; } } if (grace) { pline(lev, "\n"; } if (chord) { pline(lev, "\n"); } if (toupper(diapitch) != 'R') { pline(lev, "\n"); lev++; pline(lev, ""); cout << diapitch << "\n"; if (altered != 0) { pline(lev, ""); cout << altered << "\n"; } pline(lev, ""); cout << octave << "\n"; lev--; pline(lev, "\n"); } else { pline(lev, "\n"); } if (!grace) { pline(lev, ""); RationalNumber ratnum; ratnum = durationR * divisions; int value = (int)ratnum.getFloat(); cout << value << "\n"; if (!chord) { // don't keep track of chord notes, and presume first note of // chord has correct duration for entire chord. AbsTick += value; } output = durationR.getFloat(); } else { output = 0.0; } int tietype = 0; if (strchr(buffer, '[') != NULL) { tietype = 1; } else if (strchr(buffer, '_') != NULL) { tietype = 2; } else if (strchr(buffer, ']') != NULL) { tietype = 3; } switch (tietype) { case 1: pline(lev, "\n"); break; case 2: pline(lev, "\n"); pline(lev, "\n"); break; case 3: pline(lev, "\n"); break; } pline(lev, ""); cout << voice << "\n"; // int vcase = voice; /* int vcase = 0; if (strchr(infile[line].getSpineInfo(col), '(') == NULL) { vcase = 0; pline(lev, "1\n"); pline(lev, ""); } else if (strchr(infile[line].getSpineInfo(col), 'a') != NULL) { vcase = 1; pline(lev, "1\n"); pline(lev, ""); } else if (strchr(infile[line].getSpineInfo(col), 'b') != NULL) { vcase = 2; pline(lev, "2\n"); pline(lev, ""); } else { vcase = 3; pline(lev, "1\n"); pline(lev, ""); } */ pline(lev, ""); PerlRegularExpression pre; string newbuffer = buffer; string nodots = newbuffer; PerlRegularExpression removedots; removedots.sar(nodots, "\\.", "", "g"); pre.sar(newbuffer, "q", "", "i"); if (grace) { // if a grace note and no rhythm, set the visual duration to 8th if (!pre.search(newbuffer, "\\d")) { newbuffer = "8"; } } // have to ignore augmentation dots on rhythm? RationalNumber rat = Convert::kernToDurationR(nodots); double newduration = rat.getFloat(); RationalNumber ratout = 1; // newduration should be in terms of quarter note durations // whole = 4.0; half = 0.5, etc. double tempval = 0.0; if (newduration > 0.0) { double base2val = log10(newduration)/log10(2); tempval = pow(2.0, floor(base2val + 0.99)); newbuffer = Convert::durationToKernRhythm(tempval); } ratout = Convert::kernToDurationR(newbuffer); printDurationType(newbuffer); // printDurationType(nodots); cout << "\n"; // print number of augmentation dots in duration /////////////////// // printDots(newbuffer); printDots(buffer); /// WRITTEN ACCIDENTALS //////////////////////////////////////////// if (toupper(buff2[0]) != 'R') { if (strchr(buffer, 'n') != NULL) { pline(lev, "natural\n"); v1states[toupper(buff2[0]) - 'A'] = 0; v1lastmeasure[toupper(buff2[0]) - 'A'] = 0; } else { checkAccidentals(toupper(buff2[0]), altered, chord); } } // Time modification (tuplet indications) ////////////////////////// if (!grace) { // don't do if a grace note RationalNumber timemod = rat / ratout; if (timemod.getDenominator() != 1) { pline(lev, "\n"); pline(lev+1, ""); cout << timemod.getDenominator() << "\n"; pline(lev+1, ""); cout << timemod.getNumerator() << "\n"; pline(lev, "\n"); } } // Stem direction if (strchr(buffer, '/') != NULL) { pline(lev, "up\n"); } else if (strchr(buffer, '\\') != NULL) { pline(lev, "down\n"); } // Disabling automatic stemming. Use "autostem" to add manually, or // let the program receiving MusicXML data decide on a stem direction: /* } else if (vcase == 1) { pline(lev, "up\n"); } else if (vcase == 2) { if (strchr(buffer, '/') == NULL && strchr(buffer, '\\') == NULL) { pline(lev, "down\n"); } } */ // Notehead string notecolor = checkColor(buffer, Colorchar, Colorcode); if (notecolor != "") { pline(lev, "normal\n"; } if (durationR.getFloat() >= 1.0) { // kill rogue beam marks. beamlevel[vlevel] = 0; } if (!chord) { // processBeams(infile, line, col, buffer, vlevel); processBeams(infile, line, col, infile[line][col], vlevel); } /// WRITTEN TIES /////////////////////////////////////////////////// if (tietype) { pline(lev, "\n"); lev++; switch (tietype) { case 1: pline(lev, "\n"); break; case 2: pline(lev, "\n"); pline(lev, "\n"); break; case 3: pline(lev, "\n"); break; } lev--; pline(lev, "\n"); } /// FERMATAS /////////////////////////////////////////////////////// if (strchr(buffer, ';') != NULL) { pline(lev, "\n"); lev++; pline(lev, "\n"); lev--; pline(lev, "\n"); } /// ARTICULATIONS //////////////////////////////////////////// if (strchr(buffer, '\'') != NULL) { pline(lev, "\n"); lev++; pline(lev, "\n"); lev++; pline(lev, "\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); } if (strchr(buffer, '~') != NULL) { pline(lev, "\n"); lev++; pline(lev, "\n"); lev++; pline(lev, "\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); } if (strchr(buffer, '^') != NULL) { pline(lev, "\n"); lev++; pline(lev, "\n"); lev++; pline(lev, "\n"); lev--; pline(lev, "\n"); lev--; pline(lev, "\n"); } /// LYRICS ///////////////////////////////////////////////////////// if (!chord) { processTextUnderlay(infile, line, col); } lev--; pline(lev, "\n"); return output; } ////////////////////////////// // // processBeams -- // void processBeams(HumdrumFile& infile, int line, int col, const char* buffer, int vlevel) { int backhook = 0; int forehook = 0; int openbeam = 0; int closebeam = 0; int i=0; int sum = 0; int length = strlen(buffer); for (i=0; icontinue\n"; } return; } // int totalcount = beamlevel[vlevel] + openbeam - closebeam + // backhook + forehook; int rcount = 0; if (openbeam != 0) { // add any new beams which are starting // continue any old beams for (i=0; icontinue\n"; rcount++; } // add new beams for (i=0; ibegin\n"; rcount++; } beamlevel[vlevel] += openbeam; // add any opening beam hook for (i=0; iforward hook\n"; rcount++; } } if (closebeam != 0) { // close any old beams which are ending // continue any old beams for (i=0; icontinue\n"; rcount++; } // close old beams for (i=0; i 0) { pline(lev, "end\n"; rcount++; } } beamlevel[vlevel] -= closebeam; // add any ending beam hook for (i=0; ibackward hook\n"; rcount++; } } if (beamlevel[vlevel] < 0) { beamlevel[vlevel] = 0; } } ////////////////////////////// // // processTextUnderlay -- // void processTextUnderlay(HumdrumFile& infile, int line, int col) { int fields = infile[line].getFieldCount(); if (col >= fields-1) { return; } int tcol = col+1; int verse = 1; while (tcol < fields && strcmp(infile[line].getExInterp(tcol), "**kern") != 0) { if (strcmp(infile[line][tcol], ".") == 0) { // ignore null tokens } else if (strcmp(infile[line].getExInterp(tcol), "**text") == 0) { displayLyrics(infile, line, tcol, verse); } else if (strcmp(infile[line].getExInterp(tcol), "**Bnum") != 0) { displayUnknownTextType(infile, line, tcol, verse); } tcol++; verse++; } } ////////////////////////////// // // displayLyrics -- // void displayLyrics(HumdrumFile& infile, int line, int col, int verse) { displayUnknownTextType(infile, line, col, verse); } ////////////////////////////// // // displayUnknownTextType -- // void displayUnknownTextType(HumdrumFile& infile, int line, int col, int verse) { pline(lev, "\n"; lev++; pline(lev, "single\n"); pline(lev, ""); displayHTMLText(infile[line][col]); cout << "\n"; lev--; pline(lev, "\n"); } ////////////////////////////// // // displayHTMLText -- // void displayHTMLText(const char* buffer) { PerlRegularExpression pre; string tbuf; tbuf = buffer; pre.sar(tbuf, "&", "&", "g"); pre.sar(tbuf, "--", "--", "g"); int length = (int)tbuf.size(); for (int i=0; i': cout << ">"; break; case '"': cout << """; break; default: cout << tbuf[i]; } } } ////////////////////////////// // // checkAccidentals -- // void checkAccidentals(int diatonic, int alter, int chord) { // if a note is different than the current state // in the measure, then add an accidental to make // sure that the note is played right if (toupper(diatonic) == 'R') { return; } if (!chord) { diatonic = toupper(diatonic); if (v1states[diatonic - 'A'] != alter) { pline(lev, ""); switch (alter) { case 2: cout << "double-sharp"; break; case 1: cout << "sharp"; break; case 0: cout << "natural"; break; case -1: cout << "flat"; break; case -2: cout << "double-flat"; break; } cout << "\n"; v1states[diatonic - 'A'] = alter; v1lastmeasure[diatonic - 'A'] = alter; } else if (cautionaryQ && v1lastmeasure[diatonic - 'A'] != alter) { // if a cautionary accidental accross measure, then adjust here pline(lev, ""); switch (alter) { case 2: cout << "double-sharp"; break; case 1: cout << "sharp"; break; case 0: cout << "natural"; break; case -1: cout << "flat"; break; case -2: cout << "double-flat"; break; } cout << "\n"; v1states[diatonic - 'A'] = alter; v1lastmeasure[diatonic - 'A'] = alter; } } else { // note in a chord diatonic = toupper(diatonic); if (v1prechordstates[diatonic - 'A'] != alter) { pline(lev, ""); switch (alter) { case 2: cout << "double-sharp"; break; case 1: cout << "sharp"; break; case 0: cout << "natural"; break; case -1: cout << "flat"; break; case -2: cout << "double-flat"; break; } cout << "\n"; v1states[diatonic - 'A'] = alter; v1lastmeasure[diatonic - 'A'] = alter; } else if (cautionaryQ && v1chord[diatonic - 'A'] != alter) { // if a cautionary accidental accross measure, then adjust here pline(lev, ""); switch (alter) { case 2: cout << "double-sharp"; break; case 1: cout << "sharp"; break; case 0: cout << "natural"; break; case -1: cout << "flat"; break; case -2: cout << "double-flat"; break; } cout << "\n"; v1states[diatonic - 'A'] = alter; v1lastmeasure[diatonic - 'A'] = alter; } } } ////////////////////////////// // // printDots -- // void printDots(const char* durstring) { int length = strlen(durstring); int i; for (i=0; i\n"); } } } ////////////////////////////// // // printDurationType -- // void printDurationType(const string& durstring) { char buffer[32] = {0}; int length = (int)durstring.size(); strcpy(buffer, durstring.c_str()); int counter = 0; string buffer2; int founddot = 0; for (int i=0; i\n"); lev++; // find the start of the spine data and output a part for each // spine int i = 0; int count = 0; // the number of **kern spines int j = 0; while (i=0; j--) { if (strcmp(infile[i].getExInterp(j), "**kern") != 0) { continue; } count++; generatePartInfo(infile, i, j, count); } } lev--; pline(lev, "\n"); return count; } ////////////////////////////// // // generatePart -- // void generatePartInfo(HumdrumFile& infile, int start, int col, int count) { int i = start + 1; int j = 0; pline(lev, "\n"; lev++; int done = 0; while (!done && i < infile.getNumLines()) { if (infile[i].getType() == E_humrec_interpretation) { for (j=0; j"); cout << &(infile[i][j][2]) << "\n"; } else { // pline(lev, "XPart "); // cout << col << "\n"; pline(lev, "\n"); } lev--; pline(lev, "\n"); } ////////////////////////////// // // pline -- print a line of data // void pline(int level, const char* string, ostream& out) { for (int i=0; i& colorout) { PerlRegularExpression pre; colorchar.resize(0); colorout.resize(0); char value; string color; int i; for (i=0; i 0) { cout << "COLOR MARKERS:\n"; for (i=0; i<(int)colorchar.size(); i++) { cout << "\t\"" << colorchar[i] << "\" ==> "; cout << "\t\"" << colorout[i] << "\""; cout << "\n"; } } } } ////////////////////////////// // // checkColor -- // string checkColor(const char* note, string& colorchar, vector& colorout) { for (int i=0; i<(int)colorchar.size(); i++) { if (strchr(note, colorchar[i]) != NULL) { return colorout[i]; } } return ""; } // md5sum: fab28588e4d72e74ea25927709988315 hum2xml.cpp [20151120] //