// // Programmer: Craig Stuart Sapp // Creation Date: Thu Dec 27 19:33:37 PST 2001 // Last Modified: Wed Jan 2 14:25:02 PST 2002 // Last Modified: Thu Aug 15 12:21:21 PDT 2002 (added V and v marks) // Filename: ...sig/examples/all/koto2eps.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/koto2eps.cpp // Syntax: C++; museinfo // // Description: Convert Humdrum **koto representation to an EPS format // using arabic numerals. // // Todo: // add V and v marks // add slur marks // add chord marker to left of chord // fix chord accidental: bottom note is getting top note accidental // add rotation portrait/landscape // #include "humdrum.h" #include #include #include #include #include using namespace std; class StaffItem { public: StaffItem(void) { clear(); } ~StaffItem() { } void clear(void) { line = spine = beams = -1; hpos = width = height = -1.0; textfont = 'T'; textface = 'R'; textsize = 12.0; textjustify = 'L'; chord = grace = 0; vpos = 0; memset(name, '\0', 32); } char name[32]; // int line; // line in humdrum file of item int spine; // spine on line in humdrum file of item char grace; // 1 = grace note char chord; // 1 = grace note double hpos; // horizontal position of item double vpos; // horizontal position of item double width; // horizontal position of item double height; // horizontal position of item int beams; // for beaming information int textfont; // default font for text display (T, H, C) int textface; // default font for text display (R, I, B) double textsize; // default font size for text display int textjustify; // default text justification for text (C,L,R) protected: }; typedef Array StaffItemArray; // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void storeEpsHeader (stringstream& out, int pagecount); void storeEpsFooter (stringstream& out); void generateKotoNotation (HumdrumFile& infile, stringstream& out); void storePageStart (stringstream& out, int pagenum); void calculatePageInformation(HumdrumFile& infile, Array& systems); void drawPrintingMargin (stringstream& out); void setPageSize (const char* sizestring, double& width, double& height); double getItemWidth (const char* name, double scaling); double getItemHeight (const char* name, double scaling); char getStringSymbol (const char* string); void printSystemInformation(Array& systems); int fillSystem (HumdrumFile& infile, int start, StaffItemArray& sarray, double indent); double getKotoDuration (const char* kstring); int countKotoDots (const char* kstring); void writeStaff (stringstream& out, StaffItemArray& items, int staff, int page, HumdrumFile& infile); void printItem (stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile, StaffItemArray& items, int iline); void storeSymbols (stringstream& out); void printTechniques (stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile); int getSharpCount (const char* string); int getBeamCount (const char* string); void printBeaming (stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile, StaffItemArray& items, int iline); void appendSpace (StaffItemArray& sarray, StaffItem& spaceitem); void printTitleInformation (stringstream& out, HumdrumFile& infile); int endOfBeat (HumdrumFile& infile, int line); int endOfBeat2 (HumdrumFile& infile, int line); double adjustwidth (HumdrumFile& infile, StaffItemArray& items, int iline, int level); void processComment (const char* cstring, StaffItem& textitem, StaffItemArray& sarray, int line, int spine, double& totalwidth); void printChord (HumdrumFile& infile, StaffItem& item, stringstream& out, double vpos); void processColor (const char* cstring, StaffItemArray& sarray, double hpos); char hexdigit (int number, int digit); void printColor (stringstream& out, const char* cstring, StaffItem& item, double lmargin, double vpos); void printText (stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile); const char* getTuningInfo (HumdrumFile& infile); void printTuningInfo (stringstream& out, const char* tuning); // global variables Options options; // database for command-line arguments int staffperpage = 8; // max number of staves per page int debugQ = 0; // for debugging lines; int pagecountQ = 0; // for printing out the number of pages only double beambase = 10.5; // base line for lowest beam (8th note) double beamsep = 0.70; // distance between beams lines double beamthick = 0.35; // thickness of beams double beatspace = 1.0; // number of spaces between beats double pagewidth = 612.0; // width of the page (8.5" by default) double pageheight = 792.0; // height of the page (11" by default) double lmargin = 54.0; // left margin (0.75" by default) double rmargin = 54.0; // right margin (0.75" by default) double bmargin = 72.0; // bottom margin (1" by default) double tmargin = 108.0; // top margin (1.5" by default) double indentfirst = 18.0; // indent length for first system double scaling = 1.25; // scaling of items on staff int measurenumQ = 0; // for measure number display char titlestring[1024] = {0}; char composerstring[1024] = {0}; char composerdatestring[1024] = {0}; int verbosetitleQ = 1; // for displaying title at bottom of pages int colorQ = 1; // for -C option int textQ = 1; // for -X option int justifyQ = 1; // for -J option const char* tuning = ""; // for printing tuning specification // font control variables int textfont = 'T'; // default font for text display (T, H, C) int textface = 'R'; // default font for text display (R, I, B) double textsize = 12.0; // default font size for text display int textjustify = 'L'; // default text justification for text (C,L,R) /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { checkOptions(options, argc, argv); // process the command-line options HumdrumFile infile; if (options.getArgCount() < 1) { infile.read(cin); } else { infile.read(options.getArg(1)); } infile.analyzeRhythm(); tuning = getTuningInfo(infile); stringstream epsoutput; generateKotoNotation(infile, epsoutput); epsoutput << ends; cout << epsoutput.str(); return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // getTuningInfo -- read the first !!!tune: record in the file. // const char* getTuningInfo(HumdrumFile& infile) { int i; const char* ptr = ""; for (i=0; i systems; systems.setSize(1000); systems.setSize(0); calculatePageInformation(infile, systems); int systemcount = systems.getSize(); int pagecount = (int)((1.0 * systemcount) / staffperpage + 0.99999); int sys = 0; storeEpsHeader(out, pagecount); int i, j; for (i=0; i 1 && staff == 0) { out << "\t" << 16 << "\t(" << page << ")" << "\t\t\t\tpagenumber\n"; if (verbosetitleQ) { out << "\t" << 8 << "\t" << "(\\(" << titlestring << "\\))\t\ttitlefooter\n"; } } else if (page == 1 && staff == 0) { printTitleInformation(out, infile); if (strcmp(tuning, "") != 0) { printTuningInfo(out, tuning); } } for (i=0; i 0) { out << "\t" << 12 << "\t(" << tuning << ")" << "\t\t\ttuning\n"; } } ////////////////////////////// // // printTitleInformation -- // void printTitleInformation(stringstream& out, HumdrumFile& infile) { int i; int j; for (i=0; i 0) { out << "\t" << 18 << "\t(" << titlestring << ")\t\t\ttitle\n"; } length = strlen(composerstring); if (length > 0) { out << "\t" << 12 << "\t(" << composerstring << ")\t(" << composerdatestring << ")" << "\tcomposer\n"; } } ////////////////////////////// // // printItem -- // void printItem(stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile, StaffItemArray& items, int iline) { if (strcmp(item.name, "doublebar") == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "doublebar" << "\n"; } else if (strcmp(item.name, "finalbar") == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "fbar" << "\n"; } else if (strstr(item.name, "bar") != NULL) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << item.name << "\n"; } else if (strlen(item.name) == 1 && item.name[0] - '0' < 10 && item.name[0] - '0' >= 0) { if (item.chord) { out << "\t" << item.hpos + lmargin << "\t" << vpos - 0.5 * item.height << "\t" << scaling << "\t\t\t" << "string" << item.name << "\n"; } else if (item.grace) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 8.0 * scaling << "\t" << scaling * 0.65 << "\t\t\t" << "string" << item.name << "\n"; } else { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "string" << item.name << "\n"; } if (textQ) { printText(out, item, vpos, infile); } printTechniques(out, item, vpos, infile); printBeaming(out, item, vpos, infile, items, iline); if (strchr(infile[item.line][0], ' ') != NULL) { printChord(infile, item, out, vpos); } } else if (strlen(item.name) == 1 && item.name[0] - 'A' < 4 && item.name[0] - 'A' >= 0) { int digit = 10 + item.name[0] - 'A'; if (item.chord) { out << "\t" << item.hpos + lmargin << "\t" << vpos - 0.5 * item.height << "\t" << scaling << "\t\t\t" << "string" << digit << "\n"; } else if (item.grace) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 8.0 * scaling << "\t" << scaling * 0.65 << "\t\t\t" << "string" << digit << "\n"; } else { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "string" << digit << "\n"; } if (textQ) { printText(out, item, vpos, infile); } printTechniques(out, item, vpos, infile); printBeaming(out, item, vpos, infile, items, iline); if (strchr(infile[item.line][0], ' ') != NULL) { printChord(infile, item, out, vpos); } } else if (strcmp(item.name, "W") == 0) { if (item.chord) { out << "\t" << item.hpos + lmargin << "\t" << vpos - 0.5 * item.height << "\t" << scaling << "\t\t\t" << "wa" << "\n"; } else if (item.grace) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 8.0 * scaling << "\t" << scaling * 0.65 << "\t\t\t" << "wa" << "\n"; } else { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "wa" << "\n"; } if (textQ) { printText(out, item, vpos, infile); } printTechniques(out, item, vpos, infile); printBeaming(out, item, vpos, infile, items, iline); if (strchr(infile[item.line][0], ' ') != NULL) { printChord(infile, item, out, vpos); } } else if (strcmp(item.name, "Z") == 0) { if (item.chord) { out << "\t" << item.hpos + lmargin << "\t" << vpos - 0.5 * item.height << "\t" << scaling << "\t\t\t" << "Zu" << "\n"; } else if (item.grace) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 8.0 * scaling << "\t" << scaling * 0.65 << "\t\t\t" << "Zu" << "\n"; } else { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "Zu" << "\n"; } if (textQ) { printText(out, item, vpos, infile); } printTechniques(out, item, vpos, infile); printBeaming(out, item, vpos, infile, items, iline); if (strchr(infile[item.line][0], ' ') != NULL) { printChord(infile, item, out, vpos); } } else if (strcmp(item.name, "z") == 0) { if (item.chord) { out << "\t" << item.hpos + lmargin << "\t" << vpos - 0.5 * item.height << "\t" << scaling << "\t\t\t" << "zu" << "\n"; } else if (item.grace) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 8.0 * scaling << "\t" << scaling * 0.65 << "\t\t\t" << "zu" << "\n"; } else { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "zu" << "\n"; } if (textQ) { printText(out, item, vpos, infile); } printTechniques(out, item, vpos, infile); printBeaming(out, item, vpos, infile, items, iline); if (strchr(infile[item.line][0], ' ') != NULL) { printChord(infile, item, out, vpos); } } else if (strlen(item.name) == 1 && item.name[0] == '-') { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\t" << "dash\n"; } else if (strcmp(item.name, " ") == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << item.width << "\t\t\t" << "spacer\n"; } else if (strncmp(item.name, "measno=", 7) == 0) { int barno = 0; int count = sscanf(item.name, "measno=%d", &barno); if (count == 1) { out << "\t" << item.hpos + lmargin + getItemWidth("sbar", scaling) * 0.5 << "\t" << vpos + getItemHeight("sbar", scaling) + 6 * scaling << "\t" << 10 * scaling << "\t(" << barno << ")\t\tbarnum\n"; } } else if (strcmp(item.name, "augdot") == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\taugdot\n"; } else if (strcmp(item.name, "sha") == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos << "\t" << scaling << "\t\t\tsha\n"; } else if (strncmp(item.name, "color=", 6) == 0) { printColor(out, &item.name[6], item, lmargin, vpos); } else if (strncmp(item.name, "text", 4) == 0) { out << "\t" << item.hpos + lmargin << "\t" << vpos + 25 * scaling << "\t" << scaling << "\t"; switch (item.textfont) { case 'C': out << "/Courier"; break; case 'H': out << "/Helvetica"; break; case 'T': default: out << "/Times-Roman"; break; } out << "\t" << item.textsize; out << "\t(" << &infile[item.line][0][5] << ")"; out << "\t" << item.name << "\n"; } else if (strcmp(item.name, "indent") == 0) { // ignore code } else { out << "% unknown item : \"" << item.name << "\"\n"; } } ////////////////////////////// // // printText -- print lyrics // void printText(stringstream& out, StaffItem& item, double vpos, HumdrumFile& infile) { int line = item.line; int spine = item.spine; int spinecount = infile[line].getFieldCount(); int i = spine + 1; int verse = 1; while ((i= items.getSize()) { return items[iline].width; } // some unknown object or a barline if (strlen(items[nextitem].name) != 1) { return items[iline].width; } // if at a beat boundary, do not extend beam int boundary = endOfBeat2(infile, items[iline].line); if (boundary) { return items[iline].width; } // now at a point where the beams continues to part of same beat. // decide to continue or not int nextbeamlevel = items[nextitem].beams; if (level > nextbeamlevel) { return items[iline].width; } int i; double returnwidth = items[iline].width; for (i=iline + 1; i& systems) { int i = 0; StaffItemArray temparray; int staff = 0; while (i < infile.getNumLines()) { temparray.setSize(0); if (staff == 0) { i = fillSystem(infile, i, temparray, indentfirst); } else { i = fillSystem(infile, i, temparray, 0.0); } staff++; if (temparray.getSize() > 3) { systems.append(temparray); } } // printSystemInformation(systems); } ////////////////////////////// // // printSystemInformation -- // void printSystemInformation(Array& systems) { int i, j; for (i=0; i 0.0) { tempitem.hpos = 0; strcpy(tempitem.name, "indent"); tempitem.width = indent; sarray.append(tempitem); } tempitem.hpos = indent; tempitem.clear(); int measureno = 0; int count = 0; if (indent == 0.0 && measurenumQ) { count = sscanf (infile[start][0], "=%d", &measureno); if (count == 1) { sprintf(tempitem.name, "measno=%d", measureno); tempitem.hpos = indent; tempitem.width = 0; sarray.append(tempitem); } } strcpy(tempitem.name, "sbar"); tempitem.width = getItemWidth("sbar", scaling); sarray.append(tempitem); spaceitem.width = tempitem.width * 1.5; spaceitem.hpos = totalwidth; totalwidth += spaceitem.width; appendSpace(sarray, spaceitem); double stretchfactor = 1.0; double lastbpos; double currentpos; char notebuffer[128] = {0}; int datafoundQ = 0; // suppress the first barline int chordQ = 0; int n; int lastmeasure = 0; // storage location for previous measure if too far int lastlastmeasure = 0; // storage location for previous measure if too far int i = start + 1; char string = '0'; double duration = 0; while (itargetwidth) { goto endofloop; } break; case E_humrec_interpretation: // ignore for now, but later handle time signatures, tempo, etc. break; case E_humrec_data: datafoundQ = 1; if (strchr(infile[i][0], ' ') != NULL) { chordQ = 1; } else { chordQ = 0; } infile[i].getToken(notebuffer, 0, 0); string = getStringSymbol(notebuffer); if (string == '.') { // ignore null records break; } tempitem.name[0] = string; tempitem.line = i; tempitem.spine = 0; tempitem.name[1] = '\0'; tempitem.chord = chordQ; tempitem.width = getItemWidth(tempitem.name, scaling); tempitem.height = getItemHeight(tempitem.name, scaling); if (strchr(notebuffer, 'q') != NULL) { tempitem.width *= 0.65; tempitem.grace = 1; } duration = getKotoDuration(notebuffer); tempitem.beams = getBeamCount(notebuffer); if (duration >= 0.99) { spaceitem.hpos = totalwidth; spaceitem.width = 1.0 * getItemWidth("sbar", scaling); appendSpace(sarray, spaceitem); totalwidth += spaceitem.width; if (strchr(notebuffer, 's') != NULL) { shaitem.hpos = totalwidth; shaitem.width = getItemWidth("sha", scaling); totalwidth += shaitem.width; strcpy(shaitem.name, "sha"); sarray.append(shaitem); shaitem.clear(); } tempitem.hpos = totalwidth; sarray.append(tempitem); // standardize width of a note totalwidth += tempitem.width; if (strchr(notebuffer, '.') != NULL) { int dotcount = countKotoDots(notebuffer); for (int m=0; m 0.45) { sarray.append(tempitem); if (strchr(notebuffer, '.') != NULL) { int dotcount = countKotoDots(notebuffer); for (int m=0; mtargetwidth) { // find closest barline to targetwidth currentpos = totalwidth; lastbpos = sarray[lastlastmeasure].hpos; if (fabs(currentpos - targetwidth) < fabs(lastbpos - targetwidth)) { // current barline is closest to the target length: need to expand i = sarray[lastlastmeasure].line; sarray.setSize(lastlastmeasure+1); // remove extra blank space after last barline if necessary if (strcmp(sarray[sarray.getSize() - 1].name, " ") == 0 && strstr(sarray[sarray.getSize() - 2].name, "bar") != NULL) { sarray.setSize(sarray.getSize() - 1); } totalwidth = sarray[sarray.getSize() - 1].hpos + sarray[sarray.getSize() - 1].width + getItemWidth("sbar", scaling); spacelength = 0.0; for (n=0; n spacelength) { stretchfactor = 0.0; } else { stretchfactor = (spacelength-delta)/spacelength; } // stretchfactor = 2.0; totalwidth = 0.0; for (n=0; n= 5) { int font = cstring[4]; font = toupper(font); if (font != 'T' && font != 'H' && font != 'C') { // unknown font, do nothing } else { textfont = font; } } if (length >= 6) { int face = cstring[5]; face = toupper(face); if (face != 'R' && face != 'I' && face != 'B') { // unknown font, do nothing } else { textface = face; } } if (length > 6) { int just = cstring[length-1]; just = toupper(just); if (just != 'L' && just != 'R' && just != 'C') { // unknown font, do nothing } else { textjustify = just; } } if (length > 6 && isdigit(cstring[6])) { double fsize = 0.0; int count = sscanf(&cstring[6], "%lf", &fsize); if (count == 1) { textsize = fsize; } } } else if (strncmp(cstring, "!TA:", 4) == 0) { strcpy(textitem.name, "textabove"); textitem.width = 0; textitem.hpos = totalwidth; textitem.line = line; textitem.spine = spine; textitem.textfont = textfont; textitem.textsize = textsize; textitem.textface = textface; textitem.textjustify = textjustify; sarray.append(textitem); } else if (strncmp(cstring, "!TB:", 4) == 0) { strcpy(textitem.name, "textbelow"); textitem.width = 0; textitem.hpos = totalwidth; textitem.line = line; textitem.spine = spine; textitem.textfont = textfont; textitem.textsize = textsize; textitem.textface = textface; textitem.textjustify = textjustify; sarray.append(textitem); } else if (strncmp(cstring, "!CLR:", 5) == 0) { processColor(&cstring[5], sarray, totalwidth); } } ////////////////////////////// // // processColor -- // void processColor(const char* cstring, StaffItemArray& sarray, double hpos) { int red = 0; int green = 0; int blue = 0; int length = strlen(cstring); char *Cstring = new char[length + 1]; strcpy(Cstring, cstring); int i; for (i=0; i 2 && strncmp(sarray[endp].name, "color=", 6) == 0 && strcmp(sarray[endp-1].name, " ") == 0) { sarray[endp-1].width += spaceitem.width; } else { sarray.append(spaceitem); } } /////////////////////////////// // // countKotoDots -- // int countKotoDots(const char* kstring) { int length = strlen(kstring); int count = 0; int i = 0; for (i=0; i