// // Programmer: Craig Stuart Sapp // Creation Date: Fri Sep 14 14:23:32 PDT 2001 // Last Modified: Tue Oct 9 16:44:19 PDT 2001 (after dots added) // Last Modified: Thu Dec 27 19:22:48 PST 2001 (incorporated into museinfo) // Filename: ...sig/examples/all/bol2score.cpp // Web Address: http://sig.sapp.org/examples/museinfo/score/bol2score.cpp // Syntax: C++; museinfo // // Description: Convert tabla bol notation in the humdrum format to // SCORE notation. // #include "humdrum.h" #include #include #include // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void generateScoreNotation (HumdrumFile& infile); int getStaffCount (HumdrumFile& infile, Array& staffstart); void printLineInfo (HumdrumFile& infile, Array& staffstart); void generateStaffInfo (HumdrumFile& infile, Array&staffstart, Array& staffend, Array& duration, Array& staffpage, Array& staffnumber); void printLineInfo (Array&staffstart, Array& staffend, Array& duration, Array& staffpage, Array& staffnumber); void printScoreStaff (HumdrumFile& infile, int start, int stop, double dur, int staffno, int alignmentpoints); char* extractBol (char* buffer, const char* data); double getBolWidth (const char* buffer, double staffsize, double ptsize, int line); double getLetterWidth (char letter, double staffsize, double ptsize); double getBolDuration (const char* bol); int getDotCount (const char* string); // global variables Options options; // database for command-line arguments double lmargin = 6.0; // the right margin width double rmargin = 3.0; // the right margin width double textbase = 0.0; // vertical position of bol text double ptsize = 12.0; // pointsize of text double staffsize = 1.0; // size of staff (invisible) int staffperpage = 12; // max number of staves per page int page = 1; // page to output int debugQ = 0; // for debugging lines; int infoQ = 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 spacefactor = 0.5; // spacer shrinkage for end of beat double tfactor = 1.2; // spacing of triplet mark on beam double rfactor = 1.0; // sizing value of rests double staffspacer = -12.0; // spacing between staves double samspace = 0.2; // spacing between sams // nominal widths of characters in Helvetica 10pt double letterwidth[28] = { 2.11, // a 2.11, // b 1.90, // c 2.11, // d 2.11, // e 1.06, // f 2.11, // g 2.11, // h 0.84, // i 0.84, // j 1.90, // k 0.84, // l 3.16, // m 2.11, // n 2.11, // o 2.11, // p 2.11, // q 1.26, // r 1.90, // s 1.06, // t 2.11, // u 1.90, // v 2.74, // w 1.90, // x 1.90, // y 1.90, // z 1.60, // space 1.60 // + }; /////////////////////////////////////////////////////////////////////////// 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)); } generateScoreNotation(infile); return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { opts.define("a|append=b", "append analysis to data in output"); opts.define("debug=b", "trace input parsing"); opts.define("author=b", "author of the program"); opts.define("version=b", "compilation information"); opts.define("example=b", "example usage"); opts.define("h|help=b", "short description"); opts.define("pagecount=b", "print number of pages only"); opts.define("i|info=b", "print staff/page information only"); opts.define("m|leftmargin=d:6.0", "starting margin on left"); opts.define("r|rightmargin=d:3.0", "starting margin on right"); opts.define("b|textbase=d:0.0", "vertical position of bol text"); opts.define("z|pointsize=d:14.0", "point size of bol text"); opts.define("s|staffsize=d:1.0", "staff size"); opts.define("l|staffperpage=i:12", "number of staves per page"); opts.define("p|page=i:1", "page number to generate as output"); opts.define("base|beambase=d:10.5", "base line for lowest beam"); opts.define("sep|beamsep=d:0.7", "distance between beam lines"); opts.define("thick|beamthick=d:0.35", "thickness of beams"); opts.define("bs|beatspace=d:1.0", "spaces between beats"); opts.define("sf|spacefactor=d:0.5", "spacer shrinkage for end of beat"); opts.define("ss|staffspacer=d:-12", "spacer shrinkage between staves"); opts.define("sam|samspace=d:0.20", "space between sam staves"); opts.define("tfactor=d:1.2", "spacing of triplet mark on beam"); opts.define("rfactor=d:1.0", "sizing value of rests"); opts.process(argc, argv); // handle basic options: if (opts.getBoolean("author")) { cout << "Written by Craig Stuart Sapp, " << "craig@ccrma.stanford.edu, Sep 2001" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 14 Sep 2001" << 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); } lmargin = opts.getDouble("leftmargin"); rmargin = opts.getDouble("rightmargin"); textbase = opts.getDouble("textbase"); ptsize = opts.getDouble("pointsize"); staffsize = opts.getDouble("staffsize"); staffperpage = opts.getInt("staffperpage"); page = opts.getInt("page"); debugQ = opts.getBoolean("debug"); infoQ = opts.getBoolean("info"); pagecountQ = opts.getBoolean("pagecount"); beambase = opts.getDouble("beambase"); beamsep = opts.getDouble("beamsep"); beamthick = opts.getDouble("beamthick"); beatspace = opts.getDouble("beatspace"); spacefactor = opts.getDouble("spacefactor"); samspace = opts.getDouble("samspace"); staffspacer = opts.getDouble("staffspacer"); tfactor = opts.getDouble("tfactor"); rfactor = opts.getDouble("rfactor"); if (ptsize == 14.0) { beambase = beambase; } else if (ptsize == 10.0) { beambase = beambase * ((ptsize + 2.85) / 14.0); } else { beambase = beambase * ((ptsize + 2.6) / 14.0); } } ////////////////////////////// // // generateScoreNotation -- // void generateScoreNotation(HumdrumFile& infile) { Array staffstart; Array staffend; Array duration; Array staffpage; Array staffnumber; infile.analyzeRhythm(); // int staffcount = getStaffCount(infile, staffstart); if (pagecountQ) { cout << (int)((double)staffstart.getSize()/staffperpage + 0.99); cout << endl; exit(0); } generateStaffInfo(infile, staffstart, staffend, duration, staffpage, staffnumber); if (infoQ) { printLineInfo(staffstart, staffend, duration, staffpage, staffnumber); exit(1); } int i; int xstaffcount = 0; for (i=0; i 0) { int spacers = xstaffcount / 2; double hsize = 0.236 * xstaffcount + spacers * samspace; cout << "h\n"; cout << hsize << "\n"; if (xstaffcount % 2 == 0) { cout << "2\n"; } else { cout << "1,2\n"; } } } ////////////////////////////// // // printScoreStaff -- print the starting and stopping text line and // duration of each staff line for debugging purposes. // void printScoreStaff(HumdrumFile& infile, int start, int stop, double dur, int staffno, int alignmentpoints) { if (staffsize == 1.0) { cout << "8.0 " << staffno << ".0 0.0 " << staffno * staffspacer + staffspacer << " 0.0 0.0 -1.0" << "\n"; } else { cout << "8.0 " << staffno << ".0 0.0 " << staffno * staffspacer + staffspacer << " " << staffsize << "0.0 -1.0 0.0\n"; } // int divisions = (int)dur; // assume integer duration for now int divisions = alignmentpoints; Array position; position.setSize(divisions); position.allowGrowth(0); int i; for (i=0; i durations; durations.setSize(stop - start); durations.setSize(0); durations.allowGrowth(); double cdur = 0.0; Array dots; dots.setSize(stop-start); dots.setSize(0); int dot = 0; // fill the durations for each bol into the durations array double mindur = 9999; for (i=start; i<=stop; i++) { if (infile[i].getType() != E_humrec_data) { continue; } cdur = getBolDuration(infile[i][0]); durations.append(cdur); dot = getDotCount(infile[i][0]); dots.append(dot); if (mindur > cdur) { mindur = cdur; } } Array spacers; // number of semi-alignment spaces after each bol Array beams; // number of beams for each bol spacers.setSize(durations.getSize()); beams.setSize(durations.getSize()); int currbeat; int nnextbeat; double dursum = 0; for (i=0; i 0) { beams[i]++; } spacers[i] = (int)(durations[i] / mindur + 0.001) - 1; if (spacers[i] < 0) { spacers[i] = 0.0; } spacers[i] *= getLetterWidth(' ', staffsize, ptsize); // minimize spacers at ends of beats if (nnextbeat != currbeat) { spacers[i] *= spacefactor; } } Array bolstartpoints; bolstartpoints.setSize(spacers.getSize()); Array bolendpoints; // including spacers after bol bolendpoints.setSize(spacers.getSize()); int counter = 0; int region = 0; int lastbeat = 1; // int nextbeat = 2; beat = 1; double posit; double bbeatspace = getLetterWidth(' ', staffsize, ptsize) * beatspace; for (i=start; i<=stop; i++) { if (infile[i].getType() == E_humrec_interpretation) { if (strcmp(infile[i][0], "*sam") == 0) { posit = lmargin - getLetterWidth(' ', staffsize, ptsize) - getLetterWidth('+', staffsize, ptsize); cout << "t " << staffno << " " << posit << " 0.0 1.0 " << p6size << " 0.0 0.0 0.0 0.0 0.0\n"; cout << "_04+\n"; } } if (infile[i].getType() != E_humrec_data) { continue; } extractBol(buffer, infile[i][0]); lastbeat = beat; beat = (int)(currdur + 0.0005) + 1; if (lastbeat != beat) { position[region] += bbeatspace; } region = (int)((double)(beat - 1) / dur * divisions + 0.001); if (strchr(infile[i][0], '[') != NULL) { // display repetition marker width = 2.0 * getLetterWidth('w', staffsize, ptsize); cout << 12.0 << " " << staffno << " " << position[region] + width/2.0 << " " << 1.5 / p6size << " " << 0.0 << " " // 0 = rectangle shape << width / 2.7*rfactor << " " // 6: horizontal size << 0.0 << " " // 7: vertical size << 0.0 << " " // 8: thickness << 45.0 << " " // 9: rotation << 0.0 << " " // 10: parallelogram << 0.0 << " " // 11: endpoint in arc << 0.0 << " " // 12: changes circles into polygons << 1.0 << " " // 13: filled in << "\n"; position[region] += width; // approximate width of marker position[region] += bbeatspace; } if (strcmp(buffer, "r") == 0) { width = 2.0 * getLetterWidth('w', staffsize, ptsize); } else { width = getBolWidth(buffer, staffsize, ptsize, i+1); } bolstartpoints[counter] = position[region]; bolendpoints[counter] = bolstartpoints[counter] + spacers[counter] + width; double restvpos = 1.5 * p6size; if (strcmp(buffer, "r") == 0) { // rests displayed as circles cout << 12.0 << " " << staffno << " " << bolstartpoints[counter] + width/2.0 << " " << restvpos << " " << 1.0 << " " // 1 = circle shape << width/2.7*rfactor << " " // size << 0.0 << " " << 3.0 << " " // thickness << endl; } else if (strncmp(buffer, "ry", 2) == 0) { // don't display editor marked rests } else { cout << "t " << staffno << " " << bolstartpoints[counter] << " 0.0 1.0 " << p6size << " 0.0 0.0 0.0 0.0 0.0" << "\n"; cout << "_04" << buffer << "\n"; } position[region] += width; position[region] += spacers[counter]; currdur += getBolDuration(infile[i][0]); counter++; } // write beam lines here int j; double vertpos; double sh = 0.0; int triplet = 0; int nexttriplet = 0; int tbeat = 1; double tsum = 0; int ntbeat = 1; int stbeat = 1; int sntbeat = 1; int striplet = 0; int nextstriplet = 0; int striplethold = 0; for (i=0; i 0) { // ignoring double dots for now double offst = getLetterWidth(' ', staffsize, ptsize); vertpos = (beambase + beams[i] * beamsep + 0.5)/2.0; if (ptsize == 10.0) { vertpos = vertpos * 0.70; } cout << "12.0 " // 1: item number for circles << staffno << " " // 2: staff number << bolstartpoints[i] + offst << " " // 3: horizontal position << vertpos << " " // 4: vertical position << 1.0 << " " // 5: shape, circle=1 << 0.85 << " " // 6: size << 0.0 << " " // 7: << 0.0 << " " // 8: << 0.0 << " " // 9: << 0.0 << " " // 10: << 0.0 << " " // 11: << 0.0 << " " // 12: << 1.0 // 13: filled = 1 << "\n"; } for (j=0; j&staffstart, Array& staffend, Array& duration, Array& staffpage, Array& staffnumber) { int startpage = 0; int i; for (i=0; i 0.001) { staffstart.append(i); } else { staffstart.last() = i; } } } if (fabs(infile.getTotalDuration() - infile[staffstart.last()].getAbsBeat()) < 0.001) { staffstart.setSize(staffstart.getSize()-1); } staffstart.allowGrowth(0); return staffstart.getSize(); } ////////////////////////////// // // example -- example usage of the tertian program // void example(void) { cout << " \n" << endl; } ////////////////////////////// // // usage -- gives the usage statement for the bol2score program // void usage(const char* command) { cout << " \n" << endl; } // md5sum: cf721b2dc607eac58fa0b41509536dc8 bol2score.cpp [20160320]