&dA &dA &dE D A R M S -&dC>&dE C C A R H music translator &dA &dA &dA &dB Errors found in translation are written to the file called&d@ &dB &d@ &dA &dA &dB "trans.err." &dA &dA &dB Version 8-16-93 &d@ &dB &dA &dA &dB The description of the measure_table "data_type" is grouped with&d@ &dA &dA &dB the measure table funcitons &d@ &dA &dA #define ERROR_FILE darms.err #define FALSE 0 #define TRUE 1 #define INPUT 0 #define OUTPUT 1 #define DARMS 0 #define CCARH 1 #define DARMS>CCARH 1 #define CCARH>DARMS 2 #define XPARTS 50 #define MAX_FIG 4 #define FIG_Y 0 #define SLUR_HEIGHT 9 #define ORNY 11 #define WORD_LENGTH 36 #define MAX_TRK 6 /* &dB3 tracks per stave&d@ #define MAX_TIC 196 #define MAX_STAVES 2 #define MAX_MEAS 500 #define SYMBOL_SIZE 60 #define TRACKS_PER_STAFF 3 &dA Warning index - used to prevent repetition of error messages #define ELLIPSIS 1 #define SLASH_ZERO 2 #define NUM_WARNING_FLAGS 2 &dA Columns (C at end means column) #define BEGIN_BAR_NUMBERC 9 #define END_BAR_NUMBERC 12 #define BAR_LINE_FLAGC 17 #define NTYPE 17 #define DOTC 18 #define AXC 19 #define STEMC 23 #define BEAMC 26 #define END_BEAMC 31 #define C32 32 &dB /*&dB column for other special notations #define C43 43 &dB #define TEXTC 44 &dB /*&dB column for text&d@ #define TUPLETC 20 &dB #define BEATSC 6 #define GRACE_CUE_TYPEC 8 #define C6 6 #define C8 8 #define FIGURE_FIELDSC 17 #define STAFF_NUMBERC 24 #define TEXT_Y -6 &dB /*&dB start text layers at &d@ &dB6 and move down #define TEXT_OFF -4 &dB /*&dB place each line 4 below higher line str inlib.100,outfile.100 /*&dB variables related to mfiles int darms_file int ccarh_file table INX(100000), OUTX(100000) table OUTX2(100000) /* &dBfor cases of multiple staves, suchas piano music int partnum /* &dBindexs individual parts in a directory int xparts str in_line.160,out_line.300 /*&dB variables realted to lines str temp_line.300 str staves.40 /* &dBthe first line - contains info about multiple staves int ipnt,outpnt int out_line2_number /* &dBfor second stave&d@ int header_line int counter /*&dB loop counter int max_in_lines /*&dB number of lines of input file int old_mpt,this_mpt /*&dB remember the pointer mpt /* &dBflags&d@ &dB int iflag /*&dB int hooked_beam_marker /*&dB need to use a ; to symbolize hooked beaming int tuplet int explicit_tuplet /*&dB tuplet specified by written number /*&dB needed to tell when tuplet ends by closing beams int slur /*&dB tells if slur is turned on int art_pos /*&dB tell the verticle position of an articulation? int grace_cue /* &dBtells if grace or cue notes are being processed int chord /* &dBindicates chord - changes where pitch is found bstr warning_flag.1(NUM_WARNING_FLAGS) /*&dB prevents repetitive errors str directions.3 /*&dB CCARH musical directions int measure_number /*&dB music variables str bar_line.2,repeat_back.1,repeat_forward.1 int key int divspq,tnum,tden int measure_divisions /* &dBnumber of "ticks" in a measure int clef_type, clef_line int cflag /* &dBtells when cleffs are written to front of file or at the time they occur int octave /*&dB octave = ccarh octave number /* &dBBelow strings used for converting notes/rests&d@ str sp_code.5,axstr.15,nflg.2,durstr.10,xoff.3 str tie.3,stem.3,beamstr.7,artstr.15 str comt.40 table NX(100) str old_ntype.1 str Tuplet.7 str previous_note_line.160 str next_inline.160 str string_beats.4 /*&dB CCARH beats int beats_in_tuplet int tuplet_end,middle_tuplet,tuplet_sign int turn_tuplet_off str dynamic_sign.1, dynamics.10 str word.WORD_LENGTH /*&dB word in singing str figstr.50(MAX_FIG) /* &dBfigured bass string str Figure.10 /* &dBfigured harmony for one CCARH note int figdur /* &dBfor advance of figure division pointer int figy /* &dBtells where a figure character should be written int figlines /* &dBtells how many figure str duration_string.5 str figure_codes.200(MAX_FIG) /* &dBpush code durations for a measure - (figured bass) str error_message.80 /*&dB code for errors and warnings str error_message2.80 str Text.35 int text_layer int text_postion str numerical_parameter.3 int old_orny,orny /*&dB where an orniment is vertically located int max_height,height /*&dB used to determine height of ornaments int max_beams,beams /*&dB if a lot of beaming, need to raise ornaments higher int lowest_height int measure_lowest_point /* &dBfor determining how high figured harmonies can be placed int lowest_point /* &dBhow low a given note goes - for reasence of clearence int divcount /* &dBCCARH duration "ticks" for the measure so far int tick /* &dBthe present CCARH time division for the measure int duration /* &dBCCARH duration "ticks" for a particular notes int staff_number /* &dBused only for CCARH grand staff int number_of_tracks /* &dBa track is one part in a CCARH file int track /* &dBthe present track int base_track /* &dBuswd in writing to the out table str whole_push_codes.8(MAX_MEAS) /* &dBstores whole rest push codes for the entire work, used with multi-staff int number_of_staves /* &dBkeeps track of number of staves in a part int number_of_measures /* &dBnumber of measure in a part int lines_to_omit /*&dB counts the number of lines to be removed by a tag str single_digit_type.1 /* &dBspecifies if 01 or 1 for single digit file names str symbol_table.SYMBOL_SIZE(MAX_TRK,MAX_TIC) /*&dI &dBThe measure table structures (see below) int duration_table(MAX_TRK,MAX_TIC) /*&dI label LL1(20) &dA &d@ &dB &dA Main program&d@ &dB &dA &d@ &dB darms_file = 0 /*&dB initialization of variables ccarh_file = 1 ipnt = 1 outpnt = 1 out_line2_number = 1 counter = 1 header_line = 1 track = 1 tick = 1 staff_number = 1 old_ntype = " " putc CCARH -> DARMS music translation program putc putc Errors and warnings are written to &dJtrans_err&d@ perform get_mfilename ( ccarh_file ) perform get_mfilename ( darms_file ) putc Each file in CCARH directory should be a part. (grand staff = one file = one part) putc Enter number of parts to translate. getc xparts if xparts < 1 or xparts > XPARTS xparts = 1 putc Only doing one part end putc Which file (by number) do you want to begin with (for example: 1) ? getc counter open [2,2] outfile open [3,2] "trans.err" open [1,1] inlib /* check directory to see if 1 or 01 getf [1] in_line if in_line{1} = "0" single_digit_type = "0" else single_digit_type = "" end close [1] perform initialize_darms_file &dA Main loop&d@ TO_DARMS: loop for partnum = counter to counter + xparts - 1 cflag = FALSE tden = -1 number_of_staves = 1 number_of_measures = 1 if partnum < 10 temp_line = inlib // "\" // single_digit_type // chs(partnum) else temp_line = inlib // "\" // chs(partnum) end open [1,1] temp_line putc ~temp_line putf [3] ~temp_line ipnt = 1 perform read_file_into_INX perform translate_header_to_darms if partnum > 1 out_line = out_line // "!I" // chs(partnum) // " !-50 " /* moves down to next stave end loop while ipnt < max_in_lines tget [INX,ipnt] in_line if in_line{1} = "$" /* musical attributes perform translate_musical_attributes_to_darms end if in_line{1} = "*" /* musical directions perform translate_musical_directions_to_darms end if in_line{1} = "m" /* bar lines perform translate_bar_line_to_darms end if in_line{1} in ['A'..'G','r','g','c',' '] /* notes & rests (including grace & cue) perform translate_notes_to_darms end if in_line{1} = "f" /* figured harmony perform translate_figured_harmony_to_darms end if in_line{1} in ['i','b'] /* forward/backspace in time perform translate_fb_to_darms end if in_line{1} in ['@','&'] /* comments perform translate_comments_to_darms end if in_line{1} = "/" /* end of music or file perform translate_end_to_darms end if in_line{1} = "S" iflag = TRUE end if in_line{1} = "P" iflag = TRUE end if iflag = FALSE error_message = "unrecognized data type (line type)" perform write_error end iflag = FALSE ++ipnt repeat close [1] repeat END: perform write_file_from_OUTX putc Bye! close [2] &dA &dA &d@ &dE P R O C E D U R E S &dA &dA &dA &dB*P 1. get_mfilename &dA &dA &dB Receives as input which type of music-file object it is returning &dA &dB the name of. Then it asks the user for a name until the user types &dA &dB in an alpa-numeric responce. This value, in its corresponding &dA &dB variable, is returned. &dA procedure get_mfilename ( file_type ) int file_type str name.100 getvalue file_type if file_type = DARMS putc Please enter DARMS output file name. end if file_type = CCARH putc Please enter CCARH input directory name. end AGAIN: getc name if name = "" putc Invalid - please enter again. goto AGAIN end if file_type = DARMS outfile = name else inlib = name end return &dA &dA &dB*P 2. read_file_into_INX &dA &dA &dB Reads from the input file into the table &dEINX&dB &dA &dB This preprocesses the information and greatly speeds the program&d@ &dA &dB because it doesn't need to do many intermitant reads of the drive &dA procedure read_file_into_INX ipnt = 1 loop getf [1] in_line if in_line{1} = "a" /* &dBappend CCARH &dJappend&dB records to previous line --ipnt tget [INX,ipnt] temp_line temp_line = trm(temp_line) in_line = temp_line // in_line{2..} end if in_line{1} = "t" /* &dJtags&d@ if in_line{2} = "t" /* &dBomit tags&d@ lines_to_omit = int(in_line{3}) ++lines_to_omit /* &dBomit this line as well else in_line = in_line{2..16} // " " // in_line{17..} end end if lines_to_omit > 0 /* &dBline is to be ignored because of tag --lines_to_omit else in_line = in_line // pad(80) tput [INX,ipnt] ~in_line ++ipnt end repeat while in_line{1..4} <> "/END" max_in_lines = ipnt ipnt = 1 return &dA &dA &dB*P 3. write_file_from_OUTX &dA &dA &dB Writes to the output file by reading the table OUTX &dA procedure write_file_from_OUTX str line.300 counter = 1 putf [2] ~staves loop while counter < outpnt tget [OUTX,counter] line line = line // pad(4) putf [2] ~line ++counter repeat if number_of_staves > 1 counter = 1 putf [2] !-50 loop while counter < out_line2_number tget [OUTX2,counter] line line = line // pad(4) putf [2] ~line ++counter repeat end return &dA &dA &dB*P 4. initialize_darms_file &dA &dA &dB Writes a few global codes that CCARH doesn't account for &dA procedure initialize_darms_file staves = "!I1 16!@ " /* set instrument number & text verticle position out_line = "K DARMS file translated from CCARH Stage 2 file $" return &dA &dA &dB*P 5. translate_header_to_darms &dA &dA &dB Copies the CCARH header into comments (K...$) and places them at the &dA &dB beggining of the DARMS file. &dA procedure translate_header_to_darms in_line = " " loop while in_line{1} <> "$" tget [INX,ipnt] in_line in_line = trm(in_line) // pad(1) out_line = "K " // in_line // " $" tput [OUTX,outpnt] ~out_line ++outpnt ++ipnt repeat --outpnt /* &dBdon't want to comment the first line of code! --ipnt out_line = "" return &dA &dA &dB*P 6. translate_musical_attributes_to_darms&d@ &dA &dA &dB Translate lines beggining with a "$. &dA &dB K: Key &dA &dB Q: Divisions per quarter note &dA &dB T: Time designation &dA &dB C: Clef &dA &dB S: Staff &dA &dB D: Directive &dA &dA &dB &d@ &dBThe table &dENX&dB is a hash table containing the note names for &d@ &dB &dA &dB &d@ &dBCCARH octave and their corresponding staff line in DARMS &d@ &dB &dA &dB &d@ &dBnotation. This table is then looked up by the translate_notes &dA &dB &d@ &dBto quickly find the correct translation without calcualtion. &d@ &dB &dA &dB &d@ &dBThese values are in relationship to CCARH octave 5, where &dA &dB &d@ &dBoctaves begin with C and C4 is middle C. Since the F clef is &d@ &dB &dA &d@ &dBin octave 4, the line values for octave 5 are thus&d@ &dBin the &dA &d@ &dBteens. &dA procedure translate_musical_attributes_to_darms iflag = TRUE if in_line con "K:" key = int(in_line{mpt+2..}) testfor key > 0 /* &dBsharps&d@ if key = 1 out_line = out_line // "!K# " else out_line = out_line // "!K" // chs(key) // "# " end else (<) /* &dBflats&d@ if key = -1 out_line = out_line // "!K- " else key = 0 - key out_line = out_line // "!K" // chs(key) // "- " end else (=) /* &dBC or A min&d@ out_line = out_line // "!K " end end if in_line con "Q:" /* &dBCCARH records beats in a quarter note divspq = int(in_line{mpt+2..}) end if in_line con "T:" /* &dBtime signature tnum = int(in_line{sub+2..}) if in_line{sub} = "/" tden = int(in_line{sub+1..}) else error_message = "illegal time designation T:" // chs(tnum) // "/" // chs(tden) perform write_error end out_line = out_line // "!M" if tnum = 1 and tden = 1 /* &dBcommon time&d@ out_line = out_line // "C " else if tnum = 0 and tden = 0 /* &dBalla breve time out_line = out_line // "C/ " else if tnum = 2 and tden = 0 /* &dBsimple 2&d@ out_line = out_line // "2:2 " else if tnum = 3 and tden = 0 /* &dBsimple 3&d@ out_line = out_line // "3:3 " else out_line = out_line // chs(tnum) // ":" // chs(tden) // " " end end end end end if in_line con "C" /* &dBcleff&d@ CLEF: if in_line{mpt+1} in ['0'..'9'] ++mpt staff_number = int(in_line{mpt}) else staff_number = 1 end clef_type = int(in_line{mpt+2..}) clef_type = clef_type / 10 clef_line = 2*(6 - rem) - 1 /* &dBtranslate between line codes if clef_type = 3 /* &dBG-8&d@ if cflag = TRUE out_line = out_line // chs(clef_line) // "!G-8 " else if partnum > 1 staves = staves // "," // chs(clef_line) // "!G-8" else staves = staves // chs(clef_line) // "!G-8" /* &dBG-8 = 1 DARMS octave higher end end clef_line += 10 /* &dBG-8 CCARH G5 + 10 = clef_line end if clef_type = 0 or clef_type = 6 /* &dBG clefs&d@ if cflag = TRUE out_line = out_line // chs(clef_line) // "!G " else if partnum > 1 staves = staves // "," // chs(clef_line) // "!G" else staves = staves // chs(clef_line) // "!G" end end clef_line += 3 /* &dBCCARH G4 + 3 = clef_line end if clef_type = 2 or clef_type = 5 or clef_type = 8 /* &dBF clefs&d@ if cflag = TRUE out_line = out_line // chs(clef_line) // "!F " else if partnum > 1 staves = staves // "," // chs(clef_line) // "!F" else staves = staves // chs(clef_line) // "!F" end end clef_line += 11 /*&dB CCARH F4 + 11 = clef_line end if clef_type = 1 or clef_type = 4 or clef_type = 7 /* C if cflag = TRUE out_line = out_line // chs(clef_line) // "!C " else if partnum > 1 staves = staves // "," // chs(clef_line) // "!C" else staves = staves // chs(clef_line) // "!C" end end clef_line += 7 /* &dBCCARH C4 + 7 = clef_line end temp_line = "C" // chs(staff_number) /* &dBSet the &dENX&dB Table up. This table is used tput [NX,temp_line] ~clef_line /* &dBto keep the Darms line number for each CCARH temp_line{1} = "D" /* &dBpitch (within a one octave range). The tput [NX,temp_line] ~(clef_line + 1 ) /* &dBDARMS line number is triggered by the raw temp_line{1} = "E" /* &dBpitch and then the staff number (usually 1). tput [NX,temp_line] ~(clef_line + 2) /* &dBAll seven basic pitches are coded for at temp_line{1} = "F" /* &dBright. Each of these pitches refers to tput [NX,temp_line] ~(clef_line + 3) /* &dBthe fifth octave. temp_line{1} = "G" tput [NX,temp_line] ~(clef_line + 4) temp_line{1} = "A" tput [NX,temp_line] ~(clef_line + 5) temp_line{1} = "B" tput [NX,temp_line] ~(clef_line + 6) old_mpt = mpt if in_line{mpt+1..} con "C" mpt += old_mpt ++xparts ++partnum /* &dBadd one for each stave of grand staff ++staff_number goto CLEF /* &dBtreat each staff of grandstaff as one instrument end cflag = TRUE end if in_line con "S:" staff_number = int(in_line{mpt+2..}) end if in_line con "D:" if out_line <> "" out_line{len(out_line)} = "," end out_line = out_line // "@" // trm(in_line{mpt+2..}) // "$ " end if divspq > 0 and tden > -1 if tden = 0 and tnum = 0 /* &dBalla breve time&d@ measure_divisions = divspq * 4 else if tden = 0 and ( tnum = 2 or tnum = 3) /* simple 2 or 3 putc No time signature denominator specified. Please Enter. putc 1 = whole note 8 = 8th note note 16 = 16th etc. getc tden measure_divisions = divspq * 4 * tnum / tden else measure_divisions = divspq * 4 * tnum / tden end end end staff_number = 1 return &dA &dA &d@ &dBEND of translate_musical_attributes_to_darms&d@ &dA &dA &dB*P 7. translate_musical_directions_to_darms &dA procedure translate_musical_directions_to_darms iflag = TRUE /* parse line into variables directions = trm(in_line{17..18}) numerical_parameter = in_line{21..23} if directions con "A" /* &dBRehersal numbers/letters end if directions con "B" /* &dBRight-justified ASCII string&d@ end if directions con "C" /* &dBCentered Ascii string end if directions con "D" /* &dBLeft-justified ASCII string end if directions con "E" /* &dBBegin wedge&d@ end if directions con "F" /* &dBEnd wedge&d@ end if directions con "G" /* &dBLetter dynamics&d@ end if directions con "H" /* &dBBegin dashes (after words) end if directions con "J" /* &dBEnd Dashes&d@ end if directions con "P" /* &dBBegin Pedal&d@ artstr = artstr // "?P" end if directions con "Q" /* &dBRelease Pedal&d@ artstr = artstr // "?*" end if directions con "U" /* &dBShift notes up (e.g. 8va) end if directions con "V" /* &dBShift notes down (e.g. 8va)&d@ end if directions con "W" /* &dBStop shift&d@ end return &dA &dA &d@ &dBEND of translate_musical_directions_to_darms&d@ &dA &dA &dB*P 8. translate_bar_line_to_darms &dA &dA &dB Converts CCARH "m" lines into corresponding DARMS notation. &dA &dB Input comes from INX, and output goes to OUTX &dA &dB &d@ &dBNote: the segno sign is taken translated by the standard note/rest &dA &dB procedure because DARMS can't encode segnos at bar-lines. &dA procedure translate_bar_line_to_darms ++number_of_measures iflag = TRUE measure_number = int(in_line{BEGIN_BAR_NUMBERC..END_BAR_NUMBERC}) if in_line{2..7} = "easure" bar_line = "/" else if in_line{2..7} = "dotted" /* &dBin DARMS: bar_line = "/." /* &dB | = heavy bar line&d@ else /* &dB / = light bar line&d@ if in_line{2..7} = "double" /* &dB : = repeat bar_line = "//" else if in_line{2..7} = "heavy1" bar_line = "|" else if in_line{2..7} = "heavy2" bar_line = "/|" else if in_line{2..7} = "heavy3" bar_line = "|/" else if in_line{2..7} = "heavy4" bar_line = "||" else error_message = "unrecognized barline type" perform write_error end end end end end end end if in_line{BAR_LINE_FLAGC..} con ":|" repeat_back = ":" end if in_line{BAR_LINE_FLAGC..} con "|:" repeat_forward = ":" end if in_line{BAR_LINE_FLAGC..} con "start" /* &dBstart ending&d@ end if in_line{BAR_LINE_FLAGC..} con "stop" /* &dBstop ending&d@ end if in_line{BAR_LINE_FLAGC..} con "disc" /* &dBdiscontinue ending end figy = measure_lowest_point measure_lowest_point = 0 if figy > FIG_Y figy = measure_lowest_point end if number_of_tracks > 1 /* &dBTrack = notes overlapping in time on same part loop for counter = 1 to MAX_STAVES /* &dBsplit into "instruments" (staves really) base_track = (TRACKS_PER_STAFF * (counter - 1) ) + 1 if number_of_tracks > base_track out_line = "!& " // out_line /* &dBstart instrument's linear decomposition end if number_of_tracks > base_track loop for track = base_track to base_track + TRACKS_PER_STAFF - 2 temp_line = out_line ++track perform copy_track_to_out_line --track if out_line = "" out_line = temp_line perform copy_track_to_out_line perform write_bar_line_to_out_line out_line = out_line // " $& " perform put_out_line_to_OUTX else out_line = temp_line perform copy_track_to_out_line perform write_out_line_to_OUTX end out_line = "" repeat ++track perform copy_track_to_out_line perform write_bar_line_to_out_line whole_push_codes(number_of_measures) = "\W " // repeat_back // bar_line // repeat_forward // " " perform put_out_line_to_OUTX out_line = "" else ++track perform copy_track_to_out_line end repeat else perform copy_track_to_out_line end if figlines > 0 /* &dBif figured bass to write out_line = "!& " // out_line loop for counter = 1 to figlines perform write_out_line_to_OUTX figy -= 3 out_line = chs(figy) // "!A " // figure_codes(counter) repeat figy = FIG_Y end perform write_bar_line_to_out_line if number_of_tracks > TRACKS_PER_STAFF + 1 or figlines > 0 out_line = out_line // " $&" figlines = 0 end out_line = out_line // " " perform put_out_line_to_OUTX loop for counter = 1 to MAX_FIG figure_codes(counter) = "" /*&dB clear&d@ repeat out_line = "" repeat_back = "" /*&dB reset string flags repeat_forward = "" duration = 0 perform clear_measure_table /*&dB clears the measure_table structure return &dA &dA &d@ &dBEND of translate_bar_line_to_darms&d@ &dA &dA &dB*P 9. write_bar_line_to_out_line &dA procedure write_bar_line_to_out_line if out_line = "" return end out_line = out_line // repeat_back // bar_line // repeat_forward if measure_number > 0 out_line = out_line // chs(measure_number) end return &dA &dA &dB*P 10. write_out_line_to_OUTX &d@ &dB &dA procedure write_out_line_to_OUTX out_line = out_line // repeat_back // bar_line // repeat_forward // " &" whole_push_codes(number_of_measures) = "\W " // repeat_back // bar_line // repeat_forward // " " perform put_out_line_to_OUTX return &dA &dA &dB*P 11. write comment &d@ &dB &dA &dA &dB This procedure checks to make sure comments are only &dA &dB written when a chord is not present. Because comments &dA &dB require delimiters of a space&d@ &dBbefore and after, this &dA &dB effectively breaks up a chord into individual notes. &dA &dB Thus, the comments are all saved until after such times &dA &d@ &dBas there is no chord.&d@ &dA procedure write_comment if chord = FALSE and comt <> "" out_line = out_line // " K" // comt // "$ " comt = "" end return &dB &dA &dA &dB*P 12. translate_notes_to_darms &dA &dA &dB Translates notes and rests &dA &dB &dA &dB &d@ &dBDynamics: for dynamics, DARMS begins with a V. This is what the &dA &dB &d@ &dB variable dynamic_sign is meant to encode &dA &dA &dB &d@ &dBThis is the biggest and most important procedure in the &d@ &dB &dA &dB &d@ &dBprogram. It is responisble for converting all "notes and &d@ &dB &dA &dB &d@ &dBrests" - anything with a durational value. It draws on the &d@ &dB &dA &dB &d@ &dBmeasure table "data structure" though this is transparent &dA &dB &d@ &dBbecause it calls subfunctions to handle the interface. It &d@ &dB &dA &d@ &dBshould take one pass through to convert&d@ &dBany notehead or &dA &d@ &dBrest. &dA procedure translate_notes_to_darms int smpt,colnum,tcolnum iflag = TRUE tget [INX,ipnt + 1] next_inline if in_line{STAFF_NUMBERC} = " " staff_number = 1 else staff_number = int(in_line{STAFF_NUMBERC}) end if staff_number > number_of_staves number_of_staves = staff_number end temp_line = mrt(in_line{C6..C8}) duration = int(temp_line) if in_line{1..4} = "rest" /* &dBrest&d@ sp_code = "R" /* &dBDARMS doesn't place this correctly if track > 1 if grace_cue = TRUE grace_cue = FALSE out_line = out_line // "$Q " end else if in_line{1} in ['g','c'] /* &dBgrace note / cue note if grace_cue = FALSE grace_cue = TRUE if in_line{1} = "g" /* &dBDARMS can use G for grace note, comt = comt // " grace note(s) " /* &dBbut CCARH provides more information else /* &dBso treat as if cue comt = comt // " cue note(s) " end if in_line{2} = " " out_line{len(out_line)} = "," /* &dBreplace trailing space with comma end if in_line{GRACE_CUE_TYPEC} <> "0" /* &dBDARMS supports grace/cue type 0 - out_line = out_line // "!Q " /* &dBseperate from the general cue mechanism end end if in_line{2} = " " /* &dBgrace/cue in chord&d@ chord = TRUE end smpt = mpt if "A9876543210" con in_line{GRACE_CUE_TYPEC} mpt <<= 1 durstr = durstr // " WWW H Q E S T X Y Z G "{mpt,2} durstr = trm(durstr) if mpt = 22 comt = comt // " accented " grace_cue = FALSE end end mpt = smpt old_ntype = in_line{NTYPE} else if in_line{1} = " " /* &dBextra note in cord&d@ chord = TRUE else chord = FALSE /* &dBnormal note&d@ end if grace_cue = TRUE grace_cue = FALSE out_line = out_line // "$Q " end end perform get_symbol_height (in_line) sp_code = sp_code // chs(height) /* &dBheight is the line on which the note sits end perform write_comment smpt = mpt if " #nfxXSF&" con in_line{AXC} if mpt = 1 &dA &d@ error_message = "illegal symbol (accidental) in column " // chs(AXC) &dA &d@ perform write_error else mpt <<= 1 axstr = " # * - ####*#*---"{mpt,2} axstr = trm(axstr) end else error_message = "illegal Accidental in column " // chs(AXC) perform write_error end mpt = smpt if in_line{STEMC} = "u" stem = "U" end if in_line{STEMC} = "d" stem = "D" end if tuplet = TRUE if in_line{TUPLETC} = " " turn_tuplet_off = TRUE else if previous_note_line{C32..C43} con "!" /* &dBlook at previous note/rest line turn_tuplet_off = TRUE else if previous_note_line{BEAMC} = "]" and explicit_tuplet = FALSE turn_tuplet_off = TRUE end end end end if turn_tuplet_off = TRUE Tuplet = "$R" tuplet = FALSE turn_tuplet_off = FALSE explicit_tuplet = FALSE end if in_line{TUPLETC} con ['0'..'9'] and tuplet = FALSE /* &dBtuplet duration Tuplet = trm(in_line{TUPLETC,3}) tuplet = TRUE middle_tuplet = (int(Tuplet{1}) + 1) / 2 /* determine which note to place sign over if len(Tuplet) = 1 /* &dBneed to infer beat base /* count beats using explicit markers: * and ! beats_in_tuplet = 0 if in_line{C32..C43} con "*" explicit_tuplet = TRUE counter = ipnt loop tget [INX,counter] temp_line string_beats = temp_line{BEATSC,3} string_beats = rev(string_beats) /* &dBremove leading blanks string_beats = trm(string_beats) string_beats = rev(string_beats) beats_in_tuplet += int(string_beats) if temp_line{C32..C43} con "!" tuplet_end = TRUE end ++counter repeat while tuplet_end = FALSE tuplet_end = FALSE /* count beats using implicit markers: beaming else if in_line{BEAMC} <> "[" error_message = "not enough information to convert tuplets" end counter = ipnt loop tget [INX,counter] temp_line string_beats = temp_line{BEATSC,3} string_beats = rev(string_beats) /* &dBremove leading blanks string_beats = trm(string_beats) string_beats = rev(string_beats) beats_in_tuplet += int(string_beats) if temp_line{BEAMC} = "]" tuplet_end = TRUE end ++counter repeat while tuplet_end = FALSE tuplet_end = FALSE end middle_tuplet = (counter - ipnt + 1) / 2 /* &dBdetermine which note to place sign over if beats_in_tuplet = 0 error_message = "can't read beats (divisions)" perform write_error else &dA &dA &d@ &dB tuplets (DARMS) are indicated by : &dA &d@ &dB triplets are usually written 3:2 &dA Tuplet = "!R" // Tuplet // ":" // chs(divspq / beats_in_tuplet) if rem <> 0 error_message = "Tuplet beats don't add up evenly" perform write_error end end else Tuplet = "!R" // Tuplet end end if next_inline{1} = "m" and next_inline{BAR_LINE_FLAGC..} con "A" artstr = artstr // "?%" /* &dBcheck for segno at CCARH barline&d@ art_pos = TRUE end if durstr <> "G" /* &dBif not DARMS grace note&d@ if grace_cue = FALSE and durstr <> "G" smpt = mpt if "Lbwhqestxyzdv " con in_line{NTYPE} goto LL1(mpt) LL1(1): durstr = durstr // "WWW" goto LL1E LL1(2): durstr = durstr // "WW" goto LL1E LL1(3): durstr = durstr // ucs(in_line{NTYPE}) goto LL1E LL1(12): error_message = "can't presently handle dot independant of note" perform write_error goto LL1E LL1(13): comt = comt // "K No note in this position $ " goto LL1E LL1(14): durstr = durstr // "W" if in_line{1..4} <> "rest" error_message = "unclear duration of note - whole assumed" perform write_warning end else if "987654321" con in_line{NTYPE} durstr = durstr // "WHQESTXYZ"{mpt} goto LL1E else error_message = "can't identify duration of note or rest" perform write_error end end LL1E: mpt = smpt old_ntype = in_line{NTYPE} end if in_line{DOTC} = "." durstr = durstr // "." end if in_line{DOTC} = ":" durstr = durstr // ".." end end if in_line{STEMC} = " " and in_line{1} in ['A'..'G'] /* &dBno stem&d@ nflg = "N1" end if middle_tuplet > 0 /* &dBmiddle tuplet marks how far to writing tuplet sign --middle_tuplet end loop for counter = BEAMC to BEAMC + 6 if in_line{counter} = "[" beamstr = beamstr // "(" end if in_line{counter} = "]" beamstr = beamstr // ")" end if in_line{counter} in ['/','\'] if hooked_beam_marker = FALSE beamstr = beamstr // ";" hooked_beam_marker = TRUE end if in_line{counter} = "/" beamstr = beamstr // "(" else beamstr = beamstr // ")" end end repeat &dA &dA &d@ &dAProcess columns 32 to 43&dB &dA in_line = in_line // pad(43) loop for colnum = 32 to 43 if "()[]{}zx" con in_line{colnum} artstr = artstr // "L" // chs(mpt) slur = bit(0,mpt) /* &dBopen = 1, close = 0&d@ end if ">._i=" con in_line{colnum} mpt <<= 1 artstr = artstr // " > ' _ i _'"{mpt,2} artstr = trm(artstr) end if "AV,SFE" con in_line{colnum} mpt <<= 2 artstr = artstr // " ?102?103?108?113?109?110"{mpt,4} end if in_line{colnum} = "-" /* &dBtie&d@ tie = "J" end if in_line{colnum} = "*" /* &dBstart tuplet graphic tuplet_sign = TRUE end if "vnotrwM~c" con in_line{colnum} art_pos = TRUE mpt <<= 2 artstr = artstr // " ?V ?D ?123?111?162?125?124?125?125"{mpt,4} artstr = trm(artstr) if mpt > 31 error_message = "'wavy lines' don't translate - will assume inverted mordent" perform write_warning end end if in_line{colnum} = "Q" error_message = "DARMS doesn't support thumb position" perform write_warning comt = comt // " thumb position " end if "012345" con in_line{colnum} and in_line{colnum - 2} <> "&" art_pos = TRUE artstr = artstr // "?" // chs(185 + mpt) end if in_line{colnum} = "^" /* &dBedditorial accent comt = comt // " editorial accidental " end if in_line{colnum} = "+" /* &dBcautionary accent&d@ comt = comt // " cautionary accidental " end if "mpfZR" con in_line{colnum} dynamics = "V" // "MPFZR"{mpt} tcolnum = colnum + 1 loop while "pf" con in_line{tcolnum} and tcolnum <= 44 if tcolnum < 44 dynamics = dynamics // "PF"{mpt} end ++tcolnum repeat colnum = tcolnum - 1 if dynamics{2} = "Z" if dynamics{3} = "P" dynamics{2,1} = "SF" else dynamics{2,1} = "SFZ" end end if dynamics{2} = "R" dynamics{2,1} = "RFZ" end artstr = artstr // dynamics dynamics = "" end repeat &dA &dA &d@ Tuples need to be looked at more carefully! &dA &dA &d@ if tuplet_sign = TRUE and middle_tuplet = 0 &dA &d@ temp_line = chs(166 + int(in_line{TUPLETC})) &dA &d@ art_pos = TRUE &dA &d@ if temp_line = "166" /* &dBtuplet 0 sign &dA &d@ temp_line = "176" &dA &d@ end &dA &d@ artstr = artstr // "?" // temp_line &dA &d@ tuplet_sign = FALSE &dA &d@ end &dA &dA &d@ &dBparse words&d@ &dA &d@ if in_line{TEXTC} <> " " /* &dBif there are words&d@ text_layer = 0 counter = TEXTC loop old_mpt = mpt if in_line{counter..} con "|" /* &dBend-of-word marker&d@ word = in_line{counter..mpt-1} counter = mpt+1 else word = trm(in_line{counter..}) end this_mpt = mpt if word con "\" /* &dBconvert special textual characters smpt = mpt if word{smpt+1} = "0" if word{smpt+2} = "+" /* &dBellipsis for Italian - join two syllables word{smpt} = " " /* &dBnot - supported right now&d@ if warning_flag(ELLIPSIS) = "" error_message = "DARMS has no ellipsis for joining Italian syllables (\0+) " error_message2 = "All ellipses will be replaced with a space (without additional warnings)" perform write_warning warning_flag(ELLIPSIS) = "1" end else if warning_flag(SLASH_ZERO) = "" error_message = "Can't presently translate \0 codes in CCARH vocal text" error_message2 = "All \0s will be replaced with a space (without additional warnings)" perform write_warning word{smpt} = " " warning_flag(SLASH_ZERO) = "1" end end end if word{smpt+1} = "1" if "nNoO" con word{smpt+2} word{smpt} = "€₯υφ"{mpt} end end if word{smpt+1} = "2" if "cCoOs" con word{smpt+2} word{smpt} = "‡€στχ"{mpt} end end if word{smpt+1} = "3" if "aAeEiIoOuUyY" con word{smpt+2} word{smpt} = "„Ž‰δ‹ι”™š˜π"{mpt} end end if word{smpt+1} = "4" if "aA" con word{smpt+2} word{smpt} = "†"{mpt} end end if word{smpt+1} = "5" if "sS" con word{smpt+2} word{smpt} = "ωψ"{mpt} end end /*&dB 6 is normal characters - don't need to check for if word{smpt+1} = "7" if "aAeEiIoOuUyY" con word{smpt+2} word{smpt} = " β‚‘θ’μ£ορς"{mpt} end end if word{smpt+1} = "8" if "aAeEiIoOuU" con word{smpt+2} word{smpt} = "…αŠεη•λ—ξ"{mpt} end end if word{smpt+1} = "9" if "aAeEiIoOuU" con word{smpt+2} word{smpt} = "ƒΰˆγŒζ“κ–ν"{mpt} end end if len(word) > smpt + 2 /* &dBremove the two extra code characters word = word{1..smpt} // word{smpt + 3} else word = word{1..smpt} end mpt = smpt end Text = Text // "," // chs(TEXT_Y + (text_layer*TEXT_OFF)) // "@" // word // "$" ++text_layer repeat while old_mpt <> this_mpt /* &dBrepeat if mpt changes&d@ end hooked_beam_marker = FALSE /* set out_line if art_pos = TRUE /* &dBstate new "global" articulation verticle perform assign_verticle_position /* &dBheight now = height for ornaments if old_orny <> orny out_line = out_line // chs(orny) // "!A " old_orny = orny end end if chord = TRUE out_line{len(out_line)} = "," /* &dBreplace trailing blank with chord delimiter end if Tuplet <> "" out_line = out_line // Tuplet // " " end lowest_point = height /* &dBfind clearence underneath note if figstr(1) <> "" if stem = "D" lowest_point -= 8 if in_line{BEAMC} <> "" lowest_point -= 3 end else if artstr con "L" /* &dBslur&d@ lowest_point -= SLUR_HEIGHT end end if lowest_point > measure_lowest_point measure_lowest_point = lowest_point end end out_line = out_line // sp_code // axstr // nflg // durstr // xoff out_line = out_line // tie // stem // beamstr // artstr // Text // " " perform write_comment if figdur = 0 loop for counter = 1 to MAX_FIG figure_codes(counter) = figure_codes(counter) // "\" // durstr // figstr(counter) // " " repeat else /* &dBdelayed figured harmony figdur = duration - figdur perform get_duration_string (figdur) loop for counter = 1 to MAX_FIG figure_codes(counter) = figure_codes(counter) // "\" // duration_string // figstr(counter) // " " repeat figdur = 0 end loop for counter = 1 to MAX_FIG /* &dBclear figstr(.) array figstr(counter) = "" repeat perform put_out_line_in_measure_table tick += duration if tick > MAX_TIC error_message = "Program can't handle this many divisions per quarter." error_message2 = "Increase the size of macro MAX_TIC, and run again." perform write_error goto END_NOTE end END_NOTE: track = 1 out_line = "" sp_code = "" axstr = "" nflg = "" durstr = "" xoff = "" tie = "" beamstr = "" artstr = "" Text = "" Tuplet = "" art_pos = FALSE chord = FALSE previous_note_line = in_line return &dA &dA &d@ &dBEND of translate_notes_to_darms&d@ &dA &dA &dA &d@ &dKmeasure table functions&d@ &dA &dA &d@ A measure table is a special data structure I invented &dB &dA &d@ to help with music. It probably can be used, with some &dB &dA &d@ refinement, in a lot of music translation programs. It &dB &dA &d@ seems to get at the heart of music encrption. &dB &dA &dA &d@ Printed music seems to consist of a few basic dimensions. &dB &dA &d@ 1. Verticle extent of a symbol. &dB &dA &d@ 2. Horizontal extent of a symbol &dB &dA &d@ 3. Verticle location of a symbol &dB &dA &d@ 4. Horizontal location of a symbol &dB &dA &d@ 5. The symbol itself &dB &dA &dA &d@ Sounded music has these dimensions &dB &dA &d@ 6. which voice generates the sound(s) &dB &dA &d@ 7. temporal onset of sound &dB &dA &d@ 8. temporal duration or sound &dB &dA &d@ 9. pitch &dB &dA &dA &d@ Basically, music can be encoded with these above dimensions &dA &d@ being specified. However, printed music contains more &dA &d@ information, so the sound information ideally is already &dA &d@ encoded in the printed music. &dA &dA &d@ The difficulty with translating encoded music is that the &dB &dA &d@ symbol dimension is quite complex and multi-dimensional &dB &dA &d@ itself. Much effort is therefore dedicated to making semantic &dB &dA &d@ translation (symbol A -> symbol B) and grammatical &dB &dA &d@ translation (symbols AB -> BA). Of these two, grammatical &dB &dA &d@ translation is by far the more complicated because the number &dB &dA &d@ of dimensions of variability are quite large and it is hard &dB &dA &d@ to concieve of a shared basic structure. Grammatical &dB &dA &d@ translation would be easier if a data structure which ordered &dB &dA &d@ the information from above could be developed. By nature, &dB &dA &d@ this data structure would be a memory-hog, for it would have &dA &d@ to sub-devide the problem along its most important access &dA &d@ into the smallest necessary pieces. From there, the rest of &dA &d@ the information could be placed in this ordered structure. &dA &dA &d@ I argue that most important dimension of the problem is the &dB &dA &d@ temporal dimension. It is hard to imagine music encryption &dB &dA &d@ where the order of the symbols is contrary to the order in &dB &dA &d@ which they are played. The one exception is when multiple &dB &dA &d@ sounds are meant to be played simultaneously. After &dB &dA &d@ reviewing this exception, I have discovered that this &dB &dA &d@ situation is prevelent and very flexible. I therefore &dB &dA &d@ suggest that another important dimension is the "voice" &dB &dA &d@ (#6) but with a flexible definition of voice. If the &dA &d@ symbol itself is thought to be primarily semantic, or &dA &d@ grammatical on a local level, and the symbol is thought to &dA &d@ encode the other information, that leaves the following &dA &d@ data structure. &dA &dA &d@ The measure table stores the symbols, and the duration table &dA &d@ stores the length of a symbol's duration &dB &dA &dB &dA &d@ Ticks (each cell = minimum necessary time division) &dB &dA &d@ ΪΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔΒΔΔ ΒΔΔΏ &dB &dA &d@ ³a1³a2³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³a?ΓΏ &dB &dA &d@ ΓΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔ ΕΔΔ΄³ &dB &dA &d@"Tracks" ³b1³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³b?³³ str symbol_table ( track # , tick # ) &dB &dA &d@ ΓΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔ ΕΔΔ΄³ in front &dB &dA &d@ ³c1³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³c?³³ &dB &dA &d@ ΓΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔΕΔΔ ΕΔΔ΄³ int duration_table ( track # , tick # ) &dB &dA &d@ ³ in back &dB &dA &d@ ΐΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔΑΒΔ ΑΔΔΩ &dB &dA &d@ ΐΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔΑΔΔ ΑΔΔΩ &dB &dA &d@ Symbol and Duration structures &dB &dA &d@ &dB &dA &d@ Each cell contains a symbol S or a blank. Many times &dA &d@ cells won't be necessary. This is because the information &dA &d@ needs to be "expanded" from the presumed information &dA &d@ compression that computer encryption naturally incurs. &dA &d@ The Track allows for multiple symbols with different &dA &d@ requirements to be stored at the same time division &dA &dA &dA &dB*P 13. copy_track_to_out_line &dA procedure copy_track_to_out_line duration = 1 divcount = 0 perform get_duration_string (duration) /* &dBget the DARMS representation of a single CCARH&d@ tick loop for tick = 1 to measure_divisions duration = duration_table(track,tick) divcount += duration if divcount < tick /* &dBneed to fill in time voids&d@ loop for counter = 1 to divcount - tick out_line = out_line // "\" // duration_string // " " repeat end out_line = out_line // symbol_table(track,tick) repeat if divcount > measure_divisions error_message = "too many beats in measure" perform write_error end divcount = 0 return &dA &dA &dB*P 14. put_out_line_in_measure_table &d@ &dB &dA procedure put_out_line_in_measure_table track = (TRACKS_PER_STAFF * (staff_number - 1) ) + 1 /* &dBdistance tracks by tracks per staff loop for counter = tick + 1 to tick + duration - 1 /* &dBcheck forward for overlap if duration_table(track,tick) <> 0 ++track end repeat counter = tick loop while counter > 1 and duration_table(track,counter) = 0 /* &dBfind previous note on this track --counter repeat loop while tick - counter < duration_table(track,counter) /* &dBoverlap on this track in backwards direction ++track counter = tick loop while counter > 1 and duration_table(track,counter) = 0 /* &dBfind previous note on this track --counter repeat repeat if track > MAX_TRK error_message = "Out of tracks - increase MAX_TRK macro size" perform write_error else symbol_table(track,tick) = out_line /* &dBupdate measure table structures duration_table(track,tick) = duration end if track > number_of_tracks number_of_tracks = track end return &dA &dA &dB*P 15. clear_measure_table &d@ &dB &dA procedure clear_measure_table loop for track = 1 to number_of_tracks loop for tick = 1 to measure_divisions symbol_table(track,tick) = "" duration_table(track,tick) = 0 repeat repeat track = 1 tick = 1 number_of_tracks = 1 return &dA &dA &d@ &dA END &d@ &dIMeasure table functions &dA &dA &dB*P 16. assign_verticle_position &d@ &dB &dA &dA &dB &d@ &dBUsed to assign the verticle position for DARMS &dA &dB &d@ &dBdictionary characters, particularly the ornaments &dA procedure assign_verticle_position max_beams = 0 max_height = 0 if stem = "D" orny = height + 3 if slur = TRUE /* &dBslur requires more space orny += SLUR_HEIGHT end if orny < ORNY /* &dBminimum height&d@ orny = ORNY end else if stem = "U" if tuplet = TRUE orny = height - 4 if slur = TRUE /* &dBmake room for slur&d@ orny -= SLUR_HEIGHT end else if beamstr <> "" /* &dBbeaming can cause longer stems counter = ipnt temp_line = in_line loop while temp_line{BEAMC} <> "[" /* &dBscroll back to begging of beam --counter tget [INX,counter] temp_line repeat loop while temp_line{BEAMC} <> "]" /* &dBscroll forward to look for tallest note perform check_height repeat perform check_height orny = max_height + 9 /* &dBplace over beams&d@ if max_beams > 2 /*&dB adjust for a lot of beaming orny += 2 * (max_beams - 2) end else orny = height + 9 end if orny < ORNY /* &dBminimum height&d@ orny = ORNY end end else error_message = "placing ornaments is difficult without explicit stem direction" perform write_warning end end return /* &dBassign_verticle_position&d@ &dA &dA &d@ &dBEnd of assign_verticle_position&d@ &dA &dA &dB*P 17. check_height &d@ &dB &dA &dA &dB &d@ &dBUsed by get_verticle_height to determine the maximum &dA &dB &d@ &dBheight of a note in a beamed group. This is important &dA &dB &d@ &dBwhen placing ornaments - the beaming can easily get in &dA &d@ &dBthe way, even if the note is low. &dA procedure check_height perform get_symbol_height (temp_line) if height > max_height max_height = height end if temp_line{BEAMC..END_BEAMC} con " " /* &dBcount beam markers beams = mpt - BEAMC /* &dBmpt is = first non-beam position else beams = END_BEAMC - BEAMC /* &dBhighest number of beams&d@ end if beams > max_beams max_beams = beams end ++counter tget [INX,counter] temp_line return &dA &dA &dB*P 18. get_symbol_height &d@ &dB &dA &dA &dB &d@ &dBGets the DARMS representation of where to place a note&d@ &dBor symbol &dA &dB &d@ &dB &dJrecord&dB the CCARH input line (containing a note) &dA &dB &d@ &dJheight&dB is the line on which the symbol sits 1 = bottom line of staff &dA &dB &d@ &dB 9 = top line of staff &dA &d@ &dBThe procedure defines &dJnote&dB as the CCARH pitch information &dA procedure get_symbol_height (record) str record.160 str note.4 getvalue record if grace_cue = TRUE or chord = TRUE if grace_cue = TRUE and chord = TRUE note = trm(in_line{3..6}) else note = trm(in_line{2..5}) end else note = trm(in_line{1..4}) end temp_line = note{1} // chs(staff_number) tget [NX,temp_line] height /* &dBretrieve correlated line from table&d@ if note con ['0'..'9'] octave = int(note{mpt}) height += 7 * (octave - 5) /* &dBadd/subtract seven for every octave /* &dBaway from the fifth octave&d@ if record{C32..C43} con "U" /* &dBshift up an octave&d@ height += 7 end if record{C32..C43} con "D" /* &dBshift down an octave height -= 7 end else error_message = "no octave specified" perform write_error end return &dA &dA &d@ &dBEnd of get_symbol_height&d@ &dA &dA &dB*P 19. get_duration_string &d@ &dB &dA &dA &d@ &dBTakes the real input duration_beats and outputs the correct &dA &dB &d@ &dBDARMS string&d@ &dBrepresentation. It calculates a ratio, where &dA &dB &d@ &dBthe divisor is the the number of beats (CCARH) in a quarter &dA &dB &d@ &dBnote. &dA &dA &d@ &dBThe ratio follows a nice asymptotic curve. It is derived &d@ &dB &dA &dB &d@ &dBby having the value in question devided by the number of &dA &dB &d@ &dBbeats per quarter note. Thus, a quarter has value 1, a &dA &dB &d@ &dBwhole has value 4, and eight = .25 &dA procedure get_duration_string (duration_beats) real ratio int duration_beats getvalue duration_beats ratio = flt(duration_beats) / flt(divspq) if ratio < 1.0 if ratio >= .25 if ratio >= .5 if ratio >= .75 if ratio > .75 duration_string = "E.." else duration_string = "E." end else duration_string = "E" end else /* &dB.25 <= ratio < .5 if ratio >= .375 if ratio > .375 duration_string = "S.." else duration_string = "S." end else duration_string = "S" end end else /* &dBless than .25&d@ if ratio >= .125 if ratio >= .1875 if ratio > .1875 duration_string = "T.." else duration_string = "T." end else duration_string = "T" end else if ratio >= .0625 duration_string = "X" if ratio > .0625 duration_string = duration_string // "." end else if ratio >= .03125 duration_string = "Y" if ratio > .03125 duration_string = duration_string // "." end else if ratio >= .015625 duration_string = "Z" if ratio > .015625 duration_string = duration_string // "." end end end end end end else if ratio < 2.0 duration_string = "Q" if ratio >= 1.5 duration_string = duration_string // "." if ratio > 1.5 duration_string = duration_string // "." end end else if ratio < 4.0 duration_string = "H" if ratio >= 3.0 duration_string = duration_string // "." if ratio > 3.0 duration_string = duration_string // "." end end else if ratio < 8.0 duration_string = "W" if ratio >= 12.0 duration_string = duration_string // "." if ratio > 12.0 duration_string = duration_string // "." end end else if ratio < 16.0 duration_string = "WW" if ratio >= 24.0 duration_string = duration_string // "." if ratio > 24.0 duration_string = duration_string // "." end end else duration_string = "WWW" if ratio >= 48.0 duration_string = duration_string // "." if ratio > 48.0 duration_string = duration_string // "." end end end end end end end return &dA &dA &dB*P 20. translate_figured_harmony_to_darms &dA &dA &dB &d@ &dBInterprets the CCARH lines beginning with "f". These &dA &dB &d@ &dBlines contain the encryption of figured bass. This &dA &dB &d@ &dBprocedure creates a string in &dEfigstr(.)&d@ &dBwhich is &dA &dB &d@ &dBused by the Note/Rest translation function&d@ &dBwhen it &dA &d@ &dBwrites the following note to &dJout_line&d@ &dA &d@ &dB procedure translate_figured_harmony_to_darms int fcnt fcnt = 0 iflag = TRUE in_line = trm(in_line) // " " &dA &dA &d@ &dBparse figure fields &dA if in_line{FIGURE_FIELDSC} <> "" old_mpt = 0 if in_line{FIGURE_FIELDSC..} con " " loop ++fcnt if FIGURE_FIELDSC + old_mpt + 1 <= len(in_line) Figure = in_line{FIGURE_FIELDSC + old_mpt..FIGURE_FIELDSC + mpt - 1} end &dA &dA &d@ &dBmain process&d@ &dA &d@ counter = mpt if Figure con ['+','\'] /* &dBunusual numbers if Figure con "+" /* &dBaugmented figures if Figure con "2+" figstr(fcnt) = figstr(fcnt) // "?196" else if Figure con "4+" figstr(fcnt) = figstr(fcnt) // "?197" else if Figure con "5+" figstr(fcnt) = figstr(fcnt) // "?198" else error_message = "DARMS doesn't support unusual augmented figured harmonies :" // Figure perform write_warning end end end end if Figure con "\" /* &dBraised interval if Figure con "6\" figstr(fcnt) = figstr(fcnt) // "?199" else if Figure con "7\" figstr(fcnt) = figstr(fcnt) // "?200" else error_message = "DARMS doesn't support unusual raised figured harmonies : " // Figure perform write_warning end end end else /* &dBnormal numbers&d@ if Figure con ['0'..'9'] figstr(fcnt) = figstr(fcnt) // "?" // chs(int(Figure{mpt}) + 186) if Figure{mpt + 1} in ['0'..'9'] figstr(fcnt) = figstr(fcnt) // "?" // chs(int(Figure{mpt + 1}) + 186) end end end if Figure con "#" /* &dB(small) sharp figstr(fcnt) = figstr(fcnt) // "?47" end if Figure con "n" /* &dB(small) natural figstr(fcnt) = figstr(fcnt) // "?49" end if Figure con "f" /* &dB(small) flat&d@ figstr(fcnt) = figstr(fcnt) // "?48" end if Figure con "x" /* &dB(small) double sharp figstr(fcnt) = figstr(fcnt) // "?50" end if Figure con "-" /* &dBshort line in&d@ figstr(fcnt) = figstr(fcnt) // "?107" error_message = "basso continuo: short line in, figured harmony, may not translate" perform write_warning end if Figure con "_" /* &dBlong line from previous figure figstr(fcnt) = figstr(fcnt) // "?107" error_message = "lines in basso continuo figured harmony may not translate" perform write_warning end /* &dBskip "b" - it is merely a blank old_mpt = counter if in_line{FIGURE_FIELDSC + counter..} con " " mpt += counter else mpt = old_mpt end repeat while mpt <> old_mpt end end if fcnt > figlines figlines = fcnt end fcnt = 0 &dA &dA &d@ &dBdetermine if figure is followed by non-note delay (e.g. a quarter, instead of dotted quarter) &dA if in_line{C8} <> " " temp_line = mrt(in_line{C6..C8}) figdur = int(temp_line) /* &dBdetermine duration of figure (non-note duration) perform get_duration_string (figdur) loop for counter = 1 to MAX_FIG figure_codes(counter) = figure_codes(counter) // "\" // duration_string // figstr(counter) // " " figstr(counter) = "" /* &dBneed to clear repeat end return &dB &dA &d@ &dBEND of translate_figured_harmony_to_darms&d@ &dA &dA &dB*P 21. translate_fb_to_darms &dA &dA &dB &d@ &dBTranslates the CCARH directions of irest and back, which &dA &dB &d@ &dBmove the pointer pointing to the present beat in the measure &dA &dB &d@ &dBforward or backward. This allows for extra notes, etc., to &dA &dB &d@ &dBbe placed at the same verticle position. This can be used &dA &dB &d@ &dBfor encoding multiple voices on a single staff (multiple &dA &dB &d@ &dBtracks). The ability to do this allows great flexibility, &dA &d@ &dBand is a great aid in handling special cases in music. &dA procedure translate_fb_to_darms iflag = TRUE temp_line = mrt(in_line{C6..C8}) if in_line{1..5} = "irest" tick += int(temp_line) else if in_line{1..4} = "back" tick -= int(temp_line) else iflag = FALSE end end return &dA &dA &dB*P 22. put_out_line_to_OUTX &d@ &dB &dA procedure put_out_line_to_OUTX if out_line = "" return end if track <= TRACKS_PER_STAFF tput [OUTX,outpnt] ~out_line ++outpnt else if track > MAX_STAVES * TRACKS_PER_STAFF + 1 error_message = "Can't handle more than two staves per part presently." error_message2 = "Split up the parts if possible, then rerun" perform write_error stop end tput [OUTX2,out_line2_number] ~out_line ++out_line2_number end return &dA &dA &dB*P 23. translate_comments_to_darms &dA &dA &dB Surounds comment lines with K...$ (comments to DARMS) &dA procedure translate_comments_to_darms iflag = TRUE if in_line{1} = "&" /* &dBcycle through multiple lines of comments loop ++ipnt tget [INX,ipnt] in_line in_line = trm(in_line) // pad(1) out_line = "K " // in_line // "$" perform put_out_line_to_OUTX repeat while in_line{1} <> "&" else out_line = "K " // trm(in_line) // " $" perform put_out_line_to_OUTX end out_line = "" return &dA &dA &dB*P 24. translate_end_to_darms &dA procedure translate_end_to_darms iflag = TRUE if in_line{2..5} = "FINE" loop ++ipnt tget [INX,ipnt] in_line in_line = trm(in_line) // pad(1) if in_line <> "/END" and in_line <> " " out_line = "K " // in_line // " $" perform put_out_line_to_OUTX end repeat while in_line <> " " and in_line <> "/END" else if in_line{1..4} <> "/END" error_message = "unrecognized or out of place END type command (starts with / )" perform write_error end end return &dA &dA &dB*P 24. translate_end_to_darms &dA &dA &dB &d@ &dBWrite both to error file and to screen the parameterized &dA &dB &d@ &dBerror&d@ &dBmessage. &dA procedure write_error putc Error line ~ipnt : ~error_message putf [3] Error line ~ipnt : ~error_message if error_message2 <> "" putc ~error_message2 putf [3] ~error_message2 error_message2 = "" end putc >~in_line putf [3] >~in_line error_message = "" return &dA &dA &dB*P 25. write_warning &dA &dA &dB &d@ &dBWrite both to error file and to screen the parameterized &dA &dB &d@ &dBerror message. &dA procedure write_warning putc Warning line ~ipnt : ~error_message putf [3] Warning line ~ipnt : ~error_message if error_message2 <> "" putc ~error_message2 putf [3] ~error_message2 error_message2 = "" end putc >~in_line putf [3] >~in_line error_message = "" return run &dA &dA &dE END OF CCARH_DARMS TRANSLATOR &dA &dA