// // Programmer: John Howard <John.B.Howard@asu.edu> // Creation Date: A long time ago (circa 1990) // Filename: rmusic.c // Syntax: C // // Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu> // Filename: pe2score.c // Last Modified: Tue Aug 15 01:18:37 PDT 2006 // Extracted core portions of rmusic.c for converting // Plaine & Easie music notation into SCORE input data. // // Description: Converts RISM entries into SCORE input data which // can be used to create graphical PostScript music // notation of incipits. // // /* From: John B Howard [mailto:John_Howard@harvard.edu] Sent: Tuesday, February 10, 2004 2:37 AM To: esfield@stanford.edu Subject: Source code for RISM P&E to Score converter I'm attaching a zipped file with a couple ANSI C source code files that I used to convert RISM's P&E code to a Score input file. Unfortunately the documentation for these files is not easily accessible, but it should be possible to figure out the program operation and logic. The critical issue is probably the format of the input file. There were two possible formats that had to be dealt with: (1) SPIRES standard format, and I have at least a sample input file in the zip file of that. (2) The format used by the sequential data file on the RISM A/II CDROM. This file had tagged data on sequential lines that would not exceed 256 bytes. Syntax was: three-digit field code followed by data; if a field exceeded 256 characters it would continue on the next line, with three space characters occupying the first three bytes of the continuation. (It might still be possible to run this against the data on the CDROM -- one of the problems I had, however, was that RISM constantly changed their data standard and made 'enhancements' to the P&E encoding(which was also notoriously non-syntactical)). Choose the appropriate command-line flags and it should output as you specify -- they're explained in the source or output if the compiled program is run with no arguments. I typically would run it with first with the verbose option to identify problems without actually writing an output file. Another command-line flag controles whether Score output EPS files ... I found that I had to specify an absolute length for the incipit, otherwise the tool I used to convert the EPS files to bitmaps would vary the relative size of the images ... which was really ugly to look at on screen! */ #include <stdio.h> #include <string.h> #include "Options.h" #ifndef OLDCPP #include <sstream> #define SSTREAM stringstream #define CSTRING str().c_str() using namespace std; #else #ifdef VISUAL #include <strstrea.h> /* for windows 95 */ #else #include <strstream.h> #endif #define SSTREAM strstream #define CSTRING str() #endif Options options; void spires2rism(FILE * ifp, FILE * ofp); int MakeKeySignature(char *s); int MakeTimeSignature(char *s); int MakeClef(char *s); void MakeOctave(char *s); void MakeRhythm(char *s); void lstr(char *s, int n); void rstr(char *s, int n); char* convertPe2ScoreInput(char* output, const char* input); void checkOptions(Options& opts, int argc, char* argv[]); void usage(const char* command); void example(void); void convert(SSTREAM& output, const char* input); /////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); char *data = NULL; if (options.getArgCount() != 1) { usage(options.getCommand()); exit(1); } else { convertPe2ScoreInput(data, options.getArg(1)); } std::cout << data << endl; return 0; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // convertPe2ScoreInput -- convert a Plaine & Easie string of music // into SCORE input data which will be converted to PostScript // graphical music notation. // char* convertPe2ScoreInput(char *data, const char* input) { SSTREAM output; convert(output, input); output << ends; int length = strlen(output.CSTRING); data = new char[length+1]; strcpy(data, output.CSTRING); return data; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// void convert(SSTREAM& output, const char* input) { char id[13], incipit_id[15]; int verbose = 0; int tclef_flag; int field_cnt = 0; int next_flag = 0; int startpos = 0; int i = 0; int rc = 1; int err_cnt = 0; int w; int rism = 0; int beam_cnt = 0; int proof = 0; int print_flag = 0; int beam_flag = 0; int format = 0; // extern int tclef_flag; int wmn_flag = 0; char tmp[2056]; char key_signature[26]; int TotalIncipits = 0; int TotalRecords = 0; int TotalErrors = 0; int TotalErrorRecords = 0; char MusicOut[1028]; char RhythmOut[562]; char BeamsOut[256]; char SlursOut[256]; char ur_clef[18]; char ur_timesig[18]; char ur_keysig[18]; char start_clef[18]; char start_timesig[18]; char start_keysig[18]; char FileName[17]; char MarksOut[128]; char subdir[128]; char library[56]; char country[12]; int c; strcpy(incipit_id, "1.1.1"); strcpy(key_signature, ""); i = 0; ++TotalRecords; i = 0; field_cnt = 1; next_flag = 0; // char* country = country code // char* library = library code // 789: Component incipit (music) int incno = 0; int m_flag = 0; int Serr_flag = 0; char instrumentation[562]; char role[256]; char tempo[562]; char text[1062]; char clef[18]; char timesig[18]; char ur_music[1062]; char music[1062]; char comment[562]; char inclen[5]; char ex_music[1062]; char keysig[24]; char stitle[2056]; char value[2056]; strcpy(instrumentation, ""); strcpy(role, ""); strcpy(tempo, ""); strcpy(text, ""); strcpy(clef, ""); strcpy(timesig, ""); strcpy(music, ""); strcpy(comment, ""); strcpy(keysig, ""); strcpy(stitle, ""); strcpy(value, ""); incno = 0; strcpy(timesig, "4/4"); strcpy(clef, "G2"); strcpy(ur_clef, clef); strcpy(start_clef, clef); strcpy(music, input); strcpy(ur_music, music); /*- begin processing of incipits -*/ /*- process Score notes stage ... -*/ int n, j, o, bar_cnt, cue_flag = 0, chord_flag = 0, rep_flag = 0; char octave[3], note[3], accidental[3]; char RepFigure[356]; char LastClef[6]; char symbol[12]; char lastsymbol[12]; wmn_flag = 0; strcpy(LastClef, clef); strcpy(ur_timesig, timesig); if ((w = MakeTimeSignature(timesig)) < 0) { printf ("RISM %s (%s): invalid time signature \"%s\"\n", id, incipit_id, timesig); ++err_cnt; Serr_flag = 1; } strcpy(start_timesig, timesig); strcpy(accidental, ""); strcpy(MusicOut, ""); strcpy(symbol, ""); strcpy(lastsymbol, ""); strcpy(keysig, ""); strcpy(ur_keysig, ""); /*- But first, some proofreading ... -*/ int t, beams, exclam, octaves, parens, graces, zrhythm; char rests[4]; char reg[6]; char duration[6]; char temp[1028]; strcpy(temp, ""); strcpy(reg, ""); strcpy(duration, ""); strcpy(rests, ""); zrhythm = 'z'; exclam = 0; parens = 0; graces = 0; octaves = 0; beams = 0; bar_cnt = 1; int musiclength = strlen(music); for (n=0; n<musiclength; n++) { if (music[n] == '*' || music[n] == '%' || /* skip change of */ music[n] == '@' || music[n] == '$') { /* clef, etc. */ n++; while (music[n] != '*' || music[n] == ' ') { n++; } continue; } if (music[n] == ',' || music[n] == '\'') { octaves = 1; temp[0] = music[n]; t = 1; while (music[n + 1] == ',' || music[n + 1] == '\'') { temp[t++] = music[n++]; } temp[t] = '\0'; if (strcmp(temp, reg) == 0 && (verbose == 1)) { cerr << "WARNING: redundant octave register symbol" << "( measure " << bar_cnt << ")" << endl; continue; } else { strcpy(reg, temp); continue; } } if (music[n] == '{') ++beams; if (music[n] == '}') --beams; if (music[n] == '(') ++parens; if (music[n] == ')') --parens; if (music[n] == 'q' && music[n + 1] == 'q') { ++n; ++graces; } if (music[n] == 'r') --graces; if (music[n] == '!') { if (exclam == 0) ++exclam; else --exclam; } if (isdigit(music[n]) || music[n] == 'g') { zrhythm = music[n]; temp[0] = music[n]; t = 1; while (music[n + 1] == '.') temp[t++] = music[n++]; temp[t] = '\0'; if (strcmp(temp, duration) == 0 && (verbose == 1)) { printf ("RISM %s (%s, measure %d): redundant duration " "symbol\n", id, incipit_id, bar_cnt); } else strcpy(duration, temp); continue; } if (isupper(music[n]) || music[n] == '-') { if (zrhythm == 'z') { printf ("RISM %s (%s, measure %d): 1st note or rest " "has no rhythm\n", id, incipit_id, bar_cnt); zrhythm = '4'; ++err_cnt; continue; } if (octaves == 0 && isupper(music[n])) { printf ("RISM %s (%s, measure %d): no octave register " "at start of incipit\n", id, incipit_id, bar_cnt); octaves = 4; err_cnt++; continue; } } if (music[n] == '/') { ++bar_cnt; if (parens > 0) { printf ("RISM %s (%s measure %d): chain brackets not " "closed\n", id, incipit_id, bar_cnt); Serr_flag = 1; parens = 0; err_cnt++; continue; } if (parens < 0) { printf ("RISM %s (%s measure %d): open chain bracket " "missing\n", id, incipit_id, bar_cnt); Serr_flag = 1; parens = 0; err_cnt++; continue; } if (graces > 0) { printf ("RISM %s (%s measure %d): grace-note figure not " "closed\n", id, incipit_id, bar_cnt); Serr_flag = 1; graces = 0; err_cnt++; continue; } if (graces < 0) { printf ("RISM %s (%s measure %d): improper start of grace-" "note figure\n", id, incipit_id, bar_cnt); /* Serr_flag = 1; */ graces = 0; err_cnt++; continue; } if (exclam != 0) { printf ("RISM %s (%s measure %d): unexpected specification " "of repeated figure\n", id, incipit_id, bar_cnt); /* Serr_flag = 1; */ exclam = 0; err_cnt++; continue; } if (music[n + 1] == '/') ++n; continue; } if (music[n] == '=') { int z; for (z = 0; isdigit(music[n + 1]); n++) rests[z++] = music[n + 1]; if (z > 0) { rests[z] = '\0'; bar_cnt = ((bar_cnt - 1) + (atoi(rests))); z = 0; } } } // end of proofreading loop /// /// Score notes output stage ... /// bar_cnt = 1; if (music[0] == '<') { // other notation type n = 3; // white mensural notation: if (music[0] == 'w') { wmn_flag = 1; } } else { n = 0; } for (; n <= (int)strlen(music); n++) { if (isdigit(music[n]) || music[n] == 't' || music[n] == 'g' || music[n] == '.' || music[n] == '{' || music[n] == '}' || music[n] == ')') { continue; } switch (music[n]) { case '!': // ! = repeated figures strcpy(lastsymbol, ""); if (rep_flag == 0) { // start of figure strcpy(RepFigure, ""); rep_flag = 1; continue; } else { // end figure strcpy(lastsymbol, ""); if (music[n + 1] != 'f') { // error condition Serr_flag = 1; err_cnt++; printf ("RISM %s (%s, measure %d): repeated figure not " "followed by \"f\"\n", id, incipit_id, bar_cnt); } else { // expand figure strcat(MusicOut, RepFigure); while (music[n + 1] == 'f') { strcat(MusicOut, RepFigure); ++n; } rep_flag = 0; } } continue; case ':': if (music[n + 3] == ':') { strcat(MusicOut, "/MRD"); strcpy(lastsymbol, "/MRD"); n = n + 3; continue; } if (music[n + 2] != '\x2f') { printf("RISM %s (%s, measure %d): invalid " "encoding of repeat sign\n", id, incipit_id, bar_cnt); err_cnt++; Serr_flag = 1; } strcat(MusicOut, "/ML"); // JBH change to /ML strcpy(lastsymbol, "/MxiLR"); n = n + 2; continue; case '-': // rests chord_flag = 0; if (rep_flag == 1) strcat(RepFigure, "/R"); else { strcat(MusicOut, "/R"); strcpy(lastsymbol, "/R"); } continue; case '\x2f': // barlines chord_flag = 0; ++bar_cnt; if (music[n + 1] == '\x2f' && music[n + 2] != ':') { strcat(MusicOut, "/MD"); strcpy(lastsymbol, "/MD"); n = n + 1; continue; } if (music[n + 1] == '\x2f' && music[n + 2] == ':') { strcat(MusicOut, "/MR"); // JBH change to MR strcpy(lastsymbol, "/MR"); n = n + 2; continue; } if (rep_flag == 1) { printf ("RISM %s (%s, measure %d): repeated figure " "spans the barline\n", id, incipit_id, bar_cnt); err_cnt++; Serr_flag = 1; } strcat(MusicOut, "/M"); strcpy(lastsymbol, "/M"); continue; case 'q': // cue-sized notes if (music[n + 1] == 'q') { ++n; cue_flag = 1; if (rep_flag == 1) strcat(RepFigure, "/SU/Q+"); else { strcat(MusicOut, "/SU/Q+"); strcpy(lastsymbol, "/SU/Q+"); } } continue; case 'r': // end cue-sized notes cue_flag = 0; if (rep_flag == 1) strcat(RepFigure, "/Q0/SO"); else { strcat(MusicOut, "/Q0/SO"); strcpy(lastsymbol, "/Q0/SO"); } continue; case '\'': for (j = 0; music[n] == '\''; n++) { octave[j++] = music[n]; } octave[j] = '\0'; --n; MakeOctave(octave); continue; case ',': for (j = 0; music[n] == ','; n++) { octave[j++] = music[n]; } octave[j] = '\0'; --n; MakeOctave(octave); continue; case 'n': accidental[0] = 'N'; accidental[1] = '\0'; continue; case 'b': accidental[0] = 'F'; if (music[n + 1] == 'b') { ++n; accidental[1] = 'F'; accidental[2] = '\0'; } else { accidental[1] = '\0'; } continue; case 'x': accidental[0] = 'S'; if (music[n + 1] == 'x') { ++n; accidental[1] = 'S'; accidental[2] = '\0'; } else { accidental[1] = '\0'; } continue; case '=': chord_flag = 0; if (music[n + 1] == '\x2f') { strcat(MusicOut, "/RW"); strcpy(lastsymbol, "/RW"); continue; } for (o = 0; isdigit(music[n + 1]);) { tmp[o++] = music[++n]; } tmp[o] = '\0'; strcat(strcat(MusicOut, "/R"), tmp); strcat(strcpy(lastsymbol, "/R"), tmp); bar_cnt = (bar_cnt + (atoi(tmp) - 1)); continue; case 'i': chord_flag = 0; strcat(MusicOut, "/RP"); strcpy(lastsymbol, "/RP"); continue; case '(': if (music[n + 1] == '=' && music[n + 2] == ')') { strcat(MusicOut, "/RF"); strcpy(lastsymbol, "/RF"); n = n + 2; continue; } if (music[n + 1] == '-' && music[n + 2] == ')') { strcat(MusicOut, "/RF"); strcpy(lastsymbol, "/RF"); n = n + 2; continue; } continue; case ';': // tuplet number while (isdigit(music[++n])); continue; case '^': // U.S. RISM chords if (rep_flag == 1) { strcat(RepFigure, ":"); chord_flag = 1; } else { chord_flag = 1; strcat(MusicOut, ":"); strcat(lastsymbol, ":"); // chg from strcpy -- JBH } // so chords won't repeat continue; case '%': // change of clef chord_flag = 0; for (o = 0; music[++n] != ' ';) { clef[o++] = music[n]; } clef[o] = '\0'; if (MakeClef(clef) < 0) { printf ("RISM %s (%s, measure %d): invalid clef \"%s\"\n", id, incipit_id, bar_cnt, clef); ++err_cnt; Serr_flag = 1; continue; } if (strcmp(clef, LastClef) != 0) { strcpy(LastClef, clef); if (rep_flag == 1) strcat(strcat(RepFigure, "/"), clef); else { strcat(strcat(MusicOut, "/"), clef); strcpy(lastsymbol, clef); } } continue; case '@': // change of time signature chord_flag = 0; for (o = 0; music[++n] != ' ';) { timesig[o++] = music[n]; } timesig[o] = '\0'; if ((w = MakeTimeSignature(timesig)) < 0) { printf("RISM %s (%s): invalid time signature \"%s\"\n", id, incipit_id, timesig); ++err_cnt; Serr_flag = 1; } if (rep_flag == 1) strcat(RepFigure, timesig); else { strcat(MusicOut, timesig); strcpy(lastsymbol, "XXX"); } continue; case '$': // change of key signature chord_flag = 0; for (o = 0; music[++n] != ' ';) { keysig[o++] = music[n]; } keysig[o] = '\0'; MakeKeySignature(keysig); if (strlen(keysig) > 0) { // if there's a key signature if (rep_flag == 1) /* August 1996: don't need the slash */ /* strcat(strcat(RepFigure,"/"),keysig); */ strcat(RepFigure, keysig); else { strcat(MusicOut, keysig); strcpy(lastsymbol, keysig); } } continue; case '[': /*- used with barlines only! -*/ if (music[n + 2] != ']' && music[n + 1] != '/') { printf ("RISM %s: unexpected use of brackets\n", id); err_cnt++; continue; } if (rep_flag == 1) { printf("RISM %s (%s, measure %d): repeated " "figure spans more than one measure\n", id, incipit_id, bar_cnt); err_cnt++; Serr_flag = 1; } strcat(MusicOut, "/MS"); strcpy(lastsymbol, "/MS"); ++n; continue; } // end of switch if (isupper(music[n])) { // notes note[0] = music[n]; note[1] = '\0'; if (rep_flag == 0) { strcat(strcat (strcpy(symbol, note), accidental), octave); if (strcmp(symbol, lastsymbol) == 0 && music[n + 1] != '^' && chord_flag == 0) { strcat(MusicOut, "/"); } else { if (chord_flag == 0) { strcat(strcat(MusicOut, "/"), symbol); strcat(lastsymbol, ""); // JBH } else { strcat(MusicOut, symbol); chord_flag = 0; strcpy(lastsymbol, "XXX"); // JBH - chg fr symbol } } strcpy(accidental, ""); } else { if (chord_flag == 0) { strcat(strcat(RepFigure, "/"), note); } else { strcat(RepFigure, note); chord_flag = 0; } strcat(strcat(RepFigure, accidental), octave); strcpy(accidental, ""); } } } // now clean pitch stage data ... int LastOctave = 0; strcpy(tmp, MusicOut); strcpy(MusicOut, ""); for (n = 0, j = 0; n <= (int)strlen(tmp); n++) { // avoid counting rests as // octave registers if (tmp[n] == 'R' && isdigit(tmp[n + 1])) { MusicOut[j++] = tmp[n++]; while (isdigit(tmp[n])) MusicOut[j++] = tmp[n++]; --n; continue; } if (isdigit(tmp[n])) { if (tmp[n + 1] == ' ' || tmp[n - 1] == ' ' || tmp[n + 2] == ' ') { MusicOut[j++] = tmp[n]; continue; } if (tmp[n] == LastOctave) { continue; } else { LastOctave = tmp[n]; } } MusicOut[j++] = tmp[n]; } MusicOut[j] = '\0'; strcat(strcat(strcpy(tmp, start_clef), start_keysig), start_timesig); strcat(tmp, MusicOut); strcat(strcpy(MusicOut, tmp), "/MI;"); // end Score notes stage // process Score rhythm stage ... cue_flag = 0; rep_flag = 0; int TupletCnt = 0; int grace_flag = 0; int tuplet_flag = 0; int pc = 0; char rhythm[6][6]; strcpy(RhythmOut, ""); for (n = 0; n <= (int)strlen(music); n++) { if (music[n] == 't' || music[n] == '{' || music[n] == '}' || music[n] == ':' || music[n] == 'x' || music[n] == 'b' || music[n] == 'n' || music[n] == '+' || music[n] == '\'' || music[n] == ',' || music[n] == '[' || music[n] == ']' || music[n] == '\x2f') { continue; } /* if (isdigit(music[n])) { */ if (rc == 1) pc = 0; if (rc > 1 && pc < rc) ++pc; if (rc > 1 && pc == rc) pc = 0; if (isdigit(music[n])) { for (pc = 0, rc = 0; isdigit(music[n]); pc++, rc++, n++) { if (music[n + 1] == '(' && music[n + 3] != ')' && music[n + 4] != ')') { /*- tuplets -*/ TupletCnt = music[n]; pc = 0; continue; } rhythm[pc][0] = music[n]; rhythm[pc][1] = '\0'; MakeRhythm(rhythm[pc]); while (music[n + 1] == '.') { strcat(rhythm[pc], "."); ++n; } } --n; continue; } if (isupper(music[n]) || music[n] == '-') { /*- note values -*/ if (rep_flag == 0) { if (tuplet_flag == 0) { if (grace_flag == 0) { if (cue_flag == 1) strcat(strcat(RhythmOut, "/"), "G"); else strcat(strcat(RhythmOut, "/"), rhythm[pc]); } else { if (cue_flag == 0) grace_flag = 0; strcat(RhythmOut, "/G"); } continue; } else { /*- tuplet_flag == 1 -*/ if (grace_flag == 0) { if (rhythm[pc][0] == '3' && rhythm[pc][1] == '2') strcat(RhythmOut, "/48"); else strcat(strcat(RhythmOut, "/T"), rhythm[pc]); } else { if (cue_flag == 0) grace_flag = 0; strcat(RhythmOut, "/G"); } continue; } } else { if (tuplet_flag == 0) { if (grace_flag == 0) strcat(strcat(RepFigure, "/"), rhythm[pc]); else { if (cue_flag == 0) grace_flag = 0; strcat(RepFigure, "/G"); } } else { strcat(strcat(RepFigure, "/T"), rhythm[pc]); } continue; } } if (music[n] == '%' || music[n] == '@' || music[n] == '$') { while (music[++n] != ' '); continue; } switch (music[n]) { case '^': for (; n <= (int)strlen(music); n++) { if (isupper(music[n])) break; } continue; case 'g': grace_flag = 1; continue; case '!': // repeated figures ; if (rep_flag == 0) { // start figure strcpy(RepFigure, ""); rep_flag = 1; } else { // end figure // expand figure strcat(RhythmOut, RepFigure); while (music[n + 1] == 'f') { strcat(RhythmOut, RepFigure); ++n; } rep_flag = 0; } continue; case '(': if (music[n + 1] == '-') { if (rep_flag == 0) { strcat(strcat(RhythmOut, "/"), rhythm[pc]); n = n + 2; continue; } else { strcat(strcat(RepFigure, "/"), rhythm[pc]); n = n + 2; continue; } } else if (music[n + 1] == '=') { strcat(RhythmOut, "/H"); n = n + 2; continue; } // so it must be a tuplet figure ... if (music[n + 2] != ')' && music[n + 3] != ')') tuplet_flag = 1; continue; case 'q': // cue-sized notes if (music[n + 1] != 'q') { // appogiatura if (rep_flag == 0) { strcat(RhythmOut, "/G"); } else { strcat(RepFigure, "/G"); } // move to the note it applies to ... // Dec. 24, 1995: this code prevents value // of the appogiature from being passed on ... for (++n, j = 0; n <= (int)strlen(music); n++) { if (isdigit(music[n])) { rhythm[pc][0] = music[n]; rhythm[pc][1] = '\0'; MakeRhythm(rhythm[pc]); while (music[n + 1] == '.') { strcat(rhythm[pc], "."); n++; } } if (isupper(music[n])) { break; } } continue; } else { // qq ... r construction ++n; grace_flag = 1; // JBH98 cue_flag = 1; } continue; case 'r': // end cue-sized notes cue_flag = 0; grace_flag = 0; // JBH98 continue; case '=': while (isdigit(music[n + 1])) ++n; strcat(RhythmOut, "/W"); continue; case 'i': strcat(RhythmOut, "/W"); continue; case ';': // tuplet number tuplet_flag = 0; while (isdigit(music[++n])); continue; case ')': if (tuplet_flag == 1) tuplet_flag = 0; continue; case '[': // used with barlines only! continue; } // end of switch } for (o = 0, j = 0; o <= (int)strlen(RhythmOut); o++) { if (o > 0) { temp[j++] = RhythmOut[o]; } } temp[j] = '\0'; strcpy(RhythmOut, temp); strcat(RhythmOut, ";"); // end Score rhythm stage // expand the incipit printf("GOT HERE J9\n"); int p, q, r; for (n = 0, o = 0, p = 0; n <= (int)strlen(music); n++) { if (music[n] == '^') { for (; n <= (int)strlen(music); n++) { if (isupper(music[n])) { break; } } continue; } if (music[n] == '!') { for (++n, p = 0; n <= (int)strlen(music); n++) { if (music[n] == '!') { break; } else { if (music[n] == '%' || music[n] == '@' || music[n] == '$') { while (music[++n] != ' '); continue; } if (music[n] == '^') { // JBH, Jan 2 1996 for (; n <= (int)strlen(music) && music[n] != '!'; n++) { if (isupper(music[n])) { ++n; break; } } } /*= IF -*/ RepFigure[p++] = music[n]; ex_music[o++] = music[n]; } } RepFigure[p] = '\0'; while (music[++n] == 'f') { for (r = 0; r < (int)strlen(RepFigure); r++) { ex_music[o++] = RepFigure[r]; } } strcpy(RepFigure, ""); --n; // bug fix, Dec 16 1995 continue; } if (music[n] == '%' || music[n] == '@' || music[n] == '$' || music[n] == '*') { ++n; while (music[n] != ' ' && music[n] != '*' && music[n] != '\0') ++n; continue; } ex_music[o++] = music[n]; } /*- FOR -*/ ex_music[o] = '\0'; strcpy(tmp, music); strcpy(music, ex_music); strcpy(ex_music, tmp); // process Score marks stage (fermatas, trills, etc.) int NoteCnt = 0; char place[6]; /*- keep only notes and marks -*/ strcpy(MarksOut, ""); for (n = 0, o = 0; n <= (int)strlen(music); n++) { if (isupper(music[n]) || music[n] == '(' || music[n] == 't' || music[n] == ')' || music[n] == '-' || music[n] == '=') { temp[o++] = music[n]; } } temp[o] = '\0'; for (n = 0; n <= (int)strlen(temp); n++) { if (isupper(temp[n])) { ++NoteCnt; continue; } if (temp[n] == 't') { if ((int)strlen(MarksOut) > 0) { strcat(MarksOut, "/"); } strcat(MarksOut, "TR "); sprintf(place, "%d", NoteCnt); strcat(MarksOut, place); continue; } if (temp[n] == '(') { if (temp[n + 1] == '-' || temp[n + 1] == '=') { continue; } if (temp[n + 2] == ')') { if ((int)strlen(MarksOut) > 0) { strcat(MarksOut, "/"); } strcat(MarksOut, "FE "); sprintf(place, "%d", NoteCnt + 1); strcat(MarksOut, place); } } } strcat(MarksOut, ";"); // end Score marks stage // process Score beams stage int beams_flag = 0; cue_flag = 0; NoteCnt = 0; char CueBeamsOut[256]; beam_cnt = 0; bar_cnt = 1; strcpy(BeamsOut, ""); strcpy(CueBeamsOut, ""); for (n = 0, o = 0; n <= (int)strlen(music); n++) { if (isupper(music[n]) || music[n] == '{' || music[n] == '/' || isdigit(music[n]) || music[n] == '=' || music[n] == '}' || music[n] == 'r' || music[n] == 'q') { temp[o++] = music[n]; } } temp[o] = '\0'; for (n = 0; n <= (int)strlen(temp); n++) { if (isdigit(temp[n])) { zrhythm = temp[n]; continue; } if (temp[n] == '/') { if (beams_flag < 0) { printf ("RISM %s (%s, measure %d): start beam symbol " "\"{\" wanting\n", id, incipit_id, bar_cnt); err_cnt++; /* Serr_flag = 1; *//* changed to accommodate 20th-cent. */ } /* December 1996 -- JBH */ else if (beams_flag > 0) { printf("RISM %s (%s, measure %d): end beam " "symbol \"}\" wanting\n", id, incipit_id, bar_cnt); err_cnt++; /* Serr_flag - 1; */ } if (temp[n + 1] == '/') ++n; beams_flag = 0; ++bar_cnt; continue; if (temp[n] == 'q' && temp[n + 1] == 'q') { cue_flag = 1; if ((int)strlen(CueBeamsOut) > 0) { strcat(CueBeamsOut, "/"); } sprintf(place, "%d", NoteCnt + 1); strcat(strcat(CueBeamsOut, place), " "); beams_flag++; beam_cnt++; continue; } if (temp[n] == 'r') { cue_flag = 0; beams_flag--; sprintf(place, "%d", NoteCnt); strcat(CueBeamsOut, place); continue; } if (isupper(temp[n])) { ++NoteCnt; if (beams_flag > 0) { if (zrhythm == '1' || zrhythm == '2' || zrhythm == '4' || zrhythm == '9' || zrhythm == '0') { printf ("RISM %s (%s, measure %d): invalid rhythm " "in beamed group\n", id, incipit_id, bar_cnt); Serr_flag = 1; err_cnt++; zrhythm = '8'; } } continue; } if (temp[n] == '=') { int z; for (z = 0; isdigit(temp[n + 1]); n++) rests[z++] = temp[n + 1]; if (z > 0) { rests[z] = '\0'; bar_cnt = ((bar_cnt - 1) + (atoi(rests))); z = 0; } continue; } if (temp[n] == '{') { if (cue_flag == 0) { if ((int)strlen(BeamsOut) > 0) { strcat(BeamsOut, "/"); } sprintf(place, "%d", NoteCnt + 1); strcat(strcat(BeamsOut, place), " "); beams_flag++; beam_cnt++; continue; } else { continue; } } if (temp[n] == '}') { if (cue_flag == 0) { sprintf(place, "%d", NoteCnt); strcat(BeamsOut, place); beams_flag--; continue; } else { continue; } } if (beams_flag > 0) { printf ("RISM %s (%s): end beam symbol \"}\" wanting in " "last measure\n", id, incipit_id); err_cnt++; // Serr_flag = 1; -- JBH98 } else if (beams_flag < 0) { printf ("RISM %s (%s): start beam symbol \"{\" wanting in " "last measure\n", id, incipit_id); err_cnt++; // Serr_flag = 1; --JBH98 } if ((int)strlen(BeamsOut) > 0 && (int)strlen(CueBeamsOut) > 0) { strcat(BeamsOut, "/"); } strcat(strcat(BeamsOut, CueBeamsOut), ";"); // end Score beams stage // process Score slurs stage (ties & tuplets) int n, o, NoteCnt = 0, f_flag = 0, r_flag = 0; char place[6], temp[562], StartTuplet[6], EndTuplet[6], TupletType[3]; strcpy(SlursOut, ""); for (n = 0, o = 0; n <= (int)strlen(music); n++) { if (isdigit(music[n]) || isupper(music[n]) || music[n] == '+' || music[n] == '(' || music[n] == '-' || music[n] == ')' || music[n] == ';' || music[n] == '=') { temp[o++] = music[n]; } } temp[o] = '\0'; // process ties for (n = 0; n <= (int)strlen(temp); n++) { if (isupper(temp[n])) { ++NoteCnt; continue; } if (temp[n] == '+') { // a tie if (strlen(SlursOut) > 0) { strcat(SlursOut, "/"); } sprintf(place, "%d", NoteCnt); strcat(strcat(SlursOut, place), " "); if (n + 1 == (int)strlen(temp) || n == (int)strlen(temp)) { strcat(strcat(SlursOut, place), ".99"); } else { sprintf(place, "%d", NoteCnt + 1); strcat(SlursOut, place); } } } // process tuplets NoteCnt = 0; for (n = 0; n <= (int)strlen(temp); n++) { if (isupper(temp[n])) { ++NoteCnt; continue; } if (temp[n] == '(') { if (temp[n + 2] == ')' || temp[n + 1] == '=') { f_flag = 1; continue; } if (temp[n + 1] == '-' || (isdigit(temp[n + 1]) && temp[n + 2] == '-') || (isdigit(temp[n + 1]) && temp[n + 2] == '.' && temp[n + 3] == '-')) { r_flag = 1; } if (r_flag == 0) { sprintf(StartTuplet, "%d", NoteCnt + 1); } else { const char *fraction = ".9"; /*- JBH: 2 Jan 96, was ".8" -*/ printf ("RISM %s: tuplet figure begins with a rest !!\n", id); sprintf(StartTuplet, "%d%s", NoteCnt - 1, fraction); r_flag = 0; } continue; } if (temp[n] == ';') { /*- tuplet type -*/ TupletType[0] = temp[n + 1]; TupletType[1] = '\0'; } if (temp[n] == ')') { if (f_flag == 1) { f_flag = 0; continue; } sprintf(EndTuplet, "%d", NoteCnt); // write the output if ((int)strlen(SlursOut) > 0) { strcat(SlursOut, "/"); } if ((int)strlen(TupletType) == 0) { strcat(SlursOut, "3"); } else { strcat(SlursOut, TupletType); strcpy(TupletType, ""); } if (atoi(StartTuplet) < 10) { strcat(SlursOut, "0"); } strcat(SlursOut, StartTuplet); if (r_flag == 1) { strcat(SlursOut, ".8"); } strcat(SlursOut, " "); strcat(strcat(SlursOut, "+"), EndTuplet); r_flag = 0; } } strcat(SlursOut, ";"); // end Score slurs stage // determine width of musical notation on staff for (n = 0, o = 0; n <= (int)strlen(music); n++) { if (isupper(music[n])) { tmp[o++] = music[n]; } } tmp[o] = '\0'; n = strlen(tmp); if (n > 24) strcpy(inclen, "195"); else if (n > 22) strcpy(inclen, "185"); else if (n > 20) strcpy(inclen, "175"); else if (n > 17) strcpy(inclen, "160"); else if (n > 15) strcpy(inclen, "150"); else if (n > 13) strcpy(inclen, "140"); else if (n > 10) strcpy(inclen, "130"); else if (n > 7) strcpy(inclen, "120"); else if (n > 5) strcpy(inclen, "110"); else strcpy(inclen, "100"); TotalErrors = (TotalErrors + err_cnt); if (err_cnt > 0 || Serr_flag == 1) ++TotalErrorRecords; if (Serr_flag == 1) { printf("- processing aborted\n"); Serr_flag = 0; goto vinit; } if (rism == 0) { strcpy(FileName, id); if (incno < 100) /*- August 1996: allow for > 99 incipits */ sprintf(tmp, "%.2d", incno); else sprintf(tmp, "%.3d", incno); strcat(FileName, tmp); rstr(FileName, 5); strcpy(subdir, library); } else { /*- data from Zentralredaktion -*/ strcpy(tmp, id); lstr(tmp, 3); strcat(strcpy(subdir, library), "\\"); strcat(subdir, tmp); strcpy(tmp, id); rstr(tmp, 3); strcpy(FileName, tmp); if (incno < 100) sprintf(tmp, "%.2d", incno); else sprintf(tmp, "%.3d", incno); strcat(FileName, tmp); } if (proof == 0) { output << "-- RISM " << id << " (" << incipit_id << ") -----------------------------------------\n"; output << "-> [clef:] " << ur_clef << "\t [key signature:] " << ur_keysig << "\t [time signature:] " << ur_timesig << "\n"; output << "-> " << ur_music << "\n"; output << "IN 1\n"; output << "1.5 " << inclen << " 1\n"; output << MusicOut << "\n"; output << RhythmOut << "\n"; output << MarksOut << "\n"; output << BeamsOut << "\n"; output << SlursOut << "\n"; if (beam_flag == 1) { // add score info to thin beams int u = 0; output << "ST 1 6\n"; for (; u < beam_cnt; u++) output << "17/.8\n\n"; output << "\n"; } if (tclef_flag == 1) { // make the vocal tenor clef output << "ST 1 3\n5/.8\n\n"; tclef_flag = 0; } if (format > 0) { /* August 1996: get rid of CW1 in output */ output << "J\n1\n\n\nCW1\nSTM\nZ\n"; output << "CD \\" << country << "\\" << subdir << "\n"; output << "SA " << FileName << "\n"; if (print_flag == 0) { output << "RS\nY\n"; } } else { output << "ST 1 8\n6/" << atoi(inclen)+2 << "\n"; output << "\nJ\n1\n\n\nCW1\nSTM\nZ\n"; output << "CD \\rism\\" << country << "\\" << subdir << "\n"; output << "SA " << FileName << "\n"; if (print_flag == 0) { output << "RS\nY\n"; } } if (print_flag == 1) { if (rism == 0) output << "CD \\RISM\\temp\nPR\n"; else output << "PR\n"; if (format == 0) { output << ".42\n"; } else if (format == 1) { output << ".65\n"; } else { output << ".5\n"; } output << "\n\n1 -2\nP\n" << FileName << "\nRS\nY\n"; } } // end of "if (proof == 0)" block // reset varibles vinit: m_flag = 0; strcpy(instrumentation, ""); strcpy(role, ""); strcpy(tempo, ""); strcpy(text, ""); strcpy(clef, ""); strcpy(timesig, ""); strcpy(music, ""); strcpy(comment, ""); strcpy(keysig, ""); strcpy(stitle, ""); strcpy(start_keysig, ""); strcpy(ur_keysig, ""); strcpy(value, ""); // end processing of incipits // re-initialize selected variables startpos = 0; err_cnt = 0; printf("==========================================================================\n"); printf("\n **** Statistics for RMUSIC processing run ****\n\n"); printf("\tRecords processed:\t%d\n", TotalRecords); printf("\tIncipits processed:\t%d\n", TotalIncipits); printf("\tErrors detected:\t%d in %d records\n", TotalErrors, TotalErrorRecords); return the data string here } //////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // spires2rism -- // void spires2rism(FILE * ifp, FILE * ofp) { int c, q_flag = 0, s_flag = 0; int i = 0; int rc = 0; while ((c = getc(ifp)) != EOF) { if (c == ' ') { if (s_flag == 0) { continue; } else { putc(' ', ofp); while ((c = getc(ifp)) == ' ') { ; } } } if (c == '\"') { if (q_flag == 1) { if ((c = getc(ifp)) == '\"') { putc(c, ofp); s_flag = 1; } else { q_flag = 0; s_flag = 0; putc('\n', ofp); (c = getc(ifp)); } } else { q_flag = 1; s_flag = 1; } continue; } if (c == ';') { if (q_flag == 1) { putc(c, ofp); s_flag = 1; } else { putc('\n', ofp); s_flag = 0; (c = getc(ifp)); } continue; } if (c == '\n') { putc(' ', ofp); continue; } putc(c, ofp); s_flag = 1; } } ////////////////////////////// // // MakeOctave -- // void MakeOctave(char *s) { char *octavein[] = { "\'", "\'\'", "\'\'\'", "\'\'\'\'", "\'\'\'\'\'", ",", ",,", ",,,", ",,,," }; char *octaveout[] = { "4", "5", "6", "7", "8", "3", "2", "1", "0" }; extern char id[]; int i; for (i = 0; i <= 8; i++) { if (strcmp(s, octavein[i]) == 0) { strcpy(s, octaveout[i]); return; } } printf("RISM %s: strange octave register symbol -> %s\n", id, s); return; } ////////////////////////////// // // MakeRhythm -- // void MakeRhythm(char *s) { char *rhythmin[] = { "1", "2", "4", "8", "6", "3", "5", "7", "9", "0" }; char *rhythmout[] = { "W", "H", "Q", "E", "S", "32", "64", "128", "DW", ".25" }; extern char id[]; int i; for (i = 0; i <= 9; i++) { if (strcmp(s, rhythmin[i]) == 0) { strcpy(s, rhythmout[i]); return; } } return; } ////////////////////////////// // // MakeKeySignature -- // int MakeKeySignature(char *s) { char *keyin[] = { "bB", "bBE", "bBEA", "bBEAD", "bBEADG", "bBEADGC", "bBEADGCF", "xF", "xFC", "xFCG", "xFCGD", "xFCGDA", "xFCGDAE", "xFCGDAEB" }; char *keyout[] = { "/K1F", "/K2F", "/K3F", "/K4F", "/K5F", "/K6F", "/K7F", "/K1S", "/K2S", "/K3S", "/K4S", "/K5S", "/K6S", "/K7S" }; int i, o; extern char id[]; char tmp[12]; /*- eliminate brackets and ampersand -*/ for (i = 0, o = 0; i <= (int)strlen(s); i++) { if (s[i] == '[' || s[i] == ']' || s[i] == '&') { continue; } tmp[o++] = s[i]; } tmp[o] = '\0'; strcpy(s, tmp); if (tmp[0] == 'n') { /* make natural signs */ strcpy(s, ""); return; } for (i = 0; i <= 14; i++) { if (strcmp(s, keyin[i]) == 0) { strcpy(s, keyout[i]); return 1; } } return -1; } ////////////////////////////// // // MakeClef -- // int MakeClef(char *s) { char *clefin[] = { "G-2", "C-1", "F-4", "C-3", "C-4", "G-1", "F-3", "F-2", "C-2", "C-5", "G-3" }; char *clefout[] = { "TR", "TR", "BA", "AL", "TE", "TR", "BA", "BA", "TR", "BA", "TE" }; int i, o; extern char id[]; extern int tclef_flag; char tmp[12]; // eliminate brackets for (i = 0, o = 0; i <= (int)strlen(s); i++) { if (s[i] == '[' || s[i] == ']') { continue; } tmp[o++] = s[i]; } tmp[o] = '\0'; strcpy(s, tmp); if (s[0] == 'g') { // vocal tenor clef tclef_flag = 1; strcpy(s, "G-2"); } if (s[1] == '+') { // mensural notation s[1] = '-'; if (s[2] == '5') s[2] = '4'; if (verbose == 1) { printf("RISM %s: mensural notation is called for!\n", id); } } for (i = 0; i <= 10; i++) { if (strcmp(s, clefin[i]) == 0) { strcpy(s, clefout[i]); return 1; } } return -1; } ////////////////////////////// // // MakeTimeSignature -- // int MakeTimeSignature(char *s) { char *timein[] = { "c", "c/", "o", "o/", "&C", "&alla;", "3/1", "2/1", "4/1", "6/1", "8/1", "2/2", "3/2", "4/2", "6/2", "8/2", "2/4", "3/4", "4/4", "5/4", "6/4", "7/4", "8/4", "9/4", "10/4", "2/8", "3/8", "4/8", "5/8", "6/8", "8/8", "9/8", "12/8", "16/8", "8/16", "6/16", "9/16", "12/16", "16/16", "20/4", "20/16", "24/16", "12/4", "1/4", "10/2", "c3/2", "c3", "c/3", "38/4", "c2", "c/2", "1/2", "3", "2", "4", "1", "0", "c/3/1", "c/3/2", "c/6/4", "c6/4", "" }; char *timeout[] = { "/COM", "/CUT", "/3 1", "/3 2", "/COM", "/CUT", "/3 1", "/2 1", "/4 1", "/6 1", "/8 1", "/2 2", "/3 2", "/4 2", "/6 2", "/8 2", "/2 4", "/3 4", "/4 4", "/5 4", "/6 4", "/7 4", "/8 4", "/9 4", "/10 4", "/2 8", "/3 8", "/4 8", "/5 8", "/6 8", "/8 8", "/9 8", "/12 8", "/16 8", "/8 16", "/6 16", "/9 16", "/12 16", "/16 16", "/20 4", "/20 16", "/24 16", "/12 4", "/1 4", "/10 2", "/COM/3 2", "/COM/3", "/COM/3", "/38 4", "/COM/2", "/COM/2", "/1 2", "/3", "/2", "/4", "/1", "", "/COM/3 1", "/COM/3 2", "/COM/6 4", "/COM/6 4", "" }; int i, o; extern char id[]; char tmp[12]; /*- eliminate brackets -*/ for (i = 0, o = 0; i <= (int)strlen(s); i++) { if (s[i] == '[' || s[i] == ']') { continue; } tmp[o++] = s[i]; } tmp[o] = '\0'; strcpy(s, tmp); for (i = 0; i <= 61; i++) { if (strcmp(s, timein[i]) == 0) { strcpy(s, timeout[i]); return 1; } } /*- try to catch other time sigs -*/ printf("RISM %s (%s): unusual time signature \"%s\"\n", id, incipit_id, s); for (i = 0; i <= (int)strlen(s); i++) { if (s[i] == '/') tmp[i] = ' '; else tmp[i] = s[i]; } tmp[o] = '\0'; strcpy(s, "/"); strcat(s, tmp); return; /*- assuming nothing gets past here, the following not necessary -*/ return -1; } ////////////////////////////// // // lstr -- // void lstr(char *s, int n) { int i; char tmp[2056]; for (i = 0; i < n; i++) tmp[i] = s[i]; tmp[i] = '\0'; strcpy(s, tmp); return; } ////////////////////////////// // // rstr -- // void rstr(char *s, int n) { int i, o = 0; char tmp[2056]; for (i = 0; i <= (int)strlen(s); i++) { if (i >= n) tmp[o++] = s[i]; } tmp[o] = '\0'; strcpy(s, tmp); return; } ////////////////////////////// // // readline -- read a line of text from the input file // simulating the fgets function but better behaved // at the end of a file where there is no newline. // int readline(char * storage, int max, FILE* fr) { int i; int inchar; for (i=0; i<max-2; i++) { inchar = fgetc(fr); if (inchar == EOF) { if (i == 0) { } break; } else { storage[i] = (char)inchar; } if (storage[i] == '\n') { break; } } if (i==0 && inchar == EOF) { return 0; } if (storage[i-1] != '\n') { storage[i] = '\n'; i++; } storage[i] = '\0'; return 1; } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ////////////////////////////// // // usage -- gives the usage statement for the program // void usage(const char* command) { cout << " " << endl; // original usage statement // if (a == 0) { // printf("rmusic: prepare input file for Score music typesetting " // "program from RISM A/II SPIRES standard format\n\n"); // printf("Input file not specified\nUsage: rmusic " // "fn_in {fn_out} -lMpr\n"); // printf("\n -p = prepare EPS printing instructions\n"); // printf(" -l = print with long staves (for WWW site)\n"); // printf(" -M = omit music input files (use with -p)\n"); // printf(" -r = Score output will be written to \\rism\\temp\n"); // printf(" -P = output proofreading information only\n"); // printf(" -R = source file is from RISM Zentralredaktion\n"); // printf // (" -s = Score output file prints with size factor of .5\n"); // printf(" -b = Score output thins beams by factor of .8\n"); // return; } ////////////////////////////// // // checkOptions -- validate and process command-line options. // void checkOptions(Options& opts, int argc, char* argv[]) { // original options: // p => print_flag = 1; // M => music_flat = 1; // l => format = 1; // r => directory = 1; // R => rism = 1; // s => format = 2; // p => proof = 1; // b => beam_flat = 1; set beam thickness to 0.8 (thin) in SCORE. // v => verbose = 1; opts.define("debug=b"); // determine bad input line num opts.define("author=b"); // author of program opts.define("version=b"); // compilation info opts.define("example=b"); // example usages opts.define("h|help=b"); // short description opts.process(argc, argv); // handle basic options: if (opts.getBoolean("author")) { cout << "Written by Craig Stuart Sapp, " << "craig@ccrma.stanford.edu, August 2006" << endl; exit(0); } else if (opts.getBoolean("version")) { cout << argv[0] << ", version: 15 August 2006" << endl; cout << "compiled: " << __DATE__ << endl; exit(0); } else if (opts.getBoolean("help")) { usage(opts.getCommand()); exit(0); } else if (opts.getBoolean("example")) { example(); exit(0); } } ////////////////////////////// // // example -- example usage of the program // void example(void) { cout << " " << endl; } // md5sum: 1281b5755490cb9b169487a9cb440f43 pe2score.cpp [20110711]