╔═══════════════════════╗ ║ AUTOSET and AUTOSCR ║ ╚═══════════════════════╝ Version 4.02 (Must correspond with VERSION variable) (rev 02/06/04) (rev 03/18/06) As of 03/18/06, these two very similar programs have been unified into one source. The differences are controlled by the AUTOSCR variable at the top of the #define list. Preamble to the AUTOSCR program ======================================= This program is the first of a set of three programs designed to convert MUSEDATA Stage 2 full-score files into SCORE pmx files. The program was first derived from the 3.03 version (rev 04/08/97) of autoset. As with autoset, the input to the program are stage2 files; the output are non page specific I-files. The task of converting to SCORE is slightly different from that of typesetting, since it is not concerned with versatility of output or presentation; it is simply data conversion. The autoscr program also has additional tasks to perform and will pass on information to the i-files which is not transferred by autoset. The i-files, themselves, will have modifications that the music typesetting programs are not set up to read. This means essentially that for purposes of data conversion, we are modifying the i-file format to accommodate extra data which is specifically related to the SCORE pmx format. Since versatility of size is not a consideration in data conversion, the autoscr program is designed to operate at one size only, namely, size-14. Since we are simply concerned with transferring all data in the most compact manner, we will be constructing only full-score SCORE files. SCORE itself has a very advanced tool-set for resizing scores and for extraction of parts. .................................................................... Preamble to the AUTOSET program ======================================= Program takes input file from source library file and creates an intermediate file Note: With a program as complex as this one, there are necessarily going to be corner cases that are too difficult or too obscure to handle properly. To prevent the details of these cases from being "lost" in the program, there will appear from time to time paragraphs labled "CORNER", which decribe the situation and any potential limitations imposed on the program. .................................................................... Version control ─────────────── 09-21-93 Added 8th element to tiearr (.,TIE_FOUND) to prevent program from looking twice for tie 09-21-93 Added code to allow multiple rests when there are two or more instruments all resting. (one staff only) 09-22-93 In the old version, only one wedge, one dashes and one of each type of transpos could be active at once. By expanding the smusdir array, we can expand this to five of each type of super-object 09-22-93 Attempting to fix several things. (1) whole rest should be counted as a "pass" in computing MULTI_TRACK (2) accidentals should not be repeated on a unison sounding note (mcat >= 2) 09-23-93 Temporary ASCII data was being stored in tdata which for the multiple measure case was being overwritten. Storage is now in tsdata. 09-30-93 The sorting process for the ts(.) array has been changed. Hopefully it is now more rigorous. The old algorithm is presered in comment. 10-09-93 Autoset now works on a group of files within a stage2 directory. There is an default option for the output directory, based on the group being worked on. 10-09-93 Adding the "Print suggestion" feature to the stage2 format. All four slur letter pairs now are interchangable. Forcing a slur above or below a note is done using a print suggestion. Also, print suggestions are now the preferred way to indicate a font in a musical direction. 10-09-93 Added 9th element to tiearr (.,TIE_FORCE) to force a tie to be overhanded or underhanded 11-11-93 Added Attribute type sub-objects. Immediate application was to add duration attribute. Duration is expresed as a ratio. 1/4 = quarter note, etc. 01-08-94 A side effect of the bubble sort of the mf(.) array (c. line 3450) was that chord tones (type 2) were being separated from their principal tones (type 1). The bubble sort has been replaced with a sort that does not do this. 03-19-94 Minimum distance between notes can be set with a print record. Also note value having this minimum distance can be set with print record 03-20-94 Option added to let a note with a dot be "over-printed" (combined with) a note without a dot, and vice versa, provided the notes are the came type (color). See DOT_DIFFERENCE below. (Changed 12/24/05. This feature is now controlled by the dot_difference_flag.) 03-20-94 Typesetting of unisons refined. (1) Typeset unisons are allowed only when all notes of first chord are either equal/above all notes of second chord, or equal/below all notes of second chord. (2) Fixed a bug where typeset unisons were sometimes shifted to the right. 03-20-94 Global tuplet print options added (tuplet_print_flag). Grand staff distance option added (granddist now set by print suggestion). 03-21-94 Vertical position of musical diretions can now be modified. 03-23-94 Fixed problem of spurious accidentals being added as a result of ties from the previous measure. 03-26-94 Completely overhauled the horizonal spacing mechanism. The problem was that the logic which added extra space was located too late in the program, after detailed information about the vertical right and left profiles was lost. 03-29-94 Improved placement of ornaments, accidentals attached to ornaments, fingerings 03-30-94 Added new component of data storage to the ts array system. Basically, we would like to be able to alter the x-y position of various elements using print suggestions. To store this information, we have added a string array: tsr.48(MAX_OBJECTS) 04-07-94 Added capability to blank out notes or rests; to leave space for an irest; to shift notes or rests (the entire object) left or right, up or down; to shift a set of figures left or right, up or down. Increased length of tsr strings to 51. 04-26-94 Changing the way the program makes space for text. In the final analysis, the placement of text and the arrangement of notes over text must be done by mskpage. What is important here is that we allow enough space to accommodate text, while at at the same time adding as little as possible to the spacing parameters. Also implementing multiple text lines at this time. 05-27-94 Trying to correct a problem of slur placement. There seems to be some confusion over when to modify the position above an object, vs. below an object. For some reason I can't figure out, this information was not consistant with slur tips. Upon reflection, it seems that slurs tips should determine this correctly all of the time. I'm probably missing a subtle point here, so I'd better watch things for a while. 05-29-94 Under certain conditions, the NOTEDUR parameter can give the wrong "time-space" increment. We cannot allow this parameter to be less than the time distance (number of divisions) to the next time node. This fix may not yet be complete, since we still may have wrong values for Leland's score duration parameter. Time will tell. 06-08-94 Attempting to add code to deal with repeaters. 06-18-94 Adding feature that lets musical directions include an optional offset (measured in divisions) from the point where they occur in a measure. This allows things like cresc. to appear in the middle of longer notes. There is a slight problem in adding this feature. Normally a musical direction will generate a SIGN or a WORDS type object. This translates in the intermediate code to a "D" type object. "D" type objects belong to the group called "passing objects," which means that the mskpage program passes over them when looking for controlling nodes. The problem is that if one of this objects occupies a division by itself, it should not be passed over. The solution that seems to work the best is to assign "D" objects with this special feature (unique division number) to a new object type called "I" (isolated direction) which shares all of the properties of the "F" (figure) group of objects. This does not seem to effect their printing in any way, but it does seem to assure that they will receive proper treatment by mskpage. In order to make this work in this program, we need to set a special flag for SIGNS, WORDS and MARKS that stand on their own division (or stand with other members of this same group). If this flag is set, these elements in the ts(.) array must be treated like figures in the section of the program that computes space and syncopation. 10-11-94 Added capability to specify absolute vertical position of rests, etc. Increased length of tsr string to 68. 10-13-94 Added capability of specifying font changes for *-type records with P-print suggestions using the C<columm>: where the font change is to occure. This takes the !## change font instructions out of the source data and puts them in the P-print suggestions where they belong. 11-21-94 Small problem: We were using oldsct as the end of the valid data in tsdata. However, tsdata is loaded according to the value of @n, which can exceed sct in certain situations. In the case where action processes multiple measures, this could result in data in tsdata being overwritten. The solution was to introduce a new variable old@n, which is used to keep track of the end of valid data in tsdata. Since old@n tracks @n and not sct, no data will be overwritten. old@n is set to zero at the same time sct is set to zero. 01-01-95 Fix autoset so that it can serve as the source for both regular autoset.z and autoset6.z (notesize = 6) 01-02-95 The wedge spread parameter was not being properly scaled. It should be multiplied by notesize / 10. 02-23-95 In the case where text is sporatically present (lower voices of chorals, for example), there is no provision to mark the end of text, when the text ends with an extender (_). Introduce new variable textconflag which is turned on for notes having a simple extender and off for any other text. The combination of no text and textconflag = ON is then the situation we need to mark. We will use textconflag as a bit flag (i.e., bit 0 means extender in level one; bit 1 means extender in level two; etc.) 04-17-95 Fix autoset so that it can serve as the source for auto21.z (notesize = 21) 04-22-95 Allow situation where notesize is odd; i.e., vpar(1) <> vpar(2) / 2. In this case, we assume 2 * vpar(1) = notesize - 1 05-29-95 Unified AUTOSET for all note sizes 05-31-95 Code added to prevent tuplets over "partial" beams from being associated with those beams. 01-30-96 In non ISO case of two parts, where two notes are combined as a chord, the "main" note was not given the right stem flag. Added line to do this. When combining rests in ISO case, you need to clear last line of array ts(.,.), because you will use it later for collecting info on slurs New code to look for cases where groups of notes might be combined under the same beam. At the moment, this works only with two parts and with regular notes. 03-04-96 Added capability to handle repeaters with two alternating notes. 09-27-96 Added capability to force rests to be printed on the middle line. 10-12-96 New feature supported: ties that don't terminate on a note. The primary use of this is when there is a first ending or a da capo with a tie that refers back to an earlier point in the music. This feature is implemented using a new type of musical direction ("X"). 12-24-96 Added capability to handle triple and quadruple dots 02-02-97 Fix problem of overlapping trill extensions. Added arrays pre_tsnum, pre_ctrarrf, and pre_try (pre = preliminary) 02-19-97 Allow alternate repeaters to work on even-tuples of 6 or greater. Allow slurs with alternate repeaters, when slurs start at the beginning of a beam and end at the end of a beam 02-23-97 Allow print suggestions for different kinds of printing. Use columns 2-. Blank in column 2 = universal print suggestion. Otherwise read columns 2-- until a blank is encountered. Codes for selective suggestions: "p" = parts "s" = score "t" = short score (piano vocal) 02-23-97 Implement print suggestions for numbering measures. 02-24-97 Fixed AUTOSET so that the accumulation of inctype (the time value increment from the previous node) adds up to a full measure. This problem arrises from durations that divide the quarter note by factors other than 2 or 3. 02-24-97 Implement Y co-ordinate positioning of wavy line (~) by means of print suggestion. 02-25-97 Attempting to deal with the problem of tied notes with accidentals that span over to system boundaries. Proposed solution is to invent a catagory of "invisible" Sub-Object (type small-k), which will appear in i-files, and will only be activated in page files, when needed (i.e., when there is a new system). 03-01-97 Fix multiple accidentals on ornaments. Allow trills with wavy lines (~) to have accidentals. 03-21-97 Add print suggestions for tuplets. Square vs. round; broken vs. continuous; number inside vs. outside. 03-24-97 Implemented print suggestions for articulations. (I think) 04-08-97 Fix it so that all ornaments attached to notes of a chord are printed (i.e., ornaments are not combined the way articulations, accents, bowings, fermatas are). 04-20-03 Implemented print suggestions for ties (as a form of articulation). This involves (1) increasing the length of tsr string to 72, and (2) adding a 10th element to tiearr (.,TIE_SUGG) to contain suggestions. 04-24-03 Allowing print suggestion for extra notes of chords 05-02-03 Implemented print suggestions for extension dots and accidentals. Increasing the length of tsr string to 80. 05-02-03 Adding version control to print suggestions. Hereafter every print suggestion with a version control number will be checked against the version of autoset running. If the one's digit and the tenth's digit do not correspond, a warning message will be printed. The version also contains a 100ths digit. This allows autoset to be revised in ways wherein print suggestions are not affected. 05-06-03 Implemented print suggestions for the shape, length and position of slurs. Length of tsr string increased to 112. 05-14-03 Implementing a print suggestion for modification of the first stem length of beam. Length of tsr string increased to 116 05-17-03 Implementing editorial square brackets for dynamics, ornaments and accents (not trill super-objects, not articulations) 05-25-03 Implementing a print suggestion for preventing mskpage from altering the spacings it computes in a particular measure, when it is trying to justify a line. Obviously this will be over-ridden when there is only one measure in the line. 09-01-03 Fixing a program error. When there was a note with multiple lines of text, and the first line had an extension character ("_"), autoset was ignoring the rest of the text data (i.e., the data for the remaining lines.) 09-14-03 In the case where an "I" type object is being set, it can happen that the variable inctype is calculated incorrectly. The procedure putobj has been modified to check "I" type objects for illogical inctypes. If a correction is made, a cautionary statement is issued. This fix is somewhat of a cludge. 09-22-03 Some variables related to key and accidentals were not being properly initialized at the top of the processing loop. 10-01-03 Allowing a print suggestion for directives (* records) to set the font to zero: e.g., P C25:f0 This will cause the directive to not be printed. This feature can be used to blank directives in selected parts of a score, or allow directives to appear in parts but not in the score. 10-19-03 Corner case error: For some reason, text records are not supposed to have a "-" character in them; the solution appears to be the use of "=" as a substitute for "-". At c. line 14330, the substitution is made, but the code neglected to take into account that "\0=" = "fi". This is now fixed. 10-20-03 Introducing optional conversion to ligitures in text. Set LIGIT = 1 to convert. 11-04-03 Adding code to allow for job-specific print suggestions to be specified by column number. 11-16-03 Adding feature: It is now possible to put editorial parentheses around figured harmonies. 12-09-03 Adding a new section of code which attempts to mitigate somewhat the unevenness in note spacing introduced by the addition of text. This modification also adds an optional second sub-parameter to the second parameter (sobx) of the text record. This second sub-parameter contains the un-modified sobx for use in cases where MSKPAGE or MSKPART stretches out the notes and leaves enough room to keep the text at its original computed location. 12-10-03 Adding code to shorten the down stem for music with text for notes on middle line of staff or on the adjacent space above (B4 and C5 in the treble clef). 12-16-03 Adding the ability for print suggestions to apply to specific notesizes or to sets of note sizes. 12-16-03 Adding the option of running AUTOSET with a note compression factor. Also trying to reduce the gradularity of note distance calculations by multiplying them all by 100. Introducing new variables cfactor and xmindist 01-03-04 Adding a new print suggestion that directs autoset to generate type 7 whole rests. MSKPAGE will then be able to omit parts on a system by system basis, for those parts containing only type 7 whole rests. 01-06-04 Adding a new print suggestion to implement line control features. 01-17-04 Fix a bug in program. In order to typeset slurs, it is apparently necessary to know the terminating pitch. For this reason (only), it is sometimes necessary to process more than one measure at a time. If time changes were encountered in these additional measures, they were being typeset at the beginning of the group instead of in their proper place. The fix is to make sure that time changes encountered after the first measure are placed in the ts(.) array and processed in their proper order. Also, time changes that occur at the beginning of a measure must have their spn number set to 6913. 01-17-04 Fix a bug in program. We need to keep font changes for musical directives from interferring with the text of these directives. Font changes are signalled in-line by inserting "!<#>", where <#> is the new font number. We will now add a terminator "|" to this code, so that font changes are now signalled by "!<new font>|". 01-19-04 The problem with inctypes that was partially fixed in 09-14-03 still has the problem that the inctype total has be modified. This can cause MSKPAGE to crash. The current change is an attempt to fix this problem. The fix is still a cludge. 02-04-04 Adding the option of using Times Roman font for editorial dynamics and the trill. 02-06-04 Using grace note dot to typeset editorial staccato 03-19-04 We are in the process of converting over to a new system of font organization (and some new text fonts as well). For the moment, we will maintain both versions of AUTOSET. The new code will appear under under the #define parameter NEWFONTS. 04-22-04 As part of NEWFONTS, a new kerning feature has been introduced -- data to be stored in new variable kernmap(52,26) 05-12-04 Adding general print suggestion to turn off the printing of rests -- to be used where a blank line is supplied for a continuo part 12-18-04 Add notesize = 18 to autoset.z 01-30-05 Adding v-type print suggestion to adjust height of text 01-30-05 Adding treatment of "&" flag in measure records 03-04-05 Getting rid of all code alternate to NEWFONTS 04-10-05 In the rare case where there is text and (for reasons of singers range) an alternative pitch is suggested, there was a problem with the 12/09/03 code. It was incorrectly using the alternate pitch to adjust space. The code referenced here fixes this problem, but may alter the original algorighm in unexpected ways, i.e., the "fix" is untested. 04-26-05 Adding print suggestion that allows suppression of printing of a slur. This is used when a slur lines up with a tuple and the preference is to use a curved tuple bracket to represent the slur (thus hopefully avoiding the clash between the slur and the tuple number. The implementation of this suggestion involves the addition of a new bit to the Slur super-object situation flag, sitf. 05-14-05 Shifting position of staccato and spiccato marks when they occur at the stem end of a note (chord) 05-26-05 Expanding general print suggestions to include arbitrarily fixing the position of articulations. 05-28-05 New "C1:]" measure suggestion to implement mid-movement right justification. This is useful for page turns and for locating repeats on system boundaries. 05-29-05 Fixing a minor bug; but the change could produce unexpected results. See NOTE at change. Also fixing a bug that in certain situations reversed the order of Key-change, Time-change. This change should also be watched. 09-22-05 Trying to fix some minor bugs in the positioning of articulations 11-02-05 Allow for special case of a grace note tied to a regular note on the same division. This permits one posible representation of an arpeggiation. 11-05-05 Fixing a minor bug; Accidentals now can attach to trills that include the ~~~~~~~ super-object. Also adding feature that allows accidental to follow the tr. when used with the ~~~~~~~ super_object. (the U option) 11-05-05 Fixing a minor bug; In the case of a key change on the grand staff, cancellation naturals on the second staff where being omitted. Fix --> reset oldkey in loop 11-05-05 Fixing a minor bug; Cautionary accidentals were not being printed for tied-over note. Need to over-ride the small "k" 11-05-05 Adding feature: Tuplet (brackets and numbers) can be moved up or down, left or right, with a print suggestion on the tuplet terminator "!" 12-04-05 Fixing an obscure bug: In certain syncopated situations when processing 3 or more passes (usually on the grand staff). The DINC variable is not set correctly. The "fix" may create new problems, but only in other obscure situations. Keep a lookout! 12-18-05 New feature: a single line staff may be specified by a a clef code = 0 (i.e., "$ C:0") 12-20-05 New feature: implementing general print suggestion j: (P C0:j#) for changing stem directions. Default (j:0) indicates "no change." 12-21-05 New feature: putting "//" in the part name (line 9 of the source file) will cause that part of the name that follows to be put on a second line in the output. Essentially, this works by inserting blanks up to length 17 in place of the "//". 12-20-05 New feature: implementing general print suggestion k: (P C0:k#) for setting certain operational flag (defaults are 0) bit 0: (for two or more tracks) 0 = allow overstrike when there a dot-difference 1 = do not overstrike 01-01-06 New feature: changing the general print suggestion r<#> to be "bit" oriented, and adding a feature that allows irests to globally be passed through as non-printed rest objects. For the suggestion (P C0:r<#>) the bits now indicate as follows: (defaults are 0) bit 0: placement of rests 0 = use default placement 1 = always place on middle line bit 1: treatment of irests. 0 = use irest as a simple "backup" command 1 = treat irest as an "un-printed" rest object 01-01-06 New feature: It is now possible to use the print suggestion Px.. to ask autoset to 1) report on measure progress, and 2) to enter debug mode. Specifically: If column 3 of the command contains the letter "m", then autoset will report the measures it has completed, i.e., operate as if MREPORT = 1 If column 4 of the command contains the letter "d", then autoset will operate in debug mode, i.e., as if &process D were operative. 01-01-06 CHANGING VERSION NUMBER TO 4.01 Reason: We have made significant changes (improvements) to the way autoset processes multi-tracks under the I:2 designation. In particular, Version 4.00 accepted stem-up and stem-down iso-data and rationalized these into a single stem direction. While this allowed for easier creation of merged I:2 data files, it limited autoset in its ability to represent precisely what the encoder intended. In Version 4.01, iso-data is combined (collapsed) only when stem directions are the same. Note: files built for the older version of autoset can still be processed as intended by including the print suggestion "P C0:j3". 01-04-06 There is an on-going problem when repeaters are combined with super-objects. I have crafted a "fix" for the case of simple repeaters + tuples, but there is still much work to be done here. 01-06-06 I have allowed notes with repeaters to have articulations on the first note (I think). 01-06-06 Extending the general print suggestion d<#> to include Ending super-objects. 01-06-06 Extending the general print suggestion a<#> for articulations. 01-07-06 Adding the tremulo ornament to the group which includes trills, turns, mordents, etc. Allowing print suggestions. 01-07-06 There is a bug in the way print suggestions interact with transpositions. The "fix" works, but may expose other problems. 01-07-06 Adding some warnings re: bad format of musical directions (* type records). 01-13-06 Implementing arpeggios 01-15-06 Allowing slurs to end on a repeater (first note in group) 01-15-06 Attempting to allow repeaters on groups of alternating notes of size 6, 12, and 24; i.e., notes pairs represented with extension dots. Additions done "on the fly" and not fully reasoned or fully checked out. Keep an eye on it. 02-19-06 We need to add a feature that allows for different types of note heads to be printed. The immediate need is for an "x" for "cymbal crash," but there are many other percussion and non-standard shapes. Philosophically, this could be approached in two ways: either this information could be "hard coded" as is the note size (i.e., in column 17), or it could be done with a print suggestion. I am planning to take the second route, and here is why. Size, it could be argued should be hard coded, because it is often used to indicate editorial vs. original information, and we have chosen to hard code this distinction. Note shape, on the other hand, does not change pitch or duration, but rather indicates (at most) something about the means by which a note is played and about the sound. It would be nice to hardcode this information, but I don't see an easy way to do this. Columns 17 to 22 are designated for note description, and they are fully taken up. The only way would be to add more codes in column 17, and since printed duration is already contained here (comprising a dimension with 11 elements, we would rapidly run out of codes, if we tried to overlay another dimension of shape. The alternative is to use a print suggestion, and here we have a viable solution. There is already a print suggestion for modifying the printing of note, rest and figure objects. It's designation is "C1:". The code "p" in this catagory accounts for one of the 4 bytes available, and of the 8 bits in this byte, only 4 are currently in use. This means that we could introduce a new catagory "s", which would have 4 bits available to it. This could accommodate 15 exotic note shapes, which should be enough. 03-04-06 Revising AUTOSET so that in default mode multiple rests will be generated only when typesetting parts. Global print suggestion m<#> can be used to over-ride default. C0:m0 = no multi rests; C0:m1 = generate multi-rests 03-07-06 Adding the ability to set multiple rests up to mdouble, mdotted mheavy2, and mheavy3. Note: this feature is normally for parts only. 03-13-06 Removing type 6 and type 7 Symbol Objects (whole rests as symbols) and replacing them with type 9 Rest Objects with inc = 10000 or inc = 10001. The new MSKPAGE requires this. Also, don't even process for "multi rests" unless the multirest_flag = 1 (Normally Parts only). 03-18-06 Combining the source codes for AUTOSCR and AUTOSET. Also, adding certain features of each of these programs to the other. In the case of AUTOSET, we are adding the capability to communicate pitch and track information to the output via attribute records (A records) 03-25-06 Adding various "@" records for tranmitting source and analysis information. 08-23-06 Adding editorial accidentals to key signature 09-13-06 In the soprano clef, the placement algorithm was placing flats too low on the staff. The current "fix" covers only the placement of flat, not flat cancellations. 11-20-06 Adding feature that allows a slur over a set of repeated notes with repeater, provided that the slur covers all the notes in the group and that there are no chords in the repeated pattern. 11-26-06 Fixing a minor bug in the placement of slurs. 11-26-06 Adding feature to global print suggestion C0:k that asks that new key signatures be printed out even when they are no different from the existing one. 11-26-06 Adding feature to allow chords (double stops) with two colors of notes 11-26-06 Fixing a minor bug in the placement of extension dots when combining parts on a single staff 10-14-07 Adding code to allow autoscr to combine notes on a single beam when there are irests present. This situation comes up when there is a change from single parts to a combined part within a measure. 10-15-07 Adding code to put out "silent" key change nodes. No difference in display output. This addition just clears up a corner case bug in the mskpage process (the easiest fix in this case). 10-15-07 Adding code to deal with rests with capital letter note types. With rests, capital letter note types are used to indicate rests which might be taken out if the take out variable wrest = 1 and an entire line in a score has nothing but rests. To signal a capital letter rest, autoset/autoscr puts out a jtype = r instead of the usual jtype = R. The mskpage/spaging program knows how to deal with this and always outputs a capital "R" to the page specific files. 10-24-07 Adding grobal print suggestion for setting musical font in $ records. Default defined by DEFAULT_DTIVFONT. The mdirfont variable is now used only for text in musical directives. Its default is DEFAULT_MDIRFONT. 10-25-07 Fixing a bug in the autoscr process. Accidental shift units are scaled differently in SCORE than in Dmuse. The conversion is 25 SCORE units = vpar(2) Dmuse units. 10-28-07 There is a minor bug in autoset that we fix here. In the case where notes are combined into chords, the print suggestions for the separate notes were being or-ed together, producing unpredictable results. Actually, this is bad encoding on the part of the encoder, and should probably be flagged with a WARNING. But in any case, the print suggestions should be combined in a more intelligent way. 11-02-07 Adding a new global flag, suppress_key, which suppresses the printing of the key signature. This to be used in timpani parts where the timplani are tuned to pitches with accidentals (e.g., B-flat and F). The flag is set by bit-4 of the "k" global suggestion. 11-10-07 I uncovered a major problem in the implementation of print suggestions for articulations. First of all, byte 1 of the tcode string was not being set properly. This was causing getpxpy to return null values for the various suggestions. In addition, the interference section for the code was uniformly preempting the placement articulations irrespective of print suggestions. I have fixed (I think) the problem for the case of spiccatos, but have not checked the results for other articulations. 11-15-07 There is an obscure spacing difference between autoset and autoscr having to do with the typsetting of irest. I think it comes up when the irest has a dot. The fix here is an untested cludge, but it seems to work. 11-19-07 Adding a new global suggestion to allow the minimum space between notes to be altered. P C0:h<#> where # is a percentage of the default (= 9 for notesize 14). 11-24-07 Fixing a small detail having to do with how autoscr computes P3 and P10 12-08-07 There is a problem with the continuation of the ~~~ wavy line when there is more than one pass. The solution is to make ctrflag a one-dimention array indexed by passnum. This change may facilitate the printing multiple wavy lines in a measure on a staff, but it also may introduce some other problems. Keep an eye on this. 12-14-07 Fixing a logical problem that goes way back. The problem is with the array claveax(.), which is used to reset the measax(.,.) array, which in turn is used to determine which accidentals are used in front of notes. When there is a key change in the music, claveax(.) is adjusted AT THE TIME IT IS TYPESET. But the spelling of the notes is determined while the ts(.,.) array is being constructed. If there is a slur over a key change, the ts(.,.) array continues to be built with the old claveax(.) array. What we need is a new array tclaveax(.), which is set to claveax(.) whenever a there is a new build of the ts(.,.) array, but which can be changed if there is a key change. Then measax(.,.) can be reset from tclaveax(.) and the note spellings will reflect the new key. I have made these changes, and the program seems to work. Keep an eye on this, though. 01-01-08 Adding a minor new feature: The "c" option for print suggestion C26: The "c" option is a varient of the "a" option. It converts a single set of repeated notes to a repeater and adds a dot after the combined note value. Strictly speaking, the resulting duration is 50% too long, but the notation provides a convenient way of representing repeated triplets (or some multiple of triplets) without having to put the tuple number above the repeater. The actual duration of the note for spacing purposes is not altered. 01-26-08 Fixing a small bug in connection with editorial accents 02-03-08 Attempting to add a new feature (autoset only), which is the 'R' type musical designation; a rehearsal number of letter with a box drawn around it. The trick will be getting the box size and placement right 04-19-08 There is an error in the way single track processing handles the minimum spacing for dotted rests. This occurs at approximately lines 12300 ++. The computed minimum space is too large, because the right-hand margin gr(.,.) is made too large due to some double counting. I don't want to change this code, however, because it will alter the horizontal spacing, which can (and sometime does) change the way mskpage does the system breaks (an example of being locked in by an error). The problem is not severe, because the minimum space is often exceed anyway by the real space. Fine. But this creates another problem, namely when autoscr computes the space for rests in a multi-track measure, it always uses the multi-track code (irests are ignored by autoset in this situation). This means that the i-file spacings generated by autoset and autoscr may be slightly different; and this can lead to different system breaks. I have added some code at approximately lines 14350 ++ to simulate the single track error. The code is quite cludgey and may not work all of the time. 04-19-08 The single track error describe above also causes the dot following sixteenth and smaller rests to be placed too far to the right. I added a small bit of code to partially fix this problem, The code does not change the horizontal spacing formula. 04-22-08 Adding a new feature: the back tie. Since the position of this character depends only on the note object, it is implemented as a subobject. J = overhand back tie; K = underhand back tie. For purposes of print suggestions, the back tie is handled like a standard ornament. This means back ties may be applied to multiple notes on a chord, but it also means that a note with a back tie may have at most one ornament attached to it. Since back ties are rare (second endings, etc.), this should not be a problem. Note: for the moment, back ties are not converted to SCORE files. 05-01-08 Fixing an obscure problem with slurs. In the case where an "inside" slur is desired (e.g., underhanded in an upper part on a stave), the automatic slur adjustment algorithm tries to make this slur go below everything on the staff, which usually works, but not always. This code change implements a new global print suggest C0:g<#> which can be used to defeat (turn off) the automatic slur adjustment feature. In this case other slur print suggestions should be used to position the slur. 06-04-08 Fixing an obscure problem with the placement of accidentals on notes with repeaters. I changed the limits on the gl(.,.) array so that the accidental does "see" the repeaters. Note: this fix might introduce some overlap in some situations. 06-04-08 Expanding from three to four the number of notes allowed in a chord when multiple passes are used. (I think this works) 09-21-08 Expanding the repeater feature to include sub-groups (secondary beam) of 3 and 6. This comes up in the case of repeated triplets. At the moment, I don't have a way of making this work with the tuple numbers. I just hope the new code does't throw off the common cases. Keep an eye on this. 10-08-08 The first version of autoset permitted up to 15 different dynamic combinations. At the time (c. 1988), this seemed like plenty, so four bits were allocated in the ts(.) array for this purpose. Now, it seems, we have exceeded this limit (Beethoven writes ffp in the 7th symphony). In this code update, I have garnered another three bits, allowing for another 8 dynamic combinations. Only one of which is used at this point (ffp). We have space for 7 more in the current setup. The ts(.) element SUBFLAG_1 actually has two more bits available (before it goes negative), so we could in theory add another 24 dynamic combinations. Lets wait and see what's needed. 10-24-08 Adding a new print suggestion for breaking up a multi-measure rest "P C1:f" The suggest must follow directly after the "measure" record where the break is to occur. It applies only to the typesetting of parts. If this measure (barline) is also to serve as a system break (P C1:]), then the system break suggestion should follow after the multi-measure break. 10-29-08 There was a problem in the way single whole-measure rests were being compiled for parts. For multiple rests, field 8 (the distance increment flag) of the following barline object is irrelevant; but for single whole-measure rests, the mskpage program tries to use that flag in the normal way. When more than one part is being typeset, this can result in an accumulation error. Since typesetting multiple parts in a system is a highly useful feature (e.g., for for comparison purposes), I coded a fix for this problem -- which seems to work, but beware. It may impact the spacing of single whole-measure rests. 11-18-08 The dynamic combination "ff" has been spaced a bit too widely. Adding a new horizontal parameter hpar(140) to deal with this. 11-18-08 Also at this time, I am raising slightly the number over a multiple rest bar for notesize = 21. 12-31-08 Working on the implementation of notesize = 16. 01-02-09 Adding a provision for larger note heads in the size 16 font This effects the following parameters. Altimately, these parameters are fixed in the proofpar library; but for the time being, I want to keep this feature in this program hpar(51) = width of quarter note (approximately) hpar(82) = width of black note (for typesetting) hpar(83) = width of whole note (for typesetting) hpar(84) = width of breve note (for typesetting) 01-12-09 New general print suggestion, a subset of k. If k & 0x10 > 0, the slur pairs "{ }" and "z x" will be interpreted as editorial. 01-12-09 Fixing a minor bug in the implementation of horizontal print suggestions. When the node is isolated, the modification must be in the position of the word sub-object, not the object. 01-12-09 Encountering a new dynamic sign in Mozart of all places, mfp. We will use some of the new space created 10-08-08. 02-02-09 Adding a new element to general print suggestion C0:k Bit 5: set = typeset all new clef signs in full size (for use in multi-singer recitatives). 02-02-09 We can now use the sequence "\+" to indicate an inline "space" character. This is useful in music text underlay. 03-10-09 It turns out that conductors have varying preferences when it comes to the format and appearance of conducting scores. For example, when two instruments appear on a single staff, some conductors want to see both musical lines represented all of the time, vs. showing only the active musical lines. An acceptable variation on this is to show a single line when the instruments are playing in unison. Others would rather see the score kept as clean as possible, with the use of 1. and 2. and a single line of music when only one of the two instruments is playing. For this reason, it is necessary to implement a second score-type group, called skore, whose use we will, by convention, assign to the more complete (and busy) representation. 03-15-09 There needs to be a way to disable the feature where rests are collapsed in the two instrument isorhythmic case. We will use bit 2 of the global print suggestion P C0:r for this. The situation comes up when typesetting scores with complicated two instrument parts. 03-16-09 Encountering a new dynamic sign in Beethoven, sff. We will use some of the new space created 10-08-08. 11-23-09 Fixing a small bug that developed when I tried to improve obx spacing with repeaters. 11-27-09 Adding the "@ SCORECON pitch transposition" option for applying a post pitch modification to the P6 parameter. Program options #define XPOS_FIXED 1 /* with Beethoven, try 1 first, then 0; with Haydn, use 1 #define DISP_DISK "j" #define VERSION "4.02" /* Version 4.00 defined 05/02/03 /* Version 4.01 defined 01/01/06 /* Version 4.02 (current version) defined 02/03/08 (new data file in musprint) #define AUTOSCR 0 #define PGROUP "scrcon" #define SFZ 0 /* SFZ = 1: print sfortzando as sfz #define DOT_DIFFERENCE 1 (12/24/05 now controlled by dot_difference_flag) /* DOT_DIFFERENCE = 1: don't allow overstrike #define SUB_EDIT 1 /* SUB_EDIT = 0: do not distinguish between /* original and editorial data #define NO_EDIT 0 /* NO_EDIT = 1: do not process editorial data #define ROMAN_EDIT 0 /* ROMAN_EDIT = 1: use Times Roman font for /* editorial marks: tr, dynamics #define OLD_REPEATERS 1 /* OLD_REPEATERS = 1: use half notes instead of quarters #define CUSTOM_PAR 1 /* allows use of custom parameters, for whatever reason /* see code at CUSTOM_PAR #define LIGIT 1 /* LIGIT = 1: convert ffl, ffi, ff, fl, fi in /* text subobjects to ligitures /* see code at CUSTOM_PAR #define DEFAULT_DTIVFONT 37 #define DEFAULT_MDIRFONT 31 /* default font for musical directions #define BIG16 0 /* 01/02/09 Wide version of size 16 note heads #define REPORT4 0 #define MREPORT 0 /* 01/01/06 This feature can also be activated by /* using the print suggestion "Pxm." #define OBJ_REPORT 0 #define TRUE 0 #define FALSE 1 Actual Characters #define DOT_CHAR 44 Descriptive Definitions #define TIE_SNUM 1 #define TIE_NTYPE 2 #define TIE_VLOC 3 #define TIE_FHDIS 4 #define TIE_FSTEM 5 #define TIE_NDX 6 #define TIE_STAFF 7 #define TIE_FOUND 8 #define TIE_FORCE 9 #define TIE_SUGG 10 #define TIE_ARR_SZ 10 /* 04/20/03 new 10th element for tiearr #define FIG_SNUM 1 #define FIG_HOFF1 2 #define FIG_HOFF2 3 #define FIG_READY 4 #define REG 1 #define GRACE 2 #define CUE 3 #define CUEGRACE 4 #define BM_SNUM 1 #define BM_CNT 2 #define BM_READY 3 #define BM_STEM 4 #define BM_TUPLE 5 #define BM_SIZE 6 #define BM_SUGG 7 #define BM_SZ 7 #define SL_SNUM 1 #define SL_YSHIFT 2 #define SL_XSHIFT 3 #define SL_NEXTSNUM 4 #define SL_BEAMF 5 #define SL_SUGG 6 #define SL_SIZE 6 #define TU_SNUM 1 #define TU_Y1 2 #define TU_Y2 3 #define TU_FSTEM 4 #define TYPE 1 #define DIV 2 #define CLAVE 3 #define AX 4 #define TEMP4 4 #define NTYPE 5 #define DOT 6 #define TUPLE 7 #define STAFFLOC 8 #define SPACING 9 #define STEM_FLAGS 10 #define BEAM_FLAG 11 #define BEAM_CODE 12 #define LOCAL_XOFF 13 #define SUPER_FLAG 14 #define SLUR_FLAG 15 #define SUBFLAG_1 16 #define SUBFLAG_2 17 #define VIRT_NOTE 18 #define SORTPAR1 18 #define SORTPAR2 19 #define TEMP2 19 #define GLOBAL_XOFF 19 #define TEXT_INDEX 20 #define PASSNUM 21 #define BACKTIE 22 #define NOTE_DUR 23 #define DINC_FLAG 24 #define VIRT_STEM 25 #define ED_SUBFLAG_1 26 #define ED_SUBFLAG_2 27 #define STAFF_NUM 28 #define NUM_STAVES 28 #define MULTI_TRACK 29 #define TEMP1 30 #define SPN_NUM 30 #define OBY 31 #define SLUR_X 32 #define NODE_SHIFT 33 #define TRACK_NUM 34 #define BASE_40 35 #define NOTE_DISP 36 #define AX_DISP 37 #define AUG_DOTS 38 #define TSR_POINT 39 #define TS_SIZE 42 ts(.) Array positions for arpeggio variables (note doublings with other flags) #define ARPEG_FLAG 16 #define ARPEG_TOP 26 #define ARPEG_BOTTOM 27 #define TSR_LENG 116 #define NUMBER_OF_FIG 3 #define FIG_SPACE 4 #define FIG_DATA 5 #define MIN_FIG_SPAC 20 #define FIG_DUR 23 #define SIGN_POS 3 #define SIGN_TYPE 4 #define SUPER_TYPE 5 #define FONT_NUM 6 #define WEDGE_OFFSET 7 #define S_TRACK_NUM 8 #define WEDGE_SPREAD 10 #define POSI_SHIFT1 11 #define ISOLATED 12 #define POSI_SHIFT2 13 #define TIME_NUM 3 #define DOLLAR_SPN 5 /* (New 01/17/04) #define DIVSPQ 3 #define CLEF_NUM 3 #define CLEF_FONT 4 #define TRANS_FLAG 5 #define CLEF_STAFF_POS 6 #define BAR_NUMBER 3 #define BAR_TYPE 4 #define REPEAT 5 #define BACK_ENDING 6 #define FORW_ENDING 7 #define BAR_FLAGS 8 #define M_NUMBER 10 #define REGULAR 1 #define HEAVY 2 #define DOTTED 3 #define DOUBLE_REG 5 #define REG_HEAVY 6 #define HEAVY_REG 9 #define DOUBLE_HEAVY 10 #define DOUBLE_DOTTED 15 #define WEDGES 1 #define DASHES 2 #define OCT_UP 3 #define OCT_DOWN 4 #define DBL_OCT_UP 5 #define DBL_OCT_DOWN 6 #define NORMAL_TRANS 13 #define NOTE 1 #define XNOTE 2 #define REST 3 #define CUE_NOTE 4 #define XCUE_NOTE 5 #define CUE_REST 6 #define GR_NOTE 7 #define XGR_NOTE 8 #define NOTE_OR_REST 8 #define FIGURES 9 #define BAR_LINE 10 #define SIGN 11 #define WORDS 12 #define MARK 13 #define CLEF_CHG 14 #define DESIGNATION 15 #define METER_CHG 16 #define DIV_CHG 17 #define AX_CHG 18 #define P_SUGGESTION 19 #define MUSICAL_DIR 11 #define IREST 12 #define BACKSPACE 13 #define SEGNO 1 #define PED 2 #define END_PED 3 #define LETTER_DYNAM 4 #define RIGHT_JUST_STR 5 #define CENTER_STR 6 #define LEFT_JUST_STR 7 #define TIE_TERM 8 /* TIE_TERM added 10-12-96 #define REH_MARK 9 /* REH_MARK added 10-12-96 #define BELOW 1 #define ABOVE 2 #define HEAD 0 #define TAIL 1 #define FULLSIZE 0 #define CUESIZE 1 #define THIRTY_SECOND 4 #define SIXTEENTH 5 #define EIGHTH 6 #define QUARTER 7 #define HALF 8 #define WHOLE 9 #define BREVE 10 #define SLASH8 0 #define ARPEGGIO 33 /* ARPEGGIO added 01/13/06 #define UP 0 #define DOWN 1 #define SINGLE_NOTE 0 #define CHORD 1 #define NO_BEAM 0 #define END_BEAM 1 #define START_BEAM 2 #define CONT_BEAM 3 #define OFF 0 #define ON 1 * Parametric Definitions #define MAX_STAFF 2 #define MAX_TIES 16 #define MAX_FIG 4 #define MAX_PASS 10 #define MAX_OBJECTS 1000 #define MAX_M 400 * Other Definitions #define DUMMY_VALUE 10000 #define INT1000000 1000000 #define INT10000 10000 #define INT100 100 #define INT9000 9000 #define BHPAR1 30 #define MAX_MEAS 2000 * Process parameters *process D /* 01/01/06 This feature can also be activated by /* using the print suggestion "Px.d" * str infiles.12(100),pgroup.12 str file.100,out.280,line.180,temp.180,lib.30,temp2.160,temp3.160,temp4.160,temp5.20 str line2.180,slurstr.160,slurlet.1,slurover.80,slurunder.80 str inlib.100,outlib.100,outfile.100 str claves.7,numbers.10,accs.3 str note.4,jtype.1,codes.12 str ttext.180,msg.60,xbyte.2 /* ttext lengthened to 180 04/22/04 str tcode.4(MAX_M),tdata.80(MAX_M,2) str sobl.120(30),tsdata.100(MAX_OBJECTS) str mname.60,tname.60,wname.80,sourcename.80,partname.80 str tsr.TSR_LENG(MAX_OBJECTS) /* 05/14/03 expanded length to 116 str version.4 /* 05/02/03 str mrest_line.200 /* New 03/07/06 int tv1(MAX_M),tv2(MAX_M),tv3(MAX_M),tv4(MAX_M) int tv5(MAX_M) /* New 01/17/04 int tvar1,tvar2,tiecnt int supcnt,supnums(12) int mf(256),beampar(4,MAX_PASS,BM_SZ),mf2(120) /* 05/14/03 expanded BM_SZ to 7 int multichk(3,MAX_PASS,MAX_STAFF) int tiearr(MAX_TIES,TIE_ARR_SZ),slurar(8,SL_SIZE),tuar(4,MAX_PASS,4) int figarr(MAX_FIG,4) int sitf,super_flag,slur_flag,subflag_1,subflag_2 int spc(255),nsp(33),claveax(50),measax(4,50) /* 06/04/08 expanding measax to (4,50) int tclaveax(50) /* New 12/14/07 int zak(2,7),wak(9),hpar(200),vpar(200),bvpar(35),vpar20 int a,d,e,g,h,i,j,k,m,s,y,z int @a,@b,@c,@d,@e,@n,old@n int f1,f2,f3,f4,pmode int notesize,mtfont,twfont,beamfont,curfont,mdirfont,dtivfont int olddivspq,divspq int cline(MAX_STAFF),clef(MAX_STAFF),clave,key int a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16 int save_a4 int c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17 int t1,t2,t3,t4 int x1,x2,y1,y2,z1 int olda1,unison_flag,sugg_flg,sugg_flg2 int beamdata(4,MAX_PASS,31),beamcode(31) int passpar(MAX_PASS) int firstsp,tfirstsp,emptyspace(MAX_STAFF,45) int ts(MAX_OBJECTS,TS_SIZE) int sct,oldsct,maxsct,divpoint,mrest,measnum,totdiv,cuediv,mdiv,qflag int figdiv,esnum,smusdir(30,4) int tsnum(MAX_PASS),ctrarrf(MAX_PASS),try(MAX_PASS) int pre_tsnum(MAX_PASS),pre_ctrarrf(MAX_PASS),pre_try(MAX_PASS) int ntype,f8,inctype,jcode,pcode,nodtype,passtype,passsize,stem int firstoff,sigflag int oby,sobx,soby,sobcnt,snum int sobx2 /* added 12/09/03 int obx1,obx2,oby1,oby2 int c8flag(MAX_STAFF),transflag(MAX_STAFF),tuflag,passnum,chorddur,spn int ctrflag(MAX_PASS) /* made into an array 12/08/07 int mindist int tnum,tden,abflg,nstaves int ssize,scnt,debug_point int vflag,mcat,sflag,granddist,outpnt,tword_height int note_dur int minshort int global_tpflag int tpflag,xposi_shift,yposi_shift int save_xposi_shift /* added 01/12/09 int pcontrol,px,py,pyy,pxx int putobjpar int repeater_flag,repeater_flag2,repeater_case int repeater_dot_flag /* added 01/01/08 int repeater_dot_flag2 /* added 09/21/08 int chord_spread,mdir_offset int font_changes(10,2),changecnt int textconflag int min_space /* added 11/19/07 int slur_adjust /* added 05/01/08 bstr outslurs.8 label E(20),T(6),SS(21),PSUG(20),TPF(5),TPFF(5),ADJS(5) /* expanding PSUG 05/01/08 label R1(14) table X(10000),Y(30000) Variables added 6-19-93 for processing slurs int profile(100,2) int sgroup(13,3),nsgroups int curvedata(8,4,8) int curve Variables added 5-27-93 for pseudo typesetting of simultaneous notes int npasses,thispass,passcnt(MAX_PASS,3) int pitchcnt(10) int ndata(20,11) int pcnt int clashes(10,10) int tgroup(10),ntgroups int printpos(10) int ps_passcount(2) int gl(2,45),gr(2,45),oldgr(2,45) int pseudo_gr(2,45) int pseudo_gl(2,45) real r1,r2,r3,r4 Variables added 4-27-94 for determining text position int ttextcnt str ttextarr.80(6) str xbytearr.2(6) Variables added 6-08-94 for working or repeaters str chord_tones.4(10) int chordsize,last_chordsize,chordsize2 int checkoff(10) * int p,x,obx,dv1,dv2,dv3,dv4 Variables added 9-27-96 for controlling position of rests int restplace,restplace2 Variables added 02-23-97 for determining range of print suggestions and numbering measures; and the inctype accumulation problem str job_type.1 int m_number int inctype_rem Variables added 12/09/03 for trying to even out notes with text underlay int nspace(MAX_M,8),org_c4 Variables added 12/16/03 for running AUTOSET with a compression factor int cfactor,xmindist Variable added 01/03/04 for generating option type 7 whole rests int wrest Variable added 10/15/07 for generating optional smaller rests int opt_rest_flag Variable added 01/19/04 to fix the accumulation of inctypes int fix_next_inctype Variables added 03/19/04 to implement NEWFONTS organization str XFontstr.76(12) str kernfiles.360 int XFonts(12,19) int Fspacex(90) int revsizes(24) int nsizes(12) int sizenum int kernmap(52,26) Variables added 05/12/04 to implement print suggestion to turn off the printing of rests (for empty continuo lines). int restoff Variables added 01/30/05 to implement print suggestion to adjust height of text under staff int text_flag int text_loc Variable added 05/26/05 to implement arbitrary fixed placement of articulations int art_flag Variable added 12/18/05 to implement single line staff str LL.1 int single_line Variable added 12/20/05 to implement stem change flag int stem_change_flag bstr tbit1.2000,tbit2.2000 Variable added 12/24/05 to implement various operational flags int dot_difference_flag Variable added 01/01/06 to set various new flags int irest_flag int mreport_flag int debug_flag int ligit_flag int xdata_flag int scr_flag int rest_flag(MAX_PASS) int tracknum_flag Variable added 01/06/06 to allow the d<#> print suggestion to include Endings int ending_height Variables added 01/13/06 to implement arpeggios int arpeg_flag int arpeg_top int arpeg_bottom Variables added 03/04/06 to for controlling the setting of multi-rests int multirest_flag Variables added 11/26/06 to allow reprinting of existing key signature and chords with two colors Also fixing a minor bug in printing extension dots int key_reprint_flag int mixed_color_flag int old_c2 Variables added 10/14/07 to allow autoscr to combine notes under one beam when there are irests present. int beam_fixup_cnt int beam_fixup_arr(100,2) Variable added 11/02/07 to allow suppression of the key signature int suppress_key Variables added 02/03/08 to allow typesetting of boxes around rehearsal numbers int box_flag int font_base,font_height,zero_height Variable added 01/12/09 to allow "{ }" and "z x" to represent editorial slurs int in_line_edslur Variable added 02/02/09 to control the "large clef" option int large_clef_flag Variable added 03/15/09 to permit the disabling of rest collapse int rest_collapse Variables added 03/20/03 for additional code required by autoscr int measuremap(MAX_MEAS,5) /* 1 = number of tracks /* 2 = number of gaps 3 = pointer to data /* 4 = number of divspm 5 = number of divspq int trackstave(MAX_MEAS,9,3) /* trackstave data int timegaps(15000,3) int barnum,tgpnt,staves,track,staff,durflag,barnum2,opbarnum int trackdivpnt(9) int scr_qwidth int how_much_mrest(2) int composer_num int track_flag int track_assign(9) int instrument_number int transposition str jscrdat.80,kscrdat.100 str header1.180 str header2.180 str header3.180 str composer.80 str comp_names.80(20) Variable added 11/27/03 for additional code required by autoscr int pitch_mod ┌──────────────────────────────────────────────────────────────┐ │ Description of arrays not described elsewhere │ └──────────────────────────────────────────────────────────────┘ Description of tiearr(MAX_TIES,TIE_ARR_SZ) This is an array for collecting information on ties. The program allows up to MAX_TIES such simultaneous ties (first dimension of the array). The second dimension contains the following attributes: tiearr(TIE_SNUM) = super-object number for this tie tiearr(TIE_NTYPE) = note type: 1 = note, 2 = xnote, 4 = cue, 5 = xcue, etc. tiearr(TIE_VLOC) = location on staff of tied notes tiearr(TIE_FHDIS) = horizontal displacement of first note head from its object (chords only) tiearr(TIE_FSTEM) = stem flag for first note tiearr(TIE_NDX) = ts() index for first note in tie tiearr(TIE_STAFF) = staff number (0 or 1) for first note in tie tiearr(TIE_FOUND) = tie found flag tiearr(TIE_FORCE) = tie force flag tiearr(TIE_SUGG) = print suggestions for altering tie position (added 04/20/03) Note: It can happen that a note is tied in both directions out of the measure (e.g. pedal points). In this situation, we will need to use the information in the old tiearr before constructing a new one. Since we cannot deposit the tie super-object until we have deposited the terminating note object, and since we cannot deposit this note object without knowing the new super-object number for the forward tie, we must increment snum and store this number somewhere before writing out the note object. We will use tv4(.) to store this number. This also has a baring on how ties are handled within the measure. When a tie flag is encountered, snum is incremented and stored in tv4(.). tv4(.) is filled with ties from the top note down. After any backward ties are dealt with, a free slice of tiearr is identified and filled. The pointer to this slice of tiearr may be put in ts(22) (after old ties are taken care of). If the other end of this tie is encountered within the measure (as determined by ts(22)), then the information in tiearr is used with current information to construct the super-object. Description of figarr(MAX_FIG,4) This is an array for collecting information on continuation lines for figures. The program allows up to MAX_FIG figures, and each of these levels may have a continuation line. The first dimension is therefore MAX_FIG; the highest level is 1 and the lowest level is MAX_FIG. (In this version 3.0, MAX_FIG is 4) The second dimension contines the following attributes: figarr(FIG_SNUM) = super-object number for this continuation figarr(FIG_HOFF1) = horizontal off-set from first object figarr(FIG_HOFF2) = horizontal off-set from second object figarr(FIG_READY) = completion flag: set = array completed Description of beamdata(4,MAX_PASS,31) Note: At the moment, there is a structural reason why the third dimension of beamdata cannot exceed 31. This is because beampar(.,.,BM_STEM) stores stem directions as bits. This is an array for collecting information on the beams that connect notes together. The first dimension tells whether this information is for (1) regular notes, (2) grace notes to regular notes, (3) cue notes, or (4) grace notes to cue notes. The second dimension tells the pass number for this beam. The third dimension contains the beamcodes for the various notes under the beam. The beamcode is a number between 1 and 666661. It describes the structure of the beam for this note/chord. This version (3.0) of the program supports beams up to 256th notes. The ones column of the beamcode is for eighth notes, the tens column for sixteenth notes, etc. The digits have the following meaning: 1 = continued beam 2 = begin beam 3 = end beam 4 = forward hook 5 = backward hook 6 = repeater character 7 = begin repeated beam 8 = end repeated beam Description of beampar(4,MAX_PASS,BM_SZ) 05/14/03 expanded BM_SZ to 7 In addition to beamdata, there are seven other parameters related to beams. These parameters are represented in the array beampar as follows: beampar(BM_SNUM) = super-object number for the beam beampar(BM_CNT) = note counter for beam beampar(BM_READY) = flag that signals that a beam is complete and should be put out. beampar(BM_STEM) = stem flags for notes under beam beampar(BM_TUPLE) = tuplet flag, which relates to the beam in the following ways: a. BM_TUPLE is set to (1 + stem) when the first note of a beam is a tuplet b. BM_TUPLE must be cleared after a beam is processed c. if processing a beam, if BM_TUPLE is > 0 and if end of tuplet bit is set, then process tuplet with this beam (i.e. use no bracket and put tuplet number over the beam in the middle. beampar(BM_SIZE) = size of beam (full size vs. cue size) beampar(BM_SUGG) = suggestion for modifying length of first stem of beam New 05/14/03 Description of slurar(8,SL_SIZE) This is an array for collecting information on slurs between two notes. This program allows up to four simultaneous slurs, and four dotted slurs (hence the first dimension = 8). The second dimension contains the following elements: slurar(SL_SNUM) = super-object number for this slur slurar(SL_YSHIFT) = shift in y co-ordinate of the first note of the slur slurar(SL_XSHIFT) = shift in x co-ordinate of the first note of the slur slurar(SL_NEXTSNUM) = super-object number for next slur (or zero) slurar(SL_BEAMF) = beam flag: 0 = slur does not start on a beam 1 = slur starts on a stem-up beam 2 = slur starts on a stem-down beam slurar(SL_SUGG) = print suggestion for beginning of slur (05/06/03) Note: There are some similarities between the handling of ties and the handling of slurs. It can happen that a note will have one or more slurs ending and/or starting on it. In this case, as in the case of ties, the terminating super-objects cannot be written until the object is written, and the object cannot be written until the super-object numbers for the new slurs are known. This means that we must establish these numbers and save them before destroying the contents of the slurar for the old slurs. This is the purpose for the NEXTSNUM element in slurar. It is the super-object number for a forward slur. After the backward slur is written, and at the time the new elements of slurar are to be written, this number is moved from slurar(SL_NEXTSNUM) to slurar(SL_SNUM). Description of tuar(4,MAX_PASS,4) This is an array for collecting information on tuplet groups. The first dimension tells whether this information is for (1) regular notes, (2) grace notes to regular notes, (3) cue notes, or (4) grace notes to cue notes. The second dimension tells the pass number for this tuplet group. The elements of the third dimension are as follows: tuar(TU_SNUM) = super-object number tuar(TU_Y1) = y co-ordinate of the first object tuar(TU_Y2) = y co-ordinate of the terminating note head of the first object tuar(TU_FSTEM) = bits 0-7: stem flag of the first note bits 8-15: bracket flags (0 = no bracket) Note: Since it is not possible for a note to belong to two tuplet groups at once, we do not have the problem present in ties and slurs. There is a short-cut to processing that has been mentioned in connection with beams, and which should be mentioned here also. At processing time (when tuplet process bit is set), we should check to see if beampar(.,.,BM_TUPLE) for this pass is set. If it is, then we should do nothing; the tuplet will be processed along with the beam and without a bracket. If beampar(.,.,BM_TUPLE) is clear, then we must process the tuplet using a bracket. Handling of the long trill The long trill is a simple super-object. However, there may be several long trills in a measure-group. Therefore we need to store this information for each pass. Let us assume up to MAX_PASS passes. Then each of the parameters associated with long trills (tsnum, ctrflag, and try) will be a one dimentional array type variable. The parameters associated with long trills are as follows: ctrflag(.) = wavy line continuation flag (made into an array 12/08/07) tsnum(.) = super-object number of long trill (0 = no long trill present) ctrarrf(.) = situation flag 1 = no "tr" before long ~~~ 2 = "tr" start, no accidental 3 = "tr" start, with sharp 4 = "tr" start, with natural 5 = "tr" start, with flat try(.) = vertical displacement from associated object To deal with the case of overlapping trills (one long trill ends where the next begins), we have introduced the arrays: pre_tsnum(.) = prelimary storage for tsnum(.) pre_ctrarrf(.) = prelimary storage for ctrarrf(.) pre_try(.) = prelimary storage for try(.) for storing temporarily the associated values of tsnum, ctrarrf and try. Description of smusdir(30,4) There are actually 6 musical direction super-objects: wedges, dashes, octave-up transposition, octave-down transposition, 15-up transposition, and 15-down transposition. We may encounter these in any one of up to 5 passes. Therefore the first dimension is (super-object type - 1) * 5 + pass-number. If there is no pass number, then the first available row starting at 1 will be used (i.e., assume pass 1 first, then pass 2, etc.). If the row for a particular pass is in use, then use the next higher one, etc. If no rows are available, this should halt the program. Desciption of the second element: smusdir(.,1) = snum (0 = inactive, > 0 = active) smusdir(.,2) = spread (Wedges) = word space (Dashes) = 0 (Oct-up) = 1 (Oct-down) = 2 (15-up) = 3 (15-down) smusdir(.,3) = offset (Wedges) = font number (Dashes) = x-offset (Transpositions) smusdir(.,4) = vertical offset from top of staff Vertical Parameters vpar(.) ------------------- vpar(1) = one vertical note space vpar(2) = two " " spaces vpar(3) = three " " " vpar(4) = four " " " vpar(5) = five " " " vpar(6) = six " " " vpar(7) = seven " " " vpar(8) = eight " " " vpar(9) = nine " " " vpar(10) = ten " " " vpar(11) = vertical shift for printing multiple rest ends vpar(12) = vertical correction of dot position, if on staff line vpar(13) = height parameter for beams vpar(14) = shift in height for multiple beams vpar(15) = cutoff of severe up-down pattern under beam vpar(16) = vertical space between beams vpar(17) = fudge factor for two/more slanted beams on staff lines vpar(18) = fudge factor for one slanted beam on staff lines vpar(19) = maximum rise allowed for beam on one staff line vpar(20) = minimum rise allowed for beam crossing two staff lines vpar(21) = minimum rise allowed for beam crossing 3 staff lines vpar(22) = vertical shift for printing hooks and beams vpar(23) = shift down for printing italic 8 under treble clef vpar(24) = minimum stem length that triggers adding to 16th stem vpar(31) = vertical shift for printing add-flags vpar(32) = (un-used) vpar(33) = first level of time words vpar(34) = (un-used) vpar(35) = (un-used) vpar(36) = vertical shift for printing grace size add-flags vpar(37) = adjustment f/raising 16th beams because of short stems vpar(38) = minimum for sum of two stems under 2-note beam vpar(39) = amount to extend stems under 2-note beam (s. vpar(38)) vpar(40) = height of horizontal ending lines vertical parameters (continued) vpar(.) vpar(41) = length of vertical hooks on ending lines vpar(43) = height of signet sign above staff lines vpar(44) = height above staff for words, wedges vpar(45) = height below staff for words, wedges vpar(46) = height above staff for 8ve vpar(47) = height below staff for 8ve vpar(48) = height of figures vpar(49) = position of first figure vpar(50) = height of spiccato character vpar(51) = height of horizontal ~~~~ vpar(52) = height of turn vpar(53) = height of tr. trill character vpar(54) = height of shake vpar(55) = height of mordent vpar(56) = height of accidental over ornament vpar(57) = height of horizontal accent vpar(58) = height of vertical accent vpar(59) = height of harmonic character vpar(60) = height of thumb position character vpar(61) = height of down bow vpar(62) = height of up bow vpar(63) = height of fermata vpar(64) = height of tuplet number vpar(65) = vertical shift for adding sixteenth grace rest flag vpar(66) = default distance between staves of grand staff vpar(67) = amount to lengthen flag stem with repeater if note is on a space (stem up) vpar(68) = amount to lengthen flag stem with repeater if note is on a line (stem up) vpar(69) = location for first repeater on flag stem if note is on a space (stem up) vpar(70) = location for first repeater on flag stem if note is on a line (stem up) vpar(71) = amount to lengthen flag stem with 2 repeaters if note is on a space (stem down) vpar(72) = amount to lengthen flag stem with >2 repeaters if note is on a space (stem down) vpar(73) = amount to lengthen flag stem with 2 repeaters if note is on a line (stem down) vpar(74) = amount to lengthen flag stem with >2 repeaters if note is on a line (stem down) vpar(75) = location for first repeater on flag stem if note is on a space (stem down) vpar(76) = location for first repeater on flag stem if note is on a line (stem down) vpar(77) = maximum absolute stopping point for quarter stem with repeater (stem up) vpar(78) = mimimum absolute stopping point for quarter stem with repeater (stem down) vpar(79) = slight lengthening of quarter stem with repeater vpar(80) = more extra lengthening of quarter stem with one repeater vpar(81) = location of first repeater on quarter stem vpar(82) = location of tuple number above note or quarter stem with repeaters vpar(83) = location of tuple number above eight stem with repeaters New vertical parameters 05/17/03 vpar(84) = vertical shift up for printing square brackets for editorial dynamics vpar(85) = vertical shift up for printing square brackets for editorial trill vpar(86) = vertical shift up for printing square brackets for editorial accidentals vpar(87) = vertical shift up for printing square brackets for turn ornament vpar(88) = vertical shift up for printing square brackets for shake ornament vpar(89) = vertical shift up for printing square brackets for mordant ornament vpar(90) = vertical shift up for printing square brackets for horizontal accent vpar(91) = vertical shift up for printing square brackets for vertical accent New vertical parameter 11/16/03 vpar(92) = vertical shift up for printing small parentheses around figures vpar(93) = vertical shift up for printing large parentheses around figures vpar(101) = vertical displacement to first line of text Horizontal Parameters hpar(.) --------------------- hpar(1) = shift following accidental natural hpar(2) = shift following accidental sharp hpar(3) = shift following accidental flat hpar(4) = minimum distance between notes dotted note to note ratio = 12 / 10 triplet note to note ratio = 9 / 10 double note to note ratio = 13 / 10 (cf. determine spacing) hpar(5) = distance from beginning of staff lines to 1st character hpar(6) = shift following accidental natural-sharp hpar(7) = shift following accidental natural-flat hpar(8) = shift after big clef sign hpar(9) = shift following sharp or natural in key signature hpar(10) = shift following accidental double sharp hpar(11) = shift following flat in key signature hpar(12) = shift after key signature hpar(13) = shift if no key signature or key change hpar(14) = shift following common or cut time signature hpar(15) = shift following accidental double flat hpar(16) = shift to middle of double digit time signature hpar(17) = shift to middle of single digit time signature hpar(18) = shift after time signature hpar(19) = shift for printing staccato and spiccato at stem end (New 05/14/05) hpar(20) = shift for large number hpar(21) = half shift for large number hpar(22) = shift before printing multiple rest hpar(23) = shift after printing multiple rest hpar(24) = shift before printing whole measure rest hpar(25) = shift for complete whole measure rest hpar(26) = space taken up by up flag hpar(27) = extra shift for dot under flag hpar(28) = extra shift after note with stem-up flag hpar(29) = minimum separation between previous object and accidental hpar(30) = shift for dot after half or whole rest hpar(31) = shift for dot after quarter or smaller rest hpar(32) = shift for dot after whole note or larger hpar(33) = shift for dot after half note or smaller note hpar(34) = horizontal correction of dot position, if on staff line hpar(35) = minimum space following projecting flag hpar(36) = space before bar line hpar(37) = space after bar line hpar(38) = length of beam hook character hpar(39) = placement of movement word hpar(40) = shift for the first natural/flat of a double accidental hpar(41) = gap between ending line and measure line hpar(42) = gap between end of long trill and next object hpar(43) = distance between repeat sign and bar line hpar(44) = space between light bar and light bar hpar(45) = space between heavy bar and light bar, or light bar and heavy bar, or two heavy bars hpar(46) = space between end of wedge and dynamic hpar(47) = space between end of 8ve and next object hpar(48) = space between end of continuation and bar line hpar(49) = space add to left side of note heads to further separate them from previous objects (implemented, because the separation of hpar(29) alone is not enough between note heads) hpar(51) = width of quarter note (approximately) hpar(52) = shift of small italic 8 for octave treble clef hpar(53) = approximate width of grace note hpar(54) = right shift for adding sixteenth rest flag hpar(55) = not used hpar(56) = length of standard beam character hpar(57) = back shift before concatination character hpar(58) = space between words hpar(59) = back shift before last "__" of continuous underline hpar(60) = width of dynamic letter p hpar(61) = width of dynamic letter m hpar(62) = width of dynamic letter f hpar(63) = width of dynamic letter s hpar(64) = width of dynamic letter z hpar(65) = width of dynamic letter r hpar(66) = width of number figure hpar(67) = width of small plus figure hpar(68) = width of small x figure hpar(69) = width of two-plus figure hpar(70) = width of figured sharp hpar(71) = width of four-plus figure hpar(72) = width of five-plus figure hpar(73) = width of six-slash figure hpar(74) = width of seven-slash figure hpar(75) = width of figured natural hpar(76) = width of figured flat hpar(77) = overlap if figure continuation line hpar(78) = right shift if slur interferes with stem hpar(79) = actual thickness of light bar line hpar(80) = thickness of dot hpar(81) = actual thickness of heavy bar line hpar(82) = width of black note (for typesetting) hpar(83) = width of whole note (for typesetting) hpar(84) = width of breve note (for typesetting) hpar(85) = space between stems (for typesetting) hpar(86) = width of big clef sign (approximate) hpar(87) = width of whole rest and half rest hpar(88) = width of quarter rest and eight rest hpar(89) = right shift for adding sixteenth grace rest flag hpar(90) = width of stem hpar(91) = shift to second dot of double dot hpar(92) = width of common and cut time glyph hpar(93) = width of bar line hpar(94) = minimum extra shift, when accidental occurs on note of minimum space hpar(95) = "chip" off of note shape hpar(96) = width of heavy bar line hpar(97) = standard spacing between grace notes hpar(98) = amount by which repeater protrudes from stem hpar(99) = offset of repeater for eighth notes (stem up) hpar(100) = offset of repeater for eighth notes (stem down) hpar(101) = offset of repeater for quarter notes (stem down) hpar(102) = offset for printing tuple number above stem with repeater hpar(103) = offset for printing tuple number above note with repeater hpar(104) = back shift for printing two tuple numbers hpar(105) = forward shift for printing second of two tuple numbers hpar(106) = forward shift for printing second of two leger lines (for note on line) hpar(107) = forward shift for printing second of two leger lines (for note on space) New horizontal parameters 05/17/03 hpar(108) = width of editorial dynamic letter p hpar(109) = width of editorial dynamic letter m hpar(110) = width of editorial dynamic letter f hpar(111) = width of editorial dynamic letter s hpar(112) = width of editorial dynamic letter z hpar(113) = width of editorial dynamic letter r hpar(114) = backup to print square bracket for editorial p [p... hpar(115) = backup to print square bracket for editorial m [m... hpar(116) = backup to print square bracket for editorial f [f... hpar(117) = backup to print square bracket for editorial s [sf hpar(118) = backup to print square bracket for editorial r [rf hpar(119) = shift to print square bracket following editorial f f] hpar(120) = shift to print square bracket following editorial p p] hpar(121) = shift to print square bracket following editorial z z] hpar(122) = backup to print square bracket for editorial tr [tr] hpar(123) = shift to print square bracket following editorial tr [tr] hpar(124) = backup to print square bracket for editorial accidental hpar(125) = shift to print square bracket following editorial accidental hpar(126) = backup to print square bracket for turn ornament hpar(127) = shift to print square bracket following turn ornament hpar(128) = backup to print square bracket for shake ornament hpar(129) = shift to print square bracket following shake ornament hpar(130) = backup to print square bracket for mordant ornament hpar(131) = shift to print square bracket following mordant ornament hpar(132) = backup to print square bracket for horizontal accent hpar(133) = shift to print square bracket following horizontal accent hpar(134) = backup to print square bracket for vertical accent hpar(135) = shift to print square bracket following vertical accent New horizontal parameters 11/16/03 hpar(136) = backup to print small left parenthesis in front of figure hpar(137) = shift to print small right parenthesis after figure hpar(138) = backup to print large left parenthesis in front of figures hpar(139) = shift to print large right parenthesis after figures New horizontal parameters 11/18/08 etc. hpar(140) = width of dynamic letter f in ff combinations Vertical parameters ------------------- loop for i = 1 to 10 vpar(i) = i * 8 repeat vpar(11) = 4 vpar(12) = 7 vpar(13) = 42 vpar(14) = 7 vpar(15) = 30 vpar(16) = 13 vpar(17) = 6 vpar(18) = 9 vpar(19) = 7 vpar(20) = 22 vpar(21) = 27 vpar(22) = 4 vpar(23) = 64 vpar(24) = 40 loop for i = 1 to 24 vpar(i) = vpar(i) * notesize / 16 repeat vpar(31) = 14 * notesize + 8 / 16 vpar(32) = 0 /* was 8 vpar(33) = 5 * notesize / 3 vpar(34) = 0 /* was 121 vpar(35) = 0 /* was 15 vpar(36) = 12 * notesize + 6 / 16 vpar(37) = 3 * notesize - 8 / 16 vpar(38) = 84 * notesize / 16 vpar(39) = 15 * notesize / 16 vpar(40) = 3 * notesize vpar(41) = 3 * notesize / 2 vpar(43) = 5 * notesize / 2 vpar(44) = 5 * notesize / 2 vpar(45) = 8 * notesize vpar(46) = 4 * notesize vpar(47) = 10 * notesize vpar(48) = 3 * notesize / 2 vpar(49) = 7 * notesize vpar(50) = notesize vpar(51) = notesize vpar(52) = 3 * notesize / 2 vpar(53) = 2 * notesize vpar(54) = 3 * notesize / 2 vpar(55) = 3 * notesize / 2 vpar(56) = 4 * notesize / 3 vpar(57) = 3 * notesize / 2 vpar(58) = 3 * notesize / 2 vpar(59) = 3 * notesize / 2 vpar(60) = 3 * notesize / 2 vpar(61) = 3 * notesize / 2 vpar(62) = 9 * notesize / 4 vpar(63) = 2 * notesize vpar(64) = 3 * notesize / 2 vpar(65) = 11 (for notesize 14) 4 (for notesize 6) vpar(66) = 10 * notesize vpar(67) = 8 (for notesize 14) vpar(68) = 5 (for notesize 14) vpar(69) = 21 (for notesize 14) vpar(70) = 18 (for notesize 14) vpar(71) = 2 (for notesize 14) vpar(72) = 1 (for notesize 14) vpar(73) = 6 (for notesize 14) vpar(74) = 5 (for notesize 14) vpar(75) = 21 (for notesize 14) vpar(76) = 17 (for notesize 14) vpar(77) = 19 (for notesize 14) vpar(78) = 24 (for notesize 14) vpar(79) = 2 (for notesize 14) vpar(80) = 1 (for notesize 14) vpar(81) = 19 (for notesize 14) vpar(82) = 17 (for notesize 14) vpar(83) = 33 (for notesize 14) New vertical parameters 05/17/03 vpar(84) = 5 (for notesize 14) vpar(85) = 8 (for notesize 14) vpar(86) = 8 (for notesize 14) vpar(87) = 6 (for notesize 14) vpar(88) = 5 (for notesize 14) vpar(89) = 10 (for notesize 14) vpar(90) = 7 (for notesize 14) vpar(91) = 6 (for notesize 14) vpar(92) = 7 (for notesize 14) vpar(93) = 3 (for notesize 14) vpar(101) = 101 Horizontal parameters --------------------- hpar(1) = 17 hpar(2) = 21 hpar(3) = 18 hpar(4) = 34 hpar(5) = 6 hpar(6) = 38 hpar(7) = 35 hpar(8) = 60 hpar(9) = 18 hpar(10) = 24 hpar(11) = 15 hpar(12) = 19 hpar(13) = 4 hpar(14) = 55 hpar(15) = 35 hpar(16) = 25 hpar(17) = 11 hpar(18) = 33 hpar(19) = 8 /* New 05/14/05 hpar(20) = 24 hpar(21) = 12 hpar(22) = 10 hpar(23) = 30 hpar(24) = 30 hpar(25) = 110 hpar(26) = 15 hpar(27) = 12 hpar(28) = 5 hpar(29) = 9 hpar(30) = 36 hpar(31) = 24 hpar(32) = 37 hpar(33) = 29 hpar(34) = 2 hpar(35) = 44 hpar(36) = 5 hpar(37) = 25 hpar(38) = 18 hpar(39) = 80 hpar(40) = 17 hpar(41) = 10 hpar(42) = 32 hpar(43) = 15 hpar(46) = 20 hpar(47) = 14 hpar(48) = 30 hpar(49) = 3 loop for i = 1 to 50 hpar(i) = hpar(i) * notesize / 16 repeat hpar(44) = 6 (for notesize = 14) hpar(45) = 5 (for notesize = 14) hpar(51) = 18 * notesize + 8 / 16 hpar(52) = 7 * notesize + 2 / 7 hpar(53) = 13 * notesize + 2 / 16 hpar(54) = 4 hpar(55) = 0 /* not used, formerly 80 hpar(56) = 30 hpar(57) = 3 hpar(58) = 16 (for notesize 14) hpar(59) = 0 (not used) hpar(60) = 23 (for notesize 14) hpar(61) = 25 (for notesize 14) hpar(62) = 19 (for notesize 14) hpar(63) = 12 (for notesize 14) hpar(64) = 18 (for notesize 14) hpar(65) = 15 (for notesize 14) hpar(66) = 15 (for notesize 14) hpar(67) = 13 (for notesize 14) hpar(68) = 13 (for notesize 14) hpar(69) = 22 (for notesize 14) hpar(70) = 11 (for notesize 14) hpar(71) = 22 (for notesize 14) hpar(72) = 22 (for notesize 14) hpar(73) = 20 (for notesize 14) hpar(74) = 14 (for notesize 14) hpar(75) = 9 (for notesize 14) hpar(76) = 11 (for notesize 14) hpar(77) = 3 * notesize / 2 hpar(78) = 4 * notesize / 3 hpar(79) = 2 (for notesize 14) hpar(80) = 6 (for notesize 14) hpar(81) = 7 (for notesize 14) hpar(82) = 19 (for notesize 14) hpar(83) = 24 (for notesize 14) hpar(84) = 28 (for notesize 14) hpar(85) = 6 (for notesize 14) hpar(86) = 38 (for notesize 14) hpar(87) = 27 (for notesize 14) hpar(88) = 15 (for notesize 14) hpar(89) = 3 (for notesize 14) hpar(90) = 2 (for notesize 14) hpar(91) = 13 (for notesize 14) hpar(92) = 25 (for notesize 14) hpar(93) = 2 (for notesize 14) hpar(94) = hpar(2) >> 2 (4 for notesize 14) hpar(95) = hpar(85) + hpar(90) >> 1 (4 for notesize 14) hpar(96) = 7 (for notesize 14) hpar(97) = 21 (for notesize 14) hpar(98) = 11 (for notesize 14) hpar(99) = 1 (for notesize 14) hpar(100) = hpar(82) - hpar(99) hpar(101) = hpar(82) - hpar(90) hpar(102) = 10 (for notesize 14) hpar(103) = 2 (for notesize 14) hpar(104) = 9 (for notesize 14) hpar(105) = 17 (for notesize 14) hpar(106) = 3 (for notesize 14) hpar(107) = 1 (for notesize 14) New horizontal parameters 05/17/03 hpar(108) = 18 (for notesize 14) hpar(109) = 21 (for notesize 14) hpar(110) = 15 (for notesize 14) hpar(111) = 10 (for notesize 14) hpar(112) = 12 (for notesize 14) hpar(113) = 12 (for notesize 14) hpar(114) = 8 (for notesize 14) hpar(115) = 8 (for notesize 14) hpar(116) = 11 (for notesize 14) hpar(117) = 6 (for notesize 14) hpar(118) = 6 (for notesize 14) hpar(119) = 7 (for notesize 14) hpar(120) = 0 (for notesize 14) hpar(121) = 3 (for notesize 14) hpar(122) = 11 (for notesize 14) hpar(123) = 21 (for notesize 14) hpar(124) = 8 (for notesize 14) hpar(125) = 13 (for notesize 14) hpar(126) = 7 (for notesize 14) hpar(127) = 28 (for notesize 14) hpar(128) = 8 (for notesize 14) hpar(129) = 27 (for notesize 14) hpar(130) = 10 (for notesize 14) hpar(131) = 27 (for notesize 14) hpar(132) = 9 (for notesize 14) hpar(133) = 23 (for notesize 14) hpar(134) = 9 (for notesize 14) hpar(135) = 21 (for notesize 14) hpar(136) = 7 (for notesize 14) hpar(137) = 15 (for notesize 14) hpar(138) = 10 (for notesize 14) hpar(139) = 15 (for notesize 14) hpar(140) = 17 (for notesize 14) Description of tsr.TSR_LENG(MAX_OBJECTS) /* 05/14/03: size changed to 116 The purpose of the tsr strings is to store print suggestion data for the note object and for sub-objects in the note field 32-43. Note Object ─────────── byte1: bit 0 = control 0 = no modification of data (default in 99.9% of all cases) 1 = possible modification somewhere bits 1-4 = print modification code 0 = no modification 1 = turn off all sub-objects 2 = turn off all sub-objects but print an extension dot 3-7 = eliminate tie if there is one 3 = print object, no extension dot 4 = print object, include extension dot 5 = double note length, no extension dot 6 = double note length, include extension dot 7 = quadruple note length, no extension dot byte2: x-y active flags 0x01: active flag (0 = inactive) 0x02: 0 = x position is relative 1 = x position is absolute 0x04: 0 = y position is relative 1 = y position is absolute byte3: modification of horizontal position (from default) if byte3 >= 128, move notation to the right by the amount (byte3 - 128) if byte3 < 128, move notation to the left by the amount (128 - byte3) if byte3 = 0, do nothing byte4: modification of vertical position (from default) if byte4 >= 128, move notation down by the amount (byte4 - 128) if byte4 < 128, move notation up by the amount (128 - byte4) if byte4 = 0, do nothing Sub-objects in the Note Field 32-43 ─────────────────────────────────── At the moment, there are 19 code catagories for which data 05/02/03 can be stored. Each of these catagories requires 4 bytes. The data stored in each byte is as follows: byte1 -- Normal case: bit 0 = control 0 = no modification of data (default in 99.9% of all cases) 1 = possible modification somewhere in this byte bit 1 = major location change flag 0 = no change in position relative to staff (default) 1 = determine position relative to staff from bit 2 bit 2 = position relative to staff 0 = place notation above staff 1 = place notation below staff bit 3 = print flag for score 0 = print notation in score (default) 1 = don't print notation in score bit 4 = print flag for non-score (parts) 0 = print notation in non-score (default) 1 = don't print notation in non-score bit 5 = parentheses flag for score 0 = no action (default) 1 = surround notation with parentheses in score bit 6 = parentheses flag for non-score (parts) 0 = no action (default) 1 = surround notation with parentheses in non-score (parts) byte1 -- Ties: modification to length of tie (end position) if byte1 >= 128, make length longer by the amount (byte1 - 128) if byte1 < 128, move length shorter by the amount (128 - byte1) if byte1 = 0, do nothing to length byte2: x-y active flags 0x01: active flag (0 = inactive) 0x02: 0 = x position is relative 1 = x position is absolute 0x04: 0 = y position is relative 1 = y position is absolute byte3: modification of horizontal position (from default) if byte3 >= 128, move notation to the right by the amount (byte3 - 128) if byte3 < 128, move notation to the left by the amount (128 - byte3) if byte3 = 0, do nothing byte4: modification of vertical position (from default) if byte4 >= 128, move notation down by the amount (byte4 - 128) if byte4 < 128, move notation up by the amount (128 - byte4) if byte4 = 0, do nothing The code catagories are as follows: 1 = legato(_), staccato(.), line with dot(=) 2 = spiccato: (i) 3 = accents: horizontal(>), vertical(V), inverted vertical(A) 4 = single ornaments: turn(r), trill(t), shake(w), wavy line (~) mordent(M), delayed turn(k) 5 = second single ornament 6 = bowing: up-bow(v), down-bow(n) 7 = harmonic: string harmonic(o) 8 = thumb-open: thumb(Q), open-string(0) 9 = finger1: finger code level 1 10 = finger2: finger code level 2 11 = finger3: finger code level 3 12 = finger4: finger code level 4 13 = finger5: finger code level 5 14 = dynamics: any dynamic string 15 = upright fermata: (F) 16 = inverted fermata: (E) 17 = tie: (-) 04/20/03: added tie to list 18 = dots: (column 18) 19 = accidentals: (column 19) Slurs in the Note Field 32-43 05/06/03 ───────────────────────────── At the moment, there are 8 code catagories for which data can be stored. Each of these catagories requires 4 bytes. For codes 20-23 = starting slurs "([{z" the data stored in each byte is as follows: byte1: modification of horizontal start of slur (from default) if byte1 >= 128, move start of slur to the right by the amount (byte1 - 128) if byte1 < 128, move start of slur to the left by the amount (128 - byte1) if byte1 = 0, do nothing byte2: modification of vertical start of slur (from default) if byte2 >= 128, move start of slur down by the amount (byte2 - 128) if byte2 < 128, move start of slur up by the amount (128 - byte2) if byte2 = 0, do nothing byte3: modification of horizontal position of slur (from default) if byte3 >= 128, move entire slur to the right by the amount (byte3 - 128) if byte3 < 128, move entire slur to the left by the amount (128 - byte3) if byte3 = 0, do nothing byte4: modification of vertical position of slur (from default) if byte4 >= 128, move entire slur down by the amount (byte4 - 128) if byte4 < 128, move entire slur up by the amount (128 - byte4) if byte4 = 0, do nothing For codes 24-27 = ending slurs ")]}x" the data stored in each byte is as follows: byte1: modification of horizontal end of slur (from default) if byte1 >= 128, move end of slur to the right by the amount (byte1 - 128) if byte1 < 128, move end of slur to the left by the amount (128 - byte1) if byte1 = 0, do nothing byte2: modification of vertical end of slur (from default) if byte2 >= 128, move end of slur down by the amount (byte2 - 128) if byte2 < 128, move end of slur up by the amount (128 - byte2) if byte2 = 0, do nothing byte3: modification to curvature (normal range -1 to +5) if byte1 >= 128, increase stock slur number by amount (byte1 - 128). Up to a point, this will add to the curvature if byte1 < 128, decrease stock slur number by amount (128 - byte2). This may have the effect of flattening the slur slightly if byte1 = 0, do nothing to length Beams in the Note Field 26 /* New 05/14/03 ────────────────────────── code = 28 byte2: modification of first stem length (from default, as calculated by mskpage or mkpart) if byte2 >= 128, lengthen stem by the amount (byte2 - 128) (tenths of interline distance) if byte2 < 128, shorten stem by the amount (byte2 - 128) (tenths of interline distance) if byte2 = 0 do nothing Vertical Parameters for guessing beam positions ─────────────────────────────────────────────── bvpar(16) = height parameter for beams bvpar(17) = decrease in bvpar(16) when range of notes exceeds vpar(3) bvpar(18) = cutoff of wevere up-down pattern under beam bvpar(20) = amount to add to beam height to get stradle bvpar(22) = fudge factor for two/more slanted beams on staff lines bvpar(23) = fudge factor for one slanted beam on staff lines bvpar(24) = maximum rise allowed for beam on one staff line bvpar(25) = minimum rise allowed for beam crossing two staff lines bvpar(26) = minimum rise allowed for beam crossing three staff lines bvpar(29) = minimum stem length that triggers adding to 16th stem bvpar(30) = adjustment for raising 16th beams because of short stems bvpar(31) = beam thickness bvpar(32) = offset between beams (if two or three) bvpar(33) = offset between beams (if more than three in staff line) bvpar(34) = amount by which a hanging beam exceeds line height bvpar(35) = maximum beam slope for short beams Explanation of Variables for NEWFONTS 03/19/04 ─────────────────────────────────────────── nsizes(12) = The 12 available note sizes. Currently four sizes are available 3 [06], 8 [14], 10 [18], and 11 [21] (as of 12/18/04) revsizes(24) = The reverse map to nsizes XFonts(12,19) = The number of 10s and the 6 x 3 (sizes, styles) for each notesize XFontstr.76(12) = XFont data in string form Fspacex(90) = index from (TMS font number - 50) to record in fontspac(.) kernmap(52,26) = kerning data for current font kernfiles.360 = names of kern files Variables added 03-20-03 for additional code required by autoscr ──────────────────────────────────────────────────────────────── Description of measuremap(MAX_MEAS,5) For each measure, we need to know how many tracks are active, and in the case of the grand staff, which staff should be considered the primary staff in that measure. Parameter 1 = number of tracks active in this measure For each measure, we also need to know of any "time gaps" for any of the active tracks in the measure. Parameter 2 = number of time gaps in measure Parameter 3 = zero, if no time gaps = pointer to timegap data if present For each measure, we also need to know the number of divisions in the measure, and the number of divisions per quarter. Parameter 4 = number of divisions in the measure Parameter 5 = number of divisions per quarter Description of trackstave(MAX_MEAS,9,3) Trackstave data consists of three numbers for each of 9 possible tracks Parameter 1 = relative time spent on staff 1 Parameter 2 = relative time spent on staff 2 Parameter 3 = primary staff for this track in this measure Description of timegaps(15000,3) Timegaps data consists of groups of three numbers. Parameter 1 = track number Parameter 2 = start of time for this timegap Parameter 3 = length of time gap Description of pointers barnum = pointer into measuremap(.,.) and trackstave(.,.,.) barnum2 = second counter of measure bars opbarnum = operative barnum at typesetting stage (changed when new bar is typeset) tgpnt = pointer into timegaps(.,.) Description of other variables staves = number of staves for this file (1 or 2) track = current track number staff = current staff number durflag = flag that a duration has occurred in a measure trackdivpnt(9) = division pointer for up to nine simultaneous tracks jscrdat = line of SCORE data appended to end of object records kscrdat = line of SCORE data appended to end of sub-object records scr_qwidth = width of a SCORE quarter note is 9/10 MUSEDATA quarter how_much_mrest(2) = the divspq and divspm for a section of mrest. this is needed to construct the P7 parameter for multiple rests. str header1.80 = first header record str header2.80 = second header record str header3.80 = third header record str composer = composer name str comp_names(.)= list of supported composers (int) composer_num = composer number 1 = J.S.Bach 2 = G.F.Handel 3 = J. Haydn 4 = L. Beethoven track_flag = indicates presence of track assignments in stage2 file track_assign(9) = automatic assignment of tracks to staves initialization of these parameters ══════════════════════════════════ New code 03/19/04 revsizes(1) = 1 revsizes(2) = 1 revsizes(3) = 1 revsizes(4) = 1 revsizes(5) = 2 revsizes(6) = 3 revsizes(7) = 4 revsizes(8) = 5 revsizes(9) = 6 revsizes(10) = 6 revsizes(11) = 7 revsizes(12) = 7 revsizes(13) = 8 revsizes(14) = 8 revsizes(15) = 9 revsizes(16) = 9 revsizes(17) = 10 revsizes(18) = 10 revsizes(19) = 10 revsizes(20) = 11 revsizes(21) = 11 revsizes(22) = 11 revsizes(23) = 12 revsizes(24) = 12 start with notesize, and a number 30 to 48 (19 possibilities) want a font number, that's all XFontstr(1) = " 51 51 81 111 51 81 111 52 82 112 53 83 113 54 84 114 56 86 116" XFontstr(2) = " 51 52 82 112 53 83 113 54 84 114 55 85 115 56 86 116 58 88 118" XFontstr(3) = " 51 54 84 114 55 85 115 56 86 116 57 87 117 58 88 118 60 90 120" XFontstr(4) = " 52 55 85 115 57 87 117 58 88 118 59 89 119 60 90 120 63 93 123" XFontstr(5) = " 53 57 87 117 58 88 118 59 89 119 61 91 121 62 92 122 64 94 124" XFontstr(6) = " 55 59 89 119 61 91 121 63 93 123 64 94 124 65 95 125 68 98 128" XFontstr(7) = " 57 62 92 122 64 94 124 65 95 125 67 97 127 69 99 129 72 102 132" XFontstr(8) = " 58 64 94 124 66 96 126 68 98 128 70 100 130 72 102 132 74 104 134" XFontstr(9) = " 60 67 97 127 69 99 129 71 101 131 73 103 133 74 104 134 76 106 136" XFontstr(10) = " 61 69 99 129 71 101 131 73 103 133 74 104 134 75 105 135 78 108 138" XFontstr(11) = " 64 72 102 132 74 104 134 75 105 135 77 107 137 78 108 138 79 109 139" XFontstr(12) = " 65 74 104 134 75 105 135 77 107 137 78 108 138 79 109 139 80 110 140" loop for i = 1 to 12 sub = 1 loop for j = 1 to 19 XFonts(i,j) = int(XFontstr(i){sub..}) repeat repeat loop for a1 = 1 to 30 Fspacex(a1) = (a1 - 1) * 10 + 1 Fspacex(a1+30) = Fspacex(a1) + 400 Fspacex(a1+60) = Fspacex(a1) + 800 repeat kernfiles = "S024S027S031S034S037S041S044S048S054S058S061S065S068S075S082" kernfiles = kernfiles // "S085S088S095S098S105S109S115S119S132S146S153S160S173S203S231" kernfiles = kernfiles // "B025B028B032B035B039B042B046B049B053B056B060B064B067B074B081" kernfiles = kernfiles // "B085B088B095B099B106B109B116B120B134B145B152B159B173B205B229" kernfiles = kernfiles // "I024I027I031I034I037I041I044I048I054I058I061I065I068I075I082" kernfiles = kernfiles // "I085I088I095I098I105I109I115I119I132I146I153I160I173I203I231" kernfiles = lcs(kernfiles) End of 03/19/04 material version = VERSION #if AUTOSCR ligit_flag = 0 comp_names(1) = "J.S.Bach" comp_names(2) = "G.F.Handel" comp_names(3) = "J. Haydn" comp_names(4) = "L. Beethoven" loop for i = 1 to 9 track_assign(i) = 0 repeat putc putc ╔═════════════════════════════════════════╗ putc ║ MUSEDATA to SCORE conversion process ║ putc ║ ==================================== ║ putc ╚═════════════════════════════════════════╝ putc putc Part I: Building non page specific I-files from stage2 files putc putc The home directory for this window should be directory putc of the musical work you are converting. The directory putc should contain the sub-directories STAGE2 and OUTPUTS. putc putc ════════════════════════════════════════════════════════════ putc putc You are about to create a (set of) SCORECON I-file(s). This program putc is in development and may incur changes. For revision control purposes, putc please enter the current date (xx/xx/xx will work). You may also enter putc your name or initials, if you choose. putc Example: 04/01/03 by W Hewlett getc line putc header1 = "SCORECON I-FILE. created: " // line putc Composers currently supported by this program putc 1 = J.S.Bach putc 2 = G.F Handel putc 3 = J. Haydn putc 4 = L. Beethoven putc putc Please indicate the composer by entering the appropriate number. If the putc composer is not on the list, simply type Enter. getc composer_num if composer_num = 0 or composer_num > 4 putc Note: Header records for this conversion may not be constructed in a putc standardized manner. Please let Eleanor know that your are putc doing this conversion, so that we can add the name to our list. putc Enter the composer's name now. getc composer else composer = comp_names(composer_num) end #else ligit_flag = LIGIT putc Musical Database Typesetting Program putc #endif Q1: notesize = 14 mtfont = 31 tword_height = 6 twfont = 34 abflg = 2 cfactor = 100 sizenum = revsizes(notesize) #if AUTOSCR #else putc Enter note size (<return> = 14: x = non standard parameters) getc line line = trm(line) if line <> "" if line = "x" putc Notesize? getc notesize putc Text font? (usually 31) getc mtfont putc Time word font? (usually 34) getc twfont putc Number of beats in alle breve time? (usually 2) getc abflg if abflg <> 4 abflg = 2 end else notesize = int(line) if chr(notesize) not_in [6,14,16,18,21] /* Code modified 12/31/08 putc Note size of ~notesize is not supported at this time. putc Supported sizes are 6, 14, 16, 18, and 21 putc goto Q1 end end end sizenum = revsizes(notesize) /* New 03/19/04 putc Compression factor (<return> = none) getc line line = trm(line) if line <> "" cfactor = int(line) if cfactor = 0 cfactor = 100 end end #endif bvpar(16) = 3 * notesize bvpar(17) = notesize / 2 bvpar(18) = 30 * notesize / 16 bvpar(20) = notesize / 2 + 1 / 2 bvpar(22) = 6 * notesize / 16 bvpar(23) = 9 * notesize / 16 bvpar(24) = 7 * notesize / 16 bvpar(25) = 22 * notesize / 16 bvpar(26) = 27 * notesize / 16 bvpar(29) = 38 * notesize / 16 bvpar(30) = 3 * notesize - 8 / 16 bvpar(31) = notesize / 2 + 1 bvpar(32) = notesize * 8 + 4 / 10 bvpar(33) = notesize * 12 + 10 / 14 bvpar(34) = notesize - 3 / 9 bvpar(35) = notesize / 3 curfont = 0 initialization ══════════════ Vertical and horizontal parameters ────────────────────────────────── file = DISP_DISK // ":/release/progs/proofpar/" // chs(notesize) open [1,1] file loop for i = 1 to 200 getf [1] vpar(i) repeat loop for i = 1 to 200 getf [1] hpar(i) repeat vpar20 = 2 * vpar(10) scr_qwidth = hpar(82) * 9 / 10 #if BIG16 if notesize = 16 ++hpar(51) /* width of quarter note (approximately) ++hpar(82) /* width of black note (for typesetting) ++hpar(83) /* width of whole note (for typesetting) ++hpar(84) /* width of breve note (for typesetting) end #endif #if CUSTOM_PAR if notesize = 14 vpar(101) = 111 end if notesize = 16 vpar(101) = 126 end if notesize = 18 /* size-18 added 12/18/04 vpar(101) = 141 end if notesize = 21 vpar(101) = 171 end #endif Other parameters and variables ────────────────────────────── loop for i = 1 to 9 getf [1] wak(i) repeat loop for i = 1 to 2 loop for j = 1 to 6 getf [1] zak(i,j) repeat repeat close [1] claves = "CDEFGAB" numbers = "0123456789" accs = " #f" slurstr = "FpmFjoiOlpmFooiOphpFokoiffnFggnHFfFFIgGJcceBdddQBaAPEdQQcbeedddM" slurstr = slurstr // "KaNKddNMBaAAECCDlpmFIGGOlpmFOGOOphpFoiGHffnFggNH" slurstr = slurstr // "FfFFIgGJcceBECQQcdeAECQQcbeeddLMKaNKMdNMAaAAECCD" slurunder = "FHHFIGOOFHHFIGOOFNFFINGGFFNFIGNHFFFFIGGJBBBBECCQ" slurunder = slurunder // "BBBBECCQKCKKQNLMKKNKMLNMBKAAECCD" slurover = "lpppjoiolpppjoiophppokoiffnrggngffsngggncceedddd" slurover = slurover // "cceeddddcbeeddddcanaddndcaendddn" Meaning of curvedata: Curvedata is meant to describe the approximate shape of slurs for various situations. The slurs begin described are (flat) tips down. The end points are assumed to be 0 and are therefore not included. A slur between two notes need not be described, so that the first relevant description is a slur between three notes. The first dimension of curvedata contains the number of notes under the slur (not counting the end points). The second dimension contains a number representing the curvature of the slur (from 1 to 4). The third dimension contains the specific note number for the height data. This number will range from 1 to the number of notes under the slur (not counting the end points). Curvedata for notesize = 14 curvedata(1,1,1) = 10 curvedata(1,2,1) = 14 curvedata(1,3,1) = 18 curvedata(1,4,1) = 22 curvedata(2,1,1) = 8 curvedata(2,2,1) = 12 curvedata(2,3,1) = 16 curvedata(2,4,1) = 20 curvedata(3,1,1) = 10 /* 8 curvedata(3,1,2) = 12 /* 12 curvedata(3,2,1) = 12 /* 10 curvedata(3,2,2) = 16 /* 16 curvedata(3,3,1) = 14 /* 12 curvedata(3,3,2) = 20 /* 20 curvedata(3,4,1) = 17 /* 15 curvedata(3,4,2) = 24 /* 24 curvedata(4,1,1) = 9 /* 7 curvedata(4,1,2) = 12 /* 12 curvedata(4,2,1) = 11 /* 10 curvedata(4,2,2) = 16 /* 16 curvedata(4,3,1) = 13 /* 12 curvedata(4,3,2) = 20 /* 20 curvedata(4,4,1) = 16 /* 15 curvedata(4,4,2) = 24 /* 24 curvedata(5,1,1) = 8 /* 6 curvedata(5,1,2) = 13 /* 12 curvedata(5,1,3) = 14 /* 13 curvedata(5,2,1) = 11 /* 9 curvedata(5,2,2) = 16 /* 15 curvedata(5,2,3) = 18 /* 17 curvedata(5,3,1) = 13 /* 11 curvedata(5,3,2) = 19 /* 19 curvedata(5,3,3) = 21 /* 21 curvedata(5,4,1) = 16 /* 14 curvedata(5,4,2) = 24 /* 23 curvedata(5,4,3) = 25 /* 25 curvedata(6,1,1) = 8 /* 5 curvedata(6,1,2) = 12 /* 11 curvedata(6,1,3) = 14 /* 13 curvedata(6,2,1) = 11 /* 9 curvedata(6,2,2) = 16 /* 15 curvedata(6,2,3) = 18 /* 17 curvedata(6,3,1) = 13 /* 11 curvedata(6,3,2) = 20 /* 19 curvedata(6,3,3) = 22 /* 21 curvedata(6,4,1) = 16 /* 14 curvedata(6,4,2) = 24 /* 23 curvedata(6,4,3) = 25 /* 25 curvedata(7,1,1) = 7 /* 5 curvedata(7,1,2) = 11 /* 11 curvedata(7,1,3) = 14 /* 13 curvedata(7,1,4) = 15 /* 14 curvedata(7,2,1) = 11 /* 9 curvedata(7,2,2) = 16 /* 15 curvedata(7,2,3) = 18 /* 17 curvedata(7,2,4) = 19 /* 18 curvedata(7,3,1) = 14 /* 11 curvedata(7,3,2) = 20 /* 19 curvedata(7,3,3) = 22 /* 21 curvedata(7,3,4) = 23 /* 22 curvedata(7,4,1) = 16 /* 14 curvedata(7,4,2) = 24 /* 23 curvedata(7,4,3) = 26 /* 25 curvedata(7,4,4) = 27 /* 26 curvedata(8,1,1) = 7 /* 5 curvedata(8,1,2) = 11 /* 11 curvedata(8,1,3) = 14 /* 13 curvedata(8,1,4) = 15 /* 14 curvedata(8,2,1) = 11 /* 9 curvedata(8,2,2) = 16 /* 15 curvedata(8,2,3) = 18 /* 17 curvedata(8,2,4) = 19 /* 18 curvedata(8,3,1) = 14 /* 11 curvedata(8,3,2) = 20 /* 19 curvedata(8,3,3) = 22 /* 21 curvedata(8,3,4) = 23 /* 22 curvedata(8,4,1) = 16 /* 14 curvedata(8,4,2) = 24 /* 23 curvedata(8,4,3) = 26 /* 25 curvedata(8,4,4) = 27 /* 26 loop for c1 = 2 to 8 loop for c2 = 1 to 4 c4 = c1 + 1 / 2 + 1 c5 = 1 loop for c3 = c1 to c4 step -1 curvedata(c1,c2,c3) = curvedata(c1,c2,c5) ++c5 repeat repeat repeat Scale for notesize = 6 if notesize = 6 loop for c1 = 1 to 8 loop for c2 = 1 to 4 loop for c3 = 1 to 8 curvedata(c1,c2,c3) = curvedata(c1,c2,c3) * 3 + 3 / 7 repeat repeat repeat end Scale for notesize = 21 if notesize = 21 loop for c1 = 1 to 8 loop for c2 = 1 to 4 loop for c3 = 1 to 8 curvedata(c1,c2,c3) = curvedata(c1,c2,c3) * 21 + 7 / 14 repeat repeat repeat end Scale for notesize = 18 12/18/04 if notesize = 18 loop for c1 = 1 to 8 loop for c2 = 1 to 4 loop for c3 = 1 to 8 curvedata(c1,c2,c3) = curvedata(c1,c2,c3) * 18 + 7 / 14 repeat repeat repeat end Scale for notesize = 16 12/31/08 if notesize = 16 loop for c1 = 1 to 8 loop for c2 = 1 to 4 loop for c3 = 1 to 8 curvedata(c1,c2,c3) = curvedata(c1,c2,c3) * 16 + 7 / 14 repeat repeat repeat end * End of Initialization of parameters * Determine operating mode debug_point = 10000 pmode = 0 &D putc Debug above measure number ? (return = no debug) &D getc line &D line = trm(line) &D if line <> "" &D pmode = 4 &D debug_point = int(line) &D end #if AUTOSCR putc putc Autoscr performs the first step of the MUSEDATA to SCORE conversion process. putc Autoscr takes stage2 source files as input and produces non-page putc specific intermediate files. In this conversion process, the only putc files needed are the files with scrcon membership. putc putc Source library? (e.b46 g.b46 , stage2/01) getc inlib inlib = trm(inlib) inlib = inlib // "/" getdir line inlib = line // "/" // inlib pgroup = PGROUP job_type = "s" putc putc Autoscr works on only one movement at a time. The output library putc (for i-files) must already be allocated. Autoscr will name the putc output files (i-files) according to the order of the input files putc in the group; i.b46 e. part 1 from the input group becomes the i-file "01". putc Autoset can work on a range of parts within a group. You will be asked putc to provide this range. Enter the output library and range now. putc putc Output library? (Enter a blank line to get default output library) getc outlib outlib = trm(outlib) if outlib = "" j = len(inlib) - 1 temp = "" loop for i = j to 1 step -1 if inlib{i} <> "/" temp = inlib{i} // temp else i = 0 end repeat outlib = "outputs" line = "scrcon" perform check_for_lib (outlib,line) outlib = outlib // "/scrcon" line = "i-files" perform check_for_lib (outlib,line) outlib = outlib // "/i-files" line = temp perform check_for_lib (outlib,line) outlib = outlib // "/" // temp end #else putc putc Autoset performs the first step of the music typesetting process. putc Autoset takes stage2 source files as input and produces non-page putc specific intermediate files. Since the stage2 directory contains putc source files for a variety of uses, you need to specify the group putc (i.b46 e. sound, score, skore, parts, short or data) that you want putc autoset to work on. Enter the source library and group name now. putc putc Source library? getc inlib inlib = trm(inlib) inlib = inlib // "/" getdir line inlib = line // "/" // inlib putc Group name? (default = data) getc line line = trm(line) line = lcs(line) line = mrt(line) if "sound^short^parts^score^skore^data" con line /* 03/10/09 adding skore pgroup = line else putc This is an unconventional group name. Would you please putc verify it by typing it again (or enter a conventional name). getc temp2 temp2 = trm(temp2) temp2 = mrt(temp2) temp2 = lcs(temp2) if "sound^short^parts^score^skore^data^" con temp2 /* 03/10/09 adding skore pgroup = temp2 else if temp2 = line pgroup = line else pgroup = "data" putc group name has been set to "data" end end end Set job_type for selective print suggestions if "sound^short^parts^score^skore^data^" con pgroup i = mpt / 6 + 1 job_type = ".tpskd"{i} /* 03/10/09 Expanding job_type to include end /* k = skore (conductor's score) if job_type = "p" /* setting multirest_flag 03/04/06 multirest_flag = 1 else multirest_flag = 0 end putc putc Autoset works on only one movement at a time. The output library putc (for i-files) must already be allocated. Autoset will name the putc output files (i-files) according to the order of the input files putc in the group; i.b46 e. part 1 from the input group becomes the i-file "01". putc Autoset can work on a range of parts within a group. You will be asked putc to provide this range. Enter the output library and range now. putc putc Output library? (Enter a blank line to get default output library) getc outlib outlib = trm(outlib) if outlib = "" j = len(inlib) - 1 temp = "" loop for i = j to 1 step -1 if inlib{i} <> "/" temp = inlib{i} // temp else i = 0 end repeat outlib = "outputs/" // pgroup if notesize <> 14 if notesize < 10 outlib = outlib // "0" end outlib = outlib // chs(notesize) end line = "i-files" perform check_for_lib (outlib,line) outlib = outlib // "/i-files" if temp <> "stage2" outlib = outlib // "/" // temp end end #endif outlib = outlib // "/" getdir line outlib = line // "/" // outlib Check that outlib exists line2 = rev(outlib) line2 = line2{2..} if line2 con "/" line = line2{mpt+1..} line = rev(line) temp = rev(line2{1,mpt-1}) perform check_for_lib (line,temp) goto ALLOCATED end putc This is bullshit stop ALLOCATED: f1 = 10000 Get names of input files open [9,1] inlib loop getf [9] line line = line{33..} line = trm(line) temp = inlib // "/" // line temp = inlib // line open [2,1] temp loop for i = 1 to 11 getf [2] line2 repeat line2 = line2 // " " temp4 = " " // pgroup // " " if line2 con temp4 loop for i = 1 to 8 getf [2] line2 k = len(pgroup) if line2{1,k} = pgroup if line2 con "part " j = int(line2{sub+5..}) if f1 = 10000 k = 0 if line2 con " of " k = int(line2{sub+3..}) end putc putc There appear to be ~k parts in this group. Enter the first and putc last numbers of the range you wish, or simply type <Enter> to putc process all of them. f1 = 0 getc f1 f2 if f1 = 0 f1 = 1 f2 = k end f3 = f1 end if j >= f1 and j <= f2 infiles(j) = line end end i = 100 end repeat if i <> 100 putc file ~line has a bad group membership format putc Please fix this problem before proceeding further. putc stop end end close [2] repeat eof9: loop for i = f1 to f2 if infiles(i) = "" putc Unable to find an input file for track ~i . Please check putc to see that your tracks are within the range of the size of putc the group you are working with. putc stop end repeat BIG: m_number = 0 tuflag = 0 loop for i = 1 to MAX_STAFF c8flag(i) = 0 transflag(i) = 0 repeat ctrflag = 0 loop for i = 1 to MAX_PASS /* ctrflag(.) is an array as of 12/08/07 ctrflag(i) = 0 repeat loop for i = 1 to 4 loop for j = 1 to MAX_PASS loop for k = 1 to BM_SZ /* New size parameter 05/14/03 beampar(i,j,k) = 0 repeat repeat repeat outslurs = "00000000" /* clear all pending slur flags snum = 0 esnum = 0 loop for j = 1 to MAX_PASS tsnum(j) = 0 pre_tsnum(j) = 0 rest_flag(j) = 0 repeat figdiv = 0 cuediv = 0 measnum = 0 divpoint = 0 sct = 0 /* necessary so that ts(.,.) will be completely cleared maxsct = 0 oldsct = 0 supcnt = 0 inctype = 0 inctype_rem = 0 vflag = 1 mcat = 0 granddist = vpar(66) global_tpflag = 0 tpflag = 0 xposi_shift = 0 yposi_shift = 0 textconflag = OFF restplace = 0 fix_next_inctype = 0 mdirfont = DEFAULT_MDIRFONT dtivfont = DEFAULT_DTIVFONT Code added 09/22/03 for more complete initialization of variables key = 0 loop for i = 1 to 50 claveax(i) = 0 loop for j = 1 to 4 /* 06/04/08 was 3 measax(j,i) = claveax(i) repeat repeat restoff = 0 /* added 05/12/04 text_flag = 0 /* added 01/30/05 text_loc = vpar(101) /* added 01/30/05 art_flag = 0 /* added 05/26/05 single_line = 0 /* added 12/18/05 stem_change_flag = 0 /* added 12/20/05 dot_difference_flag = 0 /* added 12/24/05 irest_flag = 0 /* added 01/01/06 mreport_flag = 0 /* added 01/01/06 debug_flag = 0 /* added 01/01/06 ending_height = vpar(40) /* added 01/06/06 key_reprint_flag = 0 /* added 11/26/06 mixed_color_flag = 0 /* added 11/26/06 suppress_key = 0 /* added 11/02/07 min_space = hpar(29) /* added 11/19/07 slur_adjust = 0 /* added 05/01/08 in_line_edslur = 0 /* added 01/12/09 large_clef_flag = 0 /* added 02/02/09 rest_collapse = TRUE /* added 03/15/09 pitch_mod = 0 /* added 11/27/09 #if AUTOSCR xdata_flag = 1 scr_flag = 1 #else xdata_flag = 0 #endif *********** Transfer file to Data Table *********** if f3 = 0 putc Suspected problem with the allocation of group memberships putc in this directory. Please check all relevent files before putc proceeding further. putc putc Program Halted putc stop end instrument_number = f3 transposition = 50 file = inlib // infiles(f3) if f3 < 10 outfile = outlib // "0" // chs(f3) else outfile = outlib // chs(f3) end putc putc Input file = ~file putc open [1,1] file loop for i = 1 to 10 getf [1] line tput [X,i] ~line repeat Skip group membership information getf [1] line if line con ":" /* looking for group memberships j = mpt + 1 loop for k = 0 to 100 out = txt(line,[' '],j) repeat while out <> "" loop for j = 1 to k /* k = number of group memberships getf [1] line line = line // pad(1) loop while line{1} = "&" loop getf [1] line line = line // pad(1) repeat while line{1} <> "&" getf [1] line line = line // pad(1) repeat repeat end box_flag = 0 /* New 02/03/08 track_flag = 0 tracknum_flag = 0 loop getf [1] line line = line // pad(6) loop while line{1} = "&" /* skipping comments bracketed by & records loop getf [1] line line = line // pad(1) repeat while line{1} <> "&" getf [1] line line = line // pad(4) repeat if "Std" not_con line{1} /* skipping Sound records, deleted records, and tags if line{1} = "@" if line con "SCORECON" /* keep only SCORECON type comments if scr_flag = 1 ++i tput [X,i] ~line if line con "track assignment:" track_flag = 1 end end end else if line{1} = "a" /* continuation records if len(line) > 15 temp = line{16..} tget [X,i] line line = line // temp tput [X,i] ~line end else if line{1,2} = "Pv" /* New code 05/02/03 if version{1,3} <> line{3,3} putc putc CAUTIONARY NOTICE putc putc The version of autoset you are running, version ~version , putc putc does not correspond with the print suggestions, version ~line{3,4} , putc in this file. There are two possible cases: putc putc Case I: The version of autoset you are running is older (lower number) putc than the version number in the file. Your version of autoset putc is probably still good, but you should upgrade your version of putc autoset at your earliest convenience. putc putc Case II: You are running a more recent version of autoset, and the file putc you are working on may be out of date. We advise that you check putc carefully the output where print suggestions are applied to make putc sure the outcome is the desired one. If everything checks out, putc you may avoid this notice in the future by simply updating the putc print suggestion version number (the Pv record) to correspond putc with the version of autoset you are running. If the printed putc results to not look right, you will need to change (or possibly putc delete) the print suggestions in question. If you cannot get putc your desired result by these changes, we suggest you consult the putc latest version of the stage2 source file documentation file. putc putc Type any key to continue getk k else if version{4} <> line{6} putc NOTICE: Your version of autoset = ~version ; data version = ~line{3,4} if version{4} < "1" putc The processing of I:2 multi-tracks has been changed. putc We suggest you check the output. putc end if version{4} < "2" putc The data may contain rehearsal numbers/letters in boxes putc which your version will not process. putc end end end New 02/03/08 if line{1,4} >= "4.02" box_flag = 1 end else New code 01/01/06 to implement certain run-time options for autoset if line{1,2} = "Px" if line{3,3} con "m" mreport_flag = 1 end if line{3,3} con "s" xdata_flag = 1 end if line{3,3} con "d" debug_flag = 1 putc Debug above measure number ? (return = no debug) getc line line = trm(line) if line <> "" debug_point = int(line) end end else ++i tput [X,i] ~line end end end end end if line{1} = "/" line = line // pad(5) if line{1,5} = "/FINE" loop getf [1] line line = line // pad(4) repeat while line{1,4} <> "/END" end if line{1,4} = "/END" ssize = i close [1] goto LOADED end goto eof1 end repeat eof1: putc Mis-use of "/" or File not properly terminated putc putc This error can also be caused by a missing comment putc terminator "&". putc stop ┌───────────────────────────────────────────────┐ │ Start Processing Data │ └───────────────────────────────────────────────┘ LOADED: barnum = 0 tgpnt = 0 if xdata_flag = 1 perform survay_file end barnum2 = 1 opbarnum = 1 ttext = "" firstoff = 0 sigflag = 0 key = 0 loop for i = 1 to 50 claveax(i) = 0 repeat repeater_flag = 0 nstaves = 1 * tget [X,5] line line = trm(line) // " " if line con "MV#:" temp = trm(line{mpt+4..}) line = line{1,mpt-1} end if line con "WK#:" line = trm(line{mpt+4..}) end tget [X,6] sourcename tget [X,7] wname tget [X,8] mname tget [X,9] partname #if AUTOSCR header2 = "Composer: " // composer // " Source: " // sourcename if composer_num = 1 header3 = "Work: BWV " // line // ":" // temp // " " // wname // " / " // mname end if composer_num = 2 header3 = "Work: " // line // ":" // temp // " " // wname // " / " // mname end if composer_num = 3 header3 = "Work: " // wname // " Mvmt: " // mname end if composer_num = 4 header3 = "Work: " // wname // " Mvmt: " // mname end #endif putc Work #: ~line .t30 Work name: ~wname putc Movement: ~temp .t30 Movement name: ~mname putc Part name: ~partname tget [X,10] out out = trm(out) a = 0 loop for i = 1 to len(out) if "SATB" con out{i} a = text_loc /* New 01/30/05 text_flag = 1 /* New 01/30/05 a = vpar(101) end repeat scnt = 11 p = 0 tput [Y,1] ~a tput [Y,2] J D 4 500 -120 1 6913 0 0 tput [Y,3] W 0 0 44 ~mname outpnt = 3 Special case code added 01/06/04. Look for print suggestion tags placed at the beginning of the file. This must be done here for the case of tag Y U 1. The others follow along, but are not critical. Please note: This is NOT the top of the stage2 data processing loop. a10 = scnt PRA: tget [X,a10] line ++a10 line = line // pad(80) if line{1} = "P" if line{2} = " " sub = 2 goto MORE_SUGG_A end if line con " " a4 = sub temp4 = line{2..sub} This notesize filter removes all P suggestions that do not meet notesize restrictions loop for i = 1 to len(temp4) if temp4{i} = "#" if temp4{i,2} = "#<" a1 = int(temp4{i+2..}) /* sets sub if notesize >= a1 goto PRA /* This suggestion does not apply end i = sub - 1 /* prepare i for next code else if temp4{i,2} = "#>" a1 = int(temp4{i+2..}) /* sets sub if notesize <= a1 goto PRA /* This suggestion does not apply end i = sub - 1 /* prepare i for next code else a1 = int(temp4{i+1..}) /* sets sub if notesize <> a1 goto PRA /* This suggestion does not apply end i = sub - 1 /* prepare i for next code end end end repeat if temp4 con job_type sub = a4 goto MORE_SUGG_A end if temp4 con "a" sub = a4 goto MORE_SUGG_A end end goto PRA MORE_SUGG_A: if line{sub..} con "C" ++sub d = int(line{sub..}) /* column number if line{sub} = ":" ++sub /* skip ":" g = sub else temp5 = "" loop while line{sub} <> ":" and sub < len(line) temp5 = temp5 // line{sub} ++sub repeat if line{sub} <> ":" putc Incomplete print suggestion putc line = ~line goto PRA end ++sub /* skip ":" g = sub temp5 = temp5 // " " This notesize filter removes all P suggestions that do not meet notesize restrictions loop for i = 1 to len(temp5) if temp5{i} = "#" if temp5{i,2} = "#<" a1 = int(temp5{i+2..}) /* sets sub if notesize >= a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG_A end i = sub - 1 /* prepare i for next code else if temp5{i,2} = "#>" a1 = int(temp5{i+2..}) /* sets sub if notesize <= a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG_A end i = sub - 1 /* prepare i for next code else a1 = int(temp5{i+1..}) /* sets sub if notesize <> a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG_A end i = sub - 1 /* prepare i for next code end end end repeat if temp5 con job_type or temp5 con "a" sub = g /* actually unnecessary else loop while line{g} <> " " and g < len(line) ++g repeat sub = g goto MORE_SUGG_A end end g = sub /* unnecessary Column 0: general suggestions if d = 0 /* general suggestion temp = "" loop for a2 = g to len(line) temp = temp // line{g} ++g repeat while line{g} <> " " temp = temp // " " if temp con "y" a2 = mpt + 1 if temp{a2} in ['0'..'9'] a3 = int(temp{a2..}) ++outpnt tput [Y,outpnt] Y U ~a3 end end if temp con "z" a2 = mpt + 1 a3 = int(temp{a2..}) ++outpnt if a3 = 0 tput [Y,outpnt] Y P 0 else temp = temp{sub..} tput [Y,outpnt] Y P ~a3 ~temp end end else loop for a2 = g to len(line) ++g repeat while line{g} <> " " end sub = g goto MORE_SUGG_A end goto PRA end if line{1} = "$" goto PRA end End of special case code 01/06/04 Set movement word (if present) out = mname partname = trm(partname) New code to implement // feature in partnames 12/21/05 if partname con "//" temp3 = partname{mpt+2..} partname = partname{1,mpt-1} // pad(17) partname = partname // temp3 end if partname <> "" out = out // ": " // partname end if out <> "" oby = 0 - vpar(33) - notesize obx = p + hpar(39) + hpar(5) ++outpnt tput [Y,outpnt] J D 1 ~obx ~oby 1 6913 0 0 spn = 6913 ++outpnt tput [Y,outpnt] W 0 -~vpar(8) 44 ~out end mrest = 0 wrest = 0 @n = 0 old@n = 0 xmindist = hpar(4) * cfactor /* New 12/16/03 mindist = xmindist / 100 /* New 12/16/03 mindist = hpar(4) minshort = 0 goto PR ┌───────────────────────────────┐ │ Process the data file │ └───────────────────────────────┘ PR: tget [X,scnt] line ++scnt line = line // pad(80) if line{1} = "@" #if AUTOSCR if line con "SCORECON" /* This section added 11/27/09 if line con "pitch transposition:" pitch_mod = int(line{mpt+20..}) end end #endif goto PR end d = int(line{6,3}) /* possible duration g = int(line{9,4}) /* possible measure number if line{1} = "$" if mrest > 0 /* this code added 1-27-93 perform setmrest end perform process_section goto PR end #if NO_EDIT if " ABCDEFGgcri" con line{1} if line{32..43} con "&" temp = line{44..} line = line{1..sub-1} // pad(43) line = line // temp end end #endif MAIN CODE FOR PRINT SUGGESTIONS (ends around line 4800) =================================== if line{1} = "P" Re-coding this section 12/16/03 to add notesize select feature and to fix the problem of consecutive suggestion records sugg_flg = 0 /* 05/02/03 sugg_flg2 = 0 /* 05/02/03 a1 = 1 loop while a1 < 10 ++a1 tget [X,scnt-a1] temp3 repeat while temp3{1} = "P" /* This code added 02/23/97 if line{2} = " " sub = 2 goto MORE_SUGG end if line con " " a4 = sub temp4 = line{2..sub} This notesize filter removes all P suggestions that do not meet notesize restrictions loop for i = 1 to len(temp4) if temp4{i} = "#" if temp4{i,2} = "#<" a1 = int(temp4{i+2..}) /* sets sub if notesize >= a1 goto PR /* This suggestion does not apply end i = sub - 1 /* prepare i for next code else if temp4{i,2} = "#>" a1 = int(temp4{i+2..}) /* sets sub if notesize <= a1 goto PR /* This suggestion does not apply end i = sub - 1 /* prepare i for next code else a1 = int(temp4{i+1..}) /* sets sub if notesize <> a1 goto PR /* This suggestion does not apply end i = sub - 1 /* prepare i for next code end end end repeat if temp4 con job_type sub = a4 goto MORE_SUGG end if temp4 con "a" sub = a4 goto MORE_SUGG end end goto PR /* end of 02/23/97 addition sugg_flg = 0 /* 05/02/03 sugg_flg2 = 0 /* 05/02/03 line = line // " " /* This code added 02/23/97 sub = 2 if line{2} = " " tget [X,scnt-2] temp3 goto MORE_SUGG end if line con " " a4 = mpt temp3 = line{2..sub} if temp3 con job_type tget [X,scnt-2] temp3 goto MORE_SUGG end end goto PR /* end of 02/23/97 addition MORE_SUGG: if line{sub..} con "C" ++sub d = int(line{sub..}) /* column number Code added 11/04/03 to allow for job-specific print suggestions to be specified by column number. if line{sub} = ":" ++sub /* skip ":" g = sub else temp5 = "" g = sub loop while line{sub} <> ":" and sub < len(line) and sub < g + 20 temp5 = temp5 // line{sub} ++sub repeat if line{sub} <> ":" putc putc Incomplete print suggestion. This fault should be fixed. putc index = ~(scnt+5) line = ~line putc goto PR end ++sub /* skip ":" g = sub Re-coding this section 12/16/03 to add notesize select feature temp5 = temp5 // " " This notesize filter removes all P suggestions that do not meet notesize restrictions loop for i = 1 to len(temp5) if temp5{i} = "#" if temp5{i,2} = "#<" a1 = int(temp5{i+2..}) /* sets sub if notesize >= a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG end i = sub - 1 /* prepare i for next code else if temp5{i,2} = "#>" a1 = int(temp5{i+2..}) /* sets sub if notesize <= a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG end i = sub - 1 /* prepare i for next code else a1 = int(temp5{i+1..}) /* sets sub if notesize <> a1 loop while line{g} <> " " and g < len(line) ++g repeat sub = g /* skipping this suggestion goto MORE_SUGG end i = sub - 1 /* prepare i for next code end end end repeat if temp5 con job_type or temp5 con "a" sub = g /* actually unnecessary else loop while line{g} <> " " and g < len(line) ++g repeat sub = g goto MORE_SUGG end if temp5 con job_type sub = g else loop while line{g} <> " " and g < len(line) ++g repeat sub = g goto MORE_SUGG end end g = sub /* unnecessary Column 0: general suggestions if d = 0 /* general suggestion PQST: if "acdFfghjkmnpqrstvxyz" con line{g} /* "a" added 05/26/05, and PSUG nums advanced /* "x" added (and string re-ordered) 01/03/04 /* "y" and "z" added 01/06/04 /* "c" added 05/12/04, and PSUG nums advanced /* "v" added 01/30/05, and PSUG nums advanced /* "j" added 12/20/05, and PSUG nums advanced /* "k" added 12/24/05, and PSUG nums advanced /* "m" added 03/04/06, and PSUG nums advanced /* "F" added 10/24/07, and PSUG nums advanced /* "h" added 11/19/07, and PSUG nums advanced /* "g" added 05/01/08, and PSUG nums advanced goto PSUG(mpt) PSUG(1): /* line{g} = "a" (New 05/26/05) art_flag = int(line{g+1..}) g = sub goto PQST PSUG(2): /* line{g} = "c" (New 05/12/04) restoff = int(line{g+1..}) g = sub if restoff <> 0 restoff = 1 end goto PQST PSUG(3): /* line{g} = "d" (Modified 01/06/06) a6 = int(line{g+1..}) tword_height = a6 ending_height = vpar(2) * a6 / 2 /* New 01/06/06 g = sub goto PQST PSUG(4): /* line{g} = "F" dtivfont = int(line{g+1..}) g = sub goto PQST PSUG(5): /* line{g} = "f" mdirfont = int(line{g+1..}) g = sub goto PQST PSUG(6): /* line{g} = "g" (New 05/01/08) slur_adjust = int(line{g+1..}) g = sub goto PQST PSUG(7): /* line{g} = "h" (New 11/19/07) a6 = int(line{g+1..}) min_space = hpar(29) * a6 / 100 g = sub goto PQST PSUG(8): /* line{g} = "j" (New 12/20/05) stem_change_flag = int(line{g+1..}) g = sub goto PQST PSUG(9): /* line{g} = "k" (New 12/24/05) a6 = int(line{g+1..}) dot_difference_flag = a6 & 0x01 key_reprint_flag = a6 & 0x02 /* added 11/26/06 mixed_color_flag = a6 & 0x04 /* added 11/26/06 suppress_key = a6 & 0x08 /* added 11/02/07 in_line_edslur = a6 & 0x10 /* added 01/12/09 large_clef_flag = a6 & 0x20 /* added 02/02/09 g = sub goto PQST PSUG(10): /* line{g} = "m" (New 03/04/06) a6 = int(line{g+1..}) if a6 = 1 multirest_flag = 1 else multirest_flag = 0 end g = sub goto PQST PSUG(11): /* line{g} = "n" m_number = int(line{g+1..}) g = sub goto PQST PSUG(12): /* line{g} = "p" xmindist = int(line{g+1..}) * hpar(4) * cfactor / 100 /* New 12/16/03 mindist = xmindist / 100 /* New 12/16/03 mindist = int(line{g+1..}) * hpar(4) / 100 g = sub perform newnsp goto PQST PSUG(13): /* line{g} = "q" minshort = int(line{g+1..}) g = sub perform newnsp goto PQST PSUG(14): /* line{g} = "r" (New treatment 03/15/09) a6 = int(line{g+1..}) restplace = a6 & 0x01 irest_flag = (a6 & 0x02) >> 1 rest_collapse = (a6 & 0x04) >> 2 /* New 03/15/09: 0 = TRUE; 1 = FALSE g = sub goto PQST PSUG(15): /* line{g} = "s" granddist = int(line{g+1..}) g = sub granddist = granddist * vpar(2) + 5 / 10 goto PQST PSUG(16): /* line{g} = "t" global_tpflag = int(line{g+1..}) g = sub if global_tpflag > 4 global_tpflag = 4 end if global_tpflag < 0 global_tpflag = 0 end tpflag = global_tpflag goto PQST This option added 01/30/05 PSUG(17): /* line{g} = "v" a6 = int(line{g+1..}) g = sub text_loc = a6 * notesize / 20 tget [Y,1] temp4 a6 = int(temp4) temp4 = temp4 // " " temp4 = temp4{sub..} temp4 = mrt(temp4) tput [Y,1] ~text_loc ~temp4 goto PQST This option added 01/03/04; modified 01/06/04 PSUG(18): /* line{g} = "x" a6 = int(line{g+1..}) if a6 = 1 and mrest > 0 perform setmrest end wrest = a6 if wrest <> 1 wrest = 0 end g = sub goto PQST These options added 01/06/04 PSUG(19): /* line{g} = "y" a6 = int(line{g+1..}) ++outpnt tput [Y,outpnt] Y U ~a6 g = sub goto PQST PSUG(20): /* line{g} = "z" a6 = int(line{g+1..}) ++outpnt if a6 = 0 tput [Y,outpnt] Y P 0 g = sub else g = sub temp = "" loop while line{g} <> " " and g < 80 temp = temp // line{g} ++g repeat if line{g} <> " " dputc Program Error stop end tput [Y,outpnt] Y P ~a6 ~temp end goto PQST end sub = g goto MORE_SUGG end Deal with record that contains: notes, grace notes, cue notes, rests, figures if " ABCDEFGgcrif" con temp3{1} /* 04/24/03 allowing print sugg for chords a3 = mpt Column 1: The Object itself. NOTES, GRACE NOTES, CUE NOTES, RESTS, FIGURES if d = 1 if "spxXyY" con line{g} /* "X" added 05/02/03 "s" added 02/19/06 ++@n tcode(@n) = zpd(4) tcode(@n){1} = chr(1) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0300 end ABCL: if line{g} = "p" i = int(line{g+1..}) g = sub if i < 0 i = 0 end if i > 7 i = 7 end if i > 0 i = i << 1 + 1 end tcode(@n){1} = chr(i) goto ABCL end This code added 02/19/06 to implement different shapes of note heads if line{g} = "s" i = int(line{g+1..}) g = sub if i < 0 i = 0 end if i > 15 i = 15 end i <<= 4 /* use upper part of first byte a3 = ors(tcode(@n){1}) a3 |= i /* add to what is already there a3 |= 0x01 /* turn on "active" bit tcode(@n){1} = chr(a3) goto ABCL end End of 02/19/06 addition if "xXyY" con line{g} /* 05/02/03 code revised a3 = mpt if line{g+1} = "+" ++g end a2 = int(line{g+1..}) g = sub a2 += 128 if a2 <= 0 a2 = 1 end if a2 > 255 a2 = 255 end a4 = ors(tcode(@n){2}) /* 05/02/03 code revised if a3 < 3 tcode(@n){3} = chr(a2) if a3 = 1 a4 |= 0x01 /* set position as "relative" else a4 |= 0x03 /* set position as "absolute" end else tcode(@n){4} = chr(a2) if a3 = 3 a4 |= 0x01 /* set position as "relative" else a4 |= 0x05 /* set position as "absolute" end end tcode(@n){2} = chr(a4) goto ABCL end sub = g goto MORE_SUGG end Columns 18 and 19: dots and accidentals on NOTES, GRACE NOTES, CUE NOTES, and RESTS if (d = 18 or d = 19) and a3 < 12 /* 05/02/03 i = d /* 18 = dots, 19 = accs if "xXyY" con line{g} a3 = mpt ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string NXYP2: if line{g+1} = "+" ++g end a2 = int(line{g+1..}) g = sub a2 += 128 if a2 <= 0 a2 = 1 end if a2 > 255 a2 = 255 end a4 = ors(tcode(@n){2}) if a3 < 3 tcode(@n){3} = chr(a2) if a3 = 1 a4 |= 0x01 /* set position as "relative" else a4 |= 0x03 /* set position as "absolute" end else tcode(@n){4} = chr(a2) if a3 = 3 a4 |= 0x01 /* set position as "relative" else a4 |= 0x05 /* set position as "absolute" end end tcode(@n){2} = chr(a4) if "xXyY" con line{g} a3 = mpt goto NXYP2 end end sub = g goto MORE_SUGG end Columns 26 to 30: beams if (d = 26 or d = 27) and a3 < 11 if "baA" con line{g} if "baAc" con line{g} /* "c" option added 01/01/08 repeater_flag = mpt - 1 if d = 27 and repeater_flag > 0 repeater_flag += 4 end sub = g goto MORE_SUGG end if d = 26 /* New code 05/14/03 i = 28 /* 28 = beam stem length code if line{g} = "y" ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string ++g sub = g if line{sub} = "+" ++sub end a2 = int(line{sub..}) g = sub a2 += 128 if a2 < 1 a2 = 1 end if a2 > 255 a2 = 255 end tcode(@n){2} = chr(a2) end end sub = g goto MORE_SUGG end Columns 32 to 43: ties, articulations, ornaments, dynamics, fermatas, technical suggestions (fingerings, etc.) if d >= 32 and d <= 43 and a3 < 12 /* 04/24/03 11 changed to 12 Slur suggestions. Additions and modifications to code on 05/06/03 if "([{z" con temp3{d} /* start slur 1,2,3,4 a5 = mpt if "ou" con line{g} /* this is a forced slur suggestion i = a5 - 1 << 1 - 1 + mpt ++@n tv1(@n) = P_SUGGESTION tv2(@n) = i sub = g goto MORE_SUGG end i = a5 + 19 /* 20, 21, 22, 23 New code 04/26/05 for print suggestion suppressing the printing of a slur if line{g} = "*" ++@n tcode(@n) = ch4(-1) /* 0xffffffff = suppress slur tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string sub = g goto MORE_SUGG end if "xyXY" con line{g} a3 = mpt ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string NXYH: ++g sub = g if line{sub} = "+" ++sub end a2 = int(line{sub..}) g = sub a2 += 128 if a2 < 1 a2 = 1 end if a2 > 255 a2 = 255 end tcode(@n){a3} = chr(a2) if "xyXY" con line{g} a3 = mpt goto NXYH end end sub = g goto MORE_SUGG end More slur suggestions if ")]}x" con temp3{d} /* end slur 1,2,3,4 i = mpt + 23 /* 24, 25, 26, 27 if "xyh" con line{g} a3 = mpt ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string NXYH2: ++g sub = g if line{sub} = "+" ++sub end a2 = int(line{sub..}) g = sub a2 += 128 if a2 < 1 a2 = 1 end if a2 > 255 a2 = 255 end tcode(@n){a3} = chr(a2) if "xyh" con line{g} a3 = mpt goto NXYH2 end end sub = g goto MORE_SUGG end End of 05/06/03 Addition if temp3{d} = "-" if "ou" con line{g} /* this is a specified tie ++@n tv1(@n) = P_SUGGESTION tv2(@n) = mpt + 7 end end if "_.=i>VArt~wMkvnoQ012345mpfZRFE-" con temp3{d} if "_.=i>VArt~wMkTvnoQ012345mpfZRFE-" con temp3{d} /* Tremulo added 01/07/06 if "_.=i>VArt~wMkTJKvnoQ012345mpfZRFE-" con temp3{d} /* Back ties added 04/22/08 i = mpt - 1 << 1 + 1 Tremulo added to this map 01/07/06 Back ties added to this map 04/22/08 ↓ i = int("01010102030303040404040404 060607080809090909091414141414151617"{i,2}) ↓ ↓ i = int("0101010203030304040404040404 060607080809090909091414141414151617"{i,2}) i = int("01010102030303040404040404040404060607080809090909091414141414151617"{i,2}) Explanation: We need to have a code which indicates the type of element to which the suggestions is applied. So for, we have the following codes: 1 = legato, staccato, or legato-staccate articulation 2 = spiccato articulation 3 = horizontal, vertical, or inverted vertical accent 4 = turn, trill, wavy line, shake, mordant, or delayed turn ornament tremulo added 01/07/06 back ties added 04/22/08 5 = (same thing, I think) 6 = up bow, or down bow bowing 7 = harmonic 8 = open string, or thumb position 9-13 = fingering (five suggestions possible) 14 = dynamics 15 = upright fermata 16 = inverted fermata 17 = tie 18 = dots 19 = accidentals (20-23 = start slur) (24-27 = stop slur) if i = 4 /* ornament if sugg_flg2 < 2 ++sugg_flg2 i = sugg_flg2 + 3 end end if i = 9 /* fingering if d > 32 and temp3{d-1} = ":" i = 1000 /* i = 1000 means "do nothing" else if sugg_flg < 5 ++sugg_flg i = sugg_flg + 8 end end end if line{g} = "L" and i <> 17 /* 05/02/03 "L" applies only to ties i = 1000 end if i < 1000 and "xXyYabL" con line{g} /* modifications to code 05/02/03 a3 = mpt ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0200 + i /* i is index into position string NXYP: if a3 < 5 ++g sub = g if line{sub} = "+" ++sub end a2 = int(line{sub..}) g = sub a2 += 128 if a2 < 1 a2 = 1 end if a2 > 255 a2 = 255 end a4 = ors(tcode(@n){2}) if a3 < 3 tcode(@n){3} = chr(a2) if a3 = 1 a4 |= 0x01 /* set position as "relative" else a4 |= 0x03 /* set position as "absolute" end else tcode(@n){4} = chr(a2) if a3 = 3 a4 |= 0x01 /* set position as "relative" else a4 |= 0x05 /* set position as "absolute" end end tcode(@n){2} = chr(a4) if i <> 17 a2 = ors(tcode(@n){1}) | 0x01 /* added 11/10/07 Major oversight, check results tcode(@n){1} = chr(a2) end end if a3 = 5 or a3 = 6 a4 = a3 - 5 * 4 + 3 /* 5 -> 3, 6 -> 7 a2 = ors(tcode(@n){1}) | a4 tcode(@n){1} = chr(a2) ++g end if a3 = 7 /* 05/02/03 "L" changes length of tie ++g sub = g if line{sub} = "+" ++sub end a2 = int(line{sub..}) g = sub a2 += 128 if a2 < 1 a2 = 1 end if a2 > 255 a2 = 255 end tcode(@n){1} = chr(a2) end if "xXyYabL" con line{g} a3 = mpt if a3 < 7 or i = 17 /* 05/02/03 "L" applies only to ties goto NXYP end end end sub = g goto MORE_SUGG end Suggestions for tuples if temp3{d} = "*" /* 03-21-97 if "[(:;i" con line{g} a3 = mpt ++@n tv1(@n) = P_SUGGESTION tv2(@n) = 0x10 /* tuplet suggestion MOTUP: if a3 = 2 or a3 = 4 tv2(@n) |= 0x01 /* round tuplet end if a3 = 1 or a3 = 2 or a3 = 5 tv2(@n) |= 0x02 /* continuous tuplet end if a3 = 3 tv2(@n) = 0x10 /* square, broken tuplet (default) end if a3 = 5 tv2(@n) |= 0x04 /* tuplet number inside bracket end if "[(:;i" con line{g+1} ++g a3 = mpt goto MOTUP end end end if temp3{d} = "!" /* 11/05/05 New code 11/05/05 implementing post adjustment to tuple position MOTUP2: if line{g} = "x" a2 = int(line{g+1..}) a2 *= vpar(2) a2 /= 10 g = sub if abs(a2) < 128 ++@n tv1(@n) = P_SUGGESTION tv2(@n) = 0x500 /* x adjustment to tuplet a2 += 128 tv2(@n) += a2 end goto MOTUP2 end if line{g} = "y" a2 = int(line{g+1..}) a2 *= vpar(2) a2 /= 10 g = sub if abs(a2) < 128 ++@n tv1(@n) = P_SUGGESTION tv2(@n) = 0x600 /* x adjustment to tuplet a2 += 128 tv2(@n) += a2 end goto MOTUP2 end end End of 11/05/05 addition sub = g goto MORE_SUGG end end Print suggestions applied to musical directions (not modified as of 05/02/03) if temp3{1} = "*" if d >= 17 and d <= 18 if "fxypY" con line{g} ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION if "ABCDGPQ" con temp3{d} if "ABCDGPQR" con temp3{d} /* New 02/03/08 tv2(@n) = 0x0100 else tv2(@n) = 0x0101 end end NXFP: if line{g} = "f" i = int(line{g+1..}) g = sub if "ABCDG" con temp3{d} /* this is a designated font number if "ABCDGR" con temp3{d} /* this is a designated font number New 02/03/08 tcode(@n){1} = chr(i) end goto NXFP end if "xyYp" con line{g} a3 = mpt + 1 if a3 = 5 a3 -= 2 end if line{g+1} = "+" ++g end i = int(line{g+1..}) i += 0x80 if i <= 0 i = 1 end if i > 255 i = 255 end g = sub if "ABCDEFGHPQUV" con temp3{d} /* this is a position shift if "ABCDEFGHPQRUV" con temp3{d} /* this is a position shift New 02/03/08 tcode(@n){a3} = chr(i) end goto NXFP end sub = g goto MORE_SUGG end if d >= 25 and line{g} = "f" and temp3{17,2} con ['B'..'D'] if d >= 25 and line{g} = "f" and temp3{17,2} con ['B'..'D','R'] /* New 02/03/08 i = int(line{g+1..}) g = sub temp3 = temp3 // pad(100) De-construct temp3 into ASCII and font changes loop for a1 = 1 to 10 font_changes(a1,1) = 0 font_changes(a1,2) = 0 repeat changecnt = 0 sub = 25 NXFNUM: if temp3{sub..} con "!" and temp3{sub+1} in ['0'..'9'] a1 = sub a2 = int(temp3{a1+1..}) ++changecnt font_changes(changecnt,1) = a1 font_changes(changecnt,2) = a2 Code change 01/17/04 to keep font changes from interferring with the text if temp3{sub} = "|" ++sub end temp3 = temp3{1,a1-1} // temp3{sub..} sub = a1 goto NXFNUM end Add new font change and re-order in ascending order of location ++changecnt font_changes(changecnt,1) = d font_changes(changecnt,2) = i loop for a1 = changecnt to 2 step -1 a2 = a1 - 1 if font_changes(a1,1) < font_changes(a2,1) a3 = font_changes(a1,1) font_changes(a1,1) = font_changes(a2,1) font_changes(a2,1) = a3 a3 = font_changes(a1,2) font_changes(a1,2) = font_changes(a2,2) font_changes(a2,2) = a3 end repeat Merge ASCII and font changes into new temp3 temp4 = temp3{1,24} a2 = 25 loop for a1 = 1 to changecnt a3 = font_changes(a1,1) if a3 > a2 temp4 = temp4 // temp3{a2..a3-1} end a2 = a3 Code change 01/17/04 keep font changes from interferring with the text temp4 = temp4 // "!" // chs(font_changes(a1,2)) // "|" temp4 = temp4 // "!" // chs(font_changes(a1,2)) repeat temp4 = temp4 // temp3{a2..} temp3 = temp4 loop for a1 = @n to 1 step -1 if tv1(a1) = MUSICAL_DIR tdata(a1,1) = temp3{17..96} a1 = 0 end repeat sub = g goto MORE_SUGG end end Print suggestions applied to measures and barlines: New code 05/25/03 if temp3{1} = "m" if d = 1 New suggestion 10/24/08 to breakup a multi-rest measure (for parts) if line{g} = "f" and mrest > 0 perform setmrest end if line{g} = "n" ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0400 end New suggestion 05/28/05 to implement mid-movement right justification NOTE: This code contains a giant cludge. If the print suggestion follows directly after a measure record, and "]" is the only suggestion, then this code reaches directly into the output and changes it. if line{g} = "]" if @n = 0 loop for i = outpnt to (outpnt - 10) step -1 tget [Y,i] temp4 if len(temp4) > 5 and temp4{1,3} = "J B" sub = 5 a6 = int(temp4{sub..}) a7 = int(temp4{sub..}) a8 = int(temp4{sub..}) a8 += 10000000 a9 = sub temp4 = "J B " // chs(a6) // " " // chs(a7) // " " // chs(a8) // temp4{sub..} tput [Y,i] ~temp4 goto PR end repeat end ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0401 end sub = g goto MORE_SUGG end end sub = g goto MORE_SUGG end goto PR end END OF MAIN CODE FOR PRINT SUGGESTIONS ========================================== if line{8} = " " d = 0 end if mrest > 0 out = trm(line) if len(out) > 15 /* this is a normal stage2 data line perform setmrest else 03/07/06 allowing only mheavy4 of all measure codes to slip through here. if "mrib" not_con line{1} or line{1,7} = "mheavy4" if line{1,4} <> "meas" and "rib" not_con line{1} perform setmrest end end end if "ABCDEFGri" con line{1} ++@n i = NOTE if line{1} = "r" i = REST end if line{1} = "i" i = IREST end tv1(@n) = i tv2(@n) = d if " 123" con line{24} /* staff number goes in tv3(.) & 0x0000000f if mpt = 1 tv3(@n) = 0 else tv3(@n) = mpt - 2 end else putc Illegal character in staff number column (col. 24). Please fix. putc Record = ~line goto EE end Code added 01/30/05 for text under notes temp4 = trm(line) if len(temp4) > 43 text_flag = 1 end if " 123456789" con line{15} /* track number goes in tv3(.) & 0x000000f0 if mpt = 1 /* track number = 0 means no information else tracknum_flag = 1 --mpt a1 = mpt << 4 tv3(@n) += a1 end else putc Illegal character in track number column (col. 15). Please fix. putc Record = ~line goto EE end Code added 01/30/05 for text under notes temp4 = trm(line) if len(temp4) > 43 text_flag = 1 end if line{1} = "i" tcode(@n) = "ires" /* redundant, but do it to be on the safe side else tcode(@n) = line{1,4} end tdata(@n,1) = line{17..80} Code added 01/03/04 to deal with optional rests (whole and otherwise) if "WHQESTXYZ " con line{17} a1 = mpt if line{1} = "r" and wrest = 1 tdata(@n,1){1} = "W" /* New: This line replaced 10/15/07 if line{17} = " " tdata(@n,1){1} = "o" else tdata(@n,1){1} = line{17} end else tdata(@n,1){1} = "whqestxyz "{a1} end end if wrest = 1 and line{1} = "r" and line{17} = " " tdata(@n){1} = "W" end if "ri" con line{1} /* restplace flag goes in tv3(.) & 0x0000ff00 if mpt = 1 tv3(@n) += restplace << 8 end else if repeater_flag > 0 /* repeater flag goes in tv3(.) & 0x0000ff00 tv3(@n) += repeater_flag << 8 if bit(0,repeater_flag) = 1 and line{26} = "]" repeater_flag = 0 end end end Code added 05/12/04 to implement global suggestion to turn off the printing of rests (used for blank continuo parts). Note that no other print suggestions for rest can be inforce when this feature is used. Adding condition 01/01/06 to make irest_flag work if restoff = 1 if restoff = 1 or (irest_flag = 1 and tv1(@n) = IREST) ++@n tcode(@n) = zpd(4) tv1(@n) = P_SUGGESTION tv2(@n) = 0x0300 tcode(@n){1} = chr(3) end Code added 01/10/06 to expand the operation of art_flag if art_flag >= 16 and "ri" not_con line{1} a2 = art_flag >> 4 if a2 = 1 or a2 = 3 or a2 = 4 or a2 = 8 ++@n tcode(@n) = zpd(4) tcode(@n){1} = chr(1) tv1(@n) = P_SUGGESTION if a2 < 4 tv2(@n) = 0x0201 else if a2 = 4 tv2(@n) = 0x0202 else if a2 = 8 tv2(@n) = 0x0203 end end end tcode(@n){1} = chr(3) end end goto PR end if line{1} = "/" perform action ++outpnt tput [Y,outpnt] J M 0 ~obx 0 0 10000 0 0 putc END goto NEXT end if " cgf*b" con line{1} a2 = mpt e = int(line{8}) if line{8} in ['A'..'E'] if line{8} in ['A'..'E','X'] /* Implementing arpeggios 01/13/06 e = ors(line{8}) - 55 /* A = 10, etc. X = 33 (ARPEGGIO) end New code 01/13/06 implementing arpeggios; delete extraneous data if e = ARPEGGIO line = line{1,24} line = line // pad(80) end ++@n tdata(@n,1) = line{17..80} if line{1} = "f" tv3(@n) = 0 else if " 123" con line{24} /* staff number goes in tv3(.) & 0x0000000f if mpt = 1 tv3(@n) = 0 else tv3(@n) = mpt - 2 end else putc Illegal character in staff number column (col. 24). Please fix. putc Record = ~line goto EE end if a2 < 4 /* chords, grace, and cue notes if " 123456789" con line{15} /* track number goes in tv3(.) & 0x000000f0 if mpt = 1 /* track number = 0 means no information else --mpt a1 = mpt << 4 tv3(@n) += a1 end else putc Illegal character in track number column (col. 15). Please fix. putc Record = ~line goto EE end end end goto T(a2) /* a2 = mpt from ~20 lines above T(1): tv1(@n) = XNOTE tv2(@n) = 0 tcode(@n) = line{2,4} goto PR T(2): i = CUE_NOTE if line{2} = " " i = XCUE_NOTE tcode(@n) = line{3,4} e = 0 else tcode(@n) = line{2,4} end if line{2} = "r" i = CUE_REST end tv1(@n) = i tv2(@n) = e if line{2} = "r" /* restplace flag goes in tv3(.) & 0x0000ff00 tv3(@n) += restplace << 8 else if repeater_flag > 0 /* repeater flag goes in tv3(.) & 0x0000ff00 tv3(@n) += repeater_flag << 8 if bit(0,repeater_flag) = 1 and line{26} = "]" repeater_flag = 0 end end end goto PR T(3): i = GR_NOTE if line{2} = " " i = XGR_NOTE tcode(@n) = line{3,4} e = 0 else tcode(@n) = line{2,4} end tv1(@n) = i tv2(@n) = e if repeater_flag > 0 /* repeater flag goes in tv3(.) & 0x0000ff00 tv3(@n) += repeater_flag << 8 if bit(0,repeater_flag) = 1 and line{26} = "]" repeater_flag = 0 end end goto PR T(4): tv1(@n) = FIGURES tv2(@n) = d tv3(@n) = 0 tcode(@n) = line{2,4} goto PR T(5): tv1(@n) = MUSICAL_DIR if "12345" con line{15} tv2(@n) = mpt else tv2(@n) = 1 end if d > 0 tv3(@n) += d << 8 end These lines added 02/03/08. Rehearsal feature is not implemented in SCORE conversion (for the moment) #if AUTOSCR if line{17} = "R" line{17} = "D" end if line{18} = "R" line{18} = "D" end #endif tcode(@n) = line{17,4} Code added 01/07/06 to give format warning if line{17,2} = " " putc WARNING Bad format in a musical direction record temp4 = trm(line) putc Rec #~(scnt+5) -> ~temp4 putc end goto PR T(6): tv1(@n) = BACKSPACE tv2(@n) = d tv3(@n) = 0 tcode(@n) = line{1,4} goto PR end if line{1} = "m" ++barnum2 a1 = measuremap(barnum2,1) jscrdat = "| NTRACKS=" // chs(a1) if nstaves = 2 loop for a2 = 1 to 9 if trackstave(barnum2,a2,1) + trackstave(barnum2,a2,2) > 0 jscrdat = jscrdat // " (" // chs(a2) // "," // chs(trackstave(barnum2,a2,3)) // ")" end repeat end if f4 = 0 and line{2,6} <> "heavy4" 03/07/06 Allowing other measure types (except "mheavy4") here, but clearing mrest below for all cases other than "measure" if line{2,4} = "easu" and f4 = 0 out = trm(line) if len(out) < 16 New 03/13/06 Don't process for "multi-rests" unless multirest_flag = 1 Normally, this will apply to Parts only. if len(out) < 16 and multirest_flag = 1 if @n = 1 if "ir" con tcode(1){1} out = trm(tdata(1,1)) if out = "" ++mrest if mrest = 1 how_much_mrest(1) = divspq how_much_mrest(2) = tv2(1) else if divspq <> how_much_mrest(1) dputc Program error stop end if tv2(1) <> how_much_mrest(2) putc Stage 2 file format error at approx rec ~scnt putc Attempting to use indefinite rests (rest with no letter) putc of successively different lengths, without change putc of meter. putc putc Program Halted putc stop end end mrest_line = line measnum = g if wrest = 1 or multirest_flag = 0 /* New code 01/03/04 and 03/04/06 perform setmrest /* " " " else if line{2,4} <> "easu" perform setmrest /* 03/07/06 clear mrest for non-standard measures end end @n = 0 out = trm(line) if len(out) > 7 if len(out) > 12 out = line{1,8} // chs(g-1) // pad(12) out = out // line{13..} out = trm(out) else out = line{1,8} // chs(g-1) out = trm(out) end end #if MREPORT putc ~out #endif Added 01/01/06 if mreport_flag = 1 putc ~out end goto PR end end else if @n = vflag * 2 - 1 and nstaves = 1 examine loop for i = 1 to vflag * 2 step 2 out = trm(tdata(i,1)) if "ir" not_con tcode(i){1} or out <> "" i = 10000 else if i < @n out = trm(tdata(i+1,1)) if tcode(i+1) <> "back" or out <> "" i = 10000 end end end repeat if i < 10000 ++mrest if mrest = 1 how_much_mrest(1) = divspq how_much_mrest(2) = tv2(1) else if divspq <> how_much_mrest(1) dputc Program error stop end if tv2(1) <> how_much_mrest(2) putc Stage 2 file format error at approx rec ~scnt putc Attempting to use indefinite rests (rest with no letter) putc of successively different lengths, without change putc of meter. putc putc Program Halted putc stop end end mrest_line = line measnum = g if wrest = 1 or multirest_flag = 0 /* New code 01/03/04 and 03/04/06 perform setmrest /* " " " else if line{2,4} <> "easu" perform setmrest /* 03/07/06 clear mrest for non-standard measures end end @n = 0 out = trm(line) #if MREPORT putc ~out #endif goto PR Added 01/01/06 if mreport_flag = 1 putc ~out end end end end end end f4 = 0 ++@n tv1(@n) = BAR_LINE tv2(@n) = g tv3(@n) = nstaves measnum = g tcode(@n) = line{4,4} tdata(@n,1) = line{17..80} tdata(@n,2) = chs(barnum2) // "+" // jscrdat jscrdat = "" if tdata(@n,1) not_con "*" and tdata(@n,1) not_con "&" /* 2nd condition added 01/30/05 if tdata(@n,1) not_con "*" out = trm(line) if len(out) > 7 if len(out) > 12 out = line{1,8} // chs(g-1) // pad(12) out = out // line{13..} out = trm(out) else out = line{1,8} // chs(g-1) out = trm(out) end end #if MREPORT putc ~out #endif Added 01/01/06 if mreport_flag = 1 putc ~out end perform action loop for i = 1 to 50 loop for j = 1 to 4 /* 06/04/08 was 3 measax(j,i) = claveax(i) measax(j,i) = tclaveax(i) /* New 12/14/07 repeat repeat @n = 0 end goto PR end putc ~line trp = 7 goto trap * NEXT: Open output file open [3,2] outfile #if AUTOSCR putf [3] ~header1 putf [3] ~header2 putf [3] ~header3 #else New 03/25/06 tget [X,2] temp2 if temp2 con "{" temp2 = temp2{mpt..} temp2 = trm(temp2) else temp2 = "not identified" end tget [X,3] temp3 if temp3 con "TIMESTAMP:" temp3 = temp3{11..} temp3 = mrt(temp3) temp3 = trm(temp3) else temp3 = "" end putf [3] @ SOURCE: ~temp2 ~temp3 #endif tget [Y,1] a .t1 temp3 Adding this code 01/30/05 to make sure text is set at the right height if text_flag = 1 a = text_loc end if single_line = 0 LL = "L" else LL = "l" end #if AUTOSCR temp3 = temp3 // " " a2 = transposition a4 = instrument_number a1 = measuremap(1,1) if nstaves = 2 line = "" loop for a3 = 1 to 9 if trackstave(1,a3,1) + trackstave(1,a3,2) > 0 line = line // " (" // chs(a3) // "," // chs(trackstave(1,a3,3)) // ")" end repeat putf [3] L ~granddist ~a ~notesize !39~partname | NTRACKS=~a1 ~line | TRANS=~a2 INSTN=~a4 else putf [3] ~LL 0 ~a ~notesize !39~partname | NTRACKS=~a1 | TRANS=~a2 INSTN=~a4 end #else if nstaves = 2 putf [3] L ~granddist ~a ~notesize !39~partname else putf [3] ~LL 0 ~a ~notesize !39~partname end #endif loop for i = 2 to outpnt tget [Y,i] line putf [3] ~line repeat close [3] treset [X] treset [Y] * ++f3 if f3 > f2 stop end goto BIG * trap: goto E(trp) E(1): putc Chord format error goto EE E(2): putc Figured harmony error goto EE E(3): putc Tie error putc putc This is most often caused by a tie that has no terminating note putc in any part. You should first check to see that all ties in putc region where this error occurred are properly terminated. The putc problem can also be caused by excessive durations in a measure putc that has a tie. This will cause the program to think the measure putc has ended (early) and it will look for a terminating note in the putc next measure; i.b46 e., it will skip a properly placed terminating note. putc If you still can't find the error, you might try deleting ties one putc at a time to see which one is causing the problem. putc putc Another cause can be trying to tie notes which are on different putc staves of the grand staff. At the moment, autoset does not support putc this feature. goto EE E(4): putc Bar error goto EE E(5): putc Text error goto EE E(6): putc Time signature error goto EE E(7): putc No recognizable control character goto EE E(8): putc Figured harmony out of order putc putc Possibly you have entered a figured offset improperly. putc putc For example, the offset to the second figure actually appears putc in the record for the first figure. The interpretation of the putc offset number is how must to advance the division counter after putc a figure is printed. putc goto EE E(9): putc Pitch decoding error goto EE /* This error condition added 10-12-96 E(10): putc No pitch found to match tie termination (X) direction (*). putc putc Check musical direction records (*) in this measure for tie putc terminations and verify that the pitch in column 25 appears putc earlier in the measure, on the same staff. putc goto EE EE: putc putc Program Halted putc stop ┌─────────────────────────────────┐ │ End of processing music data │ └─────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ P R O C E D U R E S │ └─────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────┐ │P 1a. decodenote │ │ │ │ Input: note (string) │ │ │ │ Output: @c = clave number │ │ 100 = rest │ │ 200 = unprinted rest │ │ │ │ @d = unmodified accidental flag │ │ 0000 = no accidental │ │ 0010 = sharp │ │ 0011 = flat │ │ 1010 = sharp sharp │ │ 1111 = flat flat │ │ │ │ for rests, mf(1) = 0 ????????????? │ │ │ │ Note: decodenote is called only AFTER all note events have│ │ been reordered by time within the measure. │ │ │ └──────────────────────────────────────────────────────────────┘ procedure decodenote int a,b if note = "rest" @c = 100 @d = 0 mf(1) = 0 return end if note = "ires" @c = 200 @d = 0 return end if claves con note{1} a = mpt end @d = 0 loop for b = 2 to 4 if numbers con note{b} @c = mpt - 2 * 7 + a return end @d <<= 2 if accs con note{b} @d = @d | mpt end repeat putc note = ~note This will cause a ... return 9 ┌────────────────────────────────────────────────────────────────┐ │P 1a. decodeax (t1,t2) │ │ │ │ Input: t1 = pointer into ts array │ │ t2 = index into measax array │ │ bit(18,ts(t1,SUBFLAG_1)) = cautionary accidental flag│ │ (has effect only when no accidental would │ │ otherwise be printed) │ │ │ │ Output: correct accidental in ts(.,AX) │ │ │ │ 0000 = no accidental │ │ 0001 = natural │ │ 0010 = sharp │ │ 0011 = flat │ │ 0110 = natural sharp │ │ 0111 = natural flat │ │ 1010 = sharp sharp │ │ 1111 = flat flat │ │ │ └────────────────────────────────────────────────────────────────┘ procedure decodeax (t1,t2) int t1,t2,t3,t4,ax getvalue t1,t2 t3 = ts(t1,CLAVE) if t3 > 99 ts(t1,AX) = 0 return end adjust accident to reflect key and measure t4 = ts(t1,AX) ax = t4 if ax = measax(t2,t3) if bit(18,ts(t1,SUBFLAG_1)) = 0 t4 = 0 else if t4 = 0 t4 = 1 /* natural end end else if ax = 0 t4 = 1 else if measax(t2,t3) > 7 if ax < 4 t4 = t4 | 4 end end end measax(t2,t3) = ax end ts(t1,AX) = t4 return ┌────────────────────────────────────────────────────────────────────┐ │P 2. action │ │ │ │ Purpose: Action is basically a continuation of the music │ │ processing program. It is called when the data │ │ for a measure is complete. │ │ │ │ Inputs: @n = number of elements in data arrays │ │ tv1(.) = element type │ │ │ │ type element │ │ ---- ------- │ │ 1 regular note │ │ 2 extra regular note in chord │ │ 3 regular rest │ │ 4 cue note │ │ 5 extra cue note in chord │ │ 6 cue rest │ │ 7 grace note or grace rest │ │ 8 extra grace note in chord │ │ 9 figured harmony │ │ 10 bar line │ │ 11 musical direction │ │ 12 invisable rest │ │ 13 backspace │ │ 14 clef change │ │ 15 time designation or other directive │ │ 16 time change │ │ 17 change in divspq │ │ 18 key change │ │ 19 print suggestion │ │ │ │ tv2(.) = duration for types 1--9, 12,13 │ │ = measure number for type 10 │ │ = track number for type 11 (1 = default) │ │ = new clef number for type 14 │ │ = 0 for type 15 │ │ = new time flag for type 16 │ │ = new divspq for type 17 │ │ = new key for type 18 │ │ = type of suggestion for type 19 │ │ │ │ if between 0 and 7 │ │ 0 = force slur 1 over │ │ 1 = force slur 1 under │ │ 2 = force slur 2 over │ │ 3 = force slur 2 under │ │ 4 = force slur 3 over │ │ 5 = force slur 3 under │ │ 6 = force slur 4 over │ │ 7 = force slur 4 under │ │ │ │ if between 8 and 9 │ │ 8 = overhanded tie (tips down) │ │ 9 = underhanded tie (tips up) │ │ │ │ if between 16 and 31 (03-21-97) │ │ bit 0: clear = square tuplet │ │ set = round tuplet │ │ bit 1: clear = broken tuplet │ │ set = continuous tuplet │ │ bit 2: clear = number outside tuplet │ │ set = number inside tuplet │ │ │ │ if between 128 and 255 │ │ font = type - 128 │ │ │ │ if between 0x100 and 0x1ff │ │ vert and/or horz adj to musical dir │ │ │ │ if between 0x200 and 0x2ff │ │ vert and/or horz adj to sub-obj │ │ │ │ if between 0x300 and 0x3ff │ │ vert and/or horz adj to note/rest/fig │ │ objects. │ │ │ │ if between 0x400 and 0x4ff │ │ suggestion for barline or measure │ │ │ │ if between 0x500 and 0x5ff New 11/05/05 │ │ x adjustment to tuple │ │ (range -127 to +127) │ │ │ │ if between 0x600 and 0x6ff New 11/05/05 │ │ y adjustment to tuple │ │ (range -127 to +127) │ │ │ │ tv3(.) & 0x000f = staff number (0 or 1) │ │ │ │ For notes, rests and irests │ │ & 0x00f0 = track number (0 to 9) 0=unknown │ │ │ │ For notes, │ │ & 0xff00 = value of repeater_flag │ │ For rests, │ │ & 0xff00 = value of restplace │ │ For musical directions │ │ & 0xff00 = value of optional forward │ │ offset for division counter │ │ │ │ tv5(.) used for flagging $ data that occurs │ (New 01/17/04) │ at the beginning of a measure, but │ │ is not typeset immediately │ │ │ │ tcode(.) = pitch (rest) for types 1--8 │ │ = number of figure fields for type 9 │ │ (figured harmony) │ │ = bar type for type 10 │ │ = musical direction code and position │ │ for type 11 │ │ = "ires" for type 12 │ │ = "back" for type 13 │ │ = "0" or "128" for type 14 (clef change) │ │ = "" for types 15--18 │ │ = for type 19 (print suggestions) │ │ a 4 byte code │ │ │ │ byte 1: 0x01: active flag (0 = inactive) │ │ 0xfe: various meanings │ │ (for ties only) │ │ length modification (+128) │ │ (0 = no data) │ │ (for start slurs ([{z only) │ │ curvature modification (+128) │ │ (0 = no data) │ │ (-1 = suppress slur) 04/26/05 │ │ (for notes, etc.) │ │ upper four bits used to designate │ │ note head shape. │ │ 0 = regular │ │ 1 = x (cymbal crash) 02/19/06 │ │ (2 = diamond) │ │ │ │ │ │ byte 2: x-y active flags │ │ 0x01: active flag (0 = inactive) │ │ 0x02: 0 = x position is relative │ │ 1 = x position is absolute │ │ 0x04: 0 = y position is relative │ │ 1 = y position is absolute │ │ byte 3: x position data (+128) (0=no data) │ │ byte 4: y position data (+128) (0=no data) │ │ │ │ OLD tdata(.,.) = additional data for types 1--9, 11, 19 │ 03/21/03 adding │ tdata(.,.) = additional data for types 1--11, 19 │ tdata(.,.) for type 10 │ │ │ │ │ Output: ts(.,.) │ │ Description of ts │ │ -------------------------- │ │ │ │ Case I: Notes, Rests, Grace Notes, Cue Notes, Cue Rests │ │ Extra Regular, Grace, and Cue notes in Chords │ │ (types 1--8) │ │ │ │ ts(1) = type: 1 = note │ │ 2 = extra regular note in chord │ │ 3 = rest │ │ 4 = cue note │ │ 5 = extra cue note in chord │ │ 6 = cue rest │ │ 7 = grace note or grace rest │ │ 8 = extra grace note in chord │ │ │ │ ts(2) = division number (starting with 1) │ │ ts(3) = clave <100 = clave number │ │ 100 = rest │ │ 101 = movable rest │ │ 200 = irest <-- │ │ │ │ ts(4) (used initially to store pointer to tcode(.) ) │ │ │ │ ts(4) = accidental flag │ │ │ │ bits 0x0f: 0 = none 6 = natural-sharp │ │ 1 = natural 7 = natural-flat │ │ 2 = sharp 10 = double sharp │ │ 3 = flat 15 = double flat │ │ │ │ bit 0x10: 0 = regular 1 = "silent" │ │ │ │ bits 0xff00: left shift (positioning) │ │ │ │ │ │ ts(5) = note type │ │ │ │ 1 = 256th note 7 = quarter note │ │ 2 = 128th note 8 = half note │ │ 3 = 64th note 9 = whole note │ │ 4 = 32nd note 10 = breve │ │ 5 = 16th note 11 = longa │ │ 6 = 8th note 12 = eighth with slash │ │ │ │ ts(6) = dot flag 0 = no dot, 1 = dot, 2 = double dot │ │ ts(7) = tuplet flag 0 = no tuplet, # = tuplet │ │ 0xff first number │ │ 0xff00 second number │ │ 0xff0000 x adjustment (128 centered) │ │ 0xff000000 y adjustment (128 centered) │ │ │ │ ts(8) = location on staff │ │ ts(9) = spacing number │ │ ts(10) = stem/chord flag bit clear set │ │ ----- ------- --------- │ │ 0 no stem stem │ │ 1 step up stem down │ │ 2 single note chord │ │ 3 first note extra note │ │ 4-7 (note number in chord) │ │ │ │ ts(11) = beam flag 0 = no beam │ │ 1 = end beam │ │ 2 = start beam │ │ 3 = continue beam │ │ │ │ ts(12) = beam code (up to six digits) │ │ │ │ This is an integer less than 1000000. The one's │ │ digit is the code for the eighth beam; the │ │ tens digit is the code for the sixteenth beam, │ │ etc. │ │ │ │ digit char meaning │ │ ------- ---- --------- │ │ 0 blank no beam │ │ 1 = continued beam │ │ 2 [ begin beam │ │ 3 ] end beam │ │ 4 / forward hook │ │ 5 \ backward hook │ │ 6 simple repeater │ │ 7 begin repeated beam │ │ 8 end repeated beam │ │ │ │ ts(13) = local x-offset (for chords) │ │ │ │ ts(14) = superflag bit set │ │ ----- -------- │ │ 0 tie │ │ 1 begin ~~~~~ without tr. │ │ 2 begin ~~~~~ with tr. │ │ 3 end ~~~~~ │ │ 4 begin tuplet │ │ 5 end tuplet │ │ 6 tuple has a bracket │ │ 7 bracket is continuous │ │ (0 = broken) │ │ 8 number is inside │ │ (0 = outside) │ │ 9 bracket is round │ │ (0 = square) │ │ │ │ 16 tie is editorial (dotted) │ │ 17 ~~~ is editorial │ │ 18 tuple is editorial │ │ │ │ │ │ ts(15) = slurflag bit set meaning │ │ ------- ------- │ │ 0 start slur1 (new slur) │ │ 1 stop slur1 (from prev. note) │ │ 2 start slur2 (etc.) │ │ 3 stop slur2 │ │ 4 start slur3 │ │ 5 stop slur3 │ │ 6 start slur4 │ │ 7 stop slur4 │ │ │ │ for editorial slurs │ │ ─────────────────── │ │ 16 start slur1 (new slur) │ │ 17 stop slur1 (from prev. note) │ │ 18 start slur2 (etc.) │ │ 19 stop slur2 │ │ 20 start slur3 │ │ 21 stop slur3 │ │ 22 start slur4 │ │ 23 stop slur4 │ │ │ │ for both kinds of slurs │ │ ─────────────────────── │ │ 8 force slur1 │ │ 9 0 = up, 1 = down │ │ 10 force slur2 │ │ 11 0 = up, 1 = down │ │ 12 force slur3 │ │ 13 0 = up, 1 = down │ │ 14 force slur4 │ │ 15 0 = up, 1 = down │ │ │ │ for ties │ │ ──────── │ │ 24 specify tie orientation │ │ 25 0 = overhand; 1 = underhand │ │ │ │ │ │ ts(16) = subflag 1 bit item │ │ ----- ------- │ │ 0-3 ornaments │ │ --------- │ │ 0 = none │ │ 1 = turn │ │ 2 = trill(tr.) │ │ 3 = shake │ │ 4 = mordent │ │ 5 = delayed turn │ │ 6 = tremulo New 01/07/06 │ │ 7-15 (available) │ │ │ │ 4-9 accidental combinations │ │ with ornaments │ │ ----------------------- │ │ 4-6 accidental above ornament │ │ 7-9 accidental below ornament │ │ │ │ Accidental code │ │ --------------- │ │ 0 = none │ │ 1 = sharp-sharp │ │ 2 = flat-flat │ │ 3 = sharp │ │ 4 = natural │ │ 5 = flat │ │ 6 = (not used) │ │ 7 = (not used) │ │ │ │ 10--13 dynamics │ │ -------- │ │ 0 = none (see also bits 26 │ │ 1 = p to 28) │ │ 2 = pp │ │ 3 = ppp │ │ 4 = pppp │ │ 5 = f │ │ 6 = ff │ │ 7 = fff │ │ 8 = ffff │ │ 9 = mp │ │ 10 = mf │ │ 11 = fp │ │ 12 = sfp │ │ 13 = sf │ │ 14 = sfz │ │ 15 = rfz │ │ │ │ 14 upright fermata │ │ 15 inverted fermata │ │ │ │ 16 print note in cue size │ │ 17 editorial accidental │ │ 18 cautionary accidental │ │ │ │ 19 accidental follows trill │ │ rather than above or below │ │ (added 11/05/05) │ │ │ │ 20--23 shape of note head │ │ ------------------ │ │ 0 = regular │ │ 1 = x (cymbal crash) │ │ 2 -> (un-assigned) │ │ possibilities include │ │ normal diamond │ │ stem centered diamond │ │ blank (stem only) │ │ 18th century │ │ (added 02/19/06) │ │ │ │ 24 overhand back tie │ │ 25 underhand back tie │ │ (added 04/22/08) │ │ │ │ 26--28 more dynamics (added 10/08/08) │ │ ------------- │ │ 0 = really none │ │ 1 = ffp │ │ 2 = mfp (added 01/12/09) │ │ 3 = Zf (added 03/16/09) │ │ 4 = │ │ 5 = │ │ 6 = │ │ 7 = │ │ │ │ │ │ ts(17) = subflag 2 bit item │ │ ----- ------- │ │ n 0 down bow │ │ v 1 up bow │ │ i 2 spiccato │ │ . 3 staccato │ │ = 4 line over dot │ │ _ 5 legato │ │ > 6 horizontal accent │ │ A 7 vertical sfortzando accent │ │ V 8 vertical sfortzando accent │ │ o 9 harmonic │ │ Q 10 thumb (*) │ │ 0 11 open string (0) │ │ │ │ 12-31 fingering (up to 5 numbers) │ │ ---------- │ │ 12-14 first number │ │ 0 = no number │ │ 1 = finger 1 │ │ 2 = finger 2 │ │ 3 = finger 3 │ │ 4 = finger 4 │ │ 5 = finger 5 │ │ 15 substitution bit │ │ 0 = no substitution │ │ 1 = substitution │ │ 16-19 (second number, see 12 to 15) │ │ 20-23 (third number) │ │ 24-27 (fourth number) │ │ 28-31 (fifth number) │ │ │ │ │ │ ts(18) = used for sorting, later used to indicate position │ │ of virtual note head (for placing slurs and │ │ other articulations and signs). bit 24 │ │ set if modified │ │ ts(19) = used for sorting, later used to indicate global │ │ x-offset for chord groups │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ ts(22) = backtie flag (for regular, chord and cue notes) │ │ │ │ 0 = this note is not backward tied │ │ # = this note is backward tied │ │ │ │ Actually the BACKTIE flag has multiple uses. │ │ │ │ (1) When the ts array is first being constructed, │ │ there may be a tie into this group of notes │ │ from a previous measure. In this case, a tiearr │ │ ROW element has already been constructed. The │ │ tiearr rows need to be searched and the proper │ │ one found. This index (+ INT10000) is then │ │ stored as the backtie flag. │ │ │ │ (2) For all other row elements of the ts array, │ │ it is sufficient to store a back pointer to the │ │ ts row that originated the tie. │ │ │ │ (3) When it comes time to process the ts array, │ │ three cases may be encountered. │ │ │ │ (a) There is a non-zero backtie flag, and this │ │ flag is greater than INT10000. In this case, │ │ the backtie flag (- INT10000) points to a tiearr │ │ ROW element, and the tie may be processed. │ │ │ │ (b) There is a forward tie from this note. In │ │ this case, the backtie flag has already been │ │ used to set a tie and the element is now free │ │ for other use. We can generate a new row element│ │ in tiearr, and place the pointer to this element │ │ in the backtie flag (the term "backtie" is now │ │ a misnomer). │ │ │ │ (c) Now when we encounter a non-zero backtie │ │ flag in a new ts ROW, we know this points to a │ │ previous ts row, from which we can get the │ │ pointer to the relevant tiearr ROW in that │ │ ts(,.BACKTIE). │ │ │ │ For this method to work properly, it is │ │ necessary that backward ties be processed before │ │ forward ties. When a backward tie is processed │ │ it is important to set the backtie flag to zero. │ │ │ │ ts(23) = note duration (in divisions) │ │ ts(24) = increment distance flag │ │ │ │ 0 -- fixed distance (not to be modified by print) │ │ # -- variable distance; # = time elaps between │ │ this node and next node. │ │ (576 divisions = quarter note) │ │ │ │ ts(25) = virtual end of stem (bit 24 set if modified) │ │ ts(26) = editorial version of ts(16), subflag 1 │ │ ts(27) = editorial version of ts(17), subflag 2 │ │ ts(28) = staff number │ │ ts(29) = multi-track flag << 2 + mcat flag │ │ │ │ multi-track flag │ │ ──────────────── │ │ 0 = this note lies on a staff that has notes from │ │ only one pass (the simplest and most common │ │ situation). │ │ 1 = this note belongs to one of multiple passes │ │ on this staff and all notes on this pass │ │ have stems which point up │ │ 2 = this note belongs to one of multiple passes │ │ on this staff and all notes on this pass │ │ have stems which point down │ │ 3 = this note belongs to one of multiple passes │ │ on this staff and the notes for at least one │ │ of these passes have stem directions which │ │ are both up and down │ │ │ │ mcat flag │ │ ───────── │ │ 0 = only one independent instrument represented │ │ in this measure (vflag = 1) │ │ 1 = more than one independent instrument (vflag > 1)│ │ but only one pass and without chords (either │ │ unison part, or single part) │ │ 2 = more than one independent instrument (vflag > 1)│ │ but only one pass but with chords (more than │ │ one part, but parts are isorhythmic) │ │ 3 = more than one independent instrument (vflag > 1)│ │ and more than one pass (two or more musically │ │ independent parts) │ │ │ │ ts(30) = spacing parameter (1 <= spn <= 6913) │ │ ts(31) = y position of object (saves time in proc. chords) │ │ ts(32) = pointer to extra ts() row element for storing data │ │ on slurs. Elements 1-6 of new element are for │ │ storing global data on slurs entering and leaving │ │ the note. Elements 7-42 are taken in groups of │ │ three (expanded from two in 05/06/03 code revi- │ │ sion), making a total of 12 such groups. Each │ │ group describes a slur entering or leaving this │ │ note. The first element in the group contains │ │ general information + the x-offset; the second │ │ element in the group contains the y-offset. The │ │ third element in the group contains the integer │ │ equivalent of the 4-byte print suggestion for │ │ the slur. See TS32 for more information. │ │ │ │ ts(33) = node shift flag (positive and negative values) │ │ │ │ ts(34) = track number: 0 if not present │ │ ts(35) = base-40 pitch │ │ ts(36) = displacement of note head from the definitive │ │ node position (related to GLOBAL_XOFF) │ │ Value = -100 if the displacement is (approx.) │ │ one notehead to the left <-- │ │ Value = 100 if the displacement is (approx.) │ │ one notehead to the right --> │ │ Otherwise Value = a * INT10000 + b where │ │ a = width of notehead in dots │ │ b = displacement (right or left) meas. in dots │ │ │ │ ts(37) = SCORE P5 accidental information │ │ bits 0-7: the two digit (fractional) part of P5 │ │ bits 8-15: the one digit integer part of P5 │ │ bits 16-31: if non-zero, the number of dots │ │ to the left of the definitive node │ │ position where a CODE-9 natural │ │ must be placed. │ │ │ │ ts(38) = SCORE P9 augmentation dot information │ │ if bits 24-31 (0xff000000) are off, │ │ bits 0-7: the two digit (fractional) part of P9│ │ bits 8-15: the dot part of P9 (in 10's & 100's) │ │ otherwise, │ │ bits 24-31 (0xff000000) contain # of dots │ │ bits 0-23 contain relative dot position(in dots)│ │ x position * INT10000 + y position │ │ (must use CODE-9 to set this) │ │ │ │ ts(39) = tsr pointer │ │ │ │ │ │ Case II: Figures │ │ │ │ ts(1) = 9 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = number of figures in this chord │ │ ts(4) = space parameter │ │ ts(5) = first figure -- position one │ │ ts(6) = first figure -- position two │ │ ts(7) = first start/stop flag for continuation line │ │ ts(8) = second figure -- position one │ │ ts(9) = second figure -- position two │ │ ts(10) = second start/stop flag for continuation line │ │ ts(11) = third figure -- position one │ │ ts(12) = third figure -- position two │ │ ts(13) = third start/stop flag for continuation line │ │ ts(14) = fourth figure -- position one │ │ ts(15) = fourth figure -- position two │ │ ts(16) = fourth start/stop flag for continuation line │ │ │ │ figure field: 0 = blank │ │ 1-19 = figure │ │ 20 = + │ │ 21 = x │ │ 22 = 2+ │ │ 23 = sharp │ │ 24 = 4+ │ │ 25 = 5+ │ │ 26 = 6\ │ │ 27 = 7\ │ │ 28 = natural │ │ 29 = flat │ │ 30 = short continuation line (-) │ │ │ │ Adding 1000 to figure field (position one) indicates │ │ small parantheses around the field. │ │ Adding 2000 to figure field (position one) indicates │ │ large parantheses this figure and the one below it. │ │ Adding 3000 to figure field (position one) indicates │ │ large parantheses this figure and the two below it. │ │ (Added 11/16/03) │ │ │ │ start/stop continuation flag: 0 = none │ │ 1 = stop │ │ 2 = start │ │ 3 = continue │ │ │ │ ts(20) = minimum space for figure group │ │ ts(21) = pass number │ │ ts(23) = figure duration in divisions (0 if not given) │ │ ts(24) = increment distance flag (see notes) │ │ ts(28) = staff number │ │ │ │ Case III: Bar Lines │ │ │ │ ts(1) = 10 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = bar number (0 = none) │ │ ts(4) = bar type │ │ │ │ 1 = regular 5 = double regular │ │ 2 = heavy 6 = regular-heavy │ │ 3 = dotted 9 = heavy-regular │ │ 10 = heavy-heavy │ │ │ │ ts(5) = repeat flag │ │ │ │ 0 = no repeats 1 = forward repeat │ │ 2 = back repeat 3 = both repeats │ │ │ │ ts(6) = backward ending flag │ │ │ │ 0 = no ending │ │ # = ending number: positive = stop ending │ │ negative = discontinue │ │ ending │ │ │ │ ts(7) = forward ending flag │ │ │ │ 0 = no ending │ │ # = ending number │ │ │ │ ts(8) = flags │ │ │ │ bit set clear │ │ ----- ------------ ------- │ │ 0 continue ~~~ stop ~~~ │ │ 1 segno sign 0 │ │ 2 fermata over bar 0 │ │ 3 fermata under bar 0 │ │ │ │ ts(9) = space parameter (important for non-contr. bars) │ │ ts(10) = number over previous measure: 0 = none │ │ │ │ ts(20) = index to ASCII tsdata taken out, │ │ then put back 03/21/03 │ │ The reason for putting this back is that │ │ we need an ASCII string to communicate │ │ the NTRACK data that goes with the barline │ │ object. │ │ │ │ ts(21) = pass number │ │ ts(28) = number of staves │ │ │ │ Case IV: Signs, Words, Marks │ │ │ │ ts(1) = type sign = 11, words = 12, mark = 13 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = vertical position flag: 1 = below line │ │ 2 = above line │ │ ts(4) = sign number │ │ │ │ 0 = no sign │ │ 1 = segno │ │ 2 = ped │ │ 3 = * │ │ 4 = other letter dynamics │ │ 5 = D.S or D.C. (right justified string) │ │ 6 = fine (centered string) │ │ 7 = words (left justified string) │ │ 8 = tie terminator (added 10-12-96) │ │ 9 = rehearsal mark (left justified + box) │ │ (added 02-03-08) │ │ │ │ ts(5) = super flag │ │ │ │ 0 = no super-object │ │ 1 = start wedge │ │ 2 = stop wedge │ │ 3 = start dashes (after words) │ │ 4 = stop dashes │ │ 5 = start 8ve up │ │ 6 = stop 8ve up │ │ 7 = start 8ve down │ │ 8 = stop 8ve down │ │ 9 = start 15 up │ │ 10 = stop 15 up │ │ 11 = start 15 down │ │ 12 = stop 15 down │ │ 13 = normal transposition (temporary flag) │ │ │ │ ts(6) = parameter for words: optional font designation │ │ │ │ ts(7) = wedge offset (for cases where a wedge begins after │ │ or stops at a letter dynamic) │ │ │ │ ts(8) = track number (useful for multiple wedges, dashes │ │ or transpositions of the same type) │ │ │ │ ts(9) = spacing (for case of isolated mark) │ │ │ │ ts(10) = parameter for wedges: wedge spread │ │ │ │ ts(11) = parameter for musical directions which are │ │ objects: position shift │ │ │ │ ts(12) = special flag for case where this element is │ │ isolated on a division (possibly with other │ │ members of this same group). │ │ │ │ ts(13) = parameter for musical directions which are │ │ super-objects: position shift │ │ │ │ ts(20) = index to ASCII tsdata │ │ │ │ ts(21) = pass number │ │ │ │ ts(22) = backtie flag (for tie terminators) (added 10-12-96) │ │ │ │ ts(28) = staff number │ │ │ │ Case V: Clef change in middle of a measure │ │ │ │ ts(1) = type = 14 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = clef number │ │ ts(4) = clef font number │ │ ts(5) = transpostion flag: │ │ │ │ 1 = notes written octave higher than sound │ │ 0 = notes written at sound │ │ -1 = notes written octave lower than sound │ │ │ │ ts(6) = position on staff │ │ ts(9) = space parameter │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ ts(28) = staff number │ │ │ │ Case VI: Time designation in middle of a measure │ │ │ │ ts(1) = type = 15 │ │ ts(2) = division number (starting with 1) │ │ ts(9) = space parameter │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ ts(28) = staff number │ │ │ │ Case VII: Meter change in middle of a measure │ │ │ │ ts(1) = type = 16 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = time number (100 time numerator + denominator) │ │ ts(9) = space parameter │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ ts(28) = number of currently active staves │ │ │ │ Case VIII: Change in number of divisions per quarter │ │ │ │ ts(1) = type = 17 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = divisions per quarter │ │ ts(9) = space parameter │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ │ │ Case IX: Change in key signature │ │ │ │ ts(1) = type = 18 │ │ ts(2) = division number (starting with 1) │ │ ts(3) = new key signature │ │ ts(4) = old key signature │ │ ts(9) = space parameter │ │ ts(20) = index to ASCII tsdata │ │ ts(21) = pass number │ │ ts(28) = number of currently active staves │ │ │ └────────────────────────────────────────────────────────────────────┘ procedure action int t1,t2,t3,t4,t5,t6 int t7,t8 /* (added 10-12-96) if @n = 0 return end passnum = 1 If there are no pending slurs, then clear the ts array and set sct = 0 if sct = 0 loop for a9 = 1 to MAX_OBJECTS loop for a10 = 1 to TS_SIZE ts(a9,a10) = 0 repeat tsdata(a9) = "" tsr(a9) = zpd(TSR_LENG) /* 05/02/03: was zpd(72) ts(a9,TSR_POINT) = a9 repeat outslurs = "00000000" else if outslurs = "00000000" if sct > maxsct maxsct = sct end loop for a9 = 1 to maxsct + 10 loop for a10 = 1 to TS_SIZE ts(a9,a10) = 0 repeat tsdata(a9) = "" tsr(a9) = zpd(TSR_LENG) /* 05/02/03: was zpd(72) ts(a9,TSR_POINT) = a9 repeat sct = 0 old@n = 0 else if sct > maxsct maxsct = sct end loop for a9 = sct+1 to maxsct+10 loop for a10 = 1 to TS_SIZE ts(a9,a10) = 0 repeat tsdata(a9) = "" tsr(a9) = zpd(TSR_LENG) /* 05/02/03: was zpd(72) ts(a9,TSR_POINT) = a9 repeat end end oldsct = sct If you are starting a new version of the ts(.) array then copy claveax(.) to tclaveax(.) 12/14/07 if sct = 0 loop for a9 = 1 to 50 tclaveax(a9) = claveax(a9) repeat end Store original data in set array divpoint = 1 cuediv = 0 totdiv = 1 qflag = 0 divspq = olddivspq loop for a9 = 1 to @n tsdata(a9+old@n) = "" line = tdata(a9,1) tvar1 = tv1(a9) tvar2 = tv2(a9) if tv3(a9) > 0xff if tvar1 <= NOTE_OR_REST if tvar1 = REST or tvar1 = CUE_REST restplace2 = tv3(a9) >> 8 else repeater_flag2 = tv3(a9) >> 10 + 1 repeater_flag2 = tv3(a9) >> 8 /* changed 01/01/08 end else mdir_offset = tv3(a9) >> 8 end tv3(a9) &= 0xff else repeater_flag2 = 0 restplace2 = 0 mdir_offset = 0 end Deal with situation where there is an irest followed by a print suggestion that it should be allocated space if tvar1 = IREST if a9 < @n and tv1(a9+1) = P_SUGGESTION if tv2(a9+1) & 0xff00 = 0x0300 pcontrol = ors(tcode(a9+1){1}) if pcontrol = 3 or pcontrol = 5 tvar1 = REST /* send it through the system tcode(a9) = "rest" /* as a "regular" rest end end else if scr_flag = 1 tvar1 = REST /* send it through the system tcode(a9) = "ires" /* as a "silent" rest (but be careful) end end end Case I: notes, rests, cue notes, grace notes, extra notes in chords, figures if tvar1 <> FIGURES and tvar1 <> P_SUGGESTION figdiv = 0 end if tvar1 <= NOTE_OR_REST loop for a3 = 1 to 7 step 3 a4 = a3 + 1 if tvar1 = a4 /* extra chord tone if a9 = 1 return 1 end c5 = 1 loop while tv1(a9-c5) = P_SUGGESTION and a9 > c5 + 1 ++c5 repeat if tv1(a9-c5) <> a3 if tv1(a9-c5) <> a4 return 1 end else * tricky code to set chord bit on first note in chord ts(sct,STEM_FLAGS) += 4 /* sct -> previous array entry end end repeat ++sct /* incrementing array pointer sct ts(sct,TYPE) = tvar1 Set DIV (for cue notes) if chr(tvar1) in [CUE_NOTE,XCUE_NOTE,CUE_REST] if tvar1 <> XCUE_NOTE ts(sct,DIV) = divpoint + cuediv else ts(sct,DIV) = divpoint + cuediv - chorddur end goto WC end Set DIV (for regular and grace notes) if tvar1 = XNOTE ts(sct,DIV) = divpoint - chorddur else ts(sct,DIV) = divpoint end cuediv = 0 In special case of arpeggios 01/13/06, get vertical veriables if tvar1 = GR_NOTE and tvar2 = ARPEGGIO if line{1} = " " ts(sct,ARPEG_TOP) = int(line{2}) else ts(sct,ARPEG_TOP) = int(line{1,2}) end if line{3} = "x" ts(sct,ARPEG_FLAG) = granddist else ts(sct,ARPEG_FLAG) = 0 end if line{4} = " " ts(sct,ARPEG_BOTTOM) = int(line{5}) else ts(sct,ARPEG_BOTTOM) = int(line{4,2}) end line{1,7} = "e " end Normally at this point, we would decode the note and get its clave number and accidental. The reason we cannot safely do this at this time is that the backspace command might cause us to insert some accidentals at earlier points in the measure. Because of the current order, these notes would not be accidentalized, whereas a later one (from an earlier pass) would be. Also, we would like to allow the various passes to run through non-controlling bar lines. In any event, we must put off decoding and other calculations that depend on this data until the entries can be ordered by time. In the meantime, we will store the a pointer to the proper tcode element in ts(4) WC: ts(sct,TEMP4) = a9 a4 = tvar2 /* duration field, in this case if tvar1 > REST a5 = tvar2 /* this will become NTYPE if chr(tvar1) in [CUE_NOTE,CUE_REST] We must, in this case, try to assign a length to the cue-type entity in terms of the current value of divspq. The parameter, a4, indicates the note type: 1 = 256th note 7 = quarter note 2 = 128th note 8 = half note 3 = 64th note 9 = whole note 4 = 32nd note 10 = breve 5 = 16th note 11 = longa 6 = 8th note Columns 4-6 of the variable line contain tuple modifications to the note value --a4 a3 = 1 << a4 a3 = 64 --> means quarter note, etc. a3 *= divspq a3 --> length of notetype as measured in units (64*divspq) if line{4} <> " " a4 = int(line{4}) if line{4} in ['A'..'Z'] a4 = ors(line{4}) - 55 /* A = 10, etc end a8 = a4 / 3 /* default values for "denominator" if rem = 0 a8 *= 2 else a8 = a4 - 1 end if line{6} <> " " a8 = int(line{6}) if line{6} in ['A'..'Z'] a8 = ors(line{6}) - 55 /* A = 10, etc end end a3 *= a8 a3 /= a4 if rem <> 0 putc Unable to represent cue note in terms of current putc value of divisions per quarter putc Push <F9> to terminate examine stop end end a3 --> length of note measured in units (64*divspq) as modified by tuple information if ".:;!" con line{2} /* code modified 12-24-96 if mpt = 1 a3 = a3 / 2 * 3 else if mpt = 2 a3 = a3 / 4 * 7 else if mpt = 3 a3 = a3 / 8 * 15 else a3 = a3 / 16 * 31 end end end end a3 --> length of note measured in units (64*divspq) as further modified by dot information chorddur = a3 / 64 if rem <> 0 putc Unable to represent cue note in terms of current putc value of divisions per quarter putc Push <F9> to terminate examine stop end chorddur --> length of measured in units (divspq) cuediv += chorddur end else if tvar1 <> XNOTE chorddur = a4 divpoint += a4 if divpoint > totdiv totdiv = divpoint end end if "zyxtseqhwbL" con line{1} a5 = mpt /* this will become NTYPE else if "123456789AB" con line{1} a5 = mpt /* this will become NTYPE ts(sct,SUBFLAG_1) |= 0x010000 /* set small print flag else if tvar1 = REST New 10/15/07 if len(line) > 0 if "ZYXTSEQHW" con line{1} a5 = mpt /* this will become NTYPE with flag a5 += 0x100 else Old code Code modified 01/03/04 to deal with optional whole rests if len(line) > 0 and line{1} = "W" if line{1} = "o" /* o = float New 10/15/07 ts(sct,CLAVE) = 2 /* temporary floating rest with optionality else ts(sct,CLAVE) = 1 /* temporary floating rest flag end ts(sct,CLAVE) = 1 /* temporary floating rest flag a5 = WHOLE /* this will become NTYPE end end else Note type is missing, try to construct it. (the presence of tuplets will throw this off) putc Missing note type (column 17). Type Enter to continue. getc putc Attempting to construct note type. a8 = chorddur << 5 / divspq a5 = 1 loop while a8 > 0 a8 >>= 1 ++a5 repeat end end end end Set NTYPE ts(sct,NTYPE) = a5 Set STAFFLOC (for rests) if tvar1 = REST or tvar1 = CUE_REST ts(sct,STAFFLOC) = restplace2 end Set NOTE_DUR if chr(tvar1) in [GR_NOTE,XGR_NOTE] ts(sct,NOTE_DUR) = 0 else ts(sct,NOTE_DUR) = chorddur end a8 = int(line{4}) if line{4} in ['A'..'Z'] a8 = ors(line{4}) - 55 end if a8 > 0 Code added to account for complex tuples: 5-11-93 a3 = int(line{6}) if line{6} in ['A'..'Z'] a3 = ors(line{6}) - 55 /* A = 10, etc end a3 *= 1000 a3 *= 256 /* New 11/05/05 Set TUPLE ts(sct,TUPLE) = a8 + a3 end Set DOT if ".^:^^^;^^^^^^^!" con line{2} /* code modified 12-24-96 ts(sct,DOT) = mpt /* 1 = single dot; 3 = double dot; 7 = triple dot; 15 = end New code 11/15/07: a cludge fix to an obscure spacing problem if scr_flag = 1 and tcode(a9) = "ires" ts(sct,DOT) = 0 end if tcode(a9) <> "rest" and tcode(a9) <> "ires" ╒═════════════════════════════════════════════════════════════════╕ │ This calculation must be delayed until after the decoding │ │ --------------------------------------------------------- │ │ a1 = 52 - ts(sct,3) - cline(.) + c8flag(.) │ │ ts(sct,8) = a1 * notesize / 2 │ ╘═════════════════════════════════════════════════════════════════╛ Compute Base-40 value of pitch if xdata_flag = 1 a1 = 0 if "..C.....D.....E....F.....G.....A.....B" con tcode(a9){1} a1 = mpt if "f.#" con tcode(a9){2} a1 += (mpt - 2) end if "f.#" con tcode(a9){3} a1 += (mpt - 2) end if tcode(a9) con ['0'..'9'] a2 = int(tcode(a9){mpt}) a1 += (a2 * 40) end end ts(sct,BASE_40) = a1 end Set STEM_FLAGS (incomplete) a1 = 0 if "u@d" con line{7} /* stem direction "u" or "d" a1 = mpt end New code 12/20/05 implementing general suggestion for setting stem directions if stem_change_flag = 0 or stem_change_flag = 3 if "u@d" con line{7} /* stem direction "u" or "d" a1 = mpt end else if stem_change_flag = 1 a1 = 0 else a1 = 2 end end if tvar1 = XNOTE a1 += 12 end ts(sct,STEM_FLAGS) = a1 Set BEAM_FLAG if "][=" con line{10} ts(sct,BEAM_FLAG) = mpt else ts(sct,BEAM_FLAG) = NO_BEAM end Set BEAM_CODE a4 = 0 if ts(sct,BEAM_FLAG) > NO_BEAM if "[]=" con line{10} a3 = 1 loop for a1 = 10 to 15 if " =[]/\" con line{a1} a4 = mpt - 1 * a3 + a4 end if mpt = 1 a1 = 15 else a3 *= 10 end repeat end end ts(sct,BEAM_CODE) = a4 I think this is the place to alter the ts array, in the case where a repeater is requested if repeater_flag2 > 0 and ts(sct,BEAM_FLAG) = END_BEAM New code 01/01/08. Set the repeater_dot_flag. repeater_dot_flag = 0 a3 = repeater_flag2 & 0x03 if a3 = 3 repeater_dot_flag = 1 end End of 01/01/08 code Decision Point No. 1: Decide if repeaters are possible a3 = 1 REP2: if a4 / a3 > 9 a3 *= 10 goto REP2 end c6 = bit(1,ts(sct,STEM_FLAGS)) c7 = ts(sct,NTYPE) For purposes of the code that follows, we need to keep track of the subscripts which point to real data (i.e. not print suggestions) in the data(.), tcode(.), and tv(.) arrays. We will store these "valid" subscripts in the mf(.) array. c10 = a9 c2 = 0 /* counter for primary type c4 = 100 /* secondary beam break flag c14 = 100 /* secondary beam break flag for threesomes (09/21/08) repeater_dot_flag2 = 0 /* added 09/21/08 loop for a1 = sct to 1 step -1 /* Two exits from this loop: /* To REP1 when ts(a1,BEAM_FLAG) = START_BEAM (below) /* to NO_REP whenever a test "fails" loop while tv1(c10) = P_SUGGESTION --c10 repeat mf(a1) = c10 --c10 if ts(a1,TYPE) < tvar1 or ts(a1,TYPE) > tvar1 + 1 goto NO_REP end if ts(a1,TYPE) = tvar1 if ts(a1,TUPLE) <> 0 c4 = 100000 + (ts(a1,TUPLE) & 0xffff) end a5 = ts(a1,BEAM_CODE) / a3 if a5 > 3 or a5 = 0 goto NO_REP end if a1 < sct and a5 = 3 and c4 < 100000 /* secondary beam ends and starts again if c4 = 100 c4 = 16 end if c14 = 100 /* New 09/21/08 c14 = 6 end 09/21/08 Working on repeaters: In the case of secondary beam endings, the following (existing) code allows endings only in multiples of 2. Since multiple passes are made through this code, c4 becomes the smallest group size. Specifically, this prevents group sizes of 3 and 6, which common enough to consider. loop while c4 > 1 c5 = c2 / c4 if rem <> 0 c4 >>= 1 end repeat while rem <> 0 09/21/08 I think the solution is to run twosome and threesome tests in parallel. A jump to NO_REP occurs when both tests fail. I will use c14 for this test. (New code) loop while c14 > 1 c5 = c2 / c14 if rem <> 0 c14 >>= 1 end repeat while rem <> 0 if c4 = 1 and c14 = 1 /* c14 test added 09/21/08 goto NO_REP end end ++c2 mf2(c2) = a1 end if bit(1,ts(a1,STEM_FLAGS)) <> c6 or ts(a1,NTYPE) <> c7 or ts(a1,DOT) > 0 goto NO_REP end codes = tdata(mf(a1),1){16,12} if ts(a1,BEAM_FLAG) = START_BEAM if codes con ['-','(',')','[',']','{','}','~','>','.','_','=',','] if codes con ['-',')',']','}','~','>','.','_','=',','] /* 02/19/97 change accomodates slurs starting on beginning of beam if codes con [')',']','}','~',','] /* 01/06/06 change accomodates articulations on beginning of beam if codes con ['~',','] /* 01/13/06 change accomodates slurs ending on beginning of beam goto NO_REP end if codes con ['b','c','h'..'k','n','o','r'..'z','A','E','F','M','Q','S','V'] if codes con ['b','c','h'..'k','n','o','r'..'z','A','M','Q','S','V'] goto NO_REP end goto REP1 end if ts(a1,BEAM_FLAG) = END_BEAM if codes con ['-','(',')','[',']','{','}','~','>','.','_','=',','] if codes con ['-','(','[','{','~','>','.','_','=',','] /* 02/19/97 change accomodates slurs ending on end of beam goto NO_REP end else if codes con ['-','(',')','[',']','{','}','~','>','.','_','=','0'..'5',',',':'] goto NO_REP end end if codes con ['b','c','f','h'..'z','A','E','F','M','Q'..'S','V','Z'] goto NO_REP end repeat Case 1: Check to see if all chords under the beam are the same REP1: chordsize = 1 chord_tones(1) = tcode(mf(a1)) loop for a2 = a1 + 1 to sct if ts(a2,TYPE) = tvar1 a2 = sct else ++chordsize chord_tones(chordsize) = tcode(mf(a2)) end repeat In case of chord at end of beam, finish building mf(.) array c10 = a9 + 1 last_chordsize = 1 loop for a2 = sct + 1 to 100000 loop while tv1(c10) = P_SUGGESTION ++c10 repeat if tv1(c10) = tvar1 + 1 mf(a2) = c10 if "zyxtseqhwbL" con tdata(c10,1){1} if mpt <> c7 /* NTYPE of last chord tones goto NO_REP end else if "123456789AB" con tdata(c10,1){1} if mpt <> c7 /* NTYPE of last chord tones goto NO_REP end end end ++c10 ++last_chordsize else a2 = 100000 end repeat if c4 < 100 /* secondary beams have breaks 09/21/08 We need to put the correct value in c4 at this point if c4 = 1 c4 = c14 dputc Secondary size = ~c4 end goto REP3 end loop for a2 = a1 + chordsize to sct if ts(a2,TYPE) <> tvar1 goto REP3 end c5 = 0 loop for c6 = 1 to chordsize checkoff(c6) = 1 repeat REP4: c14 = 0 loop for c3 = 1 to chordsize if checkoff(c3) = 1 and chord_tones(c3) = tcode(mf(a2)) checkoff(c3) = 0 c14 = 1 c3 = chordsize end repeat if c14 = 0 goto REP3 end ++c5 if c5 < chordsize ++a2 if a2 <= sct if ts(a2,TYPE) <> tvar1 + 1 goto REP3 end else if "zyxtseqhwbL" con tdata(mf(a2),1){1} This was done if mpt <> c7 /* NTYPE of last chord tones earlier goto NO_REP end end if tv1(mf(a2)) <> tvar1 + 1 goto REP3 end end goto REP4 else if a2 > sct + chordsize - 1 goto NO_REP end end repeat At this point, we have determined that all chords under the beam are the same. We must compact all of these notes into one note (simplest case). c3 = sct - a1 / chordsize + 1 /* number of notes c5 = ts(a1,NTYPE) c6 = 0 c14 = ts(a1,TUPLE) c14 = ts(a1,TUPLE) & 0xffff /* added 11/05/05 if c14 > 255 /* no complex tuples allowed goto NO_REP end if c14 > 0 if c14 = c3 c7 = 2 loop c5 += 1 c8 = c3 / c7 if c8 > 1 c7 <<= 1 end repeat while c8 > 1 goto REP5 else goto NO_REP /* if tuple, then # must = group size end else if chr(c3) not_in [2,3,4,6,7,8,12,14,15,16,24,28,30,31,32] /* modified 12-24-96 goto NO_REP /* must be representable with note value + dot(s) end c7 = 2 loop c5 += 1 c8 = c3 / c7 if c8 = 1 mpt = rem if mpt > 0 /* code modified 12-24-96 if mpt = c7 >> 1 c6 = 1 else if mpt = c7 / 4 * 3 c6 = 3 else if mpt = c7 / 8 * 7 c6 = 7 else c6 = 15 end end end end else c7 <<= 1 end repeat while c8 > 1 end REP5: if chordsize > 1 a9 += chordsize - 1 /* advance a9 over rest of last chord end c7 = 6 loop for a2 = 1 to QUARTER - ts(a1,NTYPE) - 1 c7 *= 10 c7 += 6 repeat ts(a1,BEAM_CODE) = c7 /* 666... etc New code 01/01/08. Deal with special case of the repeater dot. if repeater_dot_flag = 1 and c6 = 0 c6 = 1 end loop for a2 = a1 to a1 + chordsize - 1 ts(a2,NTYPE) = c5 ts(a2,DOT) = c6 ts(a2,NOTE_DUR) *= c3 ts(a2,BEAM_FLAG) = NO_BEAM if a2 > a1 ts(a2,BEAM_CODE) = 0 end repeat 11/20/06 Adding code here that allows a slur over repeated notes with a repeater, provided that the slur covers all notes in the group and that chordsize = 1. Also, clear the rest of the ts array and reset sct a3 = 0 if (ts(a1,SLUR_FLAG) & 0xff) <> 0 and chordsize = 1 a2 = ts(a1,SLUR_FLAG) & 0xff codes = line{16,12} if codes con ")" and a2 = 1 a3 = 2 end if codes con "]" and a2 = 3 a3 = 8 end if codes con "}" and a2 = 5 a3 = 32 end if codes con "x" and a2 = 7 a3 = 128 end end We have already eliminated those cases where slurs start or end within a repeater group. (about 200 lines above) if a3 > 0 c5 = ts(sct,DIV) c6 = ts(sct,AX) c7 = ts(sct,NOTE_DUR) ts(a1,NOTE_DUR) -= c7 loop for a2 = a1 + chordsize to sct loop for c8 = 1 to TS_SIZE if c8 <> TSR_POINT ts(a2,c8) = 0 end repeat repeat ++a1 ts(a1,TYPE) = NOTE ts(a1,DIV) = c5 ts(a1,AX) = c6 ts(a1,NOTE_DUR) = c7 ts(a1,TEXT_INDEX) = c6 ts(a1,PASSNUM) = passnum ts(a1,SLUR_FLAG) = a3 End of 11/20/06 addition else loop for a2 = a1 + chordsize to sct loop for a3 = 1 to TS_SIZE if a3 <> TSR_POINT ts(a2,a3) = 0 end repeat repeat end 01/04/06: There is a problem when a tuple has been started on a repeater. First, tuflag has be set to 1, and has not been reset. Second, the SUPER_FLAG has been set to show a tuple starting, but never ending. I can fix these problems here, but this may be symtomatic of problems with other super-objects, such as slurs. I am not going to check this out at this point, but be aware! loop for a2 = a1 to a1 + chordsize - 1 if ts(a2,SUPER_FLAG) <> 0 if (ts(a2,SUPER_FLAG)) & 0x10 <> 0 tuflag = 0 ts(a2,SUPER_FLAG) &= 0xffef /* turn off start tuple else putc Warning, SUPER_FLAG is non-zero at a repeater putc at approximately measure number ~measnum end else ts(a2,TUPLE) = 0 end repeat sct = a1 + chordsize - 1 goto EBL REP3: Case 2: Check to see if chords under the beam can be arranged in groups of 2, 4, 8, or 16 c2 = number of chords mf2(.) = ts subscripts for primary notes of each chord c4 = either: maximum group size or: 100 (no group size limitation) or: >= 1000 (tuples are present; no groups allowed) if c4 >= 100000 goto REP15 /* 02/19/97 change accomodates tuples end if c4 = 100 c4 = 32 loop while c4 > c2 / 2 c4 >>= 1 repeat end loop while c4 > 1 c3 = c2 / c4 if rem <> 0 c4 >>= 1 end repeat while rem <> 0 c5 = ts(a1,NTYPE) c6 = 1 loop while c5 < EIGHTH c6 <<= 1 ++c5 repeat repeater_dot_flag2 = 0 /* New 09/21/08 if c4 > c6 c11 = c4 / 3 if rem = 0 repeater_dot_flag2 = 1 /* New 09/21/08 else c4 = c6 /* Default from old version end end dputc c4 = ~c4 if c4 = 1 goto REP15 end c4 is now the largest possible group notes under beam Next we investigate the question of whether c4 is a "legal" group size. REP11: Look for first (actually last) chord prototype c1 = 1 /* index into mf2 c3 = mf2(c1) /* c3 should start as sct chordsize = 1 chord_tones(1) = tcode(mf(c3)) ++c3 loop while chordsize < last_chordsize /* ++chordsize chord_tones(chordsize) = tcode(mf(c3)) /* accumulate chord tones ++c3 repeat Look for additional chords to match prototype REP9: c6 = 1 /* chord counter REP8: ++c1 c3 = mf2(c1) /* ts index to next primary note backward in list c5 = 0 loop for c11 = 1 to chordsize checkoff(c11) = 1 repeat REP6: c11 = 0 loop for c12 = 1 to chordsize if checkoff(c12) = 1 and chord_tones(c12) = tcode(mf(c3)) checkoff(c12) = 0 c11 = 1 c12 = chordsize end repeat if c11 = 0 goto REP7 /* this pitch (tcode) was not found in chord end ++c5 ++c3 if c5 < chordsize if c3 = mf2(c1-1) goto REP7 /* this chord is not big enough end goto REP6 else if c3 <> mf2(c1-1) goto REP7 /* this chord is too big end end ++c6 /* "valid" chord found if c6 < c4 goto REP8 end Set up to look for new chord prototype if c1 < c2 ++c1 /* index into mf2 c3 = mf2(c1) /* c3 should start as sct chordsize = 1 chord_tones(1) = tcode(mf(c3)) ++c3 loop while c3 < mf2(c1-1) ++chordsize chord_tones(chordsize) = tcode(mf(c3)) /* accumulate chord tones ++c3 repeat goto REP9 end goto REP10 /* successful pattern match REP7: c4 >>= 1 if c4 > 1 goto REP11 else goto REP15 end Repeaters on groups of chords will work, if group size = c4 REP10: c5 = ts(a1,NTYPE) c7 = c4 c15 = 0 loop ++c15 ++c5 c7 >>= 1 repeat while c7 > 1 c1 = c2 c6 = mf2(c2) /* position for revised data REP13: /* loop between groups c3 = mf2(c1) REP12: /* loop within chord ts(c3,NTYPE) = c5 ts(c3,NOTE_DUR) *= c4 ts(c3,DOT) = repeater_dot_flag2 /* New 09/21/08 if c3 <> mf2(c1) c13 = NO_BEAM ts(c3,BEAM_CODE) = 0 else temp3 = chs(ts(c3,BEAM_CODE)) c14 = len(temp3) if c1 = c2 /* beginning of first group c13 = START_BEAM temp3 = "222222"{1,c14} else if c1 = c4 /* beginning of last group c13 = END_BEAM temp3 = "333333"{1,c14} else c13 = CONT_BEAM temp3 = "111111"{1,c14} end end temp3{1,c15} = "666666"{1,c15} ts(c3,BEAM_CODE) = int(temp3) end ts(c3,BEAM_FLAG) = c13 ++c3 /* next pitch in chord if c3 < mf2(c1-1) putc Chord goto REP12 end chordsize = c3 - mf2(c1) Move data to revised position if c1 <> c2 c7 = mf2(c1) /* source location; c6 = destination loop for c8 = 1 to chordsize loop for c9 = 1 to TS_SIZE if c9 <> TSR_POINT ts(c6,c9) = ts(c7,c9) end repeat ++c6 ++c7 repeat else c6 += chordsize end if c1 > c4 c1 -= c4 goto REP13 end if last_chordsize > 1 a9 += last_chordsize - 1 /* advance a9 over rest of last chord end Clear the rest of the ts array and reset sct loop for c8 = c6 to sct loop for c9 = 1 to TS_SIZE if c9 <> TSR_POINT ts(c8,c9) = 0 end repeat repeat sct = c6 - 1 goto EBL REP15: Alternating case is the only possibility left Case 3: Check to see if chords under the beam alternate in groups of 4, 8, 16, or 32, or a tuple size which is even c2 = number of chords mf2(.) = ts subscripts for primary notes of each chord Also allow alternating groups of size 6, 12, and 24 (01/15/06) if chr(c2) not_in [4,8,16,32] if chr(c2) not_in [4,6,8,12,16,24,32] if c4 > 100000 /* 02/19/97 change accomodates tuples c4 -= 100000 if c4 & 0x01 = 0 if c4 = c2 and c4 >= 6 goto REP15A end end end goto REP16 end Look for first (actually last) chord prototype REP15A: c1 = 1 /* index into mf2 c3 = mf2(c1) /* c3 should start as sct chordsize = 1 chord_tones(1) = tcode(mf(c3)) ++c3 loop while chordsize < last_chordsize /* ++chordsize chord_tones(chordsize) = tcode(mf(c3)) /* accumulate chord tones ++c3 repeat Check all "odd" chords for a match loop for c1 = 3 to c2 - 1 step 2 c3 = mf2(c1) /* ts index to next "odd" primary note backward in list c5 = 0 loop for c11 = 1 to chordsize checkoff(c11) = 1 repeat REP17: c11 = 0 loop for c12 = 1 to chordsize if checkoff(c12) = 1 and chord_tones(c12) = tcode(mf(c3)) checkoff(c12) = 0 c11 = 1 c12 = chordsize end repeat if c11 = 0 goto NO_REP /* this pitch (tcode) was not found in chord end ++c5 ++c3 if c5 < chordsize if c3 = mf2(c1-1) goto NO_REP /* this chord is not big enough end goto REP17 else if c3 <> mf2(c1-1) goto NO_REP /* this chord is too big end end repeat Look for second (actually penultimate) chord prototype c1 = 2 /* index into mf2 c3 = mf2(c1) chordsize2 = 1 chord_tones(1) = tcode(mf(c3)) ++c3 loop while c3 <> mf2(c1-1) ++chordsize2 chord_tones(chordsize2) = tcode(mf(c3)) /* accumulate chord tones ++c3 repeat Check all "even" chords for a match loop for c1 = 4 to c2 step 2 c3 = mf2(c1) /* ts index to next "even" primary note backward in list c5 = 0 loop for c11 = 1 to chordsize2 checkoff(c11) = 1 repeat REP18: c11 = 0 loop for c12 = 1 to chordsize2 if checkoff(c12) = 1 and chord_tones(c12) = tcode(mf(c3)) checkoff(c12) = 0 c11 = 1 c12 = chordsize2 end repeat if c11 = 0 goto NO_REP /* this pitch (tcode) was not found in chord end ++c5 ++c3 if c5 < chordsize2 if c3 = mf2(c1-1) goto NO_REP /* this chord is not big enough end goto REP18 else if c3 <> mf2(c1-1) goto NO_REP /* this chord is too big end end repeat At this point, we have determined that there are c2/2 matching pairs of chords, and that c2 = 4,6,8,12,16,24 or 32, or an even tuple of 6 or greater. In this situation we may reduce these c2 entries to two entries. The duration of each entry is c2/2 times the old duration. The old duration determines the number of beams; the new duration determines the number of through beams. We are going to have to change the the division number for the second member of the group. It is the same as the division number of the (c2/2+1)-th member of the group. 01/15/06 Code added to deal with alternating groups of size 6, 12, and 24 c4 = c2 / 2 c7 = c2 / 3 if rem = 0 ts(c3,DOT) = 1 c4 = c2 / 3 else c4 = c2 / 2 end c5 = ts(a1,NTYPE) c7 = c4 loop ++c5 /* new duration c7 >>= 1 repeat while c7 > 1 if c5 > 6 and c2 < 8 /* don't do a four group of eighths, etc. goto NO_REP end c15 = 7 - ts(a1,NTYPE) /* total number of beams c14 = 7 - c5 /* number through beams if c14 < 0 c14 = 0 end #if OLD_REPEATERS if c5 = 7 c5 = 8 c14 = c15 end #endif c15 -= c14 /* number of shortened beams Code added 01/15/06 to allow alternating group sizes of 6, 12, and 24 with repeaters. This code gets the DIV variable right c12 = mf2(c4) if ts(c3,DOT) = 1 c12 = c4 * 3 / 2 /* because we are counting backward in mf2(.) c12 = mf2(c12) else c12 = mf2(c4) end c12 = ts(c12,DIV) /* division number for second member c6 = mf2(c2) /* position for revised data c3 = mf2(c2) REP19: /* loop within first chord ts(c3,NTYPE) = c5 c13 = c2 / 3 /* 02/19/97 added for 6-tuples, 12-tuples if rem = 0 ts(c3,DOT) = 1 end ts(c3,NOTE_DUR) *= c4 if c3 <> mf2(c2) c13 = NO_BEAM ts(c3,BEAM_CODE) = 0 else temp3 = "777777"{1,c15} // "222222"{1,c14} ts(c3,BEAM_CODE) = int(temp3) c13 = START_BEAM end ts(c3,BEAM_FLAG) = c13 ++c3 /* next pitch in chord if c3 < mf2(c2-1) goto REP19 end chordsize = c3 - mf2(c2) c6 += chordsize REP20: /* loop within second chord ts(c3,DIV) = c12 ts(c3,NTYPE) = c5 c13 = c2 / 3 /* 02/19/97 added for 6-tuples, 12-tuples if rem = 0 ts(c3,DOT) = 1 end ts(c3,NOTE_DUR) *= c4 if c3 <> mf2(c2-1) c13 = NO_BEAM ts(c3,BEAM_CODE) = 0 else temp3 = "888888"{1,c15} // "333333"{1,c14} ts(c3,BEAM_CODE) = int(temp3) c13 = END_BEAM end ts(c3,BEAM_FLAG) = c13 ++c3 /* next pitch in chord if c3 < mf2(c2-2) goto REP20 end chordsize = c3 - mf2(c2-1) c6 += chordsize if last_chordsize > 1 a9 += last_chordsize - 1 /* advance a9 over rest of last chord end Clear the rest of the ts array and reset sct loop for c8 = c6 to sct loop for c9 = 1 to TS_SIZE if c9 <> TSR_POINT ts(c8,c9) = 0 end repeat repeat sct = c6 - 1 goto EBL process array for last member of group Note 02/19/97: The goto EBL has been commented out so that in the case where a tuple or a slur has been started, it will be completed. This feature has not been fully tested, and may cause other problems. Beware! REP16: end NO_REP: end Construct SUPER_FLAG a14 = 0 /* a14 will become ts(14) codes = line{16,12} look for starting tuplet if ts(sct,TUPLE) > 0 if tuflag = 0 and codes con "*" tuflag = 1 a1 = mpt a14 |= 0x10 /* begin tuplet if codes con "&" and mpt < a1 a14 |= 0x40000 /* editorial tuplet flag 03-21-97 end end end look for end of ~~~~~ if ctrflag > 0 /* ctrflag = continue trill flag if ctrflag(passnum) > 0 /* ctrflag changed to array 12/08/07 if codes con "c" else a14 |= 0x08 /* end ~~~~~ if ctrflag >= 0x100 if ctrflag(passnum) >= 0x100 a14 |= 0x20000 /* editorial ~~~ flag 03-21-97 end ctrflag = 0 ctrflag(passnum) = 0 end end look for start of ~~~~~ if codes con "~" if ctrflag = 0 if ctrflag(passnum) = 0 /* New 12/08/07 a7 = mpt if codes con "&" and mpt < a7 ctrflag = 0x0200 /* editorial start ~~~~~ ctrflag(passnum) = 0x0200 /* editorial start ~~~~~ a14 |= 0x20000 /* editorial ~~~ flag 03-21-97 else ctrflag = 0x02 /* start ~~~~~ ctrflag(passnum) = 0x02 /* start ~~~~~ end if codes con "t" ctrflag <<= 1 ctrflag(passnum) <<= 1 a14 |= 0x04 /* begin ~~~ with trill else a14 |= 0x02 /* begin ~~~ without trill end end end look for forward tie if codes con "-" a7 = mpt a14 |= 0x01 /* tie flag if codes con "&" and mpt < a7 a14 |= 0x10000 /* editorial tie (dotted) 03-21-97 end end look for end of tuplet if codes con "!" and tuflag = 1 a7 = mpt a14 |= 0x20 /* end tuplet if codes con "&" and mpt < a7 a14 |= 0x40000 /* editorial tuplet flag 03-21-97 end tuflag = 0 end Set SUPER_FLAG #if SUB_EDIT #else a14 &= 0xffff /* turn off editorial flags 03-21-97 #endif ts(sct,SUPER_FLAG) = a14 a14 = 0 loop for a1 = 1 to 12 if codes{a1} = "&" /* and codes{a1+1} in ['0'..'9'] #if SUB_EDIT a14 = 1 #endif if codes{a1+1} in ['0'..'9','X'] /* New 05/17/03 ++a1 end goto TLP1 /* skip end if "()[]{}zx" con codes{a1} --mpt a7 = 1 << mpt if a14 = 1 a7 <<= 16 end ts(sct,SLUR_FLAG) |= a7 goto TLP1 end look for turns, mordents, and their accidentals (trills taken out 11/05/05) (T) tremulos added 01/07/06 if "r@wMk" con codes{a1} /* new code 03/01/97 if "r@wMkT" con codes{a1} /* code amended 01/07/06 a7 = mpt Special case of tremulo 01/07/06; no editorial and no accidentals allowed if a14 = 0 and a7 = 6 ts(sct,SUBFLAG_1) |= a7 goto TLP1 end if a14 = 0 ts(sct,SUBFLAG_1) |= a7 else ts(sct,ED_SUBFLAG_1) |= a7 end temp3 = codes // pad(13) loop for a3 = a1 + 1 to 13 repeat while "shbu" con temp3{a3} if a3 = a1 + 1 goto TLP1 end a7 = 0 temp3 = codes{a1+1..a3-1} a1 = a3 - 1 if temp3 con "u" temp4 = temp3{mpt..} // "..." if mpt = 1 temp3 = "" else temp3 = temp3{1,mpt-1} end if "uss.ubb.us..uh..ub.." con temp4{1,4} a7 = mpt + 3 a7 = a7 << 1 end end temp4 = temp3 // "...." if "ss..bb..s...h...b..." con temp4{1,4} mpt += 3 mpt >>= 2 a7 |= mpt end a7 <<= 4 if a14 = 0 ts(sct,SUBFLAG_1) |= a7 else ts(sct,ED_SUBFLAG_1) |= a7 end goto TLP1 end New code 11/05/05 for trills and their accidentals if codes{a1} = "t" a4 = 0 /* this will be bit 19 a7 = 2 if a14 = 0 ts(sct,SUBFLAG_1) |= a7 else ts(sct,ED_SUBFLAG_1) |= a7 end temp3 = codes // pad(13) loop for a3 = a1 + 1 to 13 repeat while "shbuU" con temp3{a3} if a3 = a1 + 1 goto TLP1 end a7 = 0 temp3 = codes{a1+1..a3-1} a1 = a3 - 1 if temp3 con "u" or temp3 con "U" temp4 = temp3{mpt..} // "..." if mpt = 1 temp3 = "" else temp3 = temp3{1,mpt-1} end if "uss.ubb.us..uh..ub.." con temp4{1,4} a7 = mpt + 3 /* 4,8,12,16,20 a7 = a7 << 1 /* 8,16,24,32,40 = 8 x (1,2,3,4,5) end if "Uss.Ubb.Us..Uh..Ub.." con temp4{1,4} a7 = mpt + 3 /* 4,8,12,16,20 a7 = a7 >> 2 /* 1,2,3,4,5 a4 = 1 end end temp4 = temp3 // "...." if "ss..bb..s...h...b..." con temp4{1,4} mpt += 3 mpt >>= 2 a7 |= mpt end a7 <<= 4 a4 <<= 19 if a14 = 0 ts(sct,SUBFLAG_1) |= a7 ts(sct,SUBFLAG_1) |= a4 /* establish bit 19 else ts(sct,ED_SUBFLAG_1) |= a7 ts(sct,ED_SUBFLAG_1) |= a4 /* establish bit 19 end goto TLP1 end End of 11/05/05 New Code if "FE@^+" con codes{a1} if "^+@@@@FE" con codes{a1} accidental flags moved 03/01/97 mpt += 7 mpt += 13 a7 = 1 << mpt if a14 = 0 ts(sct,SUBFLAG_1) |= a7 else ts(sct,ED_SUBFLAG_1) |= a7 end goto TLP1 end look for dynamics (This section recoded 10/08/08 to simplify and add extra dynamic combinations) if "mpfZR" con codes{a1} if mpt < 4 if mpt = 1 if "pf" con codes{a1+1} a7 = mpt + 8 /* mp = 9; mf = 10 9 10 ++a1 else a7 = 0 end else a7 = mpt - 2 * 4 + 1 /* p = 1; f = 5 1 5 if "pf" con codes{a1+1} ++a1 if codes{a1-1} <> codes{a1} if codes{a1} = "p" a7 = 11 /* fp = 11 11 end else ++a7 /* pp = 2; ff = 6 2 6 if codes{a1} = codes{a1+1} ++a1 ++a7 /* ppp = 3; fff = 7 3 7 if codes{a1} = codes{a1+1} ++a1 ++a7 /* pppp = 4; ffff = 8 4 8 end end end else if a7 = 5 and codes{a1+1} = "z" a7 = 13 /* fz = 13 13 ++a1 end end end else if mpt = 4 and a1 < len(codes) and codes{a1+1} = "p" /* Zp = sfp a7 = 12 12 ++a1 else a7 = mpt + 10 /* Z = sfz = 14; R = rfz = 15 14 15 end end a7 <<= 10 New code 10/08/08 a7 = 0 temp4 = codes // pad(13) /* so we don't run off at the end temp3 = temp4{a1} loop while "pf" con temp4{a1+1} temp3 = temp3 // temp4{a1+1} ++a1 /* this will rightsize a1 repeat temp3 = temp3 // pad(4) temp3 = temp3{1,4} temp3 = temp3 // "." /* max data length = 4; full padded length = 5 if "p .pp .ppp .pppp.f .ff .fff .ffff.mp .mf .fp .Zp .fz .Z .R ." con temp3 a7 = mpt + 4 / 5 /* values 1 to 15 a7 <<= 10 /* range in bits 0x3c00 end if "ffp .mfp .Zf ." con temp3 a7 = mpt + 4 / 5 /* 1 or 2 or 3 New 03/16/09 a7 = 1 a7 <<= 26 /* range in bits 0x1c000000 end End of new code 10/08/08 if a14 = 0 if ts(sct,SUBFLAG_1) & 0x1c003c00 = 0 /* changed 10/08/08 from 0x3100 ts(sct,SUBFLAG_1) |= a7 end else if ts(sct,ED_SUBFLAG_1) & 0x1c003c00 = 0 /* changed 10/08/08 from 0x3100 ts(sct,ED_SUBFLAG_1) |= a7 end end goto TLP1 end look for back ties New 04/22/08 if "JK" con codes{a1} a7 = 1 << (mpt + 23) ts(sct,SUBFLAG_1) |= a7 goto TLP1 end other directions connected with notes if "nvi.=_>AVoQ0" con codes{a1} --mpt a7 = 1 << mpt if a14 = 0 ts(sct,SUBFLAG_2) |= a7 else ts(sct,ED_SUBFLAG_2) |= a7 end goto TLP1 end fingering connected with notes if "12345" con codes{a1} a4 = mpt a7 = 0 a3 = 0 FINNN: if a1 < len(codes) and "12345:" con codes{a1+1} if mpt = 6 a4 += 8 else a4 <<= a3 a7 += a4 a4 = mpt a3 += 4 end ++a1 goto FINNN end a4 <<= a3 a7 += a4 a7 <<= 12 if a14 = 0 ts(sct,SUBFLAG_2) |= a7 else ts(sct,ED_SUBFLAG_2) |= a7 end goto TLP1 end TLP1: repeat tsdata(a9+old@n) = line{28..} ts(sct,TEXT_INDEX) = a9 + old@n ts(sct,PASSNUM) = passnum ts(sct,STAFF_NUM) = tv3(a9) & 0x000f ts(sct,TRACK_NUM) = tv3(a9) >> 4 & 0x000f goto EBL end Case II: figures if tvar1 = FIGURES ++sct ts(sct,TYPE) = tvar1 if figdiv = 0 figdiv = divpoint end ts(sct,DIV) = figdiv ts(sct,FIG_DUR) = tvar2 figdiv += tvar2 a3 = sct - 1 a4 = 0 loop while a3 > oldsct if ts(a3,TYPE) = FIGURES a4 = a3 end --a3 repeat while a4 = 0 * a4 = pointer to previous figure data in measure (or 0) ts(sct,NUMBER_OF_FIG) = int(tcode(a9)) if ts(sct,NUMBER_OF_FIG) > 4 return 2 end a7 = FIG_DATA loop for a5 = 1 to ts(sct,NUMBER_OF_FIG) line = mrt(line) out = rev(line) out = trm(out) line = rev(out) if line = "" return 2 end Adding new code 11/16/03 to allow for parentheses around figure fields a13 = 0 /* initialize parentheses flag to null line = line // " " if line{1} = "(" if line con ")" a6 = mpt - 1 if mpt = 2 return 2 end a13 = 1 temp = line{2..(mpt-1)} /* section of line inside () if temp{1} = " " return 2 end /* section starts with non-blank field WB1a: if temp con " " temp = temp{mpt..} /* skip over non-blank field temp = mrt(temp) /* and remove leading blanks to next field if temp = "" return 2 end ++a13 goto WB1a end if a13 > (ts(sct,NUMBER_OF_FIG) - a5 + 1) return 2 end a13 *= 1000 line = line{2..a6} /* now remove parentheses from line else return 2 end end if line con " " temp = line{1,mpt-1} line = line{mpt..} end temp = temp // pad(3) if "_-" con temp{1} if mpt = 1 if a4 = 0 return 2 end if ts(a4,a7+2) = 0 ts(a4,a7+2) = 2 else ts(a4,a7+2) = 3 end ts(sct,a7+2) = 1 else ts(sct,a7) = 30 /* 30 end else if "x@#@@@@nf" con temp{1} /* 21,23,28,29 ts(sct,a7) = mpt + 20 a6 = 2 goto WB1 end if "2@45" con temp{1} and temp{2} = "+" /* 22,24,25 ts(sct,a7) = mpt + 21 a6 = 4 goto WB1 end if "/\" con temp{2} and "67" con temp{1} /* 26,27 ts(sct,a7) = mpt + 25 a6 = 4 goto WB1 end a6 = int(temp) /* 1..19 if a6 < 0 or a6 > 19 return 2 end ts(sct,a7) = a6 if ts(sct,a7) < 10 a6 = 2 else a6 = 3 end WB1: if a6 < 4 temp = temp{a6..} if "+x@#@@@@nf" con temp{1} ts(sct,a7+1) = mpt + 19 else ts(sct,a7+1) = int(temp) end end end ts(sct,a7) += a13 /* Adding parentheses flag 11/16/03 a7 += 3 repeat ts(sct,TEXT_INDEX) = a9 Removing this line ts(sct,PASSNUM) = passnum ts(sct,STAFF_NUM) = nstaves - 1 goto EBL end Case III: bar lines if tvar1 = BAR_LINE ++sct ts(sct,TYPE) = tvar1 ts(sct,DIV) = divpoint ts(sct,BAR_NUMBER) = tvar2 if tcode(a9) = "sure" ts(sct,BAR_TYPE) = REGULAR else if "@1d@e2@@34" con tcode(a9){4} ts(sct,BAR_TYPE) = mpt end end if line con ":|" ts(sct,REPEAT) |= 0x02 end if line con "|:" ts(sct,REPEAT) |= 0x01 end if line con "stop-end" ts(sct,BACK_ENDING) = int(line{mpt+8..}) end if line con "start-end" ts(sct,FORW_ENDING) = int(line{mpt+9..}) end if line con "disc-end" a3 = int(line{mpt+8..}) ts(sct,BACK_ENDING) = 0 - a3 end 12/08/07 ctrflag made into an array if ctrflag > 0 and line con "~" if line con "~" loop for a7 = 1 to passnum if ctrflag(a7) > 0 ts(sct,BAR_FLAGS) |= 0x01 end repeat end if line con "A" ts(sct,BAR_FLAGS) |= 0x02 end if line con "F" ts(sct,BAR_FLAGS) |= 0x04 end if line con "E" ts(sct,BAR_FLAGS) |= 0x08 end ts(sct,SPACING) = hpar(37) ts(sct,M_NUMBER) = m_number if m_number > 0 ++m_number end ts(sct,TEXT_INDEX) = a9 Removing this line ts(sct,TEXT_INDEX) = a9 + old@n /* and putting it back 03/21/03 tsdata(a9+old@n) = tdata(a9,2) /* and adding this line 03/21/03 ts(sct,PASSNUM) = passnum ts(sct,NUM_STAVES) = tv3(a9) goto EBL end Case IV: signs, words, marks if tvar1 = MUSICAL_DIR ++sct a4 = 0 temp = tcode(a9) loop for a3 = 1 to 2 if "APQG" con temp{a3} ts(sct,TYPE) = SIGN ts(sct,SIGN_TYPE) = mpt end if temp{a3} = "X" /* (added 10/12/96) ts(sct,TYPE) = SIGN ts(sct,SIGN_TYPE) = TIE_TERM end if "BCD" con temp{a3} ts(sct,TYPE) = WORDS ts(sct,SIGN_TYPE) = mpt + 4 end if "R" con temp{a3} /* (added 02/03/08) ts(sct,TYPE) = WORDS ts(sct,SIGN_TYPE) = REH_MARK end if "EFHJ" con temp{a3} ts(sct,SUPER_TYPE) = mpt if mpt < 3 a4 = int(line{5..7}) /* get numerical parameter for wedges ts(sct,WEDGE_SPREAD) = a4 * notesize / 10 end end if "UWV" con temp{a3} if mpt = 2 ts(sct,SUPER_TYPE) = NORMAL_TRANS else ts(sct,SUPER_TYPE) = mpt + 4 /* 5 or 7 */ if int(tdata(a9,1){5,3}) <> 0 ts(sct,SUPER_TYPE) += 4 end end end repeat if ts(sct,TYPE) = 0 ts(sct,TYPE) = MARK end ts(sct,DIV) = divpoint + cuediv ts(sct,DIV) += mdir_offset if temp{3} = "+" ts(sct,SIGN_POS) = ABOVE else ts(sct,SIGN_POS) = BELOW end if a4 = 0 a4 = int(line{5..7}) ts(sct,FONT_NUM) = a4 /* get numerical parameter for words, etc. end ts(sct,WEDGE_OFFSET) = vpar(1) if ts(sct,SUPER_TYPE) = WEDGES << 1 /* end of wedge if ts(sct,WEDGE_SPREAD) = 0 /* point of wedge ts(sct,WEDGE_OFFSET) = notesize end end if ts(sct,SIGN_TYPE) = LETTER_DYNAM if ts(sct,SUPER_TYPE) = 1 /* start wedge line = trm(line) line = line // pad(9) temp = line{9..} Adjust temp for "Zp", "Z", and "R". temp = " " // temp // " " if temp con "Zp" temp = temp{1..mpt-1} // "sfp" // temp{mpt+2..} end if temp con "Z" #if SFZ temp = temp{1..mpt-1} // "sfz" // temp{mpt+1..} #else temp = temp{1..mpt-1} // "sf" // temp{mpt+1..} #endif end if temp con "R" #if SFZ temp = temp{1..mpt-1} // "rfz" // temp{mpt+1..} #else temp = temp{1..mpt-1} // "rf" // temp{mpt+1..} #endif end temp = temp{2..} temp = trm(temp) a5 = notesize / 2 loop for a4 = 1 to len(temp) if "pmfszr" con temp{a4} mpt += 59 a5 += hpar(mpt) end repeat ts(sct,WEDGE_OFFSET) = a5 end if ts(sct,SUPER_TYPE) = 2 /* stop wedge ts(sct,WEDGE_OFFSET) = 0 - hpar(46) end end if ts(sct,SIGN_TYPE) = CENTER_STR or ts(sct,SIGN_TYPE) = LEFT_JUST_STR if ts(sct,SUPER_TYPE) = 1 /* start wedge if len(line) > 8 ttext = line{9..} ttext = trm(ttext) Introducing optional conversion to ligitures in words before a wedge 04/22/04 if ligit_flag = 1 if ttext = "ff" ttext = "f\@f" end LIGCON4: if ttext con "ffi" ttext{mpt,3} = "\0:" goto LIGCON4 end if ttext con "ffl" ttext{mpt,3} = "\0;" goto LIGCON4 end if ttext con "ff" ttext{mpt,2} = "\0<" goto LIGCON4 end if ttext con "fi" ttext{mpt,2} = "\0=" goto LIGCON4 end if ttext con "fl" ttext{mpt,2} = "\0>" goto LIGCON4 end end #if AUTOSCR #else perform kernttext /* New 04/22/04 #endif c5 = mtfont perform wordspace │ Outputs: a5 = space taken up by word if ts(sct,SIGN_TYPE) = CENTER_STR /* centered word a5 >>= 1 end a5 += notesize / 2 ts(sct,WEDGE_OFFSET) = a5 end end if ts(sct,SUPER_TYPE) = 2 /* stop wedge ts(sct,WEDGE_OFFSET) = 0 - notesize end end tsdata(a9+old@n) = line{9..} ts(sct,TEXT_INDEX) = a9 + old@n ts(sct,PASSNUM) = passnum ts(sct,STAFF_NUM) = tv3(a9) ts(sct,S_TRACK_NUM) = tvar2 goto EBL end Case V, VI, VII and VIII: clef change, time designation, meter change, divspq change if chr(tvar1) in [CLEF_CHG,DESIGNATION,METER_CHG,DIV_CHG] ++sct ts(sct,TYPE) = tvar1 ts(sct,DIV) = divpoint ts(sct,3) = tvar2 /* first parameter if tvar1 = CLEF_CHG ts(sct,CLEF_FONT) = int(tcode(a9)) end tsdata(a9+old@n) = tdata(a9,1) ts(sct,TEXT_INDEX) = a9 + old@n ts(sct,PASSNUM) = passnum ts(sct,STAFF_NUM) = tv3(a9) ts(sct,DOLLAR_SPN) = tv5(a9) /* added 01/17/04 assure proper current value of divspq for this loop if tvar1 = DIV_CHG qflag = 1 divspq = tvar2 end goto EBL end Case IX: key change if tvar1 = AX_CHG ++sct ts(sct,TYPE) = tvar1 ts(sct,DIV) = divpoint ts(sct,3) = tvar2 /* new key ts(sct,4) = key /* old key tsdata(a9+old@n) = tdata(a9,1) ts(sct,TEXT_INDEX) = a9 + old@n ts(sct,PASSNUM) = passnum ts(sct,NUM_STAVES) = tv3(a9) ts(sct,DOLLAR_SPN) = tv5(a9) /* added 01/17/04 New 12/14/07: This code adjusts tclaveax(.) to reflect the current situation loop for a6 = 1 to 50 tclaveax(a6) = 0 repeat a6 = tvar2 if a6 > 0 a7 = 4 loop for a8 = 1 to a6 loop for c5 = a7 to 50 step 7 tclaveax(c5) = 2 repeat a7 += 4 if a7 > 7 a7 -= 7 end repeat end if a6 < 0 a6 = 0 - a6 a7 = 7 loop for a8 = 1 to a6 loop for c5 = a7 to 50 step 7 tclaveax(c5) = 3 repeat a7 -= 4 if a7 < 1 a7 += 7 end repeat end loop for a6 = 1 to 50 loop for a7 = 1 to 4 /* 06/04/08 was 3 measax(a7,a6) = tclaveax(a6) repeat repeat End of 12/14/07 addition goto EBL end Case X: irst, backspace if tvar1 = IREST divpoint += tvar2 if divpoint > totdiv totdiv = divpoint end cuediv = 0 goto EBL end if tvar1 = BACKSPACE ++passnum divpoint -= tvar2 cuediv = 0 goto EBL end Case XI: print suggestions if tvar1 = P_SUGGESTION if tvar2 < 8 /* forced slur suggestion a3 = tvar2 & 0x06 a4 = tvar2 & 0x01 a4 <<= 1 ++a4 /* 1 = over; 3 = under a4 <<= a3 + 8 ts(sct,SLUR_FLAG) |= a4 /* turn on forced slur flag goto EBL end if tvar2 < 10 if tvar2 = 8 ts(sct,SLUR_FLAG) |= 0x1000000 /* overhanded tie else ts(sct,SLUR_FLAG) |= 0x3000000 /* underhanded tie end goto EBL end if tvar2 < 32 ts(sct,SUPER_FLAG) |= 0x40 /* tuplet has a bracket 03-21-97 if bit(0,tvar2) = 1 ts(sct,SUPER_FLAG) |= 0x200 /* bracket is round 03-21-97 end if bit(1,tvar2) = 1 ts(sct,SUPER_FLAG) |= 0x80 /* bracket is continuous 03-21-97 end if bit(2,tvar2) = 1 ts(sct,SUPER_FLAG) |= 0x100 /* tuplet number is inside 03-21-97 end goto EBL end if tvar2 >= 0x100 and tvar2 < 0x200 /* musical direction a3 = ors(tcode(a9){1}) if a3 > 0 ts(sct,FONT_NUM) = a3 end a3 = ors(tcode(a9){2}) << 8 + ors(tcode(a9){3}) if tvar2 & 0xff = 0 ts(sct,POSI_SHIFT1) = a3 << 8 + ors(tcode(a9){4}) else ts(sct,POSI_SHIFT2) = a3 << 8 + ors(tcode(a9){4}) end goto EBL end if tvar2 & 0xff00 = 0x0200 /* position of ornaments, etc. a3 = tvar2 & 0xff * 4 + 1 tsr(sct){a3,4} = tcode(a9){1,4} goto EBL end if tvar2 & 0xff00 = 0x0300 /* printing of actual objects a3 = ors(tcode(a9){1}) if a3 > 6 a3 >>= 1 a3 &= 0x07 3 = print object, no extension dot 4 = print object, include extension dot 5 = double note length, no extension dot 6 = double note length, include extension dot 7 = quadruple note length, no extension dot if a3 > 2 if a3 = 4 or a3 = 6 ts(sct,DOT) = 1 else ts(sct,DOT) = 0 end if a3 > 4 ++ts(sct,NTYPE) end if a3 > 6 ++ts(sct,NTYPE) end ts(sct,SUPER_FLAG) &= 0xfffffffe /* turn off ties end end tsr(sct){1,4} = tcode(a9){1,4} goto EBL end New Code 05/25/03 and 05/28/05 if tvar2 & 0xff00 = 0x0400 /* print suggestion for preceding bar line putc Handling measure print suggestion putc value of outpnt = ~outpnt loop for c1 = outpnt to 1 step -1 tget [Y,c1] line putc rec = ~c1 line = ~line if line{1,3} = "J B" sub = 5 c2 = int(line{sub..}) /* bar number c3 = int(line{sub..}) /* obx c4 = int(line{sub..}) /* oby temp = line{sub..} if tvar2 & 0xffff = 0x0400 c4 += 1000000 /* 1 million is flag for fixed length else if tvar2 & 0xffff = 0x0401 c4 += 10000000 /* New 05/28/05 10 million is flag for end /* mid-movement right justification end line = "J B " // chs(c2) // " " // chs(c3) // " " // chs(c4) // temp tput [Y,c1] ~line putc new line = ~line c1 = 1 end repeat goto EBL end New code 11/05/05 for implementing location suggestions for tuples if tvar2 & 0xff00 = 0x0500 /* print suggestion for horizontal adjustment c2 = tvar2 & 0xff c2 <<= 16 ts(sct,TUPLE) |= c2 /* horizontal adjustment goto EBL end if tvar2 & 0xff00 = 0x0600 /* print suggestion for vertical adjustment c2 = tvar2 & 0xff c2 <<= 24 ts(sct,TUPLE) |= c2 /* vertical adjustment goto EBL end End of 11/05/05 Code end EBL: repeat old@n += @n ┌────────────────────────────────────────────┐ │ End of storing original data in set array │ └────────────────────────────────────────────┘ ╔═══════════════════════════════════════════╗ ║ N E W S O R T A L G O R I T H M ║ ╚═══════════════════════════════════════════╝ 09/30/93 Reorder set array according to location in measure. Do not separate extra chord notes from their original lead notes. Do not change the order of bar/clef/grace-note. Do not extract signs, words, or marks when they precede a bar, clef or grace note; otherwise extract them and put them in front of figures, cues and regular notes. Do not extract time designations when they precede a bar, clef or grace note; otherwise extract them and put them in front of words, signs, marks, figures, cues and regular notes. For objects at same location, the order is as follows: 1. bar, clef, grace note/chord (in original order for each div) 2. 3. 4. change in divisions per quarter 5. time designation, meter change, key change 6. word, sign, mark 7. figure 8. cue note/chord, cue rest 9. regular note/chord, regular rest Note: this is why we send irests through the system as rests and not as marks Summary of algorithm: 1. For each division, assign parameters as listed above 2. bar, clef, and grace note/chord will be assigned numbers 1, 2, and 3 in the order in which they first occur in the array on this division 3. For time designations, words, signs and marks, if they preceed a type 1,2,or 3, or if they preceed another or this kind which preceeds a 1,2 or 3, then they take this respective type 4. order the elments of mf(.) on each division according to the parameter numbers assigned to them. mf(.) will now contain the indexes for the proper order of ts(.) from oldsct to sct. 5. reorder the elements of ts(.) accordingly a7 = 0 /* global counter in measure a3 = ts(sct,DIV) /* divisions per measure loop for a2 = 1 to a3 temp = "999888007066606545" /* initial "priority" string (with unknowns = 0) a6 = 0 a8 = a7 /* local counter on this division loop for a1 = oldsct + 1 to sct if ts(a1,DIV) = a2 a4 = ts(a1,TYPE) a5 = int(temp{a4}) if a5 = 0 /* setting "unknowns" in the order they are encountered ++a6 if a4 = 7 or a4 = 8 temp{7} = chs(a6) temp{8} = chs(a6) else temp{a4} = chs(a6) end a5 = a6 end ts(a1,SORTPAR1) = a5 ++a8 mf(a8) = a1 end repeat a5 = 20 loop for a3 = a8 to a7 + 1 step -1 a1 = mf(a3) a4 = ts(a1,SORTPAR1) if a4 = 6 /* time designation, word, sign, mark if a5 < 4 /* bar, clef, grace note/chord or ... ts(a1,SORTPAR1) = a5 a4 = a5 else if ts(a1,TYPE) = DESIGNATION ts(a1,SORTPAR1) = 5 end end end a5 = a4 repeat Sort this section of mf(.) according to SORTPAR1, taking care not to separate chord tones from their principal tones. if a8 > a7 + 1 /* (1) transfer relevant portion to mf2 array loop for a3 = a7+1 to a8 mf2(a3) = mf(a3) repeat /* (2) move elements back using order of sort priorites only a6 = a7 loop for a1 = 1 to 9 /* sort priorities loop for a3 = a7+1 to a8 a5 = mf2(a3) /* a5 is a ts(.) index if a5 <> 1000 a5 = ts(a5,SORTPAR1) /* a5 is a sort priority (0 to 9) if a5 = a1 ++a6 mf(a6) = mf2(a3) /* move element back to mf mf2(a3) = 1000 /* and disqualify this element end end repeat repeat if a6 <> a8 putc Program Error in mf() sort stop end end End of mf() section sort a7 = a8 repeat /* now sort the ts(.,.) array according to the mf(.) order loop for a2 = 1 to a8 putc ~mf(a2) repeat a5 = sct + 1 /* address of "hole" a1 = oldsct + 1 loop for a2 = 1 to a8 a3 = mf(a2) if a3 <> a1 /* move ts(a1) to "hole" and put ts(a3) in a1 slot loop for a6 = 1 to TS_SIZE ts(a5,a6) = ts(a1,a6) ts(a1,a6) = ts(a3,a6) repeat /* search mf(.) array for reference to a1 element /* and tell it that this element is now in a5 loop for a7 = a2+1 to a8 if mf(a7) = a1 mf(a7) = a5 a7 = a8 end repeat mf(a2) = a1 /* set a5 to the new "hole", which is a3 a5 = a3 end /* advance the destination, a1 ++a1 repeat Code added 01/07/06 reporting on a possible failure condition brought on by a faulty stage2 file. a5 = sct - oldsct if a5 <> a8 if a5 > sct dputc I think there is a bug here. If strange things putc happen, look here first. else putc WARNING! There may be a format error in your stage2 file. putc (possibly having to do with (cue note) durations) putc type <Enter> to proceed on a probationary basis. getc sct = a8 - oldsct end end Clear work space loop for a1 = oldsct + 1 to sct ts(a1,SORTPAR1) = 0 repeat loop for a1 = 1 to TS_SIZE ts(sct+1,a1) = 0 repeat goto TS_SORTED ╔══════════════════════════════════════════╗ ║ O L D S O R T A L G O R I T H M ║ ╚══════════════════════════════════════════╝ Reorder set array according to location in measure. Do not separate extra chord notes from their original lead notes. Do not change the order of bar/clef/grace-note. Do not extract signs, words, or marks when they precede a bar, clef or grace note; otherwise extract them and put them in front of figures, cues and regular notes. For objects at same location, the order is as follows: 1. bar, clef, grace note/chord 2. change in divisions per quarter 3. time designation, meter change, key change 4. word, sign, mark 5. figure 6. cue note/chord 7. cue rest 8. regular note/chord 9. regular rest Designations have a certain amount of "glue". If they preceed a clef change, they want to keep that position. If they preceed grace notes, they want to stay there also. If they preceed a bar line, they want to stay there. Otherwise they get moved in front of everything except changes in divspq Because the position of words, signs, and marks depends on what follows, we must assign order priorities starting at the bottom of the array. TS_SORTED: Reorder multiple grace notes loop for a3 = 1 to MAX_PASS passpar(a3) = 200 /* reverse order scheme, starting at 200 repeat a6 = 200 a5 = 0 loop for a1 = sct to oldsct step -1 if a1 > oldsct and chr(ts(a1,TYPE)) in [GR_NOTE,XGR_NOTE] if a5 = 0 a5 = a1 end a2 = ts(a1,PASSNUM) ts(a1,SORTPAR1) = passpar(a2) if a6 > passpar(a2) a6 = passpar(a2) end if ts(a1,TYPE) = GR_NOTE --passpar(a2) end else if a5 > 0 /* some grace notes were found a5 -= a1 /* a5 = number of elements a4 = 0 loop for a7 = a6 to 200 a3 = 0 loop for a8 = 1 to a5 if ts(a1+a8,SORTPAR1) = a7 ++a4 mf(a4) = a1 + a8 /* here is where we must add space parameter for GRACE notes if a3 = 0 if ts(a1+a8,BEAM_FLAG) = NO_BEAM ts(a1+a8,SPACING) = hpar(97) /* Removed * 4 / 3 05-15-95 else ts(a1+a8,SPACING) = hpar(97) end a3 = 1 else ts(a1+a8,SPACING) = 0 end end repeat repeat /* mf(.) now contains the locations of array elements (in reordered form) loop for a8 = 1 to a5 a4 = mf(a8) if a1+a8 <> a4 /* what's there now is not what goes there loop for a7 = 1 to TS_SIZE ts(sct+1,a7) = ts(a1+a8,a7) /* make hole for new element ts(a1+a8,a7) = ts(a4,a7) /* move in new element ts(a4,a7) = ts(sct+1,a7) /* put old element in vacancy repeat loop for a7 = 1 to a5 if mf(a7) = a1 + a8 /* this element has been moved mf(a7) = a4 /* now give new location a7 = a5 end repeat mf(a8) = a1 + a8 end repeat /* re-initialize sorting parameters loop for a3 = 1 to MAX_PASS passpar(a3) = 200 repeat a5 = 0 a6 = 200 end end repeat loop for a1 = oldsct+1 to sct ts(a1,SORTPAR1) = 0 repeat ┌─────────────────────────┐ │ End of reorder process. │ └─────────────────────────┘ Check for isolated SIGNS, WORDS, or MARKS a2 = oldsct + 1 a5 = ts(a2,DIV) loop for a1 = oldsct+1 to sct if ts(a1,DIV) <> a5 loop for a3 = a2 to a1 - 1 nodtype = ts(a3,TYPE) if chr(nodtype) not_in [SIGN,WORDS,MARK] a3 = 1000000 end repeat if a3 <> 1000000 loop for a3 = a2 to a1 - 1 ts(a3,ISOLATED) = 1 repeat end a2 = a1 a5 = ts(a2,DIV) end repeat ┌────────────────────────────────────────────────────────────────┐ │ Before decoding the notes, we must determine if this part │ │ represents more than one independent instrument. If so then │ │ the rules regarding accidentals are slightly different. Each │ │ instrumental part must have its own, independent measax array. │ └────────────────────────────────────────────────────────────────┘ For the case where more than one independent instrument is being represented on this measure, (vflag > 1) we need to catagorize the measure into one of three types: (1) one pass, no chords. This situation arrises when we have an a2 (zu 2) situation, i.e., all instruments are active, but are playing the same music, or a 1. (2. or 3.) situation, i.e., only one instrument is specifically active -- all other instruments have been told not to play. In this case, the music is easy to typeset. (2) one pass, chords. This is the situation more than 90% of the time. Two or more parts (99.99% of the time, it is two parts) are represented in the measure, and the following conditions hold true: a) all parts have the same rhythm (including resting at the same time) b) part 1 is at unison or is higher than part 2, etc. c) all parts have identical slurs and articulations. This includes slurs entering and leaving the measure. d) if there is a unison and it is an eighth note or less, then it is not attached to a beam. The parts will be printed as chords. Slurs and articulations will be attached to the note head at the end of stem. Unison notes (represented as chords with two or more identical notes) will be printed in one of two ways: a) whole notes and larger will be printed side-by-side. b) half notes and smaller will be printed with two stems (up and down) regardless of the listed stem direction. (three unisons cannot be handled by this program) With this type, each part (defined by its position in the chord) will have its own measax array. This is because accidentals must be repeated, if they appear in different parts. (3) more than one pass. With this type, notes occuring on the same division and having the same duration and same stem direction will be combined into one chord. As with type (2) above, each part (defined in this case by pass number) will have its own measax array. Accidentals must be repeated, if they appear in different parts. Unison whole notes and larger will be printed side-by-side. if vflag > 1 if passnum = 1 Must determine if there are chords in this measure mcat = 1 loop for a1 = 1 to sct if ts(a1,TYPE) = XNOTE mcat = 2 a1 = sct end repeat else mcat = 3 end else mcat = 0 end (added 10-12-96) Determine links between tie terminators and earlier pitches Basically, we look backward through the data to find the pitch referred to by the tie terminator. If the pitch cannot be found, this is an error condition. We must search on the correct staff number. Once we have found the pitch, we need to store its index number. Later we will determine the STAFFLOC parameter. This will be used later to generate the mark object and the tie super object. loop for a1 = oldsct+1 to sct if ts(a1,TYPE) = SIGN and ts(a1,SIGN_TYPE) = TIE_TERM tsdata(ts(a1,TEXT_INDEX)) = tsdata(ts(a1,TEXT_INDEX)) // pad(4) note = tsdata(ts(a1,TEXT_INDEX)){1,4} loop for t7 = a1 to oldsct+1 step -1 if ts(t7,TYPE) <= NOTE_OR_REST if ts(t7,STAFF_NUM) = ts(a1,STAFF_NUM) t8 = ts(t7,4) /* "4" is a cluge, here (see below) if note = tcode(t8) ts(a1,BACKTIE) = t7 /* store ts index of pitch generating tie goto TIE_TERM_FOUND end end end repeat return 10 end TIE_TERM_FOUND: repeat End of 10-12-96 addition Decode pitches, store unmodified accidentals in ts(.,AX) loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a2 = ts(a1,4) note = tcode(a2) perform decodenote if @c = 100 @c += ts(a1,CLAVE) /* see "floating rest flag" end ts(a1,CLAVE) = @c /* Here is where CLAVE is definitively set ts(a1,AX) = @d a4 = ts(a1,STAFF_NUM) + 1 if @c < 100 ts(a1,STAFFLOC) = 52 - @c - cline(a4) + c8flag(a4) * notesize / 2 ts(a1,STAFFLOC) = 52 - @c - cline(a4) + c8flag(a4) + 20 * notesize / 2 - vpar20 end We need to capture the note shape data now, because it will figure in on whether a passage is iso-rhythmic; i.e., you can't have iso-rhythm with different note shapes. Code added 02/19/06 a14 = ts(a1,TSR_POINT) a4 = ors(tsr(a14){1}) if a4 > 16 a4 >>= 4 /* upper for bits a4 <<= 20 /* shifted to space 20-23 ts(a1,SUBFLAG_1) |= a4 end end if chr(nodtype) in [SIGN,WORDS,MARK] a4 = ts(a1,STAFF_NUM) + 1 /* staff number a2 = ts(a1,SUPER_TYPE) + 1 / 2 if chr(a2) in [OCT_UP,OCT_DOWN,DBL_OCT_UP,DBL_OCT_DOWN] adjust c8flag(.) if a2 = OCT_UP c8flag(a4) = -7 end if a2 = OCT_DOWN c8flag(a4) = 7 end if a2 = DBL_OCT_UP c8flag(a4) = -14 end if a2 = DBL_OCT_DOWN c8flag(a4) = 14 end transflag(a4) = 2 * a2 end if ts(a1,SUPER_TYPE) = NORMAL_TRANS c8flag(a4) = 0 /* return to normal if transflag(a4) < 2 * OCT_UP putc Possible Coding error with transpositions putc Type <Return> to continue getc end ts(a1,SUPER_TYPE) = transflag(a4) transflag(a4) = 0 end end if nodtype = CLEF_CHG a4 = ts(a1,STAFF_NUM) + 1 /* staff number clef(a4) = ts(a1,CLEF_NUM) perform zjcline (a4) * this resets clef and cline /* ts(a1,CLEF_FONT) += z Unnecessary and, in fact, an error! ts(a1,TRANS_FLAG) = k /* ts(a1,CLEF_STAFF_POS) = 5 - j * notesize /* Possibly a3 = hpar(8) * 5 / 6 /* unnecessary if ts(a1,CLEF_FONT) >= 128 /* music font /* at this a3 = a3 * 8 / 10 /* point end /* ts(a1,SPACING) = a3 /* end repeat If mcat = 3, reorganize notes on the same division. If two notes with different pass numbers have the same duration and stem directions in the same direction, and these notes do not have beam connections, then these notes can be combined into one chord. This will save considerable trouble later during the computing of x-offsets (both local and global) and the setting of stems. 09/22/93 Actually I would like to expand this section. (1) I would like to try to combine isorhythmic passages that do connect to beams (2) If the entire measure is isorhythmic, then I would like to set mcat to 2 and reduce the number of passes (3) Also, if the measure is isorhythmic, I would like to print out rests only one time (4) Also, if mcat > 1, accidentals on the same line should NOT be reprinted. This should be easy to fix, simply by looping though all simultanities on a staff and removing accidentals that occur twice on the same pitch. available variables: a1 --> a16 if mcat = 3 /* %%% add code here for changing ax behavior First thing: fix accidentals according to pass number loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a4 = ts(a1,PASSNUM) if a4 > 3 putc This code will not work with more than 3 passes examine stop end perform decodeax (a1,a4) end if nodtype = BAR_LINE loop for a3 = 1 to 50 loop for a4 = 1 to 4 /* 06/04/08 was 3 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat repeat end if nodtype = CLEF_CHG a4 = ts(a1,STAFF_NUM) + 1 /* staff number clef(a4) = ts(a1,CLEF_NUM) perform zjcline (a4) * this resets clef and cline ts(a1,CLEF_FONT) += z /* music font ts(a1,TRANS_FLAG) = k ts(a1,CLEF_STAFF_POS) = 5 - j * notesize a3 = hpar(8) * 5 / 6 /* Added 06-24-94 if ts(a1,CLEF_FONT) > 128 /* music font a3 = a3 * 8 / 10 end ts(a1,SPACING) = a3 if nstaves > 1 /* Case: assume one part to stave (usual case) loop for a3 = 1 to 50 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat else loop for a4 = 1 to 4 /* 06/04/08 was 3 loop for a3 = 1 to 50 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat repeat end end repeat Now you can combine notes into chords (and alter pass numbers) If there are notes of different note shapes in a measure, this is a non-starter for combining any notes into chords. All notes must have the same note shape (bits 20-23 of SUBFLAG_1). This information was encoded at the same time as pitch. (added 02/19/06) a2 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST if a2 = 0 a2 = a1 end if (ts(a2,SUBFLAG_1) & 0xf00000) <> (ts(a1,SUBFLAG_1) & 0xf00000) goto ISO_DONE end end repeat First check to see if the entire measure is isorhythmic. This will save time in the end, and is also necessary in determining whether or not to eliminate duplicate rests. There are some caviats here: (1) Notes with lower pass numbers must always be unison or higher on the staff (2) All stem directions must be the same (for a particular division) REMOVED (3) All beam flags for notes from each pass must be identical. (4) Every division must have a representative from each pass. These must be either all notes or all rests. /* %%% add code here for disabling isorhythmic compression loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST loop for a2 = a1 + 1 to sct if ts(a2,DIV) <> ts(a1,DIV) or ts(a2,SPACING) <> 0 goto JOL1 end if nodtype = REST or nodtype = CUE_REST if ts(a2,TYPE) <> nodtype goto JOL1 end else if ts(a2,TYPE) <> nodtype and ts(a2,TYPE) <> nodtype + 1 goto JOL1 end end repeat JOL1: --a2 if a2 - a1 + 1 < passnum goto ISO_FAIL end a4 = 0 a5 = 0 a6 = ts(a1,PASSNUM) a7 = 1000 loop for a3 = a1 to a2 if ts(a3,CLAVE) < 100 if ts(a3,STAFF_NUM) <> ts(a1,STAFF_NUM) goto ISO_FAIL end if bit(1,ts(a3,STEM_FLAGS)) <> bit(1,ts(a1,STEM_FLAGS)) goto ISO_FAIL end if ts(a3,BEAM_FLAG) <> ts(a1,BEAM_FLAG) goto ISO_FAIL end if bit(0,ts(a3,SUPER_FLAG)) <> bit(0,ts(a1,SUPER_FLAG)) /* ties goto ISO_FAIL end if bit(2,ts(a3,STEM_FLAGS)) = 0 /* number of "events" ++a4 end if ts(a3,PASSNUM) = a6 /* order of pitches */ if ts(a3,CLAVE) < a7 a7 = ts(a3,CLAVE) end else if ts(a3,CLAVE) > a7 goto ISO_FAIL end a6 = ts(a3,PASSNUM) a7 = ts(a3,CLAVE) end else ++a5 end repeat if a4 = 0 if a5 <> passnum goto ISO_FAIL end else if a4 <> passnum or a5 > 0 goto ISO_FAIL end end a1 = a2 end repeat The measure meets the conditions of isorhythmic compression. Here is what we must do: (1) Rests: Delete duplicate rests. Do this all at one time, since this involves resizing the ts array. Note on this: I don't think autoscr actually wants to delete rests, but rather to make them "silent." To do otherwise might remove time from a track. (2) Notes--situation 1: Note not connected to a beam New condition 12/20/05: If stem_change_flag < 3, then do the steps below only if the stem directions are the same. If no unison and no chords in separate parts, then combine all pitches into one chord If separate stem directions do not agree, determine best direction; otherwise use common direction TYPE: for each note group, make first type 1,4,7 and all others 2,5,8 STEM_FLAGS: set all bit2's; set all bit3's for all but first member of group BEAM_FLAG: zero for all but first member of chord group BEAM_CODE: zero for all but first member of chord group PASSNUM: equal to PASSNUM for first member of group Otherwise, set the stem direction for the upper pass to up and for the lower pass to down. (3) Notes--situation 2: Note is connected to a beam For all notes on that beam determine if there are any unisons or any chords in separate chords. If no unisons and no chords, then combine all pitches into one chord If separate stem directions do not agree, determine best direction; otherwise use common direction TYPE: for each note group, make first type 1,4,7 and all others 2,5,8 STEM_FLAGS: set all bit2's; set all bit3's for all but first member of group BEAM_FLAG: zero for all but first member of chord group BEAM_CODE: zero for all but first member of chord group PASSNUM: equal to PASSNUM for first member of group If unisons, then set the stem direction for the upper pass to up and for the lower pass to down. (4) If all notes in measure were combined into chords, then decrease passnum by amount of largest PASSNUM + 1 / 2 (1) Rests: Delete duplicate rests a1 = oldsct+1 COMPRESS1: nodtype = ts(a1,TYPE) if (nodtype = REST or nodtype = CUE_REST) and rest_collapse = TRUE loop for a2 = a1 + 1 to sct if ts(a2,DIV) <> ts(a1,DIV) or ts(a2,TYPE) <> nodtype goto JOL2 end repeat JOL2: #if AUTOSCR This section of code different from AUTOSET if a2 > a1 + 1 /* a2 points beyond last dup. rest if nodtype = CUE_REST a5 = a1 + 1 loop for a3 = a2 to sct loop for a4 = 1 to TS_SIZE ts(a5,a4) = ts(a3,a4) repeat ++a5 repeat loop for a4 = 1 to TS_SIZE /* 1/30/96 clear last ts(.,.) line ts(sct,a4) = 0 repeat sct -= a2 - a1 - 1 else loop for a4 = a1 + 1 to a2 - 1 if chr(ts(a4,CLAVE)) in [100,101,200] ts(a4,CLAVE) = 200 ts(a4,PASSNUM) = ts(a1,PASSNUM) /* I hope this works ???? else dputc Program Error: rest found whose CLAVE was improperly set. stop end repeat a1 += (a2 - a1 - 1) /* move a1 to last dup. rest end end #else This section of code different from AUTOSCR if a2 > a1 + 1 /* do this only if another rest is found a5 = a1 + 1 loop for a3 = a2 to sct loop for a4 = 1 to TS_SIZE ts(a5,a4) = ts(a3,a4) repeat ++a5 repeat loop for a4 = 1 to TS_SIZE /* 1/30/96 clear last ts(.,.) line ts(sct,a4) = 0 repeat sct -= a2 - a1 - 1 end #endif end ++a1 if a1 <= sct goto COMPRESS1 end (2) (3) Notes-- situations 1 and 2 a16 = 0 /* New 12/20/05 and be careful not to modify this in other parts of AUTOSET a15 = 0 /* New 12/20/05 a10 = 0 a5 = 0 a6 = 0 a7 = 0 a8 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE or nodtype = CUE_NOTE or nodtype = GR_NOTE loop for a2 = a1 + 1 to sct if ts(a2,DIV) <> ts(a1,DIV) or ts(a2,SPACING) <> 0 goto JOL3 end repeat while ts(a2,TYPE) = nodtype or ts(a2,TYPE) = nodtype + 1 JOL3: --a2 Move all dynamics for notes on same division to first note (because it is easy to do at this point) (12/20/05 moving this code inside processing loop) a4 = 0 a7 = 0 /* New 05/17/03 loop for a3 = a1 to a2 a4 |= ts(a3,SUBFLAG_1) & 0x3c00 /* 0000 0000 0011 1100 0000 0000 ts(a3,SUBFLAG_1) &= 0xffc3ff /* 1111 1111 1100 0011 1111 1111 a7 |= ts(a3,ED_SUBFLAG_1) & 0x3c00 /* 0000 0000 0011 1100 0000 0000 05/17/03 ts(a3,ED_SUBFLAG_1) &= 0xffc3ff /* 1111 1111 1100 0011 1111 1111 05/17/03 repeat ts(a1,SUBFLAG_1) |= a4 ts(a1,ED_SUBFLAG_1) |= a7 /* New 05/17/03 Remove duplicate fermatas for notes on same division (because it is easy to do at this point) a4 = ts(a1,SUBFLAG_1) & 0x0080 /* 0000 0000 0000 0000 1000 0000 a7 = ts(a1,ED_SUBFLAG_1) & 0x0080 /* 0000 0000 0000 0000 1000 0000 05/17/03 loop for a3 = a1 + 1 to a2 if ts(a3,SUBFLAG_1) & 0x0080 = a4 /* 1 1111 1111 1111 1111 1111 0111 1111 "1 1111 " added 04/22/08 and 10/08/08 ts(a3,SUBFLAG_1) &= 0x1fffff7f end if ts(a3,ED_SUBFLAG_1) & 0x0080 = a7 /* New 05/17/03 /* 1 1111 1111 1111 1111 1111 0111 1111 "1 1111 " added 04/22/08 and 10/08/08 ts(a3,ED_SUBFLAG_1) &= 0x1fffff7f end repeat if a2 - a1 + 1 > passnum a7 = 1 /* chords are present on this division end Determine if there is a unison in this group if a7 = 0 if a7 = 0 and stem_change_flag = 3 /* New condition 12/20/05 loop for a3 = a1 + 1 to a2 if ts(a3,CLAVE) = ts(a3-1,CLAVE) a7 = 1 end repeat end if a16 = 0 loop for a3 = a1 + 1 to a2 if bit(1,ts(a3,STEM_FLAGS)) <> bit(1,ts(a1,STEM_FLAGS)) a8 = 1 /* conflicting stem directions end repeat end if ts(a1,BEAM_FLAG) <> 0 /* this note is on a beam a15 = 1 /* New 12/20/05 "beam flag" if ts(a1,BEAM_FLAG) = START_BEAM a16 = a1 /* index starts (first/top) beam end if ts(a1,BEAM_FLAG) = END_BEAM a16 += INT10000 /* beams end; now use saved value of a1 from above end else a16 = a1 + INT10000 /* "no beam" case end if a16 > INT10000 /* process notes here a16 -= INT10000 /* recover value of starting "a1" New condition 12/20/05: If stem_change_flag < 3, then (for non-beam case) do steps below only if the stem directions are the same. (i.e., when a15 = 0, a8 must be zero, if stem_change_flag < 3) if a15 = 0 /* no beam if stem_change_flag < 3 and a8 = 1 a10 = 1 /* New condition 12/20/05 goto NO_STEM_CHANGE end end At this point: either a15 = 1 (this is a beamed group or set of beamed groups) or stem_change_flag = 3 (old code situation) or a8 = 0 (all stems point the same way) Case 1: either a unison between passes or a chord on one of the passes (note: in order for a unison to trigger this case, stem_change_flag must = 3 otherwise, unisons will fall into case 2 if a7 = 1 New 12/20/05 change stem directions only of stem_change_flag = 3 if stem_change_flag = 3 loop for a3 = a16 to a2 /* all notes inclusive a7 = ts(a3,TYPE) if a7 <= NOTE_OR_REST and a7 <> REST and a7 <> CUE_REST if ts(a3,PASSNUM) = ts(a16,PASSNUM) ts(a3,STEM_FLAGS) &= 0xfffd /* stem up for upper pass else ts(a3,STEM_FLAGS) |= 0x0002 /* stem down for lower pass end end repeat end a10 = 1 else Old Case 2: no unisons, no chords -- combine passes in one chord (and stem_change_flag = 3) 12/20/05 Case 2: no chords -- combine passes in one chord (note: unisons may fall into this case if stem_change_flag < 3) if a8 = 1 and stem_change_flag < 3 /* New condition 12/20/05 a10 = 1 goto NO_STEM_CHANGE end if a8 = 1 /* determine stem direction a8 = 0 loop for a3 = a16 to a2 a7 = ts(a3,TYPE) if a7 <= NOTE_OR_REST and a7 <> REST and a7 <> CUE_REST a8 += ts(a3,STAFFLOC) end repeat a8 <<= 1 a8 /= notesize a9 = a2 - a16 + 1 a8 += a9 + 1 / 2 a8 /= a9 if a8 >= 5 a9 = UP else a9 = DOWN end else a9 = bit(1,ts(a16,STEM_FLAGS)) end a11 = 0 a12 = 0 loop for a3 = a16 to a2 /* put all notes into chords a7 = ts(a3,TYPE) if a7 <= NOTE_OR_REST and a7 <> REST and a7 <> CUE_REST ts(a3,STEM_FLAGS) &= 0xfffd /* prepare for new stem direction ts(a3,STEM_FLAGS) |= a9 << 1 Also move all dynamics for notes on same division to first note (This is correct place to do this operation 12/20/05) This code uses a4, a6 and a14 in a temporary manner if ts(a3,DIV) <> a11 or ts(a3,SPACING) <> 0 or a12 <> a7 or a3 = a16 a12 = a7 a11 = ts(a3,DIV) ts(a3,STEM_FLAGS) |= 0x04 a8 = a3 Collect dynamics data for this note (a3) 12/20/05 /* 1 1100 0000 0000 0011 1100 0000 0000 "1 1100 " added 10/08/08 a4 = ts(a3,SUBFLAG_1) & 0x1c003c00 /* 1 1100 0000 0000 0011 1100 0000 0000 "1 1100 " added 10/08/08 a6 = ts(a3,ED_SUBFLAG_1) & 0x1c003c00 else ts(a3,TYPE) = ts(a8,TYPE) + 1 ts(a3,STEM_FLAGS) |= 0x0c ts(a3,BEAM_FLAG) = 0 ts(a3,BEAM_CODE) = 0 if ts(a3,PASSNUM) > a5 a5 = ts(a3,PASSNUM) /* save max passnum end ts(a3,PASSNUM) = ts(a8,PASSNUM) Merge dynamics data with data for first (a8) note /* 1 1100 0000 0000 0011 1100 0000 0000 "1 1100 " added 10/08/08 a4 |= ts(a3,SUBFLAG_1) & 0x1c003c00 /* 1 1100 0000 0000 0011 1100 0000 0000 "1 1100 " added 10/08/08 a6 |= ts(a3,ED_SUBFLAG_1) & 0x1c003c00 Turn off dynamics data for this note (a3) /* 0 0011 1111 1111 1100 0011 1111 1111 "0 0011 " added 04/22/08 and 10/08/08 ts(a3,SUBFLAG_1) &= 0x1fffc3ff /* 0 0011 1111 1111 1100 0011 1111 1111 "0 0011 " added 04/22/08 and 10/08/08 ts(a3,ED_SUBFLAG_1) &= 0x1fffc3ff Add in (new) dynamics data to first (a8) note ts(a8,SUBFLAG_1) |= a4 ts(a8,ED_SUBFLAG_1) |= a6 The following code is untested, and may cause problems. Note: 10/28/07 it has! I will make some changes that fix a definite bug, but there may still be other problems. a14 = ts(a3,TSR_POINT) /* combine tsr strings tbit2 = cbi(tsr(a14)) a14 = ts(a8,TSR_POINT) tbit1 = cbi(tsr(a14)) tbit1 = bor(tbit1,tbit2) tsr(a14) = cby(tbit1) c4 = ts(a3,TSR_POINT) c5 = ts(a8,TSR_POINT) /* byte 1 c6 = ors(tsr(c4){1}) & 0xff c7 = ors(tsr(c5){1}) & 0xff c7 |= c6 tsr(c5){1} = chr(c7) /* byte 2 c6 = ors(tsr(c4){2}) & 0xff c7 = ors(tsr(c5){2}) & 0xff c7 |= c6 tsr(c5){2} = chr(c7) /* byte 3 = x offset (modification by suggestion) c6 = ors(tsr(c4){3}) & 0xff c7 = ors(tsr(c5){3}) & 0xff if c6 <> c7 putc WARNING at approximate measure number ~(measnum - 1) putc putc You have asked autoset/scr to combine into a chord two putc pitches which have different x offsets. This will be done, but putc the results are unpredictable. Note combination usually arrises putc when two instruments occupy the same staff (multi track) and have putc simultaneous notes with the same stem direction. If you really putc want different x offsets, you should make the stem directions on putc these notes different. putc end tsr(c5){3} = chr(c7) /* byte 4 = y offset (modification by suggestion) c6 = ors(tsr(c4){4}) & 0xff c7 = ors(tsr(c5){4}) & 0xff if c6 <> c7 putc WARNING at approximate measure number ~(measnum - 1) putc putc You have asked autoset/scr to combine into a chord two putc pitches which have different y offsets. This will be done, but putc the results are unpredictable. Note combination usually arrises putc when two instruments occupy the same staff (multi track) and have putc simultaneous notes with the same stem direction. If you really putc want different x offsets, you should make the stem directions on putc these notes different. putc end tsr(c5){4} = chr(c7) c7 = TSR_LENG a14 = ts(a3,TSR_POINT) /* combine tsr strings tbit2 = cbi(tsr(a14){5..}) a14 = ts(a8,TSR_POINT) tbit1 = cbi(tsr(a14){5..}) tbit1 = bor(tbit1,tbit2) tsr(a14){5..c7} = cby(tbit1) End of 10/28/07 modifications End of dynamics merge process (moved here 12/20/05) end end repeat end NO_STEM_CHANGE: a16 = 0 a7 = 0 a8 = 0 a15 = 0 /* New 12/20/05 end a1 = a2 end repeat (4) If all notes in measure were combined into chords, then Adjust PASSNUM for all nodes and decrease passnum by amount of largest PASSNUM + 1 / 2 (not fully implemented) if a10 = 0 if a5 > 2 putc This program may have problems with more than putc two separate instruments on a staff line end loop for a1 = oldsct+1 to sct ts(a1,PASSNUM) = 1 repeat passnum = 1 end goto ISO_DONE ISO_FAIL: loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST and ts(a1,BEAM_FLAG) = NO_BEAM a4 = ts(a1,DIV) /* test note a5 = ts(a1,NOTE_DUR) a6 = bit(1,ts(a1,STEM_FLAGS)) a7 = ts(a1,STAFF_NUM) if nodtype = NOTE or nodtype = CUE_NOTE loop for a3 = a1+1 to sct if ts(a3,DIV) = a4 if ts(a3,TYPE) = nodtype and ts(a3,NOTE_DUR) = a5 if bit(1,ts(a3,STEM_FLAGS)) = a6 and ts(a3,BEAM_FLAG) = NO_BEAM if ts(a3,STAFF_NUM) = a7 Move this to be part of a chord on test note a9 = a1+1 perform rotate_array (a9,a3) ts(a9,TYPE) = nodtype + 1 /* chord note ts(a9,STEM_FLAGS) |= 0x0c ts(a1,STEM_FLAGS) |= 0x04 /* make note at a1 "first" in chord 1/30/96 ts(a9,PASSNUM) = ts(a1,PASSNUM) end end end else a3 = sct end repeat end if nodtype = GR_NOTE a8 = ts(a1,NTYPE) loop for a3 = a1+1 to sct if ts(a3,DIV) = a4 if ts(a3,TYPE) = GR_NOTE and ts(a3,NTYPE) = a8 and ts(a3,SPACING) = 0 if bit(1,ts(a3,STEM_FLAGS)) = a6 and ts(a3,BEAM_FLAG) = NO_BEAM if ts(a3,STAFF_NUM) = a7 Move this to be part of a chord on test note a9 = a1+1 perform rotate_array (a9,a3) ts(a9,TYPE) = XGR_NOTE ts(a9,STEM_FLAGS) |= 0x0c ts(a1,STEM_FLAGS) |= 0x04 /* make note at a1 "first" in chord 1/30/96 ts(a9,PASSNUM) = ts(a1,PASSNUM) end end end else a3 = sct end repeat end end repeat New code 10/14/07 Without wrecking what already works with autoset, I will now attempt to combine groups of notes under the same beam for the case where there is a third "silent" track or other disruptive objects. #if AUTOSCR loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE and ts(a1,BEAM_FLAG) = START_BEAM a4 = ts(a1,DIV) /* test note a5 = ts(a1,NOTE_DUR) a6 = bit(1,ts(a1,STEM_FLAGS)) a7 = ts(a1,STAFF_NUM) Question 1: Is there another note on this division? loop for c1 = a1 + 1 to sct if ts(c1,DIV) = a4 if ts(c1,TYPE) = NOTE goto BCOMA_1 end else a1 = c1 - 1 goto NO_BCOMA end repeat goto NO_BCOMA BCOMA_1: Question 2: Does this note have the proper characteristics? a2 = c1 if ts(a2,BEAM_FLAG) <> START_BEAM goto NO_BCOMA end if ts(a2,NOTE_DUR) <> a5 goto NO_BCOMA end if bit(1,ts(a2,STEM_FLAGS)) <> a6 goto NO_BCOMA end if ts(a2,STAFF_NUM) <> a7 goto NO_BCOMA end Setup fixup array beam_fixup_cnt = 1 beam_fixup_arr(1,1) = a1 beam_fixup_arr(1,2) = a2 Go looking for other note pairs c3 = a2 BCOMA_4: loop for c1 = c3 + 1 to sct if ts(c1,TYPE) = NOTE goto BCOMA_2 end repeat goto NO_BCOMA BCOMA_2: loop for c2 = c1 + 1 to sct if ts(c2,TYPE) = NOTE goto BCOMA_3 end repeat goto NO_BCOMA Note pair found; check fit BCOMA_3: if ts(c1,BEAM_FLAG) = CONT_BEAM or ts(c1,BEAM_FLAG) = END_BEAM if ts(c2,BEAM_FLAG) <> ts(c1,BEAM_FLAG) goto NO_BCOMA end if ts(c2,DIV) <> ts(c1,DIV) or ts(c2,NOTE_DUR) <> ts(c1,NOTE_DUR) goto NO_BCOMA end if bit(1,ts(c1,STEM_FLAGS)) <> a6 or bit(1,ts(c2,STEM_FLAGS)) <> a6 goto NO_BCOMA end if ts(c1,STAFF_NUM) <> a7 or ts(c2,STAFF_NUM) <> a7 goto NO_BCOMA end ++beam_fixup_cnt beam_fixup_arr(beam_fixup_cnt,1) = c1 beam_fixup_arr(beam_fixup_cnt,2) = c2 if ts(c1,BEAM_FLAG) = CONT_BEAM c3 = c2 goto BCOMA_4 /* go look for more pairs end end Now move these notes to be part of chords on test notes loop for c3 = 1 to beam_fixup_cnt c1 = beam_fixup_arr(c3,1) c2 = beam_fixup_arr(c3,2) ts(c2,TYPE) = nodtype + 1 /* chord note ts(c2,STEM_FLAGS) |= 0x0c ts(c1,STEM_FLAGS) |= 0x04 ts(c2,PASSNUM) = ts(c1,PASSNUM) ts(c1,SUBFLAG_1) |= ts(c2,SUBFLAG_1) /* 02-11-96 move subflags to main note ts(c2,SUBFLAG_1) = 0 /* this may cause problems ts(c1,ED_SUBFLAG_1) |= ts(c2,ED_SUBFLAG_1) /* New 05/17/03 ts(c2,ED_SUBFLAG_1) = 0 ts(c1,SUBFLAG_2) |= ts(c2,SUBFLAG_2) /* New 05/17/03 ts(c2,SUBFLAG_2) = 0 ts(c1,ED_SUBFLAG_2) |= ts(c2,ED_SUBFLAG_2) /* New 05/17/03 ts(c2,ED_SUBFLAG_2) = 0 repeat a1 = c2 end NO_BCOMA: repeat End of 10/14/07 New code #else New code 1/30/96 to look for cases where groups of notes might be combined under the same beam. At the moment, this works only with two parts and with regular notes. loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE and ts(a1,BEAM_FLAG) = START_BEAM a4 = ts(a1,DIV) /* test note a5 = ts(a1,NOTE_DUR) a6 = bit(1,ts(a1,STEM_FLAGS)) a7 = ts(a1,STAFF_NUM) a2 = a1 + 1 if ts(a2,TYPE) = NOTE and ts(a2,BEAM_FLAG) = START_BEAM if ts(a2,DIV) = a4 and ts(a2,NOTE_DUR) = a5 if bit(1,ts(a2,STEM_FLAGS)) = a6 and ts(a2,STAFF_NUM) = a7 c1 = a1 + 2 c2 = a2 + 2 loop while ts(c1,BEAM_FLAG) = CONT_BEAM or ts(c1,BEAM_FLAG) = END_BEAM if ts(c2,BEAM_FLAG) <> ts(c1,BEAM_FLAG) goto NO_BCOM end if ts(c1,TYPE) <> NOTE or ts(c2,TYPE) <> NOTE goto NO_BCOM end if ts(c2,DIV) <> ts(c1,DIV) or ts(c2,NOTE_DUR) <> ts(c1,NOTE_DUR) goto NO_BCOM end if bit(1,ts(c1,STEM_FLAGS)) <> a6 or bit(1,ts(c2,STEM_FLAGS)) <> a6 goto NO_BCOM end if ts(c1,STAFF_NUM) <> a7 or ts(c2,STAFF_NUM) <> a7 goto NO_BCOM end c1 += 2 c2 += 2 repeat c1 -= 2 c2 -= 2 if ts(c1,BEAM_FLAG) <> END_BEAM or ts(c2,BEAM_FLAG) <> END_BEAM goto NO_BCOM end Move these notes to be part of chords on test notes loop for c3 = a1 to c1 step 2 a9 = c3 + 1 ts(a9,TYPE) = nodtype + 1 /* chord note ts(a9,STEM_FLAGS) |= 0x0c ts(c3,STEM_FLAGS) |= 0x04 ts(a9,PASSNUM) = ts(c3,PASSNUM) ts(c3,SUBFLAG_1) |= ts(a9,SUBFLAG_1) /* 02-11-96 move subflags to main note ts(a9,SUBFLAG_1) = 0 /* this may cause problems ts(c3,ED_SUBFLAG_1) |= ts(a9,ED_SUBFLAG_1) /* New 05/17/03 ts(a9,ED_SUBFLAG_1) = 0 ts(c3,SUBFLAG_2) |= ts(a9,SUBFLAG_2) /* New 05/17/03 ts(a9,SUBFLAG_2) = 0 ts(c3,ED_SUBFLAG_2) |= ts(a9,ED_SUBFLAG_2) /* New 05/17/03 ts(a9,ED_SUBFLAG_2) = 0 repeat a1 = a9 end end end end NO_BCOM: repeat #endif Check to see if the number of passes has been reduced (omitted for the moment; may not be necessary) ISO_DONE: end Make sure at this point that all chords are oriented with the top note first. Also, for each note (or set of notes = chord), compute the position of the note head at the end of the stem, and also compute the position of the end of the stem. Later, we will make a "best guess" about what the beam height for those notes belonging to a beam. Store the note position in VIRT_NOTE (for all notes of the chord) and the stem position in VIRT_STEM (for all notes of the chord) loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if chr(nodtype) in [NOTE,CUE_NOTE,GR_NOTE] if bit(2,ts(a1,STEM_FLAGS)) = 1 /* This is a chord a5 = ts(a1,STEM_FLAGS) & 0x03 /* save lower two bits a2 = a1 + 1 loop while ts(a2,TYPE) = nodtype + 1 ++a2 repeat --a2 /* a2 = last note in chord Bubble sort loop for a3 = a1 to a2-1 loop for a4 = a3 to a2 if ts(a3,CLAVE) < ts(a4,CLAVE) loop for a7 = 2 to TS_SIZE /* keep primary type on top if a7 <> BEAM_FLAG and a7 <> BEAM_CODE /* and don't move beam flags, etc. ts(sct+1,a7) = ts(a3,a7) /* make hole for new element ts(a3,a7) = ts(a4,a7) /* move in new element ts(a4,a7) = ts(sct+1,a7) /* put old element in vacancy end repeat end repeat repeat Rewrite stem flags loop for a3 = a1 to a2 if a3 = a1 ts(a3,STEM_FLAGS) = a5 + 0x04 /* turn bit 2 else ts(a3,STEM_FLAGS) = a5 + 0x0c /* turn bits 2 and 3 (01-31-97 added a5) end a4 = a3 - a1 + 1 << 4 ts(a3,STEM_FLAGS) += a4 /* note number in chord repeat else a2 = a1 end Put in y location of object, y location of end note head and (tentitive) y location of end of stem. if bit(1,ts(a1,STEM_FLAGS)) = UP a4 = ts(a1,STAFFLOC) a5 = ts(a2,STAFFLOC) a6 = ts(a1,STAFFLOC) if a6 >= vpar(5) c3 = vpar(7) else c3 = vpar(6) if ts(a1,NTYPE) > EIGHTH and a6 < 0 - vpar(1) c3 -= vpar(1) c3 = vpar(5) end end if nodtype <> NOTE and c3 > vpar(5) c3 -= vpar(1) if c3 = vpar(6) c3 = vpar(5) else c3 = vpar(6) end end a6 -= c3 a6 += vpar(1) /* FUDGE if a6 > vpar(5) a6 = vpar(5) end else a4 = ts(a2,STAFFLOC) a5 = ts(a1,STAFFLOC) a6 = ts(a2,STAFFLOC) if a6 <= vpar(3) if a6 <= vpar(4) /* 09/22/05 was vpar(3) c3 = vpar(7) else c3 = vpar(6) if ts(a1,NTYPE) > EIGHTH and a6 >= vpar(10) c3 -= vpar(1) c3 = vpar(5) end end if nodtype <> NOTE and c3 > vpar(5) c3 -= vpar(1) if c3 = vpar(6) c3 = vpar(5) else c3 = vpar(6) end end a6 += c3 a6 -= vpar(1) /* FUDGE if a6 < vpar(3) a6 = vpar(3) end end loop for a3 = a1 to a2 ts(a3,OBY) = a4 ts(a3,VIRT_NOTE) = a5 ts(a3,VIRT_STEM) = a6 repeat a1 = a2 /* advance index to last note of chord end repeat Now we can make a "best guess" about what the beam height for those notes (chords) belonging to a beam. Store the modified height (for all notes of the chord) in VIRT_STEM. loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if chr(nodtype) in [NOTE,CUE_NOTE,GR_NOTE] c5 = ts(a1,BEAM_FLAG) if c5 <> NO_BEAM c3 = ts(a1,PASSNUM) c4 = nodtype + 2 / 3 /* 1, 2, or 3 if c5 = START_BEAM passcnt(c3,c4) = 0 end ++passcnt(c3,c4) c6 = passcnt(c3,c4) beamdata(c4,c3,c6) = a1 /* index to this note if c5 = END_BEAM stem = bit(1,ts(a1,STEM_FLAGS)) c8 = 1 if stem = DOWN c8 = -1 end if c4 = 1 c5 = 0 else c5 = 1 end loop for c7 = 1 to c6 c1 = beamdata(c4,c3,c7) mf(c7) = ts(c1,OBY) /* vpar(7) * c8 + ts(c1,VIRT_STEM) beamcode(c7) = ts(c1,BEAM_CODE) repeat perform guessbeam (c10, c11) Put in "new" values for virtual stem position loop for c7 = 1 to c6 c9 = c7 - 1 * vpar(6) * c10 / BHPAR1 c1 = beamdata(c4,c3,c7) ts(c1,VIRT_STEM) = c11 + c9 repeat end end end repeat loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if chr(nodtype) in [XNOTE,XCUE_NOTE,XGR_NOTE] ts(a1,VIRT_STEM) = ts(a1-1,VIRT_STEM) end repeat If mcat = 2, decode all accidentals using a measax array which depends on the note position in a chord. if mcat = 2 /* %%% add code here for changing ax behavior loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a4 = ts(a1,STEM_FLAGS) >> 4 /* Note number in chord if a4 = 0 a4 = 1 end if a4 > 4 /* 06/04/08 was 3 putc This code will not work with more than 4 notes in chord examine stop end perform decodeax (a1,a4) end if nodtype = BAR_LINE loop for a3 = 1 to 50 loop for a4 = 1 to 4 /* 06/04/08 was 3 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat repeat end if nodtype = CLEF_CHG a4 = ts(a1,STAFF_NUM) + 1 /* staff number clef(a4) = ts(a1,CLEF_NUM) perform zjcline (a4) * this resets clef and cline ts(a1,CLEF_FONT) += z /* music font ts(a1,TRANS_FLAG) = k ts(a1,CLEF_STAFF_POS) = 5 - j * notesize a3 = hpar(8) * 5 / 6 /* Added 06-24-94 if ts(a1,CLEF_FONT) > 128 /* music font a3 = a3 * 8 / 10 end ts(a1,SPACING) = a3 if nstaves > 1 /* Case: assume one part to stave (usual case) loop for a3 = 1 to 50 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat else loop for a4 = 1 to 4 /* 06/04/08 was 3 loop for a3 = 1 to 50 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat repeat end end repeat end Decode all accidentals for all other cases if mcat < 2 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a4 = ts(a1,STAFF_NUM) + 1 /* staff number perform decodeax (a1,a4) end if nodtype = BAR_LINE loop for a3 = 1 to 50 loop for a4 = 1 to 4 /* 06/04/08 was 3 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat repeat end if nodtype = CLEF_CHG a4 = ts(a1,STAFF_NUM) + 1 /* staff number clef(a4) = ts(a1,CLEF_NUM) perform zjcline (a4) * this resets clef and cline ts(a1,CLEF_FONT) += z /* music font ts(a1,TRANS_FLAG) = k ts(a1,CLEF_STAFF_POS) = 5 - j * notesize a3 = hpar(8) * 5 / 6 /* Added 06-24-94 if ts(a1,CLEF_FONT) > 128 /* music font a3 = a3 * 8 / 10 else a3 = a3 * 6 / 5 /* Added 12/09/03 as a cludge end ts(a1,SPACING) = a3 loop for a3 = 1 to 50 measax(a4,a3) = claveax(a3) measax(a4,a3) = tclaveax(a3) /* New 12/14/07 repeat end repeat end Now remove all places where accidentals have been placed twice on the same line as a result of multiple parts playing the same altered note. This code added 09/22/93 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST loop for a2 = a1 + 1 to sct repeat while ts(a2,SPACING) = 0 and ts(a2,DIV) = ts(a1,DIV) and ts(a2,TYPE) <= NOTE_OR_REST --a2 if a2 > a1 loop for a3 = a1 to a2 if ts(a3,AX) > 0 loop for a4 = a3 + 1 to a2 if ts(a4,STAFF_NUM) = ts(a3,STAFF_NUM) if ts(a4,CLAVE) = ts(a3,CLAVE) if ts(a4,AX) = ts(a3,AX) ts(a4,AX) = 0 end end end repeat end repeat end a1 = a2 end repeat Set backtie for division 1 elements in the ts() array. If this is the measure in a group of measures, then BACKTIE for division 1 will point to a ROW element of tiearr, otherwise (2) BACKTIE for division 1 will point to the ts() ROW element that originated the tie. loop for a1 = 1 to MAX_TIES if tiearr(a1,TIE_SNUM) > 0 and tiearr(a1,TIE_FOUND) = 0 Case 1: division 1 of first measure in group if oldsct = 0 loop for a2 = 1 to sct if ts(a2,DIV) = 1 a3 = tiearr(a1,TIE_NTYPE) a4 = ts(a2,TYPE) xbyte = chr(a3) // chr(a4) if ts(a2,STAFFLOC) = tiearr(a1,TIE_VLOC) if ts(a2,STAFF_NUM) = tiearr(a1,TIE_STAFF) if ts(a2,BACKTIE) = 0 if xbyte in [NOTE,XNOTE] /* i.e., both a3 and a4 are in set ts(a2,BACKTIE) = a1 + INT10000 /* backtie = tie number goto TS1 end if xbyte in [CUE_NOTE,XCUE_NOTE] ts(a2,BACKTIE) = a1 + INT10000 /* backtie = tie number goto TS1 end end end end end repeat return 3 else Case 2: division 1 for subsequent measures in group loop for a2 = oldsct+1 to sct if ts(a2,DIV) = 1 a3 = tiearr(a1,TIE_NTYPE) a4 = ts(a2,TYPE) xbyte = chr(a3) // chr(a4) if ts(a2,STAFFLOC) = tiearr(a1,TIE_VLOC) if ts(a2,STAFF_NUM) = tiearr(a1,TIE_STAFF) if xbyte in [NOTE,XNOTE] /* i.e., both a3 and a4 are in set ts(a2,BACKTIE) = tiearr(a1,TIE_NDX) /* backtie = ts index tiearr(a1,TIE_SNUM) = 0 /* free-up this ROW element of tiearr goto TS1 end if xbyte in [CUE_NOTE,XCUE_NOTE] ts(a2,BACKTIE) = tiearr(a1,TIE_NDX) /* backtie = ts index tiearr(a1,TIE_SNUM) = 0 /* free-up this ROW element of tiearr goto TS1 end end end end repeat return 3 end TS1: tiearr(a1,TIE_FOUND) = 1 end repeat Set backtie for all non-division-1 elements in the ts() array. loop for a1 = oldsct+1 to sct Special case: Grace note tied to a regular note on the same division 11/02/05 if chr(ts(a1,TYPE)) in [GR_NOTE,XGR_NOTE] if bit(0,ts(a1,SUPER_FLAG)) = 1 and a1 < sct /* tie present a4 = ts(a1,DIV) loop for a2 = a1+1 to sct if ts(a2,DIV) = a4 if ts(a1,STAFF_NUM) = ts(a2,STAFF_NUM) if ts(a1,STAFFLOC) = ts(a2,STAFFLOC) if chr(ts(a2,TYPE)) in [NOTE,XNOTE] ts(a2,BACKTIE) = a1 /* Case: backtie = ts index to first note goto SEARCH_DONE end end end else a2 = 1000000 end repeat end end End of 11/02/05 special case if chr(ts(a1,TYPE)) in [NOTE,XNOTE,CUE_NOTE,XCUE_NOTE] if bit(0,ts(a1,SUPER_FLAG)) = 1 and a1 < sct /* tie present a4 = ts(a1,DIV) + ts(a1,NOTE_DUR) Try it first where pass numbers must be the same (usual case) loop for a2 = a1+1 to sct if ts(a2,DIV) = a4 and ts(a1,PASSNUM) = ts(a2,PASSNUM) if ts(a1,STAFFLOC) = ts(a2,STAFFLOC) if chr(ts(a1,TYPE)) in [NOTE,XNOTE] if chr(ts(a2,TYPE)) in [NOTE,XNOTE] ts(a2,BACKTIE) = a1 /* Case: backtie = ts index to first note goto SEARCH_DONE end else if chr(ts(a2,TYPE)) in [CUE_NOTE,XCUE_NOTE] ts(a2,BACKTIE) = a1 /* Case: backtie = ts index to first note goto SEARCH_DONE end end end end repeat Now try it where pass numbers need not be the same (unusual case) loop for a2 = a1+1 to sct if ts(a2,DIV) = a4 if ts(a1,STAFFLOC) = ts(a2,STAFFLOC) if chr(ts(a1,TYPE)) in [NOTE,XNOTE] if chr(ts(a2,TYPE)) in [NOTE,XNOTE] ts(a2,BACKTIE) = a1 /* Case: backtie = ts index to first note goto SEARCH_DONE end else if chr(ts(a2,TYPE)) in [CUE_NOTE,XCUE_NOTE] ts(a2,BACKTIE) = a1 /* Case: backtie = ts index to first note goto SEARCH_DONE end end end end repeat If you reach this point (i.e., you have not found a terminating note), then you must use the tiearr to temporarily store the information about this note for future reference. This info must be discarded before the final processing of the ts() array. * identify free slice of tiearr loop for c7 = 1 to MAX_TIES if tiearr(c7,TIE_SNUM) = 0 goto XXX2 end repeat Here is where the pseudo tiearr is built XXX2: tiearr(c7,TIE_SNUM) = INT1000000 /* pseudo super number tiearr(c7,TIE_NTYPE) = ts(a1,TYPE) tiearr(c7,TIE_VLOC) = ts(a1,STAFFLOC) tiearr(c7,TIE_NDX) = a1 tiearr(c7,TIE_STAFF) = ts(a1,STAFF_NUM) tiearr(c7,TIE_FOUND) = 0 tiearr(c7,TIE_FORCE) = ts(a1,SLUR_FLAG) >> 24 /* 04/20/03: New code c6 = ts(a1,TSR_POINT) tiearr(c7,TIE_SUGG) = ors(tsr(c6){69,4}) end end SEARCH_DONE: repeat Determine space parameter for notes and figures (and isolated signs, words and marks) loop for a1 = 1 to 120 mf(a1) = 0 repeat a9 = 0 divspq = olddivspq inctype_rem = 0 /* Code added 02/24/97 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = DIV_CHG mdiv = ts(a1,DIV) divspq = ts(a1,DIVSPQ) end if nodtype = METER_CHG perform newnsp end if nodtype > NOTE_OR_REST and nodtype <> FIGURES if chr(nodtype) in [SIGN,WORDS,MARK] and ts(a1,ISOLATED) = 1 else goto TS3 end end if chr(nodtype) not_in [XNOTE,XCUE_NOTE,XGR_NOTE] if nodtype = GR_NOTE goto TS3 /* grace note spacing has already been computed. see GRACE end determine space and duration for this note/figure if nodtype <= NOTE_OR_REST a5 = a1 perform getspace a7 = a6 a8 = ts(a1,NOTE_DUR) Code added 05-29-94 We cannot allow a8 to be less than time distance to the next division. Code added 06-18-94 We also cannot allow a8 to be more than the time distance to the next division, if the next division contains an isolated sign, words, or mark. loop for a2 = a1+1 to sct a3 = ts(a2,DIV) - ts(a1,DIV) if a3 > 0 if a3 > a8 a8 = a3 end if chr(ts(a2,TYPE)) in [SIGN,WORDS,MARK] and ts(a2,ISOLATED) = 1 if a3 < a8 a8 = a3 end end a2 = sct end repeat else case 2: figures (and isolated signs, words, and marks) 1) determine duration (given or implied) if nodtype = FIGURES and ts(a1,FIG_DUR) > 0 a8 = ts(a1,FIG_DUR) else if figure is not isolated, adopt a duration, else impute duration if a1 <> sct loop for a11 = a1+1 to sct if ts(a11,DIV) = ts(a1,DIV) if ts(a11,TYPE) <= NOTE_OR_REST a8 = ts(a11,NOTE_DUR) goto TS4 end else isolated figure in middle of data a8 = ts(a11,DIV) - ts(a1,DIV) goto TS4 end repeat end isolated figure at end of data a8 = divspq end 2) compute space for this duration TS4: a10 = a8 a) adjust duration for triplet a12 = 0 a11 = divspq / 3 if rem = 0 a11 = a10 / 3 if rem > 0 a10 = a10 * 3 / 2 a12 = 1 end end b) find index into space parameter array a11 = 35 - a12 a12 = divspq * 16 loop a13 = a10 / a12 a12 >>= 1 a11 -= 3 repeat while a13 = 0 if rem > 0 ++a11 end a7 = nsp(a11) end a14 = a7 notes and figures re-unified at this point in program a7 = space for first note/figure in node a8 = duration for first note/figure in node a14 = largest space for shortest full duration on this division (initially a14 = a7) ++a9 ts(oldsct+a9,TEMP1) = a7 ts(oldsct+a9,TEMP2) = a8 mf(a9) = a8 proceeding from this point, we have only regular and cue notes, rests and chords on this division if a1 < sct loop for a2 = a1+1 to sct if ts(a2,DIV) <> ts(a1,DIV) --a2 goto TS2 else a11 = ts(a2,TYPE) if a11 <> XNOTE and a11 <> XCUE_NOTE a5 = a2 perform getspace a15 = ts(a2,NOTE_DUR) 12/04/05 This code moved from below (before modifying a15) ++a9 mf(a9) = a15 if a15 < a8 /* modified 3/20/94 a7 = a6 a14 = a7 Code added 05-29-94 We cannot allow the "time-space increment" to be less than the time distance to the next division. loop for a3 = a2+1 to sct if ts(a3,DIV) <> ts(a1,DIV) a15 = ts(a3,DIV) - ts(a1,DIV) a8 = a15 a3 = sct end repeat else if a15 = a8 if a6 < a7 a7 = a6 end if a6 > a7 a14 = a6 end end end 12/04/05 Moving this code to a point before a15 is modified ++a9 mf(a9) = a15 ts(oldsct+a9,TEMP1) = a6 ts(oldsct+a9,TEMP2) = a15 end end repeat a2 = sct else a2 = a1 end a2 = pointer into set for last figure/note/rest/cue on this division a7 = smallest space for notes for shortest duration on this division a8 = duration of notes of shortest duration on this division a9 = total size of mf array (notes longer than smallest) a14 = largest space for shortest full duration on this division TS2: a4 = 10000 a5 = 10000 a6 = a7 loop for a3 = 1 to a9 if mf(a3) > 0 if mf(a3) < a4 a4 = mf(a3) end 07/01/03: Fixing this to account for irests with null space if ts(oldsct+a3,TEMP2) <= a5 if ts(oldsct+a3,TEMP2) < a5 a5 = ts(oldsct+a3,TEMP2) if ts(oldsct+a3,TEMP1) > 0 a6 = ts(oldsct+a3,TEMP1) end a6 = ts(oldsct+a3,TEMP1) end end repeat a4 = smallest number of divisions from left over notes a5 = duration of shortest note sounding at this point a6 = space parameter for this shortest note a4 < a8 means syncopation here also is where we set the increment distance flag. Since we are going to increment the distance, we know at this point what technique we will be using. ts(24) describes this technique. if a4 < a8 a7 = a6 * a4 / a5 a8 = a4 else a7 = a14 end a7 = space parameter for this node a8 = real duration of this node dv4 = 576 * a8 / divspq inctype_rem += rem /* Code added 02/24/97 if inctype_rem > (divspq / 2) inctype_rem -= divspq ++dv4 end /* End of 02/24/97 addition ts(a1,DINC_FLAG) = dv4 loop for a3 = 1 to a9 mf(a3) -= a8 if mf(a3) < 0 mf(a3) = 0 end repeat if chr(nodtype) in [SIGN,WORDS,MARK] ts(a1,SPACING) = a7 /* must be small, but non-zero else if nodtype <= NOTE_OR_REST ts(a1,SPACING) = a7 else if a1 = a2 ts(a1,FIG_SPACE) = a7 ts(a1,MIN_FIG_SPAC) = a7 else a6 = a1 + 1 if ts(a6,TYPE) <= NOTE_OR_REST ts(a6,SPACING) = a7 else return 8 end end end end a1 = a2 end TS3: repeat /* for debug purposes only if inctype_rem <> 0 putc Logical Problem with typeinc_rem putc Check it out! end Update olddivspq olddivspq = divspq if mdiv = totdiv /* added 1-27-93 This code is necessary qflag = 0 /* to cope with the situation where the end /* divisions-per-quarter is changed at the /* end of the measure * loop for a1 = 1 to a9 ts(oldsct+a1,TEMP1) = 0 ts(oldsct+a1,TEMP2) = 0 repeat Space parameter is initialized We have computed ts(24), the distance increment flag, for all regular/cue/figure nodes. This parameter is the time elaps between this node and the next node in the measure. It is measured in divisions, with 576 divisions being the equivalent of a quarter note. In the example below the notes are triplet eights and regular sixteenths respectively. The distances are listed by letter. :=======:=======: triplet 8ths | | | | a = 144 (reg 16th) @ @ @ O b = 48 / a /b/ c / d /e/ f / c = 96 @ @ @ @ O d = 96 sixteenths | | | | | e = 48 |_____|_____|_____| f = 144 (reg 16th) *=====*=====*=====* These parameters will be assigned to the first object in the node FOLLOWING THE DISTANCE, whatever it is. It might, for example, be a grace note, or some kind of sign. The first object in the node is the one where we can best describe the distance that has been traversed. In order to accomplish this, we do not set the inctype parameter until after the object containing the ts(24) parameter is processed. When spn rolls over to a new value, the object in question will be assigned the prior ts(24) parameter. tfirstsp = 0 *************************************************************** Debug Information g = measnum - 1 if bit(2,pmode) = 1 and g >= debug_point Condition changed 01/01/06 if (bit(2,pmode) = 1 or debug_flag = 1) and g >= debug_point putc Set Array at Point No. 1: measure ~g putc Look? getc jtype if jtype = "y" perform display_ts end end End debug information *************************************************************** Adjust accidentals for case where tie crosses bar line a10 = 1 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if ts(a1,DIV) = a10 and ts(a1,BACKTIE) > 0 if chr(nodtype) in [NOTE,XNOTE,CUE_NOTE,XCUE_NOTE] loop for a3 = a1+1 to sct if ts(a3,DIV) > a10 and ts(a3,TYPE) <= NOTE_OR_REST if ts(a3,CLAVE) = ts(a1,CLAVE) if ts(a3,STAFF_NUM) = ts(a1,STAFF_NUM) /* added 3-23-94 if ts(a3,AX) = 0 ts(a3,AX) = ts(a1,AX) end Now remove any similar accidentals which might have existed previously on this <pitch, staff, division> combination. loop for a4 = a3 + 1 to sct repeat while ts(a4,SPACING) = 0 and ts(a4,DIV) = ts(a3,DIV) and ts(a4,TYPE) <= NOTE_OR_REST --a4 loop for a5 = a3 + 1 to a4 if ts(a5,STAFF_NUM) = ts(a3,STAFF_NUM) if ts(a5,CLAVE) = ts(a3,CLAVE) if ts(a5,AX) = ts(a3,AX) ts(a5,AX) = 0 end end end repeat goto XD end end end repeat XD: if ts(a1,AX) > 0 if ts(a1,AX) > 0 and (ts(a1,SUBFLAG_1) & 0x040000) = 0 /* condition added 11/05/05 ts(a1,AX) |= 0x10 /* Code added 02/25/97. This is the "silent" flag end end end if nodtype = BAR_LINE /* non-controlling case a10 = ts(a1,DIV) end repeat We have a tiny chore to do here. In the case where we have a down-up pattern of stems on the same beam, we need to be sure the spacing between these notes is at least some minimum distance. (This code will work most of the time). a5 = hpar(4) * 4 / 5 + hpar(82) a4 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a3 = nodtype + 1 / 3 /* This code assumes if rem <> 0 /* XNOTE=2 XCUE_NOTE=5 XGR_NOTE=8 if ts(a1,SPACING) > 0 a4 = a1 /* save index to spacing number end end if nodtype = NOTE or nodtype = GR_NOTE or nodtype = CUE_NOTE if bit(1,ts(a1,STEM_FLAGS)) = UP c12 = ts(a1,BEAM_FLAG) if c12 = CONT_BEAM or c12 = START_BEAM a3 = 0 loop for a2 = a1 + 1 to sct if ts(a2,SPACING) > 0 ++a3 if a3 > 1 goto NEXTNOTE end end if ts(a2,TYPE) = nodtype if ts(a2,PASSNUM) = ts(a1,PASSNUM) if bit(1,ts(a2,STEM_FLAGS)) = DOWN if a4 = 0 putc Program error examine end if ts(a4,SPACING) < a5 ts(a4,SPACING) = a5 end end goto NEXTNOTE end end repeat end end end end NEXTNOTE: repeat Make space for text This is not an easy task to perform. I have tried a couple of methods already and am not too happy with them. Let me start by summarizing the objectives. 1) We want to underlay the text in as compact a way as possible The reason for this is that in the later stages of typesetting we almost always expand the music, so we want to start with as compact a version as possible. 2) We want the notes to be as true to their rythmic values as possible. 3) We need to preserve spacings attached to grace notes, clef signs, key changes, etc. a2 = firstoff a3 = hpar(37) + tfirstsp a11 = 0 c11 = 0 /* added 12/09/03 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE a8 = ts(a1,TEXT_INDEX) temp2 = trm(tsdata(a8)) temp2 = temp2 // pad(1) if temp2{1} in ['A'..'Z','a'..'z','!'..'(','\','='] New test for text data 09/01/03 c6 = 0 if temp2{1} in ['A'..'Z','a'..'z','!'..'(','\','='] c6 = 1 else temp2 = temp2 // " " loop for c7 = 1 to len(temp2) if temp2{c7} = "|" and temp2{c7+1} in ['A'..'Z','a'..'z','!'..'(','\','='] c6 = 1 c7 = len(temp2) end repeat temp2 = trm(temp2) end if c6 = 1 End of test 09/01/03 c11 = 1 /* added 12/09/03 textconflag = OFF Look for case of multiple text c6 = 0 c7 = 0 temp2 = temp2 // "| " CCCB: if temp2 con "|" ttext = temp2{1,mpt-1} We don't do this here because it will perform kernttext screw things up later. We are willing to live with an approximate word length temp2 = temp2{mpt+1..} c5 = mtfont perform wordspace a6 = len(ttext) if "-_" con ttext{a6} if mpt = 1 a5 -= spc(45) else a5 -= spc(95) end else c7 = 1 end if c6 < a5 c6 = a5 end goto CCCB end a5 = c6 if c7 = 0 /* all words end in "_" or "-" if a1 <> sct and ts(a1+1,TYPE) = NOTE c8 = ts(a1+1,TEXT_INDEX) temp2 = trm(tsdata(c8)) temp2 = temp2 // pad(1) if "-_" con temp2{1} a4 = a5 - ts(a1,SPACING) - hpar(51) / 3 if a4 < 0 a4 = 0 end goto CCCC end end if bit(0,ts(a1,SUPER_FLAG)) = 1 a4 = a5 - ts(a1,SPACING) - hpar(51) / 3 if a4 < 0 a4 = 0 end goto CCCC end else /* 12/09/03 try removing this if a1 <> oldsct+1 c8 = ts(a1-1,TEXT_INDEX) /* This code is a cludge and temp2 = trm(tsdata(c8)) /* and is no longer an addition. temp2 = temp2 // pad(1) /* The 12/09/03 post-adjustment if "-_" con temp2{1} /* provides a much better fix. a4 = a5 >> 1 - (spc(45) >> 1) goto CCCC end end end a4 = a5 / 3 - (spc(45) >> 1) CCCC: a6 = a3 - a4 a7 = a2 - a6 a5 = projected space taken up by syllable a4 = amount by which a syllable is backed up from the note position tfirstsp = amount by which first note is shifted forward to make space for text a3 = projected position of current note from bar line a6 = projected position of beginning of current syllable firstoff = amount by which last syllable from previous measure overhangs the space allowed for the last note a2 = smallest value of a6 allowed a7 = difference between smallest allowed a6 and current a6 if a7 > 0 if a11 = 0 tfirstsp += a7 a3 += a7 else if ts(a10,TYPE) = NOTE c8 = ts(a10,TEXT_INDEX) temp2 = trm(tsdata(c8)) temp2 = temp2 // pad(1) if "-_" con temp2{1} c9 = 0 loop for c10 = a10 - 1 to oldsct + 1 step -1 if ts(c10,SPACING) > 0 and ts(c10,TYPE) < GR_NOTE c9 = c10 c10 = 0 end repeat if c9 > 0 ts(c9,SPACING) += a7 >> 1 ts(a10,SPACING) += a7 >> 1 goto CCCA end end end ts(a10,SPACING) += a7 /* a10 set later end a3 += a7 end CCCA: tsdata(a8) = trm(tsdata(a8)) // "$$$$" // chs(a4) a5 -= a4 a2 = a3 + a5 + hpar(58) /* hpar(58) = space between words end if temp2{1} = "_" a5 = a3 + spc(95) if a5 > a2 a2 = a5 end end temp2 = trm(tsdata(a8)) temp2 = temp2 // pad(1) if temp2{1} = "_" textconflag = ON end sub = 1 a11 = 1 loop while temp2{sub..} con "|" a11 <<= 1 ++sub if temp2{sub} = "_" textconflag += a11 end repeat if temp2 = " " and textconflag > OFF /* code added 02-23-95 tsdata(a8) = pad(10) loop for a11 = 0 to 9 if bit(a11,textconflag) = ON tsdata(a8){a11+1} = "~" end repeat tsdata(a8) = trm(tsdata(a8)) textconflag = OFF end a11 = 1 end if nodtype = REST and ts(a1,CLAVE) < 200 /* code added 02-23-95 textconflag = OFF end if nodtype = BAR_LINE if a2 - hpar(36) > a3 ts(a10,SPACING) += a2 - hpar(36) - a3 a3 = a2 - hpar(36) end end * a10 = backpointer to prior space for note/rest object set if ts(a1,SPACING) > 0 and ts(a1,TYPE) < GR_NOTE a10 = a1 end firstoff = 0 if a1 = sct a4 = a2 - hpar(36) if a4 > a3 firstoff = a4 - a3 end else a3 += ts(a1,SPACING) end repeat Adding a new section of code (12/09/03) which attempts to midigate somewhat the unevenness in note spacing introduced by the addition of text. Code uses c11 to c17 as temporary variables, as well as a new array variable nspace(.,.) if c11 = 1 c12 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE or nodtype = REST a8 = ts(a1,TEXT_INDEX) temp2 = trm(tsdata(a8)) #if REPORT4 putc a1 = ~a1 .t10 NTYPE = ~ts(a1,NTYPE) .t22 SPACING = ~ts(a1,SPACING) .t37 ... putc TYPE = ~ts(a1,TYPE) .t12 text = ~temp2 #endif ++c12 nspace(c12,1) = a1 nspace(c12,2) = ts(a1,NTYPE) nspace(c12,2) = ts(a1,NTYPE) & 0xff /* new 10/15/07 nspace(c12,3) = ts(a1,SPACING) nspace(c12,4) = ts(a1,TYPE) if temp2 con "$$$$" nspace(c12,5) = int(temp2{mpt+4..}) else nspace(c12,5) = 0 end nspace(c12,6) = 0 nspace(c12,7) = 0 nspace(c12,8) = 0 end repeat Algorithm. (1) examine all pairs of notes. Find the pair for which (a) same duration (b) if d1 = distance after 1st note, and d2 = distance after 2nd note and both d1 and d2 are non-zero (added 04/10/05) and abs(d1 - d2) > 1 (c) smallest distance in this set (2) try moving 2nd note one unit either towards (d1 > d2) or away from (d2 > d1) first note. (a) resulting total shift of 2nd note cannot more than 1/2 nspace(.,5) to the right or more than nspace(.,5) to the left (b) if note cannot be moved, goto (1) and consider next pair (3) if (1)+(2) fail, look for situations where (a) a note of longer duration follows a note of shorter duration, and the shorter note is allowed more space. Try moving the 2nd note closer to the first, then goto (1). (b) a note of shorter duration follows a note of longer duration, and the shorter note is allowed more space. Try moving the 2nd note away from the first, then goto (1). (c) in all cases under (3), principal (2)(a) must be followed, and both notes in question must have non-zero following distances (added 04/10/05) NXPAIR: #if REPORT4 loop for c13 = 1 to c12 loop for c14 = 1 to 6 putc .w8 ~nspace(c13,c14) ... repeat putc repeat putc getc #endif c15 = 1000 c16 = 0 loop for c13 = 1 to c12 - 1 if nspace(c13,2) = nspace(c13+1,2) (new condition below added 04/10/05) if nspace(c13,2) = nspace(c13+1,2) and nspace(c13+1,3) <> 0 and nspace(c13,3) <> 0 c14 = abs(nspace(c13,3) - nspace(c13+1,3)) if c14 > 1 if c14 < c15 if nspace(c13+1,5) = 0 /* next node is a rest, etc. if nspace(c13+1,6) > -6 /* max incroachment is 6 c15 = c14 c16 = c13 end else if nspace(c13,3) > nspace(c13+1,3) /* move 2nd note to the left if nspace(c13+1,6) < 0 if abs(nspace(c13+1,6)) < nspace(c13+1,5) c15 = c14 c16 = c13 end else c15 = c14 c16 = c13 end else /* move 2nd note to the right if nspace(c13+1,6) < (nspace(c13+1,5) + 1 >> 1) c15 = c14 c16 = c13 end end end end end end repeat if c16 > 0 loop for c13 = 1 to c12 nspace(c13,7) = 0 repeat end if c16 = 0 loop for c13 = 1 to c12 - 1 if nspace(c13,2) = nspace(c13+1,2) (new condition below added 04/10/05) if nspace(c13,2) = nspace(c13+1,2) and nspace(c13+1,3) <> 0 and nspace(c13,3) <> 0 c14 = abs(nspace(c13,3) - nspace(c13+1,3)) if c14 = 1 and nspace(c13,7) = 0 if nspace(c13+1,5) = 0 /* next node is a rest, etc. if nspace(c13+1,6) > -6 /* max incroachment is 6 c16 = c13 c13 = c12 end else if nspace(c13,3) > nspace(c13+1,3) /* move 2nd note to the left if nspace(c13+1,6) < 0 if abs(nspace(c13+1,6)) < nspace(c13+1,5) c16 = c13 c13 = c12 end else c16 = c13 c13 = c12 end else /* move 2nd note to the right if nspace(c13+1,6) < (nspace(c13+1,5) + 1 >> 1) c16 = c13 c13 = c12 end end end end end repeat if c16 > 0 nspace(c16,7) = 1 end end if c16 > 0 /* note pair found if nspace(c16,3) > nspace(c16+1,3) if c16 > 1 and nspace(c16-1,2) > nspace(c16,2) and nspace(c16,6) < nspace(c16,5) --nspace(c16,3) ++nspace(c16-1,3) ++nspace(c16,6) else --nspace(c16,3) ++nspace(c16+1,3) --nspace(c16+1,6) end else ++nspace(c16,3) --nspace(c16+1,3) ++nspace(c16+1,6) end goto NXPAIR end loop for c13 = 1 to c12 - 1 if nspace(c13,3) <> 0 and nspace(c13+1,3) <> 0 /* this condition added 04/10/05 if nspace(c13,2) > nspace(c13+1,2) if nspace(c13,3) < nspace(c13+1,3) if nspace(c13+1,6) < nspace(c13+1,5) or (nspace(c13+1,4) = 3 and nspace(c13+1,6) < 6) ++nspace(c13,3) --nspace(c13+1,3) ++nspace(c13+1,6) goto NXPAIR end end end if nspace(c13,2) < nspace(c13+1,2) if nspace(c13,3) > nspace(c13+1,3) if abs(nspace(c13+1,6)) < (nspace(c13+1,5) + 1 >> 1) --nspace(c13,3) ++nspace(c13+1,3) --nspace(c13+1,6) goto NXPAIR end end end end repeat #if REPORT4 putc NO MORE IMPROVEMENTS getc #endif c12 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE or nodtype = REST a8 = ts(a1,TEXT_INDEX) temp2 = trm(tsdata(a8)) ++c12 if nspace(c12,1) <> a1 dputc Program Error stop end ts(a1,SPACING) = nspace(c12,3) if temp2 con "$$$$" c13 = nspace(c12,5) + nspace(c12,6) temp2 = temp2{1,mpt+3} // chs(c13) // "," // chs(nspace(c12,5)) tsdata(a8) = trm(temp2) end end repeat end End of 12/09/03 addition Make space for text (very old version) a2 = firstoff a3 = hpar(37) + tfirstsp a11 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype = NOTE a8 = ts(a1,TEXT_INDEX) ttext = trm(tsdata(a8)) ttext = ttext // pad(1) if ttext{1} in ['A'..'Z','a'..'z','!'..'(','\','='] c5 = mtfont perform wordspace a6 = len(ttext) if ttext{a6} = "_" a5 -= 20 end if ttext{a6} = "-" a5 -= 10 end if ttext{a6} = "_" a4 = a5 - ts(a1,SPACING) - hpar(51) / 3 if a4 < 0 a4 = 0 end goto CCCA end a4 = a5 / 3 - 6 CCCA: a6 = a3 - a4 a7 = a2 - a6 a5 = projected space taken up by syllable a4 = amount by which a syllable is backed up from the note position tfirstsp = amount by which first note is shifted forward to make space for text a3 = projected position of current note from bar line a6 = projected position of beginning of current syllable firstoff = amount by which last syllable from previous measure overhangs the space allowed for the last note a2 = smallest value of a6 allowed a7 = difference between smallest allowed a6 and current a6 if a7 > 0 if a11 = 0 tfirstsp += a7 else ts(a10,SPACING) += a7 /* a10 set later end a3 += a7 end a5 -= a4 a2 = a3 + a5 + 16 /* 16 = space between words (magic) end if ttext{1} = "_" a5 = a3 + spc(95) if a5 > a2 a2 = a5 end end a11 = 1 end * a10 = backpointer to prior space for note/rest object set if ts(a1,SPACING) > 0 a10 = a1 end firstoff = 0 if a1 = sct a4 = a2 if a4 > a3 firstoff = a4 - a3 end else if nodtype < 11 a3 += ts(a1,SPACING) end end repeat ***************************************************************** Debugging Information if jtype = "y" if bit(2,pmode) = 1 and g >= debug_point Condition changed 01/01/06 if (bit(2,pmode) = 1 or debug_flag = 1) and g >= debug_point putc Set Array at Point No. 2: including text, ... putc measure ~g putc firstspace = ~tfirstsp putc perform display_ts end end If there is more that one pass in this measure, one of the things we need to know is the number of passes per staff. If this number is greater than one for a particular staff, then we are going to need to know (1) whether ties have tips up or down for each pass, and (2) whether slurs should connect to note heads or to stems. I propose the following rule: If there is more than one track on a particular staff and if stem directions are consistant for each track on that particular staff, then (1) tie tips will always go the opposite direction of the stem direction (2) slurs should connect to stems rather than to note heads Before beginning the processing loop, I need to determine the situation, since it is dependent on what happens in the entire measure. I propose (6-4-93) to add a new element to the ts(.) array, in this case, element 29 = MULTI_TRACK flag. The meaning of this flag will be as follows: 0 = this note lies on a staff that has notes from only one pass. In this situation, mcat can be 0, 1 or 2 (1) mcat = 0 or mcat = 1. Any tie or slur starting or ending on this note will follow the rules for a single part on a staff. (2) mcat = 2 There is only one pass, but notes will occur in chords. In this case, slurs and articulations will mainly fall on the note head at the end of the stem. In the case where both stem directions are involved, slurs are generally put above the notes (tips down) 1 = this note belongs to one of multiple passes on this staff and all notes on this pass have stems which point up. In this situation, mcat can be either 0 or 3, depending on the value of vflag. Whatever the case, slurs will go above the notes (tips down). 2 = this note belongs to one of multiple passes on this staff and all notes on this pass have stems which point down. In this situation, mcat can be either 0 or 3, depending on the value of vflag. Whatever the case, slurs will go below the notes (tips up). 3 = this note belongs to one of multiple passes on this staff and the stem directions for the note of at least one of these passes on this staff are inconsistant (both up and down). In this situation, mcat can be either 0 or 3, depending on the value of vflag. In either case, the placement of slurs cannot be inferred from this parameter. The note in question might belong to a track that is "well behaved", i.e., not the "rogue track". In this case, determining the type and placement of the slur will be straight- forward. In the case where mcat = 0 (i.e. vflag = 1), it is likely that the rules for a single part may work fairly well. In the case where mcat = 3 (i.e. vflag > 1), a number of difficult situations can arrise, such as a slur from a stem-up chord note (pass one) to a stem down note (pass two). Such situation will have to be handled in a way that seems best under the particular circumstances. The MULTI_TRACK parameter will actually be combination of the multi-track flag and the value of mcat, according to the formula below: ts(.,MULTI_TRACK) = multi-track << 2 + mcat loop for a2 = 1 to 3 loop for a3 = 1 to passnum /* assume passnum = total # of passes loop for a4 = 1 to MAX_STAFF multichk(a2,a3,a4) = 0 repeat repeat repeat loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a2 = nodtype + 2 / 3 a3 = ts(a1,PASSNUM) a4 = ts(a1,STAFF_NUM) + 1 /* staff number a6 = multichk(a2,a3,a4) if rem <> 2 a5 = bit(1,ts(a1,STEM_FLAGS)) + 1 if a6 = 0 or a6 = 4 multichk(a2,a3,a4) = a5 else if a6 <> a5 multichk(a2,a3,a4) = 3 end end else if a6 = 0 multichk(a2,a3,a4) = 4 /* rest (stem direction unspecified) end end end repeat loop for a2 = 1 to 3 /* loop through note types i.e. reg,cue,grace loop for a4 = 1 to MAX_STAFF a5 = 0 a6 = 0 loop for a3 = 1 to passnum a7 = multichk(a2,a3,a4) if a7 = 3 /* Case: multiple stem directions a6 = 100 end if a7 > 0 ++a5 if a7 = 4 a8 = a3 + 1 / 2 /* set multichk to 1 for odd passnums, 2 for even multichk(a2,a3,a4) = rem + 1 /* for parts with only rests end end repeat if a6 = 100 and a5 > 1 /* Case: mult passes on staff and ambiguous stem dirs loop for a3 = 1 to passnum multichk(a2,a3,a4) = 3 /* all notes (for this type) on this staff have mt = 3 repeat end if a5 = 1 /* Case: single pass on this staff (for this note type) loop for a3 = 1 to passnum multichk(a2,a3,a4) = 0 /* all notes (for this type) on this staff have mt = 0 repeat end repeat repeat loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a2 = nodtype + 2 / 3 a3 = ts(a1,PASSNUM) a4 = ts(a1,STAFF_NUM) + 1 /* staff number a5 = multichk(a2,a3,a4) << 2 ts(a1,MULTI_TRACK) = a5 + mcat end repeat if oldsct = 0 firstsp = tfirstsp else Include tfirstsp in the spacing after previous completed bar if ts(oldsct,TYPE) <> BAR_LINE if ts(oldsct,SPACING) = 0 putc There is something you didn't think about examine stop end ts(oldsct,SPACING) += tfirstsp else ts(oldsct,SPACING) += tfirstsp end end Compute the spn (spacing) parameter loop for a1 = oldsct+1 to sct if ts(a1,TYPE) = DIV_CHG and qflag = 1 qflag = 2 end if qflag = 0 a5 = totdiv - 1 a4 = ts(a1,DIV) - 1 if a5 = a4 spn = 6913 else spn = 6912 / a5 * a4 + 1 end else if qflag = 1 a5 = mdiv - 1 a4 = ts(a1,DIV) - 1 if a5 = a4 spn = 3457 else spn = 3456 / a5 * a4 + 1 end else a5 = totdiv - mdiv a4 = ts(a1,DIV) - mdiv if a5 = a4 spn = 6913 else spn = 3456 / a5 * a4 + 3457 end end end ts(a1,SPN_NUM) = spn repeat We have a choice at this point whether to do extra calculations on the placement of notes, note-dots, and note-accidentals, or to wait to do this until the point when we process the entire array. I think now is a good time to do this, because (1) I prefer to do work I think I know how to do earlier rather than later (you never know just what kinds of tasks you may have to do later, so why not get this one out of the way), and (2) the information gained in the this process might help us in the placement of slurs (which we will need to do first thing when we begin processing the entire array). Basically we are going to try to compute the following information for each "musical node". The definition of a "musical node" is the set of one or more objects (chords + dots + accidentals) occuring on the same division number and which would, if possible, be placed in the same x-position on the staff. (1) the global x-offset. This is the amount by which each object is displaced from the 0 x-position of all objects on this musical node. I believe the global x-offset is always >= 0. (2) the local x-offset for note heads. This is the amount by which each note head of a particular object is displaced from the x position of the object. (3) the location of rests on the staff (based on the position of other objects at this location). (4) the x and y offsets for any dot(s) which might follow each note head of a particular object. Note: the y-position of an object which has more than one note head (chord) is the y position of the note head furthest from the note-end of the stem (i.e., therefore nearest to the beam end of the stem, if there is a beam). (5) the x offset (as measured to the left) of any accidental(s) which might precede each note head. I. How to store this information. (0) The grouping of elements in the ts(.,.) array into "musical nodes" can be determined by the space parameter "SPACING". The first array element of a "musical node" will have a non-zero space parameter, and any other element in the node will have a space parameter = 0. (1) The global x-offset can be stored in the GLOBAL_XOFF element of the ts(.,.) array. If we further specify that the GLOBAL_XOFF element will be set to INT10000 * a1 (index of first note in the chord) + a2 (index of last note in chord), this will give us an easy way to determine the number of array elements (note heads) in the object (chord). (2) The local x-offset for note heads can be stored in the LOCAL_XOFF element of the ts(.,.) array. (3) The location of rests on the staff can be stored in the STAFFLOC element of the ts(.,.) array. (4) For the x and y offsets for any dots(s), we can use the DOT (modified 12-24-96) element of the ts(.,.) array. Up to this point, the DOT element could have five values: 0 = no dot; 1 = single dot; 3 = double dot; 7 = triple dot; 15 = quadruple dot. We need to preserve this information, which uses bits 0 through 3 of the integer. Since the x offset is always positive, and the y offset may be positive or negative, we can construct a number which is x * INT10000 + y, shift it over 4 and OR it with the current value of DOT. (5) For the x offset of any accidental(s), we can use the AX element of the ts(.,.) array. Up to this point, the AX element could have sixteen values: 0 to 15. There is also the "silent" flag in bit 4 (value 16) which we need to preserve. Altogether (added 02/25/97) we need to preserve bits 0 through 4 of the integer. Since the x offset (measured to the left) is always positive, we can simply shift this offset over 8 and OR with the current value of AX. II. Method of computation. The first task will be to compute the global and local x-offset for the note heads in each musical node. We have a way of doing this, which we call pseudo-typesetting. A concurrent task will be to compute the y location of rests in each musical node. The second task will be to compute the x and y offsets for any dots(s). The method will be as follows (for each staff): (1) If there is only one note head on the staff, use the single note method for determining dot position. Otherwise, determine the x position for a "row of dots". This position will be to the right of the right-most note head on the stave. (Note that the x-offset for each dot is the x position minus the global x-offset for each object). (2) Starting with the left-most objects in the "musical node" and moving to the right, set dot positions according to the following algorithm (keeping track of all previous dots for this stave): Start with the note head furtherest from note-end of stem If note on line, if space above is free, put dot there else put dot in first free space below else if space is free, put dot there else put dot in first free space in reverse direction end The third task will be to compute the x offsets for any accidental(s) for each note head. The method will be as follows (for each staff): (1) Check the left-hand border from the typesetting operation. If there are any accidentals that could be set on right- shifted note heads, set these first, starting from the top down. This defines column 1 of the accidentals. Otherwise, column one is the first free location to the left of the left-most note head. (2) For all remaining accidentals to set, start at the top of the group. Make successive passes until all accidentals are set. (a) moving down, put in as many accidentals as possible where the distance between eligible notes (delta) >= vpar(6), with the caviat that you do not put an accidental on the lower half of a second before the upper half of a second (as you move down). (b) move to the left by the largest thickness of accidentals just placed. Decide on the direction to move for the next pass and goto (a). The new direction will be down (again) if the previous pass hit the lowest remaining accidental; otherwise, the new direction will be up. Good Luck with all of this! If you get it right, you will have accomplished a good deal of the task of setting simultaneous notes! 3-23-94: I am going to add another element to this process. It turns out that this is the best time to determine whatever extra space is required for each object, based on the items previously typeset. (We had been doing this later, but without the detailed information available in this part of the process, i.e. global-right boundaries, etc.). We start with the fact that the process below begins either after the initial setting of the clef, key and time, or after a controlling bar line. In either case, we know the profile of "emptyspace" relative to the position we are about to put something. After processing each object, we need to be sure two things are done. (1) If there will be a need to shift the position of a node, the value of this shift (positive or negative) needs to be stored in the array element: NODE_SHIFT. (2) The values of emptyspace need to be updated. olda1 = 0 loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype > NOTE_OR_REST A. Figure out space for Bar Line if nodtype = BAR_LINE a5 = 1000000 loop for a3 = 1 to MAX_STAFF loop for a4 = 1 to 45 if emptyspace(a3,a4) < a5 a5 = emptyspace(a3,a4) end repeat repeat a6 = mindist - hpar(82) - a5 Task (1) if a6 > 0 ts(a1,NODE_SHIFT) = a6 end Task (2) a5 = ts(a1,SPACING) - hpar(93) loop for a4 = 1 to MAX_STAFF loop for a3 = 1 to 45 emptyspace(a4,a3) = a5 repeat repeat goto WWWW end B. Figure out space for Clef change if nodtype = CLEF_CHG a3 = ts(a1,STAFF_NUM) + 1 /* staff number Check to see if we can "backup" the node position a5 = 1000000 loop for a4 = 1 to 45 if emptyspace(a3,a4) < a5 a5 = emptyspace(a3,a4) /* minimum emptyspace on this staff end repeat Task (1) if a5 > ts(a1,SPACING) >> 1 a4 = a5 * 2 / 3 a7 = ts(a1,SPACING) c2 = 0 loop for c1 = a1+1 to sct /* check if following note has accidentals if ts(c1,DIV) <> ts(a1,DIV) goto HJKO end a6 = ts(c1,TYPE) if a6 > FIGURES goto HJKO end if a6 <> REST and a6 <> CUE_REST and a6 <> FIGURES if ts(c1,STAFF_NUM) = ts(a1,STAFF_NUM) a6 = ts(c1,AX) & 0x1f if a6 > 0 and hpar(a6) > c2 if a6 < 0x10 and a6 > 0 and hpar(a6) > c2 /* Code modified 02/25/97 c2 = hpar(a6) end end end repeat HJKO: a7 += c2 if a4 > a7 a4 = a7 end ts(a1,NODE_SHIFT) = 0 - a4 /* negative shift else a6 = mindist - hpar(82) - a5 if a6 > 0 ts(a1,NODE_SHIFT) = a6 end end Task (2) a5 = ts(a1,SPACING) - a4 /* amount by position really advanced a7 = hpar(86) if z > 128 a7 = a7 * 7 / 10 /* use to be 8 / 10 end a7 = ts(a1,SPACING) - a7 /* empty space after clef sign loop for a4 = 1 to MAX_STAFF if a4 = a3 loop for a6 = 1 to 45 emptyspace(a4,a6) = a7 repeat else loop for a6 = 1 to 45 emptyspace(a4,a6) += a5 repeat end repeat goto WWWW end C. Figure out space for Time change if nodtype = METER_CHG a5 = 1000000 loop for a3 = 1 to MAX_STAFF loop for a4 = 1 to 45 if emptyspace(a3,a4) < a5 a5 = emptyspace(a3,a4) end repeat repeat a6 = hpar(12) - a5 Task (1) if a6 > 0 ts(a1,NODE_SHIFT) = a6 end Task (2) loop for a4 = 1 to MAX_STAFF loop for a3 = 1 to 45 emptyspace(a4,a3) = min_space /* replaces hpar(29) 11/19/07 repeat repeat goto WWWW end D. Figure out space for Key change if nodtype = AX_CHG a5 = 1000000 loop for a3 = 1 to MAX_STAFF loop for a4 = 1 to 45 if emptyspace(a3,a4) < a5 a5 = emptyspace(a3,a4) end repeat repeat a6 = hpar(37) - hpar(93) - a5 Task (1) if a6 > 0 ts(a1,NODE_SHIFT) = a6 end Task (2) loop for a4 = 1 to MAX_STAFF loop for a3 = 1 to 45 emptyspace(a4,a3) = hpar(12) repeat repeat goto WWWW end E. Figure out space for Signs, Words and Marks which are Objects if nodtype = SIGN or nodtype = WORDS or nodtype = MARK ts(a1,NODE_SHIFT) = 0 goto WWWW end F. Figure out space for Figures if nodtype = FIGURES c3 = FIG_DATA c11 = 0 c14 = 0 /* Flag for preceding accidentals on figures loop for c2 = 1 to ts(a1,NUMBER_OF_FIG) c12 = 0 Code added 11/16/03 to deal with parentheses around figures c6 = ts(a1,c3) c13 = 0 /* Flag for parentheses around figures if c6 > 1000 c6 -= 1000 if c6 > 1000 /* large parentheses c6 = c6 / 1000 c6 = rem c13 = hpar(138) + hpar(139) else /* small parentheses c13 = hpar(136) + hpar(137) end end And this code rewritten 11/16/03 if c6 > 0 temp = chr(c6+28) if "1389" con temp /* case: accidental x,#,f,n c4 = ts(a1,c3+1) if c4 > 0 /* sub-case: accidental followed by figure c14 = hpar(c4+47) /* result: set flag for preceding accidental if c4 < 20 /* figure if c4 < 10 c12 = hpar(66) else c12 = hpar(66) << 1 end else c12 = hpar(c4+67) end else c12 = hpar(c6+47) /* 20 <= c6 <= 30 --> hpar(67) to hpar(77) end else if c6 < 20 /* case: figure if c6 < 10 c12 = hpar(66) else c12 = hpar(66) << 1 end c4 = ts(a1,c3+1) if c4 > 0 /* accidental following number temp = chr(c4+28) if "01389" con temp c12 += hpar(c4+47) end end else /* cases: isolated +,2+,4+,5+,6\,7\,- c12 += hpar(c6+47) end end end c12 += c13 /* Adding space for parentheses 11/16/03 if c12 > c11 c11 = c12 end c3 += 3 repeat c11 += c14 /* Adding space for pre-accidentals 11/16/03 c11 += hpar(75) /* free space = width of natural if ts(a1,MIN_FIG_SPAC) < c11 ts(a1,MIN_FIG_SPAC) = c11 end if ts(a1,FIG_SPACE) > 0 and ts(a1,FIG_SPACE) < c11 ts(a1,FIG_SPACE) = c11 end a4 = ts(a1,FIG_SPACE) ts(a1,NODE_SHIFT) = 0 if a4 > 0 loop for a3 = 1 to MAX_STAFF loop for a2 = 1 to 45 emptyspace(a3,a2) += a4 repeat repeat end goto WWWW end goto WWWW end PROCESSING NOTES AND RESTS NOW npasses = 1 a3 = 1 if a1 = sct /* added 01-31-97 a2 = a1 pitchcnt(1) = 1 goto X1 end loop for a2 = a1+1 to sct if ts(a2,SPACING) <> 0 --a2 pitchcnt(npasses) = a3 goto X1 end if ts(a2,TYPE) > NOTE_OR_REST --a2 pitchcnt(npasses) = a3 goto X1 end if nodtype = GR_NOTE if ts(a2,TYPE) = XGR_NOTE ++a3 else pitchcnt(npasses) = a3 a3 = 1 ++npasses end else if ts(a2,TYPE) = XNOTE or ts(a2,TYPE) = XCUE_NOTE ++a3 else pitchcnt(npasses) = a3 a3 = 1 ++npasses end end repeat X1: a2 = index to last element in node npasses = number of passes pitchcnt(.) = size of chord for each pass if a1 = a2 /* Simple (and most common) case: single element, a2 = a1 if ts(a1,MULTI_TRACK) < 4 and a1 = a2 a3 = ts(a1,STAFF_NUM) + 1 /* staff number c1 = a1 passnum = ts(c1,PASSNUM) ntype = ts(c1,NTYPE) ntype = ts(c1,NTYPE) & 0xff /* new 10/15/07 stem = bit(1,ts(c1,STEM_FLAGS)) if nodtype <= REST passtype = REG passsize = FULLSIZE if bit(16,ts(c1,SUBFLAG_1)) = 1 passsize = CUESIZE /* EXPERIMENT 06-24-94 end else passsize = CUESIZE if nodtype <= CUE_REST passtype = CUE else passtype = GRACE end end a) rests if nodtype = REST or nodtype = CUE_REST if scr_flag = 1 if ts(c1,CLAVE) = 200 /* "silent" rest ts(c1,STAFFLOC) = 0 ts(c1,OBY) = 0 ts(c1,DOT) = 0 ts(a1,NODE_SHIFT) = 0 goto MMMMM end end if nodtype = REST c8 = vpar(4) else c8 = vpar(2) end if ts(c1,STAFFLOC) = 1 c8 = vpar(4) end ts(c1,STAFFLOC) = c8 ts(c1,OBY) = c8 if ts(c1,DOT) > 0 c4 = 0 /* additions to "eighth rest" c2 = 0 /* y shift down for starting rests c6 = 0 /* extra height of dot (negative shift) if ntype <= SIXTEENTH c6 = notesize c4 = EIGHTH - ntype c2 = notesize if ntype < THIRTY_SECOND c2 = THIRTY_SECOND - ntype * notesize + c2 end end if ntype > QUARTER c3 = hpar(30) else c3 = c4 * hpar(54) + hpar(31) c6 *= c4 end if passsize = CUESIZE c3 = c3 * 8 / 10 end c7 = c3 Minor code modification 04/19/08 if ntype <= SIXTEENTH c3 -= hpar(54) end c6 += vpar(1) /* shift to space OK 4-21-95 /* c3 is the x shift to the dot(s) c2 -= c6 /* final y offset c9 = c2 /* x * INT10000 + y, shift it over 4 and OR it with DOT (code modified 12-24-96) c3 *= INT10000 c3 += c2 c3 <<= 4 /* (code modified 12-24-96) ts(c1,DOT) |= c3 else c7 = 0 c9 = 0 end Task (1) a5 = 1000000 loop for a4 = 1 to 45 if emptyspace(a3,a4) < a5 a5 = emptyspace(a3,a4) /* minimum emptyspace on this staff end repeat a6 = mindist - hpar(82) - a5 if a6 > 0 ts(a1,NODE_SHIFT) = a6 end Task (2) loop for a6 = 1 to 45 gr(a3,a6) = -200 repeat if ts(c1,CLAVE) < 200 or scr_flag = 0 perform rest_occupy_space (c8,a3) /* ntype is read directly end if ts(c1,DOT) > 0 c8 += c9 if c8 >= 0 c8 = 2 * c8 + 1 / vpar(2) else c8 = 2 * c8 - 1 / vpar(2) end c8 = 23 - c8 c7 += hpar(80) if ts(c1,DOT) & 0x0e > 0 /* code modified 12-24-96 if ts(c1,DOT) & 0x02 > 0 c7 += hpar(91) /* extra shift to second dot end if ts(c1,DOT) & 0x04 > 0 c7 += hpar(91) /* extra shift to third dot end if ts(c1,DOT) & 0x08 > 0 c7 += hpar(91) /* extra shift to fourth dot end end loop for a6 = c8 - 1 to c8 + 1 gr(a3,a6) += c7 repeat end c10 = ts(c1,SPACING) loop for c11 = 1 to MAX_STAFF if c11 = a3 loop for c6 = 1 to 45 if gr(c11,c6) = -200 emptyspace(c11,c6) += c10 else emptyspace(c11,c6) = c10 - gr(c11,c6) end repeat else loop for c6 = 1 to 45 emptyspace(c11,c6) += c10 repeat end repeat else b) notes repeater_case = 0 ts(c1,LOCAL_XOFF) = 0 ts(c1,GLOBAL_XOFF) = 0 Technically, this code must also appear here, although it is highly unlikely that anyone would want to shift a single note on a stave from its primary position. All New code 05/02/03 At this point, we need to see if the note object position has been modified "absolutely" by a print suggestion. If this is the case, we need to make the adjustment here, AND, elimate the suggestion from the tsr string. c6 = ts(c1,TSR_POINT) c7 = ors(tsr(c6){2}) if bit(0,c7) = 1 px = ors(tsr(c6){3}) if px > 0 px = px - 128 * notesize / 10 pxx = c7 & 0x02 >> 1 if pxx = 1 ts(c1,GLOBAL_XOFF) = px tsr(c6){3} = chr(0) /* here is where suggestion is zerod out end end end End of new code 05/02/03 c6 = ts(c1,STAFFLOC) / vpar(1) c6 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 if ts(c1,DOT) > 0 if ntype > HALF c3 = hpar(32) else c3 = hpar(33) end c10 = ts(c1,STAFFLOC) / notesize c10 = rem /* c10 = 0 means note on line if stem = UP if ts(c1,BEAM_FLAG) = NO_BEAM and ts(c1,NTYPE) < QUARTER c3 += hpar(27) if c10 <> 0 c3 -= hpar(34) end end end c8 = c3 * if dot is on staff line, c10 = 0 if c10 = 0 c2 = 0 - vpar(12) /* lower dot if more than one track and stem is down if bit(3,ts(c1,MULTI_TRACK)) = 1 if stem = DOWN c2 = vpar(12) end end c3 -= hpar(34) else c2 = 0 end if ntype > HALF c8 -= hpar(32) else c8 -= hpar(33) end if c8 < 3 c8 = 0 end if passsize = CUESIZE c3 = c3 * 8 / 10 c8 = c8 * 8 / 10 end /* c3 = x shift /* c2 = y offset c7 = ts(c1,DOT) & 0x0f c7 = int("1.2...3.......4"{c7}) /* convert to SCORE code c7 *= 10 if c2 > 0 c7 += 100 end c8 = c8 * 30 / scr_qwidth /* 100ths part of P9 if c8 > 99 c8 = 99 end c7 = c7 << 8 + c8 ts(c1,AUG_DOTS) = c7 /* x * INT10000 + y, shift it over 2 and OR it with DOT (code modified 12-24-96) c7 = c3 c8 = c2 c3 *= INT10000 c3 += c2 c3 <<= 4 /* code modified 12-24-96 ts(c1,DOT) |= c3 end Delete this code from this location. Add this task below where limits for accidentals are established if ts(c1,AX) > 0 c5 = ts(c1,AX) & 0x0f c7 = hpar(c5) /* shift this offset over 4 and OR with AX c7 <<= 4 ts(c1,AX) |= c7 end Task (1) loop for c10 = 1 to 45 gl(a3,c10) = 200 pseudo_gl(a3,c10) = 200 gr(a3,c10) = -200 repeat c6 = 23 - c6 if c6 > 45 or c6 < 1 putc putc FAULT CONDITION putc putc Note out of staff range. Please check clef. putc putc Program Halted putc stop end /* Determine thickness of note: c11 if ntype <= HALF or ntype = SLASH8 c11 = hpar(82) else if ntype >= BREVE c11 = hpar(84) else c11 = hpar(83) end end if passsize = CUESIZE c11 = c11 * 8 / 10 end /* Put in limits of note head gl(a3,c6+1) = hpar(95) pseudo_gl(a3,c6+1) = 0 gl(a3,c6) = 0 gr(a3,c6+1) = c11 gr(a3,c6) = c11 - hpar(95) if ntype < WHOLE /* Determine length of stem: c10 if ntype > EIGHTH c10 = 8 /* length of stem else c10 = 7 if ntype < EIGHTH c10 += EIGHTH - ntype end end if passsize = CUESIZE c10 = c10 * 8 / 10 end if ts(c1,BEAM_FLAG) = NO_BEAM and ts(c1,BEAM_CODE) > 0 repeater_case = 1 c13 = ts(c1,BEAM_CODE) / 10 loop while c13 > 0 c13 /= 10 c10 += 2 repeat end /* Determine thickness of stem: c12 if ts(c1,BEAM_FLAG) = NO_BEAM and ntype < QUARTER c12 = hpar(26) if passsize = CUESIZE c12 = c12 * 8 / 10 end else if stem = UP c12 = 0 else c12 = hpar(90) end end /* Put in limits of gl(.,.) and gr(.,.) for stem 06/04/08 Fixing case where there are no-beam repeaters if stem = UP c13 = c6 + c10 if c13 > 45 c13 = 45 end gr(a3,c6+1) = c11 + c12 loop for c14 = c6 + 2 to c6 + 3 /* No repeaters near note head gr(a3,c14) = c11 + c12 gl(a3,c14) = c11 - hpar(90) repeat if repeater_case = 1 c15 = hpar(98) + hpar(90) if ntype >= QUARTER c12 += hpar(98) end else c15 = hpar(90) end loop for c14 = c6 + 4 to c13 /* 06/04/08 changing c6 + 2 to c6 + 4 gr(a3,c14) = c11 + c12 gl(a3,c14) = c11 - c15 repeat else c13 = c6 - c10 if c13 < 1 c13 = 1 end loop for c14 = c6 - 2 to c6 - 1 /* No repeaters near note head gr(a3,c14) = c12 gl(a3,c14) = 0 repeat if repeater_case = 1 c11 = hpar(98) else c11 = 0 end loop for c14 = c13 to c6 - 3 /* 06/04/08 changing c6 - 1 to c6 - 3 gr(a3,c14) = c12 gl(a3,c14) = 0 - c11 repeat end end Put in limits of for accidentals and store location of accidental if ts(c1,AX) > 0 c5 = ts(c1,AX) & 0x0f c7 = passsize perform place_accidental (a3,c6,c5,c7) /* returns c7 = negative offset Note: place_accidental operates over the entire simultaneity, and therefore returns an absolute (negative, left <--) shift relative to the undisplaced musical node. This is exactly the information that SCORE wants in parameter P5, fractional part. Note that SCORE assigns the fractional value .00 to the normal position of the accidental, which in the MUSEDATA I-file is shifted. One extra twist: SCORE provides no direct way a representing natural-sharp, and natural-flat in a notehead. We will have to set the P5 parameter as if the natural were not there and indicate the relative position where a natural will have to be set using a CODE-9 item. Since the code that determines P5 and the CODE-9 item must execute every time place_accidental runs, I am going to try to put this code inside the place_accidental procedure. There will be a need to return data in a second parameter. I propose using the third parameter in the list. ts(c1,AX_DISP) = c5 /* capture this parameter, returned from place_accidental /* shift the offset over 8 and OR with AX c7 = 0 - c7 /* we store positive value c7 <<= 8 /* 02/25/97 shift changed from 4 to 8 ts(c1,AX) |= c7 end Adjust the gr(.,.) array to accommodate space for dots (added 04/04/94) c8 = ts(a1,STAFF_NUM) + 1 /* staff number c3 = ts(a1,DOT) if c3 > 0 /* code modified 12-24-96 c4 = c3 & 0x0f /* dot flag /* 12-24-96 c3 >>= 4 /* 12-24-96 c5 = c3 / INT10000 /* x offset c6 = rem /* y offset if c6 > INT10000 >> 1 c6 -= INT10000 ++c5 end c6 = c6 + vpar(8) - 1 / vpar(1) - 7 c6 = c6 + vpar(8) * 2 - 1 / vpar(2) - 7 c6 = 0 - ts(a1,STAFFLOC) / vpar(1) + 23 - c6 c10 = ts(a1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c10 - c6 c5 += hpar(80) if c4 > 1 /* modified 12-24-96 c5 += hpar(91) /* second dot if c4 > 4 c5 += hpar(91) /* third dot end if c4 > 8 c5 += hpar(91) /* fourth dot end end if c6 < 46 and c6 > 0 gr(c8,c6) = c5 end end /* Calculate NODE_SHIFT c10 = 0 if c1 = 1 or ts(c1-1,TYPE) < CUE_NOTE c6 = min_space /* replaces hpar(29) 11/19/07 else c6 = min_space / 2 /* replaces hapr(29) / 2 11/19/07 end loop for c11 = 1 to 45 if gl(a3,c11) > pseudo_gl(a3,c11) gl(a3,c11) = pseudo_gl(a3,c11) end c12 = c6 - gl(a3,c11) - emptyspace(a3,c11) /* should be negative if c12 > c10 /* most of the time c10 = c12 end repeat before02/25/97if ts(c1,AX) > 0 and ts(c1,SPACING) = mindist and c10 < hpar(94) if (ts(c1,AX) & 0x0f) > 0 and ts(c1,SPACING) = mindist and c10 < hpar(94) c10 = hpar(94) end if c10 > 0 ts(c1,NODE_SHIFT) = c10 end Task (2) c10 = ts(c1,SPACING) loop for c11 = 1 to MAX_STAFF if c11 = a3 loop for c6 = 1 to 45 if gr(c11,c6) = -200 emptyspace(c11,c6) += c10 else emptyspace(c11,c6) = c10 - gr(c11,c6) end repeat else loop for c6 = 1 to 45 emptyspace(c11,c6) += c10 repeat end repeat end else ╔════════════════════════════════════════════════════════════════╗ ║ ║ ║ Here is where you deal with chords and with multiple passes ║ ║ ║ ╚════════════════════════════════════════════════════════════════╝ ┌──────────────────────┐ │ D I S C U S S I O N │ └──────────────────────┘ To start with, a major difference between the single note version and this multiple note version is the placement of (1) the note heads in chords and (2) the chord groups, themselves. The major problem is to determine the x-offset for each note in a chord and the x-offset for each chord group. Once this information is known, it will then be possible to typeset the various entities in a manner somewhat similar to the case of the single note version above. The x placement of all of the elements of a multiple note node requires consideration of all of the elements; i.e., they cannot be simply put down in a serial fashion. Therefore, we must do a pseudo- typesetting of the elements, and from this extract the x-offsets we need to do the real job. I note that set array elements 13 and 19 are free at this point, so we can use them to store local x-offset and global x-offset, respectively (LOCAL_XOFF, GLOBAL_XOFF). Also, the vertical placement of rests must be taken into consideration. There is no definite parameter in the stage2 source file that tells us were to locate rests vertically. We have two indirect parameters available: (1) the pass number, based on the the order of encoding the material, and (2) the optional track number. I would favor using the pass number at this point. Where the maximum pass number is 2, rests could be located "high" and "low" for passes 1 and 2, respectively; where the maximum pass number is 3, rests could be located "high", "medium" and "low", etc. In the case of the grand staff (two or more staves), these locations could be refined to reflect the staff on which the rests are being put. ╔═════════════════════════════════════════════════════╗ ║ ║ ║ (A) pseudo-typeset the notes ║ ║ ║ ╚═════════════════════════════════════════════════════╝ ┌─────────────────────────┐ │ construct note data │ └─────────────────────────┘ ndata(1) = pass number (set to 0, after chord is typeset) ndata(2) = stem flag: bit 0: direction 0 = up, 1 = down bit 1: repeater 0 = none, 1 = present bits 2-4: flag flag 0 = no flag 1 = eighth flag 2 = sixteenth flag 3 = 32nd flag 4 = 64th flag 5 = 128th flag 6 = 256th flag ndata(3) = color 0 = black, 1 = half, 2 = whole, 3 = breve ndata(4) = dot 0 = none, 1 = dot ndata(5) = pitch ndata(6) = position in chord (from note end of stem) ndata(7) = final x-position of this pitch within chord ndata(8) = pass number ndata(9) = staff number ndata(10) = note size (full size vs. que size) ndata(11) = ntype pcnt = total number of notes (and rests) #define PS_PASS 1 #define PS_STEM 2 #define PS_COLOR 3 #define PS_DOT 4 #define PS_PITCH 5 #define PS_RANK 6 #define PS_XPOS 7 #define PS_PASS2 8 #define PS_STAFF 9 #define PS_NSIZE 10 #define PS_NTYPE 11 loop for i = 1 to 45 /* initialize right and left boundaries gr(1,i) = -200 gr(2,i) = -200 pseudo_gr(1,i) = -200 pseudo_gr(2,i) = -200 pseudo_gl(1,i) = 200 pseudo_gl(2,i) = 200 gl(1,i) = 200 gl(2,i) = 200 repeat pcnt = 0 putc Note data array putc ─────────────────────────── c1 = a1 ps_passcount(1) = 0 ps_passcount(2) = 0 loop for thispass = 1 to npasses c2 = ts(c1,STAFF_NUM) + 1 /* staff number ++ps_passcount(c2) c2 = 0 loop for c3 = 1 to pitchcnt(thispass) ++pcnt ndata(pcnt,PS_PASS2) = thispass ndata(pcnt,PS_PASS) = thispass ndata(pcnt,PS_STEM) = bit(1,ts(c1,STEM_FLAGS)) if c3 = 1 and ts(c1,BEAM_FLAG) = NO_BEAM if ts(c1,BEAM_CODE) > 0 ndata(pcnt,PS_STEM) += 2 end if ts(c1,NTYPE) < QUARTER c4 = QUARTER - ts(c1,NTYPE) << 2 ndata(pcnt,PS_STEM) += c4 end end if ts(c1,CLAVE) < 100 /* note if ts(c1,NTYPE) < HALF ndata(pcnt, PS_COLOR) = 0 else ndata(pcnt,PS_COLOR) = ts(c1,NTYPE) - 7 end else ndata(pcnt,PS_COLOR) = ts(c1,NTYPE) ndata(pcnt,PS_COLOR) = ts(c1,NTYPE) & 0xff /* new 10/15/07 end ndata(pcnt,PS_NTYPE) = ts(c1,NTYPE) ndata(pcnt,PS_NTYPE) = ts(c1,NTYPE) & 0xff /* new 10/15/07 if ts(c1,TYPE) <= REST ndata(pcnt,PS_NSIZE) = bit(16,ts(c1,SUBFLAG_1)) else ndata(pcnt,PS_NSIZE) = CUESIZE end ndata(pcnt,PS_DOT) = ts(c1,DOT) if ts(c1,CLAVE) < 100 /* note ndata(pcnt,PS_PITCH) = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 c10 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 ndata(pcnt,PS_PITCH) = 23 - c10 else ndata(pcnt,PS_PITCH) = 100 /* rest end ndata(pcnt,PS_XPOS) = 0 ndata(pcnt,PS_STAFF) = ts(c1,STAFF_NUM) ++c1 compute horizontal placement of notes for down stems (on the fly) if bit(0,ndata(pcnt,PS_STEM)) = DOWN and c3 > 1 c4 = ndata(pcnt-1,PS_PITCH) - ndata(pcnt,PS_PITCH) if c4 = 1 if c2 = 0 ndata(pcnt,PS_XPOS) = -1 c2 = 1 else c2 = 0 end else c2 = 0 end end rank the notes in a chord if bit(0,ndata(pcnt,PS_STEM)) = UP ndata(pcnt,PS_RANK) = pitchcnt(thispass) + 1 - c3 else ndata(pcnt,PS_RANK) = c3 end repeat compute horizontal placement of notes for up stems if pcnt > 0 and bit(0,ndata(pcnt,PS_STEM)) = UP and pitchcnt(thispass) > 1 c5 = pcnt c2 = 0 loop for c3 = 2 to pitchcnt(thispass) c4 = ndata(c5-1,PS_PITCH) - ndata(c5,PS_PITCH) if c4 = 1 and c2 = 0 ndata(c5-1,PS_XPOS) = 1 c2 = 1 else c2 = 0 end --c5 repeat end c2 = pcnt - pitchcnt(thispass) + 1 loop for c3 = c2 to pcnt loop for c5 = 1 to 7 putc .w4 ~ndata(c3,c5) ... repeat putc repeat repeat determine all clashes between chords loop for c2 = 1 to npasses loop for c3 = 1 to npasses clashes(c2,c3) = 0 repeat repeat loop for c2 = 1 to pcnt - 1 loop for c3 = c2+1 to pcnt c4 = ndata(c2,PS_PASS) c5 = ndata(c3,PS_PASS) if c4 <> c5 and ndata(c2,PS_STAFF) = ndata(c3,PS_STAFF) if ndata(c2,PS_XPOS) = 0 and ndata(c3,PS_XPOS) = 0 if ndata(c2,PS_PITCH) < 100 c6 = ndata(c2,PS_PITCH) - ndata(c3,PS_PITCH) if c6 = 0 /* same pitch if bit(0,ndata(c2,PS_STEM)) = bit(0,ndata(c3,PS_STEM)) clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end if ndata(c2,PS_COLOR) <> ndata(c3,PS_COLOR) clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end if ndata(c2,PS_NSIZE) <> ndata(c3,PS_NSIZE) clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end #if DOT_DIFFERENCE 12/24/05 This optional code is now controlled by dot_difference_flag if dot_difference_flag = 1 if ndata(c2,PS_DOT) <> ndata(c3,PS_DOT) clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end end #endif if ndata(c2,PS_RANK) * ndata(c3,PS_RANK) <> 1 clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end We must now ask the question: are all notes of first chord either equal/above all notes of second chord, or equal/below all notes of second chord. c10 = 0 loop for c9 = 1 to pcnt if ndata(c9,PS_PASS) = ndata(c2,PS_PASS) if ndata(c9,PS_PITCH) <> ndata(c2,PS_PITCH) if ndata(c9,PS_PITCH) > ndata(c2,PS_PITCH) if c10 = -1 c10 = 1000 else c10 = 1 end end if ndata(c9,PS_PITCH) < ndata(c2,PS_PITCH) if c10 = 1 c10 = 1000 else c10 = -1 end end end end repeat if c10 = 1000 clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end loop for c9 = 1 to pcnt if ndata(c9,PS_PASS) = ndata(c3,PS_PASS) if ndata(c9,PS_PITCH) <> ndata(c3,PS_PITCH) if ndata(c9,PS_PITCH) > ndata(c3,PS_PITCH) if c10 = 0 c10 = -1 end if c10 = 1 c10 = 1000 end end if ndata(c9,PS_PITCH) < ndata(c3,PS_PITCH) if c10 = 0 c10 = 1 end if c10 = -1 c10 = 1000 end end end end repeat if c10 = 1000 clashes(c4,c5) = 1 clashes(c5,c4) = 1 goto PS_D2 end clashes(c4,c5) = 2 clashes(c5,c4) = 2 goto PS_D2 end if c6 = 1 or c6 = -1 clashes(c4,c5) = 1 clashes(c5,c4) = 1 end end end end PS_D2: repeat repeat typeset all groups of chords for which there are no clashes loop for c2 = 1 to npasses tgroup(c2) = 0 repeat ntgroups = 0 loop for c2 = 1 to npasses c5 = 0 loop for c3 = c2+1 to npasses if clashes(c2,c3) <> 1 and tgroup(c3) = 0 if c5 = 0 ++ntgroups c5 = 1 tgroup(c2) = ntgroups tgroup(c3) = ntgroups else loop for c4 = c2+1 to c3-1 if tgroup(c4) = ntgroups and clashes(c4,c3) = 1 c4 = 1000 end repeat if c4 <> 1000 tgroup(c3) = ntgroups end end end repeat repeat loop for c3 = 1 to npasses putc tgroup(~c3 ) = ~tgroup(c3) repeat c10 = 0 /* initialize right-hand chord boundary loop for c3 = 1 to ntgroups /* number of typeset groups typeset chords loop for c4 = 1 to 2 /* typeset stem down first c5 = 2 - c4 PS_CC: c6 = 0 c7 = 0 c15 = 0 loop for c2 = 1 to pcnt c9 = ndata(c2,PS_PASS) if c9 > 0 and tgroup(c9) = c3 /* this typeset group if bit(0,ndata(c2,PS_STEM)) = c5 if ndata(c2,PS_PITCH) > c6 /* typeset highest pitch first if c6 > 0 and c15 > EIGHTH /* but check first to see if if ndata(c2,PS_NTYPE) < QUARTER /* type is quarter or greater if ndata(c2,PS_PITCH) - c6 < 3 goto NOSWITCH end end end c6 = ndata(c2,PS_PITCH) c7 = ndata(c2,PS_PASS) c15 = ndata(c2,PS_NTYPE) NOSWITCH: else if c15 < QUARTER and ndata(c2,PS_NTYPE) > EIGHTH if c6 - ndata(c2,PS_PITCH) < 3 c6 = ndata(c2,PS_PITCH) c7 = ndata(c2,PS_PASS) c15 = ndata(c2,PS_NTYPE) end end end end end repeat if c7 > 0 c8 = 100 loop for c2 = 1 to npasses if clashes(c2,c7) = 2 /* unison c8 = c2 c2 = 100 end repeat perform ps_setchord (c7, c8, c10) goto PS_CC end repeat repeat determine if there are clashes left PS_B: loop for c2 = 1 to pcnt - 1 if ndata(c2,PS_PASS) > 0 and ndata(c2,PS_XPOS) = 0 /* chord(PS_PASS) has not been set loop for c3 = c2+1 to pcnt if ndata(c3,PS_XPOS) = 0 and ndata(c3,PS_PASS) > 0 if ndata(c2,PS_STAFF) = ndata(c3,PS_STAFF) if ndata(c2,PS_PITCH) < 100 c4 = ndata(c2,PS_PITCH) - ndata(c3,PS_PITCH) if c4 = 0 if bit(0,ndata(c2,PS_STEM)) = bit(0,ndata(c3,PS_STEM)) goto PS_CL end if ndata(c2,PS_COLOR) <> ndata(c3,PS_COLOR) goto PS_CL end #if DOT_DIFFERENCE 12/24/05 This optional code is now controlled by dot_difference_flag if dot_difference_flag = 1 if ndata(c2,PS_DOT) <> ndata(c3,PS_DOT) goto PS_CL end end #endif if ndata(c2,PS_RANK) * ndata(c3,PS_RANK) <> 1 goto PS_CL end We must now ask the question: are all notes of first chord either equal/above all notes of second chord, or equal/below all notes of second chord. c10 = 0 loop for c9 = 1 to pcnt if ndata(c9,PS_PASS) = ndata(c2,PS_PASS) if ndata(c9,PS_PITCH) <> ndata(c2,PS_PITCH) if ndata(c9,PS_PITCH) > ndata(c2,PS_PITCH) if c10 = -1 c10 = 1000 else c10 = 1 end end if ndata(c9,PS_PITCH) < ndata(c2,PS_PITCH) if c10 = 1 c10 = 1000 else c10 = -1 end end end end repeat if c10 = 1000 goto PS_CL end loop for c9 = 1 to pcnt if ndata(c9,PS_PASS) = ndata(c3,PS_PASS) if ndata(c9,PS_PITCH) <> ndata(c3,PS_PITCH) if ndata(c9,PS_PITCH) > ndata(c3,PS_PITCH) if c10 = 0 c10 = -1 end if c10 = 1 c10 = 1000 end end if ndata(c9,PS_PITCH) < ndata(c3,PS_PITCH) if c10 = 0 c10 = 1 end if c10 = -1 c10 = 1000 end end end end repeat if c10 = 1000 goto PS_CL end goto PS_UNIS /* typeset unison end if c4 = 1 or c4 = -1 if ndata(c2,PS_PASS) <> ndata(c3,PS_PASS) goto PS_CL end end end end end repeat end repeat no clashes found putc No clashes typeset chords loop for c4 = 1 to 2 /* typeset stem down first c5 = 2 - c4 PS_C: c6 = 0 c7 = 0 loop for c2 = 1 to pcnt if ndata(c2,PS_PASS) > 0 and bit(0,ndata(c2,PS_STEM)) = c5 if ndata(c2,PS_PITCH) > c6 /* typeset highest pitch first c6 = ndata(c2,PS_PITCH) c7 = ndata(c2,PS_PASS) end end repeat if c7 > 0 c8 = 100 perform ps_setchord (c7, c8, c10) goto PS_C end repeat Note: When you have reached this point in the code, you have determined the local position of all notes (but not rests) in the simultaneity. The arrays gr(.,.) and gl(,.,) have been computed (if there were notes in the simultaneity). You can now use this information to try to place any rests vertically as best you can. After this, you need to compute the NODE_SHIFT parameter (from emptyspace(.,.) and gl(,.,) and then the new values for emptyspace(.,.) putc typeset music on page loop for c2 = 1 to npasses putc position of chord ~c2 is ~printpos(c2) repeat Now store results in set array (watch out for c9 and c10 in this loop) c2 = 0 c5 = 0 pitchcnt(1) = 0 pitchcnt(2) = 0 loop for c1 = a1 to a2 ++c2 c4 = ts(c1,STAFF_NUM) + 1 /* staff number thispass = ndata(c2,PS_PASS2) if thispass <> c5 c5 = thispass ++pitchcnt(c4) end if ndata(c2,PS_PITCH) = 100 /* rest ntype = ndata(c2,PS_COLOR) c6 = ntype << 1 - 1 c8 = int("1008060402020402030303"{c6,2}) c7 = int("0505050505030301000101"{c6,2}) if ps_passcount(c4) = 1 c3 = vpar(4) if ts(c1,MULTI_TRACK) >= 4 c6 = ts(c1,MULTI_TRACK) >> 2 if c6 = 1 c3 -= vpar(2) end if c6 = 2 c3 += vpar(4) end end else if ps_passcount(c4) = 2 if pitchcnt(c4) = 1 if chr(ts(c1+1,TYPE)) in [NOTE,CUE_NOTE] c3 = ts(c1+1,STAFFLOC) else 05/10/05 Addition to allow a single rest (expressing parallel rests) to be located at vpar(4), the middle staff line. Note: this work-around may not cover all cases. if ts(c1+1,TYPE) = REST and ts(c1+1,CLAVE) = 200 c3 = vpar(4) goto RTYY3 else c3 = vpar(2) if ts(c1,NTYPE) < EIGHTH and c3 > 0 if (ts(c1,NTYPE) & 0xff) < EIGHTH and c3 > 0 /* new 10/15/07 c3 = 0 end end c3 = vpar(2) if ts(c1,NTYPE) < EIGHTH and c3 > 0 c3 = 0 end end c6 = 0 - c3 / vpar(1) + 23 c11 = c3 + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c11 c13 = c6 loop while gr(c4,c6) <> -200 c3 -= vpar(1) c3 -= vpar(1) c11 = c3 * 2 / vpar(2) c3 -= rem /* tricky code ++c6 repeat c6 -= c7 /* c7 is lower part of rest loop while gr(c4,c6) <> -200 c3 -= vpar(1) c3 -= vpar(1) c11 = c3 * 2 / vpar(2) c3 -= rem /* tricky code ++c6 repeat if c6 > c13 + 8 c3 += vpar(2) end if c3 > vpar(2) c3 = vpar(2) end c6 = c3 / notesize if rem <> 0 c3 -= vpar(1) /* OK 4-21-95 end else if chr(ts(c1-1,TYPE)) in [REST,CUE_REST] if ts(c1-1,CLAVE) < 200 or scr_flag = 0 c3 = vpar(8) else c3 = vpar(4) goto RTYY3 end else c3 = ts(c1-1,STAFFLOC) + vpar(2) end c6 = 0 - c3 / vpar(1) + 23 c11 = c3 + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c11 c13 = c6 loop while gr(c4,c6) <> -200 c3 += vpar(1) c11 = c3 * 2 / vpar(2) if rem <> 0 /* tricky code ++c3 end c3 += vpar(1) --c6 repeat c6 += c8 /* c8 is "clearance" at top of rest loop while gr(c4,c6) <> -200 c3 += vpar(1) c11 = c3 * 2 / vpar(2) if rem <> 0 /* tricky code ++c3 end c3 += vpar(1) --c6 repeat if c6 < c13 - 8 c3 -= vpar(2) end if c3 < vpar(8) c3 = vpar(8) end c6 = c3 / notesize if rem <> 0 c3 += vpar(1) c3 = c6 + 1 * notesize end end else if pitchcnt(c4) = 1 if chr(ts(c1+1,TYPE)) in [NOTE,CUE_NOTE] c3 = ts(c1+1,STAFFLOC) else c3 = vpar(2) end if ts(c1,NTYPE) < EIGHTH and c3 > 0 if (ts(c1,NTYPE) & 0xff) < EIGHTH and c3 > 0 /* new 10/15/07 c3 = 0 end c6 = 0 - c3 / vpar(1) + 23 c11 = c3 + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c11 c13 = c6 loop while gr(c4,c6) <> -200 c3 -= vpar(1) c3 -= vpar(1) c11 = c3 * 2 / vpar(2) c3 -= rem /* tricky code ++c6 repeat c6 -= c7 /* c7 is lower part of rest loop while gr(c4,c6) <> -200 c3 -= vpar(1) c3 -= vpar(1) c11 = c3 * 2 / vpar(2) c3 -= rem /* tricky code ++c6 repeat if c6 > c13 + 8 c3 += vpar(2) end if c3 > vpar(2) c3 = vpar(2) end c6 = c3 / notesize if rem <> 0 c3 -= vpar(1) /* OK 4-21-95 end else if pitchcnt(c4) = ps_passcount(c4) if chr(ts(c1-1,TYPE)) in [REST,CUE_REST] if ts(c1-1,CLAVE) < 200 or scr_flag = 0 c3 = vpar(10) else c3 = vpar(4) end else c3 = ts(c1-1,STAFFLOC) + vpar(2) end c6 = 0 - c3 / vpar(1) + 23 c11 = c3 + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c11 c13 = c6 loop while gr(c4,c6) <> -200 c3 += vpar(1) c11 = c3 * 2 / vpar(2) if rem <> 0 /* tricky code ++c3 end c3 += vpar(1) --c6 repeat c6 += c8 /* c8 is "clearance" at top of rest loop while gr(c4,c6) <> -200 c3 += vpar(1) c11 = c3 * 2 / vpar(2) if rem <> 0 /* tricky code ++c3 end c3 += vpar(1) --c6 repeat if c6 < c13 - 8 c3 -= vpar(2) end if c3 < vpar(8) c3 = vpar(8) end c6 = c3 / notesize if rem <> 0 c3 += vpar(1) c3 = c6 + 1 * notesize end else Look for empty space in middle of staff loop for c3 = 45 to 1 step -1 repeat while gr(c4,c3) = -200 if c3 <= 21 /* suppose there's nothing up there c3 += 3 if c3 < 19 c3 = 19 end goto RTYY2 end loop while c3 > 0 --c3 repeat while gr(c4,c3) <> -200 RTYY: loop for c6 = 1 to 8 --c3 repeat while c3 > 0 and gr(c4,c3) = -200 if c6 = 8 or c3 <= 0 c3 += 3 else goto RTYY end RTYY2: c3 = 23 - c3 * vpar(1) c3 = 43 - c3 / 2 * vpar(2) c3 += rem * vpar(1) c3 -= vpar20 end end end end RTYY3: if ts(c1,CLAVE) < 200 or scr_flag = 0 if ts(c1,STAFFLOC) = 1 c3 = vpar(4) end ts(c1,STAFFLOC) = c3 perform rest_occupy_space (c3,c4) /* ntype is read directly ts(c1,OBY) = ts(c1,STAFFLOC) end else c3 = ndata(c2,PS_COLOR) if c3 < 3 c4 = hpar(82) else if c3 = 3 c4 = hpar(83) else c4 = hpar(84) end end if ndata(c2,PS_NSIZE) = CUESIZE c4 = c4 * 8 / 10 end c4 -= 1 Note: LOCAL_XOFF will now be set for this notehead, and will not be changed. The value is negative, zero, or positive by the approximate thickness of a notehead. This information can be used in the final computation of P10 for this notehead. ts(c1,LOCAL_XOFF) = c4 * ndata(c2,PS_XPOS) /* uniquely set here NOTE: Do not call procedure get_topbottom before this point in the program Note: We are about to set GLOBAL_XOFF for all noteheads in a chord to the value in printpos(thispass). The spacing of simultaneous chords in this program is hopelessly complicated. Therefore we cannot know directly whether a notehead has been shifted exactly one thickness to the right or left, or whether the shift has been built up in several parts. All we know is that the shift adds up to GLOBAL_XOFF. In order to set the NOTE_DISP parameter properly, we will need to compare GLOBAL_XOFF with autoscr's normal shift distance = (width of black note - 2). If GLOBAL_XOFF is within 2 dots either side of +/- (hpar(82) - 2), then we will infer that the shift was an integral notehead thickness; otherwise we must record the shift measured in dots. A shift of an integral notehead thickness will be recorded as -100 or +100. if chr(ts(c1,TYPE)) in [NOTE,CUE_NOTE,GR_NOTE] c9 = c1 ts(c1,GLOBAL_XOFF) = printpos(thispass) All New code 05/02/03 At this point, we need to see if the note object position has been modified "absolutely" by a print suggestion. If this is the case, we need to make the adjustment here, AND, elimate the suggestion from the tsr string. c4 = ts(c1,TSR_POINT) c3 = ors(tsr(c4){2}) if bit(0,c3) = 1 px = ors(tsr(c4){3}) if px > 0 px = px - 128 * notesize / 10 11/24/07 We need to take action in both the relative and absolute cases of x-shift. Apparently, there is a difference, at least here. Relative shift ("x") is added to whatever is already in the GLOBAL_XOFF; whereas absolute shift ("X") replaces any value in GLOBAL_XOFF. This holds for note placement, but I am unclear whether it is true for musical signs, dynamics, etc. pxx = c3 & 0x02 >> 1 if pxx = 1 /* true when "X" is used ts(c1,GLOBAL_XOFF) = px tsr(c4){3} = chr(0) /* here is where suggestion is zeroed out else ts(c1,GLOBAL_XOFF) += px tsr(c4){3} = chr(0) /* here is where suggestion is zeroed out end if pxx = 1 /* true when "X" is used ts(c1,GLOBAL_XOFF) = px tsr(c4){3} = chr(0) /* here is where suggestion is zeroed out end end end printpos(thispass) = ts(c1,GLOBAL_XOFF) End of new code 05/02/03 #if AUTOSCR c3 = printpos(thispass) if c3 <> 0 if ts(c1,TYPE) = NOTE c4 = hpar(82) - 2 /* autoset doesn't shift full width else c4 = hpar(82) * 8 / 10 - 2 end if abs(c3) > c4 - 3 and abs(c3) < c4 + 3 if c3 > 0 ts(c1,NOTE_DISP) = 100 else ts(c1,NOTE_DISP) = -100 end else ts(c1,NOTE_DISP) = scr_qwidth * INT10000 + c3 end else ts(c1,NOTE_DISP) = 0 end #endif c10 = c1 + 1 loop while ts(c10,TYPE) = ts(c1,TYPE) + 1 ++c10 repeat --c10 else ts(c1,GLOBAL_XOFF) = c9 * INT10000 + c10 /* temporary storage of indexes ts(c1,NOTE_DISP) = ts(c9,NOTE_DISP) end end repeat *************************************************************** Debug Information if bit(2,pmode) = 1 and g >= debug_point Condition changed 01/01/06 g = measnum - 1 if (bit(2,pmode) = 1 or debug_flag = 1) and g >= debug_point putc Set Array at Point No. 3: measure ~g putc Look? getc jtype if jtype = "y" perform display_ts end end End debug information *************************************************************** goto PS_END Clashes PS_CL: putc clash c2 = ~c2 c3 = ~c3 c4 = ndata(c2,PS_PASS) c5 = ndata(c3,PS_PASS) if ndata(c2,PS_DOT) > 0 and ndata(c3,PS_DOT) = 0 c7 = c5 goto PS_CLT end if ndata(c2,PS_DOT) = 0 and ndata(c3,PS_DOT) > 0 c7 = c4 goto PS_CLT end if bit(0,ndata(c2,PS_STEM)) = UP and bit(0,ndata(c3,PS_STEM)) = DOWN c7 = c4 goto PS_CLT end if bit(0,ndata(c2,PS_STEM)) = DOWN and bit(0,ndata(c3,PS_STEM)) = UP c7 = c5 goto PS_CLT end if ndata(c2,PS_PITCH) >= ndata(c3,PS_PITCH) c7 = c4 else c7 = c5 end PS_CLT: putc clash between pitch chords ~c4 and ~c5 c8 = 100 perform ps_setchord (c7, c8, c10) goto PS_B * PS_UNIS: putc unison c2 = ~c2 c3 = ~c3 c7 = ndata(c2,PS_PASS) c8 = ndata(c3,PS_PASS) perform ps_setchord (c7, c8, c10) goto PS_B PS_END: At this point you have accomplished tasks (1), (2), and (3) for the case of multiple note heads on a division. You now need to do the following (for all ts(.,.) elements from a1 to a2). (4) Compute the x and y offsets for any dot(s) which might follow each note head. (5) Compute the x offset (as measured to the left) of any accidental(s) which might precede each note head. (4) X and Y offsets for dots (a) determine number and spacing of note heads on each stave to determine method of placement of dots. Use column method if note heads (with dots) occur on space and line on the same staff. Otherwise use conventional placement. (This code assumes MAX_STAFF <= 3) First find all staves where all offsets (global and local) are zero. In these cases, we can use the absolute method. tgroup(1) = 4 tgroup(2) = 4 tgroup(3) = 4 loop for c1 = a1 to a2 c8 = ts(c1,STAFF_NUM) + 1 /* staff number if chr(ts(c1,TYPE)) in [NOTE,CUE_NOTE,GR_NOTE] if ts(c1,GLOBAL_XOFF) > 0 tgroup(c8) = 0 end end if ts(c1,LOCAL_XOFF) > 0 tgroup(c8) = 0 end repeat loop for c1 = a1 to a2 if ts(c1,DOT) > 0 c8 = ts(c1,STAFF_NUM) + 1 /* staff number if tgroup(c8) <> 4 c9 = ts(c1,STAFFLOC) / vpar(1) c9 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c9 = bit(0,c9) + 1 if tgroup(c8) = 0 tgroup(c8) = c9 else if tgroup(c8) <> c9 tgroup(c8) = 3 /* use column method end end end end repeat (b) for those staves using the column method, determine the x offset of the column. c5 = 0 loop for c8 = 1 to 3 if tgroup(c8) = 3 tgroup(c8) = 1 c5 = 1 else tgroup(c8) = 0 end repeat if c5 = 1 loop for c1 = a1 to a2 if ts(c1,GLOBAL_XOFF) < INT10000 c9 = ts(c1,GLOBAL_XOFF) /* global offset end if ts(c1,DOT) > 0 c8 = ts(c1,STAFF_NUM) + 1 /* staff number if tgroup(c8) > 0 c7 = c9 + ts(c1,LOCAL_XOFF) /* note head position c10 = ts(c1,TYPE) / 3 if rem = 0 if ts(c1,NTYPE) > QUARTER c3 = hpar(30) else c3 = hpar(31) end else if ts(c1,NTYPE) > HALF c3 = hpar(32) else c3 = hpar(33) end end if rem = 1 and bit(1,ts(c1,STEM_FLAGS)) = UP if ts(c1,BEAM_FLAG) = NO_BEAM and ts(c1,NTYPE) < QUARTER c3 += hpar(27) end end if ts(c1,TYPE) > REST c3 = c3 * 8 / 10 end c7 += c3 /* dot position for this note head if tgroup(c8) < c7 tgroup(c8) = c7 end end end repeat (c) place dots for all staves which use the column method (relative x placement; absolute y placement) Starting with the left-most objects in the "musical node" and moving to the right, set dot positions according to the following algorithm (keeping track of all previous dots for this stave): Start with the note head furtherest from note-end of stem If note on line, if space above is free, put dot there else put dot in first free space below else if space is free, put dot there else put dot in first free space in reverse direction end loop for c13 = 1 to 3 /* loop though staves if tgroup(c13) > 0 c5 = 0 c10 = 0 /* count up for stems up c11 = 1000 /* count down for stems down Special case: two notes on stave and multi-tracks on this stave if a2 = a1 + 1 if ts(a1,MULTI_TRACK) >= 4 if abs(ts(a1,STAFFLOC) - ts(a2,STAFFLOC)) > notesize if bit(1,ts(a1,STEM_FLAGS)) <> bit(1,ts(a2,STEM_FLAGS)) loop for c1 = a1 to a2 c8 = ts(c1,GLOBAL_XOFF) if c8 >= INT10000 c8 /= INT10000 c8 = ts(c8,GLOBAL_XOFF) end #if AUTOSCR Start by setting the SCORE P9 parameter (AUG_DOTS) c16 = ts(c1,STAFFLOC) / notesize c16 = rem /* set 16 to rem c9 = tgroup(c13) if ts(c1,TYPE) > XNOTE c9 = c9 * 10 + 6 / 8 end if ts(c1,NTYPE) > HALF if (ts(c1,NTYPE) & 0xff) > HALF /* new 10/15/07 c9 -= hpar(32) else c9 -= hpar(33) end if c9 < 3 c9 = 0 end if ts(c1,TYPE) > XNOTE c9 = c9 * 8 / 10 end c9 = c9 * 30 / scr_qwidth /* 100ths part of P9 if c9 > 99 c9 = 99 end c10 = ts(c1,DOT) & 0x0f c10 = int("1.2...3.......4"{c10}) /* convert to SCORE code c10 *= 10 if c16 = 0 and bit(1,ts(c1,STEM_FLAGS)) = DOWN c10 += 100 end c10 = c10 << 8 + c9 ts(c1,AUG_DOTS) = c10 #endif c10 = ts(c1,STAFFLOC) c9 = c10 / notesize if rem = 0 /* note on line if bit(1,ts(c1,STEM_FLAGS)) = UP c10 -= vpar(12) else c10 += vpar(12) end end c10 -= ts(c1,OBY) /* convert to relative y offset c9 = tgroup(c13) - c8 /* relative x offset from obx c9 *= INT10000 c9 += c10 c9 <<= 4 /* code modified 12-24-96 ts(c1,DOT) |= c9 repeat goto X_DOT end end end end /* global offset loop for c1 = a1 to a2 if ts(c1,GLOBAL_XOFF) < INT10000 c9 = ts(c1,GLOBAL_XOFF) /* global offset end c8 = ts(c1,STAFF_NUM) + 1 /* staff number if ts(c1,DOT) > 0 and c8 = c13 /* dot on this staff ++c5 c12 = bit(1,ts(c1,STEM_FLAGS)) if c12 = UP /* stem up ndata(c5,1) = c10 ++c10 else ndata(c5,1) = c11 --c11 end ndata(c5,1) += c9 * 10000 /* tricky code (for ordering) ndata(c5,2) = c1 ndata(c5,3) = c12 /* stem direction ndata(c5,4) = c9 /* global x offset ndata(c5,5) = 100 end repeat Sort the ndata array by ndata(.,1) smallest on top first by global offset, then by stem (up first), then by order on stem (up in order, down reverse order) loop for c8 = 1 to c5 c6 = 10000000 loop for c4 = 1 to c5 if ndata(c4,5) = 100 and ndata(c4,1) < c6 c6 = ndata(c4,1) c7 = c4 end repeat ndata(c7,6) = c8 ndata(c7,5) = 0 repeat Typeset dots on this staff loop for c8 = 1 to 50 mf(c8) = 0 repeat loop for c8 = 1 to c5 c7 = ndata(c8,6) /* typeset this note head c1 = ndata(c7,2) /* c1 is the index c9 = tgroup(c13) - ndata(c7,4) /* relative x offset from obx c4 = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 c16 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c4 = 23 - c16 /* 23 = top line of staff If note on line, if space above is free, put dot there else put dot in first free space below else if space is free, put dot there else put dot in first free space in reverse direction end if bit(0,c4) = 1 /* if note on line if mf(c4+1) = 0 mf(c4+1) = 1 c10 = c4 + 1 /* absolute y offset (23 = top line) else c10 = 0 --c4 loop if mf(c4) = 0 mf(c4) = 1 c10 = c4 else c4 -= 2 if c4 = 0 putc Program error setting dots stop end end repeat while c10 = 0 end else /* else, note on space if mf(c4) = 0 mf(c4) = 1 c10 = c4 else if ndata(c7,3) = UP /* if stem up, look up c10 = 0 c4 += 2 loop if mf(c4) = 0 mf(c4) = 1 c10 = c4 else c4 += 2 if c4 = 50 putc Program error setting dots stop end end repeat while c10 = 0 else /* else, stem is down; look down c10 = 0 c4 -= 2 loop if mf(c4) = 0 mf(c4) = 1 c10 = c4 else c4 -= 2 if c4 = 0 putc Program error setting dots stop end end repeat while c10 = 0 end end end c10 is the absolute y position (23 = top line) for the dot(s) c10 = 23 - c10 * vpar(1) /* convert to absolute staff position c10 = 43 - c10 / 2 * vpar(2) c10 += rem * vpar(1) c10 -= vpar20 #if AUTOSCR This is all getting pretty hairy, but we need to try to convert the current shift data to data that SCORE can use. The problem with SCORE is that it does not allow a dot to be shifted down by more than one scale step. This creates problems even for SCORE data entry, but it creates nightmares for conversion, unless we simply set every dot using CODE-9 items. I will attempt a compromise. If the y-position is "settable" with a SCORE P9 parameter, I will do it; otherwise we need to use a CODE-9 item. I shutter to think of what the output of this will look like. Use c7,c16,c4,c12 c16 = ts(c1,STAFFLOC) c4 = c16 / notesize c4 = rem if (c4 = 0 and abs(c16 - c10) < vpar(2)) or (c4 <> 0 and c16 = c10) /* can set with SCORE c7 = c9 if ts(c1,TYPE) > XNOTE c7 = c7 * 10 + 6 / 8 end if ts(c1,NTYPE) > HALF if (ts(c1,NTYPE) & 0xff) > HALF /* new 10/15/07 c7 -= hpar(32) else c7 -= hpar(33) end if c7 < 3 c7 = 0 end if ts(c1,TYPE) > XNOTE c7 = c7 * 8 / 10 end c12 = ts(c1,GLOBAL_XOFF) if c12 >= INT10000 c12 /= INT10000 /* index to top note c12 = ts(c12,GLOBAL_XOFF) end c7 = c7 * 30 / scr_qwidth /* 100ths part of P9 if c7 > 99 c7 = 99 end c12 = ts(c1,DOT) & 0x0f c12 = int("1.2...3.......4"{c12}) /* convert to SCORE code c12 *= 10 if c4 = 0 and c10 > c16 /* dot below notehead c12 += 100 end c12 = c12 << 8 + c7 ts(c1,AUG_DOTS) = c12 else ts(c1,AUG_DOTS) = 0x01000000 /* goto CODE-9 ts(c1,AUG_DOTS) += (c9 * INT10000) ts(c1,AUG_DOTS) += c10 end #endif Store relative values of x and y for this note head c9 is the relative x shift to the dot(s) from obx x * INT10000 + y, shift it over 4 and OR it DOT (modified 12-24-96) c9 *= INT10000 c10 -= ts(c1,OBY) /* convert to relative y offset c9 += c10 c9 <<= 4 /* code modified 12-24-96 ts(c1,DOT) |= c9 repeat X_DOT: end repeat end (d) place dots for all remaining note heads (absolute placement first) old_c2 = 10000 /* added 11/26/06 loop for c1 = a1 to a2 if ts(c1,DOT) > 0 and ts(c1,DOT) < INT9000 /* dot not yet placed ntype = ts(c1,NTYPE) ntype = ts(c1,NTYPE) & 0xff /* new 10/15/07 c10 = ts(c1,TYPE) / 3 if rem = 0 /* rests if ntype > QUARTER c3 = hpar(30) else c3 = hpar(31) end else if ntype > HALF c3 = hpar(32) else c3 = hpar(33) end end c6 = ts(c1,STAFFLOC) / vpar(1) c6 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c5 = ts(c1,STAFFLOC) / notesize c5 = rem /* c5 = 0 means note on line if bit(1,ts(c1,STEM_FLAGS)) = UP if ts(c1,BEAM_FLAG) = NO_BEAM and ts(c1,NTYPE) < QUARTER c10 = ts(c1,TYPE) / 3 if rem = 1 c3 += hpar(27) if c5 <> 0 c3 -= hpar(34) end end end end * if dot is on staff line, c5 = 0 if c5 = 0 c2 = 0 - vpar(12) /* lower dot if more than one track and stem is down if bit(3,ts(c1,MULTI_TRACK)) = 1 if bit(1,ts(c1,STEM_FLAGS)) = DOWN c2 = vpar(12) end end c3 -= hpar(34) else c2 = 0 end if ts(c1,TYPE) <= REST c5 = bit(16,ts(c1,SUBFLAG_1)) else c5 = CUESIZE end if c5 = 1 c3 = c3 * 8 / 10 end c2 += ts(c1,STAFFLOC) #if AUTOSCR if ts(c1,TYPE) <> REST and ts(c1,TYPE) <> CUE_REST use c7,c16,c4,c12,c5 c16 = ts(c1,STAFFLOC) c4 = c16 / notesize c4 = rem if (c4 = 0 and abs(c16 - c2) < vpar(2)) or (c4 <> 0 and c16 = c2) /* can set with SCORE c7 = c3 if ts(c1,TYPE) > XNOTE c7 = c7 * 10 + 6 / 8 end if ts(c1,NTYPE) > HALF if (ts(c1,NTYPE) & 0xff) > HALF /* new 10/15/07 c7 -= hpar(32) else c7 -= hpar(33) end if c4 = 0 c7 += hpar(34) end if c7 < 3 c7 = 0 end if ts(c1,TYPE) > XNOTE c7 = c7 * 8 / 10 end c12 = ts(c1,GLOBAL_XOFF) if c12 >= INT10000 c12 /= INT10000 c12 = ts(c12,GLOBAL_XOFF) end c7 = c7 * 30 / scr_qwidth /* 100ths part of P9 if c7 > 99 c7 = 99 end c12 = ts(c1,DOT) & 0x0f c12 = int("1.2...3.......4"{c12}) /* convert to SCORE code c12 *= 10 if c4 = 0 and c2 > c16 /* dot below notehead c12 += 100 end c12 = c12 << 8 + c7 ts(c1,AUG_DOTS) = c12 else c12 = ts(c1,DOT) & 0x0f c12 = int("1.2...3.......4"{c12}) /* convert to SCORE code c12 <<= 24 ts(c1,AUG_DOTS) = c12 /* goto CODE-9 ts(c1,AUG_DOTS) += (c3 * INT10000) ts(c1,AUG_DOTS) += c2 end end #endif c2 -= ts(c1,OBY) This code added 11/26/06 (as a cludge) to fix a minor bug in the placement extension dots when one is "on top of" another. if ts(c1,TYPE) = XNOTE or ts(c1,TYPE) = XCUE_NOTE or ts(c1,TYPE) = XGR_NOTE if abs(old_c2 - c2) < vpar(1) c2 += vpar(2) end end old_c2 = c2 End of 11/26/06 addition /* c3 = x offset to the dot(s) from obx /* c2 = y offset to the dot(s) from oby /* x * INT10000 + y, shift it over 4 and OR it with DOT (modified 12-24-96) c3 *= INT10000 c3 += c2 c3 <<= 4 /* code modified 12-24-96 ts(c1,DOT) |= c3 end repeat Adjust the gr(.,.) array to accommodate space for dots c17 = 0 /* used below loop for c1 = a1 to a2 if ts(c1,GLOBAL_XOFF) < INT10000 c9 = ts(c1,GLOBAL_XOFF) /* global offset end c8 = ts(c1,STAFF_NUM) + 1 /* staff number Special code added to deal with the discrepency in how single vs. multiple tracks handle the minimal spacing for dotted rests. 04/19/08 This section computes the value of the right hand border for the dot, c7 It also sets the exception variable c17 = 1 c7 = 10000 /* "normal" condition if scr_flag = 1 if c1 < a2 and ts(c1,TYPE) = REST if ts(c1+1,TYPE) = REST and ts(c1+1,CLAVE) = 200 if ts(c1,DOT) > 0 c7 = 1 end c17 = 1 /* used below end end end c3 = ts(c1,DOT) if c3 > 0 if c7 = 1 ntype = ts(c1,NTYPE) & 0xff c4 = 0 if ntype <= SIXTEENTH c4 = EIGHTH - ntype end if ntype > QUARTER c7 = hpar(30) else c7 = c4 * hpar(54) + hpar(31) end c7 += hpar(80) if ntype > WHOLE c4 = hpar(87) * 4 / 3 else if ntype > QUARTER c4 = hpar(87) else if ntype > EIGHTH c4 = hpar(88) else c4 = EIGHTH - ntype * hpar(54) + hpar(88) end end end c7 += c4 if ts(c1,DOT) & 0x0e > 0 if ts(c1,DOT) & 0x02 > 0 c7 += hpar(91) /* extra shift to second dot end if ts(c1,DOT) & 0x04 > 0 c7 += hpar(91) /* extra shift to third dot end if ts(c1,DOT) & 0x08 > 0 c7 += hpar(91) /* extra shift to fourth dot end end dputc gr(.) = ~c7 end c4 = c3 & 0x0f /* dot flag (modified 12-24-96) c3 >>= 4 /* code modified 12-24-96 c5 = c3 / INT10000 /* x offset c6 = rem /* y offset if c6 > INT10000 >> 1 c6 -= INT10000 ++c5 end c6 = c6 + vpar(8) - 1 / vpar(1) - 7 c6 = c6 + vpar(8) * 2 - 1 / vpar(2) - 7 c6 = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 - c6 c16 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c6 = 23 - c16 - c6 c5 += c9 + ts(c1,LOCAL_XOFF) /* final offset for dot c5 += hpar(80) if c4 > 1 /* code modified 12-24-96 c5 += hpar(91) /* second dot if c4 > 4 c5 += hpar(91) /* third dot end if c4 > 8 c5 += hpar(91) /* fourth dot end end if c6 < 46 and c6 > 0 More code added to deal with the discrepency in how single vs. multiple tracks handle the minimal spacing for dotted rests. 04/19/08 This section sets the value of the right hand object "border" gr(.,.) gr(c8,c6) = c5 if c7 = 10000 /* "normal" condition gr(c8,c6) = c5 else gr(c8,c6) = c7 if c6 < 44 gr(c8,c6+1) = c7 gr(c8,c6+2) = c7 end end end end repeat (5) Compute the x offset (as measured to the left) of any accidental(s) which might precede each note head. (a) Check the left-hand border from the typesetting operation. If there are any accidentals that could be set on right- shifted note heads, set these first, starting from the top down. This defines column 1 of the accidentals. Otherwise, column one is the first free location to the left of the left-most note head. (b) For all remaining accidentals to set, start at the top of the group. Make successive passes until all accidentals are set. 1. moving down, put in as many accidentals as possible where the distance between eligible notes (delta) >= vpar(6), with the caviat that you do not put an accidental on the lower half of a second before the upper half of a second (as you move down). 2. move to the left by the largest thickness of accidentals just placed. Decide on the direction to move for the next pass and goto (a). The new direction will be down (again) if the previous pass hit the lowest remaining accidental; otherwise, the new direction will be up. (Maximum staves for this code is 2, because this is the size of gl(.,.)) tgroup(1) = 0 tgroup(2) = 0 tgroup(3) = 0 c5 = 0 loop for c1 = a1 to a2 if ts(c1,AX) > 0 c8 = ts(c1,STAFF_NUM) + 1 /* staff number ++tgroup(c8) ndata(tgroup(c8),c8) = c1 c5 = 1 end repeat if c5 = 1 /* Don't change this variable (c5) /* until task (1) is complete loop for c13 = 1 to 2 /* loop though staves if tgroup(c13) > 0 if a1 = a2 /* simple case (one note group) c1 = ndata(1,c13) /* index c3 = ts(c1,AX) & 0x0f c2 = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 c16 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c2 = 23 - c16 if ts(c1,TYPE) > REST c4 = CUESIZE else c4 = bit(16,ts(c1,SUBFLAG_1)) end perform place_accidental (c13,c2,c3,c4) /* returns c4 = absolute x ts(c1,AX_DISP) = c3 /* capture this parameter, from place_accidental /* shift offset left 8 and OR with AX c4 = 0 - c4 c4 <<= 8 /* 02/25/97 shift changed from 4 to 8 ts(c1,AX) |= c4 else (1) We must re-order elements so that they are in descending order on the staff. Use bubble sort. loop for c7 = 1 to tgroup(c13) - 1 loop for c8 = c7+1 to tgroup(c13) c1 = ndata(c7,c13) c2 = ndata(c8,c13) if ts(c1,STAFFLOC) > ts(c2,STAFFLOC) ndata(c7,c13) = c2 ndata(c8,c13) = c1 end repeat repeat (2) Try first to set accidentals on "right shifted chords" loop for c8 = 1 to tgroup(c13) c1 = ndata(c8,c13) if c8 > 1 c2 = ndata(c8-1,c13) if c2 < DUMMY_VALUE if ts(c1,STAFFLOC) - ts(c2,STAFFLOC) = vpar(1) /* second c16 = ts(c1,STAFFLOC) - ts(c2,STAFFLOC) if c16 = vpar(1) or c16 = vpar(1) + 1 /* second if ts(c1,LOCAL_XOFF) < ts(c2,LOCAL_XOFF) /* don't set accidental in this situation goto QQQ1 end end end end c2 = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 c16 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c2 = 23 - c16 c4 = 200 c12 = ts(c1,AX) & 0x0f c14 = c2 - int("221002200100001"{c12}) /* lower limit c15 = c2 + int("333003300200003"{c12}) /* upper limit loop for c3 = c14 to c15 if c3 > 0 and c3 <= 45 if gl(c13,c3) <= 0 c3 = 1000 else if gl(c13,c3) < c4 c4 = gl(c13,c3) end end end repeat if c3 < 1000 c3 = ts(c1,AX) & 0x0f if ts(c1,TYPE) > REST c4 = CUESIZE else c4 = bit(16,ts(c1,SUBFLAG_1)) end perform place_accidental (c13,c2,c3,c4) /* returns c4 = absolute x ts(c1,AX_DISP) = c3 /* capture this parameter, from place_accidental c3 = ts(c1,GLOBAL_XOFF) if c3 > INT10000 c3 /= INT10000 /* index of top of chord c3 = ts(c3,GLOBAL_XOFF) end c6 = c3 - c4 /* relative x offset (to the left) /* shift offset left 8 and OR with AX c6 <<= 8 /* 02/25/97 shift changed from 4 to 8 ts(c1,AX) |= c6 ndata(c8,c13) = DUMMY_VALUE /* accidental set end QQQ1: repeat (3) Now make successive passes until all accidentals are set c10 = DOWN loop c6 = 0 loop for c8 = 1 to tgroup(c13) if ndata(c8,c13) <> DUMMY_VALUE /* accidental not set c6 = c8 end repeat if c6 = 0 goto QQQ2 /* DONE end if c10 = DOWN c11 = 1 c12 = tgroup(c13) c9 = 1 else c11 = tgroup(c13) c12 = 1 c9 = -1 end c10 = UP loop for c8 = c11 to c12 step c9 c1 = ndata(c8,c13) if c1 = DUMMY_VALUE goto QQQ3 end if c8 > 1 c2 = ndata(c8-1,c13) if c2 < DUMMY_VALUE if ts(c1,STAFFLOC) - ts(c2,STAFFLOC) = vpar(1) /* second c16 = ts(c1,STAFFLOC) - ts(c2,STAFFLOC) if c16 = vpar(1) or c16 = vpar(1) + 1 /* second if ts(c1,LOCAL_XOFF) < ts(c2,LOCAL_XOFF) /* don't set accidental in this situation goto QQQ3 end end end end if c8 = c6 c10 = DOWN end c2 = 0 - ts(c1,STAFFLOC) / vpar(1) + 23 c16 = ts(c1,STAFFLOC) + vpar20 * 2 + 1 / vpar(2) - 20 c2 = 23 - c16 c3 = ts(c1,AX) & 0x0f if ts(c1,TYPE) > REST c4 = CUESIZE else c4 = bit(16,ts(c1,SUBFLAG_1)) end perform place_accidental (c13,c2,c3,c4) /* returns c4 = absolute x ts(c1,AX_DISP) = c3 /* capture this parameter, from place_accidental c3 = ts(c1,GLOBAL_XOFF) if c3 > INT10000 c3 /= INT10000 /* index of top of chord c3 = ts(c3,GLOBAL_XOFF) end c15 = c3 - c4 /* relative x offset (to the left) /* shift offset left 8 and OR with AX c15 <<= 8 /* 02/25/97 shift changed from 4 to 8 ts(c1,AX) |= c15 ndata(c8,c13) = DUMMY_VALUE /* accidental set QQQ3: repeat repeat QQQ2: end end repeat end Task (1) Calculate NODE_SHIFT c10 = 0 if c17 = 0 /* set above loop for a3 = 1 to nstaves loop for c11 = 1 to 45 if gl(a3,c11) > pseudo_gl(a3,c11) gl(a3,c11) = pseudo_gl(a3,c11) end 11/19/07 min_space replaces hpar(29) c12 = min_space - gl(a3,c11) - emptyspace(a3,c11) /* should be negative if c11 >= 14 and c11 <= 22 dputc Sorry c12 = ~c12 putc gl(~a3 ,~c11 ) = ~gl(a3,c11) putc emptyspace(~a3 ,~c11 ) = ~emptyspace(a3,c11) end if c12 > c10 /* most of the time c10 = c12 end repeat repeat if c5 > 0 and ts(a1,SPACING) = mindist and c10 < hpar(94) c10 = hpar(94) end else More code from the 04/19/08 cludge This section uses the single-track formula to compute the value of this nodes NODE_SHIFT. loop for a3 = 1 to nstaves c7 = 100000 loop for c11 = 1 to 45 if emptyspace(a3,c11) < c7 c7 = emptyspace(a3,c11) /* minimum emptyspace on this staff end repeat c10 = mindist - hpar(82) - c7 repeat end dputc Value of c10 is ~c10 if c10 > 0 ts(a1,NODE_SHIFT) = c10 end Task (2) c10 = ts(a1,SPACING) dputc spacing = ~c10 loop for a3 = 1 to nstaves loop for c6 = 1 to 45 if pseudo_gr(a3,c6) > gr(a3,c6) gr(a3,c6) = pseudo_gr(a3,c6) end if gr(a3,c6) = -200 emptyspace(a3,c6) += c10 else emptyspace(a3,c6) = c10 - gr(a3,c6) end if c6 >= 19 and c6 <= 21 dputc gr(1,~c6 ) = ~gr(1,c6) dputc emptyspace(1,~c6 ) = ~emptyspace(1,c6) end repeat repeat ╔═══════════════════════════════════════════════════════════════╗ ║ ║ ║ End of where you deal with chords and with multiple passes ║ ║ ║ ╚═══════════════════════════════════════════════════════════════╝ end MMMMM: We need to check (for now) if the present simultaneity generates a "clash" with the previous simultaneity. if olda1 > 0 c6 = -1000 loop for c3 = 1 to 2 loop for c4 = 1 to 45 c5 = oldgr(c3,c4) - gl(c3,c4) if c5 > c6 c6 = c5 end repeat repeat if c6 > ts(olda1,SPACING) + ts(olda1,NODE_SHIFT) putc Potential clash, possible program error end end loop for c3 = 1 to 2 loop for c4 = 1 to 45 oldgr(c3,c4) = gr(c3,c4) repeat repeat olda1 = a1 a1 = a2 WWWW: repeat ╔═══════════════════════════════════════════════════════════════╗ ║ ║ ║ End of calculations on the placement of notes, note-dots, ║ ║ and note-accidentals. ║ ║ ║ ╚═══════════════════════════════════════════════════════════════╝ *************************************************************** Debug Information g = measnum - 1 if bit(2,pmode) = 1 and g >= debug_point Condition changed 01/01/06 if (bit(2,pmode) = 1 or debug_flag = 1) and g >= debug_point putc Set Array at Point No. 3: measure ~g putc Look? getc jtype if jtype = "y" perform display_ts end end End debug information *************************************************************** ╔════════════════════════════════════════════════════════════════════════╗ ║ ║ ║ At this point, we have a decision to make. Either we process the ║ ║ ts array now (i.e. typeset the music) or we return from this ║ ║ procedure and let the ts array continue to grow. The question that ║ ║ must be answered is "will all outstanding slurs be processed when ║ ║ the ts array is fully processed?" If "yes", then we can go ahead ║ ║ and process the ts array; otherwise, not. ║ ║ ║ ║ The information we need is contained in the SLUR_FLAG portion ║ ║ of the ts array. We need to cycle through the array elements we ║ ║ have added, taking note of where slurs terminate and where they ║ ║ start. We need a variable to keep track of the state of slur ║ ║ completion. We call this variable bstr "outslurs". The relevant ║ ║ bits will be bits 1 to 8. When a slur is initiated, the relevant ║ ║ bit will be turned on; when a slur is terminated, the relevant ║ ║ bit will be turned off. If at the end of this process, ║ ║ outslurs = "00000000", then we can process the array. ║ ║ ║ ╚════════════════════════════════════════════════════════════════════════╝ loop for a1 = oldsct+1 to sct nodtype = ts(a1,TYPE) if nodtype <= NOTE_OR_REST a2 = ts(a1,SLUR_FLAG) & 0xff a3 = ts(a1,SLUR_FLAG) >> 8 a3 &= 0xff00 a3 += a2 /* 16 bits, i.e., stop,start,stop,start etc. if a3 > 0 a5 = 1 loop for a4 = 1 to 8 if bit(a5,a3) = 1 if outslurs{a4} = "0" /* can't stop a non-existant slur putc Slur error: Can't stop a non-existant slur (possible missing instigation) stop else outslurs{a4} = "0" end end --a5 if bit(a5,a3) = 1 if outslurs{a4} = "1" /* can't start an existing slur putc Slur error: Can't start an existing slur (possible missing termination) stop else outslurs{a4} = "1" end end a5 += 3 repeat end end repeat if outslurs <> "00000000" return end At this point we will be working with the entire ts array. First thing, we must clear the pseudo tiearr ROWs. loop for c7 = 1 to MAX_TIES if tiearr(c7,TIE_SNUM) = INT1000000 /* pseudo super number tiearr(c7,TIE_SNUM) = 0 end repeat Slur Analysis We am now in a position to compile complete information on slurs, so that they can more or less be set properly. We possess the following information for the notes on which the slur starts and ends: (1) pitch (also whether it is part of a chord, also top or not) (2) stem direction (dist from end of stem, also if beam connects) (3) pass number (4) staff number (5) values of mcat and MULTI In addition, we need to compile the following information for each slur: (1) the "high point" and "low point" for all objects on the slur staff between the starting and ending notes. Based on this analysis, it should be possible to state: (1) whether the slur has tips up or down (2) the x-shift and y-shift for the start of the slur (3) the x-shift and y-shift for the end of the slur (4) any extra curviture that might help the situation In computing the parameters in (2), (3) and (4), it may be helpful to something about the profile of the desired slur. For example: * * * * * * * * * * * * * * * * * * * * * * * * 1. * * 2. * * 3. * * 4. * * 5. * raise start raise both raise end raise both add to some a lot curviture Storage of Information We need to figure out where we are going to store this information. The way this program is constructed, it is possible (in theory at least) for eight slurs to end and for eight slurs to start on the same note. This could require as many as 32 separate parameters at one ts(.,.) element, to say nothing about the 16 curviture numbers, which must be stored somewhere. Rather than extend the size of the second dimension of the ts array by this amount, I would rather propose that we add one more element, call it SLUR_X, which would be a pointer to an additional ROW element in the ts array, somewhere below sct (the size of ts, after all, must be much larger than necessary, in order to accommodate 99.99% of all situations). While it is possible for eight slurs (four regular and four editorial) to start or end on one chord, I think it is unlikely that more than four would do so. I would therefore propose that we use a system of flags to define the meaning of a data element within the ROW. As will be explained below, the first 6 elements of the ROW are reserved for current information about the chord generating the slur, and after this, elements 7 to 32 can be used to hold data on slurs. We will need to use two elements to contain all of the data. Let us establish the convention that the first element will contain the key to the meaning of data as well as the type of slur (tips up/down), extra information on curvature, and the x-offset. Specifically, the key will occupy bits 24-27, with the slur number (1-8) being stored in bits 24-26, and bit 27 being the the start/end flag (0 = start, 1 = end). Bit 16 will be the up/down flag (0 = tips up, 1 = tips down) and bits 17-23 will contain information on extra curvature (this information is necessary only in a slur-end element). Bits 0-15 will contain the x-offset + 1000 (always a positive number). The second element will contain the absolute y-position. Since there are 26 free elements in the ROW, we can accommodate 13 data groups in this fashion (surely more than necessary). Several points to note: (1) for purposes of these calculations, and temporary data stroage, it will be simplest to record all y values as absolute y positions (relative to the staff lines). x values can be stored as offsets. (2) In cases where more than one slur starts on a note head, or more than one slur ends on a note head, care must be taken to insure that the "longer" slur stays "on top" (assuming they have tips going in the same direction). Let's take the situation pictured below: * * * * * * * * slur 1 * * * * * * * * * * slur 1a * * * * * slur 2 * * * * * * * slur 4 * * * slur 3 * * * * ** * ** * *** note 1 note 2 note 3 note 4 note 5 Slur 1 would be encountered first as we proceeded through the ts array. If we were to try to process this slur when we first encountered it, we would discover that another slur (slur 2) ended on the same note as slur 1. Since slur 2 is shorter than slur 1, (and therefore should lie "under" it), we cannot fully process slur 1 until we have processed slur 2. But in looking back to the beginning of slur 2, we see that another slur (slur 3) also starts on the same note, and that slur 3 (which also we have not seen before) must be processed before we can process slur 2. Clearly we cannot simply follow the rule of "process a slur when you first come to it". A similar argument can be used to show that you cannot simply work your way through the ts array from end to the start. Here is how the process must be conducted: You proceed forward though the ts array, but do nothing until you encounter the end of a slur (or more than one end, as in the case of note 5 above). If there is more than one slur ending on this note (chord), you can determine which one is shorter by looking backward in the array. The shorter one should be processed first. In this way, you can always be sure that shorter slurs will be processed before longer ones. This method will require extra work in keeping track of what has already been done. This is the purpose of the first 6 elements of the extra ts ROW element. In our example above, slur 4 will be the first to be processed. Since it is the first slur for both note 1 and note 2, SLUR_X records must be generated for both of these notes. In the case of note 2, this is the only slur, but for note 1 we will be processing another slur (slur 1) much later. We need to keep track of what has already transpired as a result of slur 4. The first 6 elements of the SLUR_X ROW element will contain the information listed below: (1) current y-position above object for incoming slurs. (2) " below " " " " . (3) " above " " outgoing " . (4) " below " " " " . (5) y-position for staccato, legato, etc. (6) 2 = marks above chord; 1 = marks below chord; 0 = don't use Clearly, the information about what has happened at note 1 will be available when it comes time to set slur 1. One more thing: in handling this problem, we must deal with a chord as one object. A chord may be made up of several elements (notes), and slurs coming to or leaving this chord may be coded on separate elements. Nevertheless, the processing of information requires that all data related to slurs be stored in one place. Therefore, when a slur ROW element is allocated, the pointer to the element must be put in SLUR_X for all notes in the chord. (3) It should be noted that the smallest meaningful resolution of a y-position as far as slurs are concerned is vpar(1), since the printing program treats these shifts as adjusted note positions. (4) The curvature parameter should be a number from 0 to 9 (9 being the most curved). The printing program actually uses a look-up method to determine which slur to put in a particular position. One of the characterizations of such a slur is its curvature (this is part of the slur number). It only makes sense to change this number if the new curvature is more than the "look up" value. Since increasing the curvature will put the "cross part" of the slur at a different height, a new curvature should only be suggested in those cases where it is thought that the slur will not be interfering with staff lines. One other thing: we do not know the final length of the slur until print time. It turns out that for slurs longer than a certain length (I think about .6 inches) there are varients available which are asymmetric (where the relative high point comes either earlier or later in the slur). It is possible to "make a suggestion" to the print program that an asymmetric slur be used, if one is available. Adding 10 to the curvature will suggest that the high point be delayed; and adding 20 to the curvature will suggest that the high point come earlier. Actually, as I remember it, slurs longer about 1.3 inches only come in asymmetric versions, so for slurs that appear to be really long (either many notes, or multiple measures), it might actually be helpful to make a recommendation. S U M M A R Y O F I N F O R M A T I O N (TS32) ─────────────────────────────────────────── 1. A slur is processed when its end is encountered. If there is more than one slur on a chord, the shortest one is processed first. If more than one of the same length is encountered, the one on the lowest note is processed first. 2. The first time a slur is encountered on a chord, a new ts ROW element is allocated and a pointer to it is placed in the SLUR_X element for all notes in the chord. 3. The first six elements of a slur ROW element are reserved for the following information: (1) current y-position above object for incoming slurs. (2) " below " " " " . (3) " above " " outgoing " . (4) " below " " " " . (5) y-position for staccato, legato, etc. (6) 2 = marks above chord; 1 = marks below chord; 0 = don't use 4. Specific information about slurs coming to or leaving a chord is stored in groups of three (up from two 05/06/03) elements, starting with element 7. The format is as follows: first element ──────────────────── bit 27: start/end flag (0 = start, 1 = end) bits 24-26: slur number - 1 (0 to 7) bits 17-23: curvature information (end only) bit 16: up/down flag (0 = tips up, 1 = tips down) (end only) bits 0-15: x-offset + 1000 (always a positive number) second element ───────────────────── y position relative to the staff third element (added 05/06/03) ───────────────────── integer equivalent of 4-byte print suggestion for slur ┌─────────────────────────────────────────┐ │ │ │ P R O C E S S I N G S L U R S │ │ │ └─────────────────────────────────────────┘ a14 = sct + 2 /* SLUR_X pointer loop for a1 = 1 to sct nodtype = ts(a1,TYPE) if nodtype > NOTE_OR_REST goto YYYY end a4 = ts(a1,SLUR_FLAG) & 0x00aa00aa if a4 > 0 /* a slur ends here Compile a list of all slurs that end on this note and on any other (lower) notes in this chord. a5 = a4 >> 1 a5 &= 0x00ff00ff /* a list of starts to look for ndata(1,1) = a5 ndata(1,2) = a1 pcnt = 1 perform get_topbottom (a1,c1,c2) loop for a2 = a1+1 to c2 a4 = ts(a2,SLUR_FLAG) & 0x00aa00aa if a4 > 0 /* a slur ends here a5 = a4 >> 1 a5 &= 0x00ff00ff /* a list of starts to look for ++pcnt ndata(pcnt,1) = a5 ndata(pcnt,2) = a2 end repeat a1 = c2 /* so that we don't look at these notes again examine /* 09/28/93 nsgroups = 0 c9 = pcnt /* moved here from +3 lines 09/28/93 loop for c7 = c1-1 to 1 step -1 if ts(c7,TYPE) <= NOTE_OR_REST a6 = ts(c7,SLUR_FLAG) & 0x00550055 /* starts on this note loop for c8 = 1 to pcnt a5 = ndata(c8,1) /* list of starts for this note of chord a2 = ndata(c8,2) /* index to this note of chord a7 = a6 & a5 /* a7 = matches if a7 > 0 if a7 & 0x00100010 > 0 This code a2 |= 0x00010000 /* this is a "force over" slur must be else changed if a7 & 0x00400040 > 0 to below a2 |= 0x00020000 /* this is a "force under" slur 10-09-93 end end c11 = a7 >> 8 c11 &= 0xff00 c11 += a7 & 0xff /* compact a7 into 16 bits a7 = not(a7) a5 &= a7 /* remove this slur from a5 ndata(c8,1) = a5 c10 = 0 /* slur number - 1 c6 = a2 loop while c11 > 0 if bit(0,c11) = 1 c4 = c10 & 0x03 /* slur number mod(4) c5 = 1 << (c4 * 2) c5 <<= 8 if c5 & ts(c7,SLUR_FLAG) > 0 /* this slur is forced c5 <<= 1 if c5 & ts(c7,SLUR_FLAG) = 0 c6 |= 0x00010000 /* this is a "force over" slur else c6 |= 0x00020000 /* this is a "force under" slur end end ++nsgroups sgroup(nsgroups,1) = c7 /* record index starting note sgroup(nsgroups,2) = c6 /* record index ending note (+ flags) sgroup(nsgroups,3) = c10 /* slur number - 1 end c11 >>= 2 ++c10 repeat if a5 = 0 --c9 if c9 = 0 /* no more slurs to look for c7 = 0 end end end repeat end repeat if nsgroups = 0 or c9 > 0 putc Can't find start to a slur examine stop end At this point, we have a list of slurs which end on this chord. We need to decide what to do with them. We certainly can proceed by looping though the group, but we should probably first learn something about the chords we are dealing with. For example, is the stem up or down? Where on the chords do the slurs attach? Do the note heads (or chords) have staccato, legato or spiccato marks on them? (Remember that the notes of a chord have been re-ordered so that the top note comes first; i.e., the top note head may not be at the note end of the stem.) The purpose of all of this "research" is basically to answer the following two questions: (1) should the slur be oriented with tips up or tips down, and (2) should the slur take its position from the note head or from the end of the stem? I think I have found a system which will at least (1) give an answer to every possible situation, and (2) give "right" answers for most situations. Essentially, what I will use is "situation based" programming, rather than "rule based" programming. I have described all possible situations under two conditions: (1) the final note has the multi-track flag = 0, and (2) the final note has the multi-track flag > 0. These templates are laid out below I. Final note multi-track flag = 0 starting note ending note x-shift stem option overrides stem position stem position tips 1st 2nd 1st 2nd code over under ────────────── ────────────────┬────┬───────┬────────────────┬────┬────┬────┬ up single up single │ up │H H │ no │ F │ l │ F │ (multi-track = 0) up top of many │down│ no │s s │ p │ p │ G │ up middle of many │down│nr Y │ no │ m │ p │ H │ up bottom of many │ up │H H │ no │ F │ p │ F │ down single │down│nr H │s H (if flag)│ j │ j │ I │ down top of many │down│ no │s H │ o │ o │ G │ down middle of many │down│nr H │ │ i │ i │ O │ down bottom of many │ up │ no │H s │ O │ o │ O │ │ │ │ │ │ │ │ up single up single │down│nr H │s s (mid stf)│ l │ l │ F │ (multi-track > 0) up top of many │down│ no │s s │ p │ p │ G │ up middle of many │down│nr Y │ no │ m │ p │ H │ up bottom of many │ up │H H │ no │ F │ p │ F │ down single │down│ no │s H │ o │ j │ I │ down top of many │down│ no │s H │ o │ o │ G │ down middle of many │down│nr H │ │ i │ i │ O │ down bottom of many │ up │ no │H s │ O │ o │ O │ │ │ │ │ │ │ │ up top of many up single │down│ no │s s │ p │ p │ F │ (multi-track = 0) up top of many │down│nr n │s s (no oths)│ h │ h │ N │ (multi-track > 0) up middle of many │down│ no │s s │ p │ p │ F │ up bottom of many │ up │H H │ no │ F │ p │ F │ down single │down│ no │s H │ o │ o │ I │ down top of many │down│nr H │s H (no oths)│ k │ k │ N │ down middle of many │down│ no │s H │ o │ o │ G │ down bottom of many │down│nr H │ no │ i │ i │ G │ │ │ │ │ │ │ │ up middle of many up single │down│Yr n │ no │ f │ f │ F │ (multi-track = 0) up top of many │down│Yr n │ no │ f │ f │ F │ (multi-track > 0) up middle of many │down│nr nl│ no │ n │ n │ N │ up bottom of many │ up │H H │ no │ F │ r │ F │ down single │down│Yr H │ no │ g │ g │ I │ down top of many │down│Yr H │ no │ g │ g │ G │ down middle of many │down│nr nl│ no │ n │ n │ N │ down bottom of many │ up │H nl│ no │ H │ g │ H │ │ │ │ │ │ │ │ up botton of many up single │ up │H H │ no │ F │ f │ F │ (multi-track = 0) up top of many │down│Yr n │ no │ f │ f │ F │ (multi-track > 0) up middle of many │ up │H H │ no │ F │ s │ F │ up bottom of many │ up │H H │ no │ F │ n │ F │ down single │ up │H nl│H s (positio)│ I │ g │ I │ down top of many │down│Yr H │ no │ g │ g │ G │ down middle of many │ up │H Yl│ │ G │ g │ G │ down bottom of many │ up │H nl│H s (p n oth)│ J │ n │ J │ │ │ │ │ │ │ │ down single up single │down│H n │H s (positio)│ c │ c │ B │ (multi-track = 0) up top of many │down│H n │H s (positio)│ c │ c │ B │ up middle of many │down│H Y │ no │ e │ e │ B │ up bottom of many │ up │n H │s H (positio)│ B │ e │ B │ down single │down│H H │ no │ d │ d │ E │ down top of many │down│H H │ no │ d │ d │ C │ down middle of many │down│H H │ no │ d │ d │ C │ down bottom of many │ up │ no │s s │ Q │ d │ Q │ │ │ │ │ │ │ │ down single up single │ up │n H │s H (positio)│ B │ c │ B │ (multi-track > 0) up top of many │down│H n │ no │ a │ c │ B │ up middle of many │ up │n H │ no │ A │ e │ B │ up bottom of many │ up │ no │s H │ P │ e │ B │ down single │ up │n nl│s s (mid stf)│ E │ d │ E │ down top of many │down│H H │ no │ d │ d │ C │ down middle of many │ up │ no │s s │ Q │ d │ C │ down bottom of many │ up │ no │s s │ Q │ d │ Q │ │ │ │ │ │ │ │ down top of many up single │down│H n │H s (positio)│ c │ c │ K │ (multi-track = 0) up top of many │down│H n │H s (p n oth)│ b │ b │ C │ (multi-track > 0) up middle of many │down│H Y │ no │ e │ e │ K │ up bottom of many │down│H Y │ no │ e │ e │ K │ down single │down│H H │ no │ d │ d │ Q │ down top of many │down│H H │ no │ d │ d │ N │ down middle of many │down│H H │ no │ d │ d │ L │ down bottom of many │ up │Y nl│ no │ M │ d │ M │ │ │ │ │ │ │ │ down middle of many up single │ up │Y H │ no │ K │ c │ K │ (multi-track = 0) up top of many │down│H n │ no │ a │ a │ K │ (multi-track > 0) up middle of many │ up │nr nl│ no │ N │ n │ N │ up bottom of many │ up │Y H │ no │ K │ a │ K │ down single │down│H H │ no │ d │ d │ M │ down top of many │down│H H │ no │ d │ d │ L │ down middle of many │ up │nr nl│ no │ N │ n │ N │ down bottom of many │ up │Y nl│ no │ M │ d │ M │ │ │ │ │ │ │ │ down bottom of many up single │ up │n H │s H (positio)│ B │ c │ B │ (multi-track = 0) up top of many │down│H n │ no │ a │ a │ K │ (multi-track > 0) up middle of many │ up │n H │ no │ A │ e │ A │ up bottom of many │ up │n H │ no │ A │ n │ A │ down single │ up │n nl│s s (mid stf)│ E │ d │ E │ down top of many │ up │n Yl│ no │ C │ d │ C │ down middle of many │ up │n Yl│ no │ C │ d │ C │ down bottom of many │ up │n nl│s s (no oths)│ D │ n │ D │ II. Final note multi-track flag > 0 starting note ending note x-shift stem option (same) stem position stem position tips 1st 2nd 1st 2nd code (overrides) ────────────── ────────────────┬────┬───────┬────────────────┬────┬ up single up single │down│nr H │s s (mid stf)│ l │ (multi-track = 0) up top of many │down│ no │s s │ p │ up middle of many │down│nr Y │ no │ m │ up bottom of many │ up │H H │ no │ F │ down single │ up │H nl│H s (positio)│ I │ down top of many │ up │H Yl│ no │ G │ down middle of many │ up │H Yl│ no │ G │ down bottom of many │ up │ no │H s │ O │ │ │ │ │ │ up single up single │down│nr H │s s (mid stf)│ l │ (multi-track > 0) up top of many │down│ no │s s │ p │ up middle of many │down│nr Y │ no │ m │ up bottom of many │ up │H H │ no │ F │ down single │ up │ no │H s │ O │ down top of many │ up │H Yl│ no │ G │ down middle of many │ up │ no │H s │ O │ down bottom of many │ up │ no │H s │ O │ │ │ │ │ │ up top of many up single │down│ no │s s │ p │ (multi-track = 0) up top of many │down│nr n │s s (no oths)│ h │ (multi-track > 0) up middle of many │down│ no │s s │ p │ up bottom of many │ up │H H │ no │ F │ down single │down│ no │s H │ o │ down top of many │down│nr H │ no │ i │ down middle of many │ up │H Yl│ no │ G │ down bottom of many │ up │H nl│ no │ H │ │ │ │ │ │ up middle of many up single │down│Yr n │ no │ f │ (multi-track = 0) up top of many │down│Yr n │ no │ f │ (multi-track > 0) up middle of many │down│nr nl│ no │ n │ up bottom of many │ up │H H │ no │ F │ down single │down│Yr H │ no │ g │ down top of many │down│Yr H │ no │ g │ down middle of many │ up │nr nl│ no │ N │ down bottom of many │ up │H nl│ no │ H │ │ │ │ │ │ up botton of many up single │ up │H H │ no │ F │ (multi-track = 0) up top of many │down│Yr n │ no │ f │ (multi-track > 0) up middle of many │ up │H H │ no │ F │ up bottom of many │ up │H H │ no │ F │ down single │ up │H nl│H s (positio)│ I │ down top of many │down│Yr H │ no │ g │ down middle of many │ up │H Yl│ no │ G │ down bottom of many │ up │H nl│H s (p n oth)│ J │ │ │ │ │ │ down single up single │down│H n │H s (positio)│ c │ (multi-track = 0) up top of many │down│H n │H s (positio)│ c │ up middle of many │down│H Y │ no │ e │ up bottom of many │ up │n H │s H (positio)│ B │ down single │ up │n nl│s s (mid stf)│ E │ down top of many │ up │n Yl│ no │ C │ down middle of many │ up │ no │s s │ Q │ down bottom of many │ up │ no │s s │ Q │ │ │ │ │ │ down single up single │down│H n │H s (positin)│ c │ (multi-track > 0) up top of many │down│H H │ no │ d │ up middle of many │down│H Y │ no │ e │ up bottom of many │ up │n H │ no │ A │ down single │ up │n nl│s s (mid stf)│ E │ down top of many │ up │n Yl│ no │ C │ down middle of many │ up │ no │s s │ Q │ down bottom of many │ up │ no │s s │ Q │ │ │ │ │ │ down top of many up single │down│H n │H s (positio)│ c │ (multi-track = 0) up top of many │down│H n │H s (p n oth)│ b │ (multi-track > 0) up middle of many │down│H Y │ no │ e │ up bottom of many │down│H Y │ no │ e │ down single │down│H H │ no │ d │ down top of many │down│H H │ no │ d │ down middle of many │ up │Y Yl│ no │ L │ down bottom of many │ up │Y nl│ no │ M │ │ │ │ │ │ down middle of many up single │ up │Y H │ no │ K │ (multi-track = 0) up top of many │down│H n │ no │ a │ (multi-track > 0) up middle of many │ up │nr nl│ no │ N │ up bottom of many │ up │Y H │ no │ K │ down single │ up │Y nl│ no │ M │ down top of many │down│H H │ no │ d │ down middle of many │ up │nr nl│ no │ N │ down bottom of many │ up │Y nl│ no │ M │ │ │ │ │ │ down bottom of many up single │ up │n H │ no │ A │ (multi-track = 0) up top of many │down│H n │ no │ a │ (multi-track > 0) up middle of many │ up │n H │ no │ A │ up bottom of many │ up │n H │ no │ A │ down single │ up │n nl│s s (mid stf)│ E │ down top of many │ up │n Yl│ no │ C │ down middle of many │ up │n Yl│ no │ C │ down bottom of many │ up │n nl│s s (p n oth)│ D │ Meaning of codes ─────────────────────────────────────── x-shift stem option code tips 1st 2nd 1st 2nd ───── ────── ────────── ─────────── A up n H no B up n H s H (position) C up n Yl no D up n nl s s (no others) E up n nl s s (mid stuff) F up H H no G up H Yl no H up H nl no I up H nl H s (position) J up H nl H s (pos no oth) K up Y H no L up Y Yl no M up Y nl no N up nr nl no O up no H s P up no s H Q up no s s a down H n no b down H n H s (pos no oth) c down H n H s (position) d down H H no e down H Y no f down Yr n no g down Yr H no h down nr n s s (no oths) i down nr H no j down nr H s H (if flag) k down nr H s H (no oths) l down nr H s s (mid stuff) m down nr Y no n down nr nl no o down no s H p down no s s Extra codes Meaning of codes ─────────────────────────────────────── x-shift 2nd option code tips 1st 2nd 1st 2nd ───── ────── ────────── ─────────── R up n nl no q down nr n no r down Yr Yl no s down Yr Y no t down no H s This information is combined into a 160 byte string. By correctly diagnosing the situation, we can therefore determine what actions should be taken. For both and starting note and the ending note we need to determine: (1) multi-track flag? (zero or non-zero) (2) stem direction? (up or down) (3) note catagory? (single, top of many, middle of many, bottom of many) ╔════════════════════════════════════════════╗ ║ This is the loop which processes slurs ║ ╚════════════════════════════════════════════╝ loop for a4 = 1 to nsgroups /* loop through all slurs ending on this chord examine a6 = sgroup(a4,1) a7 = sgroup(a4,2) c7 = a7 >> 16 /* get forced slur flag a7 &= 0xffff /* clean up index 1a. Get information on starting note c1 = multi-track flag for this note c2 = stem direction for this note c3 = note catagory for this note: 0 = single 1 = top of many 2 = middle of many 3 = bottom of many c7 = forced slur flag c1 = ts(a6,MULTI_TRACK) >> 2 c2 = bit(1,ts(a6,STEM_FLAGS)) c3 = bit(2,ts(a6,STEM_FLAGS)) if c3 = 1 and bit(3,ts(a6,STEM_FLAGS)) = 1 ++c3 if ts(a6+1,TYPE) <> ts(a6,TYPE) ++c3 end end 1b. Get information on ending note c4 = multi-track flag for this note c5 = stem direction for this note c6 = note catagory for this note: 0 = single 1 = top of many 2 = middle of many 3 = bottom of many c4 = ts(a7,MULTI_TRACK) >> 2 c5 = bit(1,ts(a7,STEM_FLAGS)) c6 = bit(2,ts(a7,STEM_FLAGS)) if c6 = 1 and bit(3,ts(a7,STEM_FLAGS)) = 1 ++c6 if ts(a7+1,TYPE) <> ts(a7,TYPE) ++c6 end end 1c. Modify multi-track flags under certain conditions if c1 > 0 and c4 > 0 /* CHANGED from = 3 on 9-10-93 if ts(a6,PASSNUM) = ts(a7,PASSNUM) and c2 = c5 if ts(a6,PASSNUM) = 1 and c2 = DOWN c1 = 0 c4 = 0 end if ts(a6,PASSNUM) = 2 and c2 = UP c1 = 0 c4 = 0 end end end 2. Derive "situation" letter from c1 - c7. c8 = c3 if c8 <> 0 or c1 <> 0 ++c8 end if c2 = DOWN c8 += 5 end if c4 > 0 and c7 = 0 c8 += 10 end c8 *= 8 /* c8 ranges by 8's from 0 to 19*8 c8 += c6 if c5 = DOWN c8 += 4 end ++c8 /* c8 ranges from 1 to 160 (1 to 80 for forced slurs) if c7 = 0 slurlet = slurstr{c8} if c1 = 0 and c4 = 0 if chr(ts(a6,TYPE)) in [GR_NOTE,XGR_NOTE] if chr(ts(a7,TYPE)) in [NOTE,XNOTE] slurlet = slurunder{c8} /* force under end end end else if c7 = 1 slurlet = slurover{c8} /* force over else slurlet = slurunder{c8} /* force under end end 2a. Attempt to account for interfering beams if ts(a6,TYPE) < GR_NOTE or ts(a7,TYPE) > XNOTE if "abcIJijAB" con slurlet if mpt < 6 c12 = ts(a7,BEAM_FLAG) if c12 = CONT_BEAM or c12 = END_BEAM if mpt < 4 /* down-up; tips down; modify end slurlet = "t" else /* up-down; tips up; modify end slurlet = "O" end end else c12 = ts(a6,BEAM_FLAG) if c12 = CONT_BEAM or c12 = START_BEAM if mpt < 8 /* down-up; tips up; modify beginning slurlet = "o" else /* up-down; tips down; modify beginning slurlet = "P" end end end end end 3. Decompose "compound" situations into separate "simple" situations (1) if code in [D,J,b,h,k], are there other slurs between the chords? If yes, then these codes become [R,H,a,q,i] (2) if code = I or J, is ending note vpar(6) higher than starting note? If yes, then these codes both become O, otherwise they become H (3) if code in [B,b,c], is ending note vpar(6) lower than starting note? If yes, then codes become [P,t,t]; otherwise they become [A,a,a] (4) if code = j, does starting note have a flag? If yes, it becomes an "o". Otherwise it is an "i" (5) if code = l or E, is there anything between the notes (chords) If yes, they become p and Q; otherwise they are i and R. if "DJbhk" con slurlet c12 = mpt perform get_topbottom (a6,c1,c2) perform get_topbottom (a7,c4,c5) if c2 > c1 and c5 > c4 /* both chords loop for c3 = c1 to c2 /* first chord if c3 <> a6 /* look for other slurs c8 = ts(c3,SLUR_FLAG) & 0x00550055 if c8 > 0 /* slur(s) start(s) c8 <<= 1 /* set of end flags for these slurs loop for c9 = c2 + 1 to c5 c10 = ts(c9,TYPE) if chr(c10) in [NOTE,XNOTE,CUE_NOTE,XCUE_NOTE,GR_NOTE,XGR_NOTE] c11 = ts(c9,SLUR_FLAG) & c8 if c11 > 0 /* slur ends if c9 >= c4 and c9 <> a7 /* condition met! slurlet = "RHaqi"{c12} goto SSEND1 else c11 = not(c11) c8 &= c11 /* turn off this possibility end end end repeat end /* now look for ties if bit(0,ts(c3,SUPER_FLAG)) = 1 loop for c9 = c4 to c5 if c9 <> a7 c10 = ts(c9,BACKTIE) if c10 = c3 /* condition met! (tricky code) slurlet = "RHaqi"{c12} goto SSEND1 end end repeat end end repeat end slurlet = "QJbpo"{c12} end SSEND1: c7 = 0 /* option flag if "IJBbcjlE" con slurlet c8 = ts(a6,BEAM_FLAG) c9 = ts(a7,BEAM_FLAG) goto SS(mpt) SS(1): /* "IJ" if ts(a6,STAFFLOC) - ts(a7,STAFFLOC) > vpar(7) c7 = 1 end if ts(a6,TYPE) < GR_NOTE or ts(a7,TYPE) > XNOTE if c9 = CONT_BEAM or c9 = END_BEAM c7 = 1 end end goto SSEND SS(3): /* "Bbc" if ts(a7,STAFFLOC) - ts(a6,STAFFLOC) > vpar(7) if slurlet = "B" c7 = 1 else /* (New 05/17/03) if ts(a7,SUBFLAG_2) & 0x3c > 0 or ts(a7,ED_SUBFLAG_2) & 0x3c > 0 if ts(a7,STAFFLOC) - ts(a6,STAFFLOC) > vpar(9) c7 = 1 end else c7 = 1 end end end if mpt = 3 if c8 = START_BEAM or c8 = CONT_BEAM c7 = 1 end else if c9 = CONT_BEAM or c9 = END_BEAM c7 = 1 end end goto SSEND SS(6): /* "j" if c8 = NO_BEAM if ts(a6,NTYPE) < QUARTER c7 = 1 end else if c8 = START_BEAM or c8 = CONT_BEAM c7 = 1 end end goto SSEND SS(7): /* "lE" beams on both notes of slur? if c8 > NO_BEAM and c9 > NO_BEAM slurlet = " pQ"{mpt} end goto SSEND2 At this point in the code, a1,a4,a6,a7 and a14 should not be changed SSEND: Break 'm up if c7 = 1 slurlet = "OOPttopQ"{mpt} else slurlet = "HHAaaiiR"{mpt} end end At this point, you have determined the "situation" letter for the between "a6" and "a7" (with the exception of the cases "l" and "E", which depend on the material between the slurs). You now need to compile a profile of whatever material might be between the slurs on this staff. (organized by advancing division) SSEND2: c12 = 0 if "lE" con slurlet /* we do cases "l" and "E" here c12 = mpt c3 = ts(a6,STAFFLOC) c4 = ts(a7,STAFFLOC) if c3 < c4 c3 = c4 c4 = ts(a6,STAFFLOC) end if mpt = 1 c4 -= vpar(4) else c3 += vpar(4) end end c9 = 0 c7 = 0 c8 = ts(a7,STAFF_NUM) c15 = ts(a6,DIV) c10 = a7 loop while chr(ts(c10,TYPE)) in [XNOTE,XCUE_NOTE,XGR_NOTE] --c10 repeat --c10 /* c10 will not point to the last chord loop for c1 = a6+1 to c10 if ts(c1,STAFF_NUM) = c8 nodtype = ts(c1,TYPE) if chr(nodtype) in [NOTE,CUE_NOTE,GR_NOTE] if bit(1,ts(c1,STEM_FLAGS)) = UP c5 = ts(c1,VIRT_STEM) c6 = ts(c1,VIRT_NOTE) else c5 = ts(c1,VIRT_NOTE) c6 = ts(c1,VIRT_STEM) end else if chr(nodtype) in [REST,CUE_REST] c5 = ts(c1,STAFFLOC) - vpar(3) c6 = ts(c1,STAFFLOC) + vpar(3) else if nodtype = CLEF_CHG c5 = 0 c6 = vpar(8) else 11/26/06 Fixing a minor bug in the placement of slurs c5 = 10000 if nodtype < METER_CHG c5 = 1000 c6 = -1000 else c5 = 10000 end End of 11/26/06 change end end end if c5 < 10000 if c12 > 0 if c3 > c5 and c4 < c6 c7 = 1 end end if ts(c1,DIV) <> c15 ++c9 /* Case 1: profile(c9,1) = c5 - vpar(2) /* new division profile(c9,2) = c6 + vpar(2) /* else if c9 > 0 c5 -= vpar(2) /* Case 2: c6 += vpar(2) /* more notes if c5 < profile(c9,1) /* on same profile(c9,1) = c5 /* division end /* if c6 > profile(c9,2) profile(c9,2) = c6 end end end end end if ts(c1,TYPE) = BAR_LINE c15 = 0 else c15 = ts(c1,DIV) end repeat if c12 > 0 if c7 = 1 slurlet = "pQ"{c12} else slurlet = "iR"{c12} end end More modifications to slurlet. If there are staccatos, legatos, or spiccatos connected to the note head, then under certain conditions the slur must start at the stem of the note. /* New code rewritten 05/17/03 c16 = ts(a6,SUBFLAG_2) | ts(a6,ED_SUBFLAG_2) /* combination subflag_2 at a6 c16 &= 0x3c /* staccato, legato, etc. c17 = ts(a7,SUBFLAG_2) | ts(a7,ED_SUBFLAG_2) /* combination subflag_2 at a7 c17 &= 0x3c /* staccato, legato, etc. if slurlet < chr(96) /* tips up if c16 > 0 if bit(1,ts(a6,STEM_FLAGS)) = DOWN if "ACRKLM" con slurlet slurlet = "PQQPQQ"{mpt} end end end if ts(a6,TYPE) < GR_NOTE and c17 > 0 if bit(1,ts(a7,STEM_FLAGS)) = DOWN if "CGHLMR" con slurlet slurlet = "QOOQQQ"{mpt} end end end else /* tips down if c16 > 0 if bit(1,ts(a6,STEM_FLAGS)) = UP if "fgimqrs" con slurlet slurlet = "poopppp"{mpt} end end end if c17 > 0 if bit(1,ts(a7,STEM_FLAGS)) = UP if slurlet = "o" slurlet = "p" end end end end /* End of 05/17/03 rewrite Updated list of letter codes ──────────────────────────────── tips up tips down explanation code 1st 2nd code 1st 2nd letter meaning ───── ────────── ───── ────────── ────── ───────────────── A n H a H n n note C n Yl d H H nr start right of note F H H e H Y nl end left of note G H Yl f Yr n H head of chord H H nl g Yr H Y position of object K Y H i nr H (opposite of H) L Y Yl m nr Y Yr start right of object M Y nl n nr nl Yl end left of object N nr nl o s H s stem O H s p s s P s H q nr n Q s s r Yr Yl R n nl s Yr Y t H s At this point, we need to check to see of this is the first time either chord has been touched by a slur. When creating the slur element ROW, we need to write in the first four elements: (1) current y-position above object for incoming slurs. (2) " below " " " " . (3) " above " " outgoing " . (4) " below " " " " . perform get_topbottom (a6,c1,c2) if ts(a6,SLUR_X) = 0 ++a14 loop for c8 = c1 to c2 ts(c8,SLUR_X) = a14 repeat if bit(1,ts(a6,STEM_FLAGS)) = UP ts(a14,1) = ts(a6,VIRT_STEM) ts(a14,2) = ts(a6,VIRT_NOTE) ts(a14,3) = ts(a6,VIRT_STEM) ts(a14,4) = ts(a6,VIRT_NOTE) else ts(a14,1) = ts(a6,VIRT_NOTE) ts(a14,2) = ts(a6,VIRT_STEM) ts(a14,3) = ts(a6,VIRT_NOTE) ts(a14,4) = ts(a6,VIRT_STEM) end end if bit(1,ts(a6,STEM_FLAGS)) = UP c3 = c2 c2 = c1 c1 = c3 end perform get_topbottom (a7,c3,c4) if ts(a7,SLUR_X) = 0 ++a14 loop for c8 = c3 to c4 ts(c8,SLUR_X) = a14 repeat if bit(1,ts(a7,STEM_FLAGS)) = UP ts(a14,1) = ts(a7,VIRT_STEM) ts(a14,2) = ts(a7,VIRT_NOTE) ts(a14,3) = ts(a7,VIRT_STEM) ts(a14,4) = ts(a7,VIRT_NOTE) else ts(a14,1) = ts(a7,VIRT_NOTE) ts(a14,2) = ts(a7,VIRT_STEM) ts(a14,3) = ts(a7,VIRT_NOTE) ts(a14,4) = ts(a7,VIRT_STEM) end end if bit(1,ts(a7,STEM_FLAGS)) = UP c5 = c4 c4 = c3 c3 = c5 end a6 = note we are looking at in first chord c1 = head of first chord c2 = last note (Y) of first chord a7 = note we are looking at in second chord c3 = head of second chord c4 = last note (Y) of second chord If this slur starts or ends on an element which has either (1) a staccato dot and/or a legato line, or (2) a spiccato indication associated with it, then we need to check to see if this is the first time the element in question has been encountered, i.e., element (5) of the slur element ROW is zero. If so, this parameter needs to be adjusted to make space for the indication. This will also shift the position of the slur. (1) starting c5 = ts(a6,SUBFLAG_2) | ts(a6,ED_SUBFLAG_2) /* New 05/17/03 /* At the moment, I am treating /* editorial marks the same way /* as regular. In fact, the /* addition of square brackets /* may require additional /* vertical space c14 = ts(a6,SLUR_X) /* index to slur element ROW temp = "FGHOadet" /* note (changed at bottom of loop) temp2 = "PQop" /* stem (changed at bottom of loop) loop for c15 = 2 to 0 step -2 /* cases: 2 = start; 0 = end if c5 & 0x3c > 0 if ts(c14,5) = 0 if temp con slurlet /* if slur starts (ends) on a note We need to write elements (5) and (6) and to modify elements (1) and (3), or elements (2) and (4). if mpt < 5 /* this works for both cases stem = UP t3 = 1 y = ts(c14,c15+2) else stem = DOWN t3 = -1 y = ts(c14,c15+1) end if c5 & 0x38 > 0 /* staccato or legato t2 = notesize y += t2 * t3 /* check for interference t4 = 1 if stem = DOWN if y >= 0 t1 = y / notesize t4 = rem else y = 0 - notesize / 4 + y end else if y <= vpar(8) t1 = y / notesize t4 = rem else y = notesize / 4 + y end end /* adjust for interference with staff if t4 = 0 /* interference t2 += vpar(1) c16 = t2 + vpar20 / vpar(2) if rem <> 0 ++t2 end t2 += vpar(1) y = vpar(1) * t3 + y c16 = t3 + 20 * vpar(2) / 2 - vpar20 y += c16 end c10 = t2 if c5 & 0x10 > 0 /* line over dot y = notesize * t3 + y c10 += notesize end /* write elements ts(c14,5) = y if stem = UP ts(c14,2) += c10 ts(c14,4) += c10 ts(c14,6) = BELOW else ts(c14,1) -= c10 ts(c14,3) -= c10 ts(c14,6) = ABOVE end end if c5 & 0x04 > 0 /* spiccato if stem = DOWN if y > vpar(1) y = vpar(1) end else if y < vpar(7) y = vpar(7) end end y = 5 * notesize / 4 * t3 + y if stem = UP y += vpar(50) end /* write elements ts(c14,5) = y if stem = UP ts(c14,2) = y ts(c14,4) = y ts(c14,6) = BELOW else ts(c14,1) = y - vpar(50) ts(c14,3) = y - vpar(50) ts(c14,6) = ABOVE end end else if temp2 con slurlet /* if slur starts (ends) on the stem We need to write element (5) and (6) and to modify elements (1) and (3), or elements (2) and (4). if mpt > 2 /* works in both cases stem = UP t3 = -1 y = ts(c14,c15+1) else stem = DOWN t3 = 1 y = ts(c14,c15+2) end if c5 & 0x38 > 0 /* staccato or legato t2 = vpar(1) y += t2 * t3 (y = vpar(1) * t3 + y) c16 = t3 + 20 * vpar(2) / 2 - vpar20 y += c16 /* check for interference t4 = 1 if stem = UP if y >= 0 t1 = y / notesize t4 = rem else y = 0 - notesize / 4 + y end else if y <= vpar(8) t1 = y / notesize t4 = rem else y = notesize / 4 + y end end /* adjust for interference with staff if t4 = 0 /* interference t2 += vpar(1) c16 = t2 + vpar20 / vpar(2) if rem <> 0 ++t2 end t2 += vpar(1) y = vpar(1) * t3 + y c16 = t3 + 20 * vpar(2) / 2 - vpar20 y += c16 end c10 = t2 if c5 & 0x10 > 0 /* line over dot y = notesize * t3 + y c10 += notesize end /* write elements ts(c14,5) = y if stem = DOWN ts(c14,2) += c10 ts(c14,4) += c10 ts(c14,6) = ABOVE else ts(c14,1) -= c10 ts(c14,3) -= c10 ts(c14,6) = BELOW end end if c5 & 0x04 > 0 /* spiccato if stem = DOWN if y < vpar(8) y = vpar(8) end else if y > 0 y = 0 end end y = vpar(1) * t3 + y c16 = t3 + 20 * vpar(2) / 2 - vpar20 y += c16 if stem = DOWN y += vpar(50) end /* write elements ts(c14,5) = y if stem = DOWN ts(c14,2) = y ts(c14,4) = y ts(c14,6) = ABOVE else ts(c14,1) = y - vpar(50) ts(c14,3) = y - vpar(50) ts(c14,6) = BELOW end end end end end end (2) ending c5 = ts(a7,SUBFLAG_2) | ts(a7,ED_SUBFLAG_2) /* New 05/17/03; see above. c14 = ts(a7,SLUR_X) /* index to slur element ROW temp = "AFKPdgio" temp2 = "OQpt" repeat Now you can affix the position of the slur, and store the results in the appropriate slur element ROWS. Also, the values of elements (1) (2) (3) or (4) can be updated. T H E P L A N ───────────────────── 1. Using slurlet and elements (1) to (4), determine tentative start-y and end-y values for slur. Determine orientation (tips up/down) 2. If c9 = 0, no adjustments are necessary; proceed with placing slur. 3. Using curve data, convert actual interior y-values to relative interior y-values. If all interior y-values fall below (above) the straight line connecting the end points, proceed with placing slur. 4. Determine interior point with maximum deviation, and raise (lower) the slur end-point on that side to the next multiple of vpar(1). If there is more than one interior point at the maximum, or if the interior point with the maximum is in the center of the slur, raise (lower) both slur end-points to the next multiple of vpar(1). 5. If all interior y-values now fall below (above) straight line connecting the end points, proceed with placing slur. 6. Determine interior point(s) with maximum deviation. If this point (all of these points) fall with the 25%-75% region of the slur, increase the curvature one notch, and goto (3); otherwise goto (4). To execute this plan, we will need to set up some temporary variables. y1 = starting point of slur y2 = ending point of slur c5 = counting index for interior points c6 = index for maximum on left c7 = index for maximum on right c9 = number of interior points (don't change this) I think the easiest way to handle the up/down situation is to convert all down values to 1000 * vpar(1) - down, and treat this as part of the "up" case. Initial data includes y1, y2 and the profile data. When we are done, we simply perform the same tranformation to get the final y1 and y2 values. New feature 05/01/08. If slur_adjust flag is non-zero, then this should turn off all automatic post adjustment of slur posiiton. I think we can do this by setting c9 = 0, which essentially turns off the profile. if slur_adjust <> 0 c9 = 0 end A C T I O N ───────────── 1. Using slurlet and elements (1) to (4), determine tentative start-y and end-y values for slur. Determine orientation (tips up/down) if "ACNRimnq" con slurlet /* slur starts on note y1 = ts(a6,STAFFLOC) else if "KLMfgrs" con slurlet /* slur starts on Y y1 = ts(a6,OBY) else c13 = 3 c14 = ts(a6,SLUR_X) c15 = bit(1,ts(a6,STEM_FLAGS)) if "FGHOadet" con slurlet /* slur starts on H if c15 = UP ++c13 end else if c15 = DOWN ++c13 end end y1 = ts(c14,c13) end end if "HMNRafnq" con slurlet /* slur ends on note y2 = ts(a7,STAFFLOC) else if "CGLemrs" con slurlet /* slur ends on Y y2 = ts(a7,OBY) else c13 = 1 c14 = ts(a7,SLUR_X) c15 = bit(1,ts(a7,STEM_FLAGS)) if "AFKPdgio" con slurlet /* slur ends on H if c15 = UP ++c13 end else if c15 = DOWN ++c13 end end y2 = ts(c14,c13) end end 2. If c9 = 0, no adjustments are necessary; proceed with placing slur. if c9 = 0 curve = 1 goto PLACE_SLUR end c10 = 1000 * vpar(1) c10 = 500 * vpar(2) if slurlet < chr(96) /* tips up y1 = c10 - y1 y2 = c10 - y2 loop for c13 = 1 to c9 profile(c13,1) = c10 - profile(c13,2) /* first cut repeat else y1 += c10 y2 += c10 loop for c13 = 1 to c9 profile(c13,1) += c10 repeat end 3. Using curve data, convert actual interior y-values to relative interior y-values. If all interior y-values fall below (above) the straight line connecting the end points, proceed with placing slur. (see beginning of program for construction of curvedata). t1 = 0 t2 = 0 curve = 1 sflag = 1 if abs(ts(a6,STAFFLOC) - ts(a7,STAFFLOC)) <= vpar(1) if abs(ts(a6,STAFFLOC) - ts(a7,STAFFLOC)) <= vpar(1) + 1 if bit(1,ts(a6,STEM_FLAGS)) = bit(1,ts(a7,STEM_FLAGS)) sflag = 0 end end NEW_CURVE: if c9 < 9 loop for c10 = 1 to c9 profile(c10,2) = profile(c10,1) + curvedata(c9,curve,c10) repeat else loop for c10 = 1 to 4 profile(c10,2) = profile(c10,1) + curvedata(8,curve,c10) repeat loop for c10 = 5 to c9 - 4 profile(c10,2) = profile(c10,1) + curvedata(8,curve,4) - 1 repeat c11 = 1 loop for c10 = c9 to c9 - 4 step -1 profile(c10,2) = profile(c10,1) + curvedata(8,curve,c11) ++c11 repeat end r1 = flt(y1) + .5 - flt(vpar(2)) r2 = flt(y2 - y1) r3 = flt(c9+1) r2 = r2 / r3 c14 = 0 c15 = 0 c12 = c9 + 1 >> 1 c13 = c9 >> 1 + 1 t5 = 0 t6 = 0 loop for c5 = 1 to c9 r1 += r2 c11 = fix(r1) c11 -= profile(c5,2) if c11 > 0 if c5 <= c12 if c11 > c14 c14 = c11 t5 = c5 end end if c5 >= c13 if c11 > c15 c15 = c11 t6 = c5 end end end repeat if c14 = 0 and c15 = 0 goto FIX_ENDS end 4. Determine interior point with maximum deviation, and raise (lower) the slur end-point on that side to the next multiple of vpar(1). If there is more than one interior point at the maximum, or if the interior point with the maximum is in the center of the slur, raise both slur end-points to the next multiple of vpar(1). c7 = 0 if c9 > 4 and bit(0,c9) = 0 /* c6 = c9 >> 1 /* if t5 = c6 or t6 - 1 = c6 /* TRIAL c7 = 1 /* if bit(1,ts(a6,STEM_FLAGS)) <> bit(1,ts(a7,STEM_FLAGS)) /* if abs(ts(a6,STAFFLOC) - ts(a7,STAFFLOC)) <= vpar(10) /* if curve = 1 /* if c15 > c14 /* t1 = 2 /* else /* t2 = 2 /* end /* TRIAL c7 = 0 /* end /* end /* end /* end end NEW_HEIGHT: if c15 = c14 or sflag = 0 or c7 = 1 y2 /= vpar(1) --y2 y2 *= vpar(1) /* raise the end y1 /= vpar(1) --y1 y1 *= vpar(1) /* raise the start y2 -= vpar(1) c16 = y2 * 2 / vpar(2) y2 -= rem y1 -= vpar(1) c16 = y1 * 2 / vpar(2) y1 -= rem if sflag = 0 sflag = 1 end else JKL: if c15 > c14 if t2 > 0 t1 = 0 t2 = 0 end if t1 = 2 t1 = 0 c14 = c15 + 1 else ++t1 y2 /= vpar(1) --y2 y2 *= vpar(1) /* raise the end y2 -= vpar(1) c16 = y2 * 2 / vpar(2) y2 -= rem end end if c14 > c15 if t1 > 0 t1 = 0 t2 = 0 end if t2 = 2 t2 = 0 c15 = c14 + 1 goto JKL else y1 /= vpar(1) --y1 y1 *= vpar(1) /* raise the start y1 -= vpar(1) c16 = y1 * 2 / vpar(2) y1 -= rem end end end 5. If all interior y-values now fall below (above) straight line connecting the end points, proceed with placing slur. r1 = flt(y1) + .5 - flt(vpar(2)) r2 = flt(y2 - y1) r3 = flt(c9+1) r2 = r2 / r3 c14 = 0 c15 = 0 c6 = 0 c7 = 0 c12 = c9 + 1 >> 1 c13 = c9 >> 1 + 1 loop for c5 = 1 to c9 r1 += r2 c11 = fix(r1) c11 -= profile(c5,2) if c11 > 0 if c5 <= c12 if c11 > c14 c6 = c5 c14 = c11 end end if c5 >= c13 if c11 > c15 c7 = c5 c15 = c11 end end end repeat if c6 = 0 and c7 = 0 goto FIX_ENDS end t5 = c6 t6 = c7 6. Determine interior point(s) with maximum deviation. If this point (all of these points) fall with the 25%-75% region of the slur, increase the curvature one notch, and goto (3); otherwise goto (4). c5 = 10000 / (c9 + 1) c6 *= c5 c7 *= c5 if c14 >= c15 and c6 >= 2500 and curve < 4 ++curve goto NEW_CURVE end if c14 <= c15 and c7 <= 7500 and curve < 4 ++curve goto NEW_CURVE end goto NEW_HEIGHT Transform to actual y-values FIX_ENDS: c10 = 1000 * vpar(1) c10 = 500 * vpar(2) if slurlet < chr(96) /* tips up y1 = c10 - y1 y2 = c10 - y2 else y1 -= c10 y2 -= c10 end Adjust slur height if both ends show tuplet if bit(4,ts(a6,SUPER_FLAG)) = 1 and bit(5,ts(a7,SUPER_FLAG)) = 1 c10 = 0 /* = no goto ADJS(tpflag+1) ADJS(1): if ts(a6,BEAM_FLAG) > 0 and ts(a7,BEAM_FLAG) > 0 if ts(a7,MULTI_TRACK) = 0 c10 = 1 end else c10 = 1 end goto ADJSE ADJS(2): /* always c10 = 1 goto ADJSE ADJS(3): /* never goto ADJSE ADJS(4): /* only when tips down if slurlet > chr(96) /* tips down c10 = 1 end goto ADJSE ADJS(5): /* only when tips up if slurlet < chr(96) /* tips up c10 = 1 end ADJSE: if c10 = 1 if slurlet < chr(96) /* tips up if y1 + y2 > vpar(6) << 1 y1 += vpar(2) y2 += vpar(2) end else if y1 + y2 < vpar(4) y1 -= vpar(2) y2 -= vpar(2) end end end end For both starting and ending chords, (1) find next empty slot in in each SLUR_X row and construct the following information: first element ──────────────────── bit 27: start/end flag (0 = start, 1 = end) bits 24-26: slur number - 1 (0 to 7) bits 17-23: curvature information (end only) bit 16: up/down flag (0 = tips up, 1 = tips down) (end only) bits 0-15: x-offset + 1000 (always a positive number) second element ───────────────────── y position relative to the staff third element (05/06/03) ───────────────────── print suggestion for this end of the slur PLACE_SLUR: Starting point c10 = 1000 /* x-offset if "ACRNimnq" con slurlet /* start on "n" if ts(a6,LOCAL_XOFF) > 0 c10 += ts(a6,LOCAL_XOFF) end if mpt > 3 c10 += hpar(82) * 3 / 4 end else if "KLMfgrs" con slurlet /* start on "Y" if bit(1,ts(a6,STEM_FLAGS)) = UP if ts(c2,LOCAL_XOFF) > 0 c10 += ts(a6,LOCAL_XOFF) end if mpt > 3 c10 += hpar(82) * 3 / 4 end end else if "PQop" con slurlet /* start on "s" if mpt < 3 c10 -= hpar(82) / 3 else c10 += hpar(82) / 3 end end end end c11 = sgroup(a4,3) << 24 /* slur number c11 += c10 /* odd numbered element c12 = ts(a6,SLUR_X) loop for c13 = 7 to 31 step 2 loop for c13 = 7 to (TS_SIZE - 2) step 3 /* 05/06/03 if ts(c12,c13) = 0 goto PLACE_SLUR1 end repeat PLACE_SLUR1: ts(c12,c13) = c11 ++c13 ts(c12,c13) = y1 Fine tuning for special situation if slurlet = "i" if ts(a6,STAFFLOC) - ts(a7,STAFFLOC) >= 0 c17 = ts(a7,SUBFLAG_2) | ts(a7,ED_SUBFLAG_2) /* New 05/17/03 if c17 & 0x3c > 0 /* New ts(c12,c13) -= vpar(2) end end end Code added 05/06/03 get print suggestion for this end of slur ++c13 c11 = sgroup(a4,3) /* 0 to 7 if c11 > 3 c11 -= 4 /* 0 to 3 = (,[,{,z end c11 *= 4 /* 0,4,8,12 c11 += 81 /* 81,85,89,93 (97,101,105,109) c10 = ts(a6,TSR_POINT) ts(c12,c13) = ors(tsr(c10){c11,4}) End code addition 05-27-94 Somehow, I can't figure out why this code was written this way It seems that tips up would automatically imply that the slur was under the object, and tips down would imply that the slur was over the object. The revised code reflects this thought (which may very well be naive). if "PQadet" con slurlet /* starting from over (3) ts(c12,3) = y1 /*? - vpar(1) end if "FGHOop" con slurlet /* starting from under (4) ts(c12,4) = y1 /*? + vpar(1) end if "opadet" con slurlet /* starting from over (3) ts(c12,3) = y1 - vpar(1) /* new value ts(c12,3) = y1 - vpar(1) c16 = ts(c12,3) * 2 / vpar(2) ts(c12,3) -= rem end if "FGHOPQ" con slurlet /* starting from under (4) ts(c12,4) = y1 + vpar(1) /* new value ts(c12,4) = y1 c16 = ts(c12,4) * 2 / vpar(2) if rem <> 0 ++ts(c12,4) end ts(c12,4) += vpar(1) end Ending point c10 = 1000 /* x-offset if "HMNRnafq" con slurlet /* end on "n" if ts(a7,LOCAL_XOFF) < 0 c10 += ts(a6,LOCAL_XOFF) end if mpt < 6 c10 -= hpar(82) * 3 / 4 end else if "CGLrems" con slurlet /* end on "Y" if bit(1,ts(a7,STEM_FLAGS)) = DOWN if ts(c4,LOCAL_XOFF) < 0 c10 += ts(a6,LOCAL_XOFF) end if mpt < 5 c10 -= hpar(82) * 3 / 4 end end else if "OQpt" con slurlet /* end on "s" if mpt < 3 c10 -= hpar(82) / 3 else c10 += hpar(82) / 3 end end end end c11 = sgroup(a4,3) /* slur number c11 += 16 /* end flag c11 <<= 8 c11 += curve << 1 /* curvature if slurlet > chr(96) /* tips up ++c11 /* tips up/down flag end c11 <<= 16 c11 += c10 /* x-offset c12 = ts(a7,SLUR_X) loop for c13 = 7 to 31 step 2 loop for c13 = 7 to (TS_SIZE - 2) step 3 /* 05/06/03 if ts(c12,c13) = 0 goto PLACE_SLUR2 end repeat PLACE_SLUR2: ts(c12,c13) = c11 ++c13 ts(c12,c13) = y2 Code added 05/06/03 get print suggestion for this end of slur ++c13 c11 = sgroup(a4,3) /* 0 to 7 if c11 > 3 c11 -= 4 /* 0 to 3 = (,[,{,z end c11 *= 4 /* 0,4,8,12 c11 += 97 /* 97,101,105,109 c10 = ts(a7,TSR_POINT) ts(c12,c13) = ors(tsr(c10){c11,4}) End code addition 05-27-94 See above. I don't understand how this code got written as it did. It seems self evident that the over-under question is decided entirely by the direction of the slur tips. if "OQdgio" con slurlet /* ending from over (1) ts(c12,1) = y2 /*? - vpar(1) end if "AFKPpt" con slurlet /* ending from under (2) ts(c12,2) = y2 /* + vpar(1) end if "ptdgio" con slurlet /* ending from over (1) ts(c12,1) = y2 - vpar(1) /* new value ts(c12,1) = y2 - vpar(1) c16 = ts(c12,1) * 2 / vpar(2) ts(c12,1) -= rem end if "AFKPOQ" con slurlet /* ending from under (2) ts(c12,2) = y2 + vpar(1) /* new value ts(c12,2) = y2 c16 = ts(c12,2) * 2 / vpar(2) if rem <> 0 ++ts(c12,2) end ts(c12,2) += vpar(1) end repeat ╔═══════════════════════════════════════════════════════╗ ║ This is the end of the loop which processes slurs ║ ╚═══════════════════════════════════════════════════════╝ end YYYY: repeat maxsct = a14 ***************************************************************** Processing loop (loop ends at ZZZ) PROCESSING TS ARRAY Actions: I. Construct text sub-object, if present II. Deal with music A. Bar Lines B. Clef changes, Time changes C. Signs, Words, Marks D. Figures E. Notes/Rests 1. Accidentals 2. Note heads, dots 3. Leger lines 4. Stems and beams III. Write object records into intermediate file p += firstsp loop for a1 = 1 to sct nodtype = ts(a1,TYPE) a5 = ts(a1,TEXT_INDEX) if a5 > 0 ttext = tsdata(a5) // pad(1) else ttext = pad(1) end sobcnt = 0 obx = p if nodtype = DIV_CHG goto ZZZ end Get the spn (spacing) parameter spn = ts(a1,SPN_NUM) I am moving this code to the point where notes are really typeset. The problem with having it here is that if there are chords with text, or if there are cue-notes simultaneous with the text, then the text may not get set. I. Construct Text Sub-Object if nodtype = NOTE if ttext{1} in ['A'..'Z','a'..'z','!'..'(','\','='] c5 = mtfont perform spacepar temp2 = ttext if temp2 con "$$$$" ttext = temp2{1,mpt-1} a4 = int(temp2{mpt+4..}) /* x offset (calculated earlier) else putc Program Error at 10052 end temp2 = ttext // "| " ttextcnt = 0 CCCD: if temp2 con "|" ttext = temp2{1,mpt-1} temp2 = temp2{mpt+1..} ++ttextcnt ttextarr(ttextcnt) = trm(ttext) goto CCCD end loop for a7 = 1 to ttextcnt ttext = ttextarr(a7) determine values of xbytearr a6 = len(ttext) xbytearr(a7) = "* " if "-_" con ttext{a6} ttext = ttext{1,a6-1} xbytearr(a7) = "-_"{mpt} // " " if mpt = 2 a6 = len(ttext) if ",.;:!?" con ttext{a6} ttext = ttext{1,a6-1} xbytearr(a7) = ",.;:!?"{mpt} // " " end end end ttextarr(a7) = ttext repeat determine length of ttext a5 = 0 loop for a7 = 1 to ttextcnt c5 = 0 ttext = ttextarr(a7) loop for c4 = 1 to len(ttext) * adjust for backslash (\) sequence if ttext{c4} = "\" a6 = ors(ttext{c4+2}) if ttext{c4+1} = "0" a6 += 128 end c4 += 2 else a6 = ors(ttext{c4}) end c5 += spc(a6) repeat if c5 > a5 a5 = c5 end repeat determine relative position of ttext x = p - a4 sobx = x - obx loop for a8 = 1 to ttextcnt ttext = ttextarr(a8) ++sobcnt temp3 = "T " // chs(sobx) // " " // chs(a8) // " " if ttext con "=" ttext{mpt} = "-" end temp3 = temp3 // ttext // " " sobl(sobcnt) = temp3 // xbytearr(a8) // chs(a5) repeat end end II. Typeset Music A. Typeset Bar Line if nodtype = BAR_LINE Zero out the rest_flag(s) 03/18/06 loop for a2 = 1 to MAX_PASS rest_flag(a2) = 0 repeat a2 = hpar(36) a14 = ts(a1,BAR_TYPE) determine location of obx for this object if bit(1,ts(a1,REPEAT)) = 1 /* backward repeat a2 += hpar(43) end a10 = hpar(43) + hpar(93) - hpar(80) Old Version shift for forward dots(repeats) a14 a2+ (add to p) a4 (1st shft) a5 (2nd shft) a8 (inc) a10 ---- ---- ---- --------- ---- ----- 1 0 0 0 0 a10 2 hpar(79) -hpar(79) 0 0 a10 3 0 0 0 0 a10 5 hpar(44) -a2 0 0 a10 6 hpar(81) + hpar(79) -a2 -hpar(79) 0 a10 9 0 0 +hpar(45) hpar(45) a10 + hpar(45) 10 hpar(45) -hpar(45) 0 hpar(79) hpar(43)+hpar(96)-hpar(80) hpar(44) = actual white space between two light lines hpar(45) = actual white space between heavy/light, light/heavy and heavy/heavy combinations hpar(79) = thickness of light line hpar(81) = thickness of heavy line shift for forward dots(repeats) a14 a2+ (add to p) a4 (1st shft) a5 (2nd shft) a8 (inc) a10 ---- ---- ---- --------- ---- ----- 1 0 0 0 0 a10 2 { hpar(81) - hpar(79 a2 0 0 a10 + 1 } 3 0 0 0 0 a10 5 hpar(44) + hpar(79) a2 0 0 a10 6 { hpar(45) + hpar(81) a2 - { hpar(81) - hpar(79) 0 a10 + 1 } + 1 } 9 0 0 hpar(81) + hpar(45) a5 a10 + a5 10 hpar(81) + hpar(45) a2 0 { hpar(81) - hpar(43)+hpar(96)-hpar(80) hpar(79) + 1 } a4 = 0 a5 = 0 a8 = 0 if a14 = HEAVY a2 += hpar(81) - hpar(79) + 1 a4 = hpar(81) - hpar(79) + 1 end if a14 = DOUBLE_REG or a14 = DOUBLE_DOTTED a2 += hpar(44) + hpar(79) a4 = hpar(44) + hpar(79) end if a14 = REG_HEAVY a2 += hpar(45) + hpar(81) + 1 a4 = hpar(45) + hpar(81) + 1 a5 = 0 - (hpar(81) - hpar(79) + 1) end if a14 = HEAVY_REG a5 = hpar(81) + hpar(45) a8 = a5 a10 += a5 end if a14 = DOUBLE_HEAVY a2 += hpar(81) + hpar(45) a4 = hpar(81) + hpar(45) a8 = hpar(81) - hpar(79) + 1 a10 = hpar(43) + hpar(96) - hpar(80) end obx = p + a2 if ts(a1,NODE_SHIFT) > 0 putc node_shift for barline = ~ts(a1,NODE_SHIFT) obx += ts(a1,NODE_SHIFT) end * * put out signet signs (if present) * if bit(1,ts(a1,BAR_FLAGS)) = 1 /* segno sign out = "0" jtype = "D" jcode = 8 + sigflag pcode = 106 /* music font oby = vpar(45) if nstaves = 2 oby += 1000 end putobjpar = 0 jscrdat = "" perform putobj jcode = 5 - sigflag oby = 0 - vpar(43) jscrdat = "" perform putobj if sigflag = 0 sigflag = 1 end end * * put out fermata signs (if present) * if ts(a1,BAR_FLAGS) & 0x000c > 0 putobjpar = 0 if bit(2,ts(a1,BAR_FLAGS)) = 1 /* fermata over bar out = "0" jtype = "D" jcode = 5 pcode = 101 /* music font oby = 0 - vpar(3) obx -= vpar(2) jscrdat = "" perform putobj obx += vpar(2) end if bit(3,ts(a1,BAR_FLAGS)) = 1 /* fermata under bar out = "0" jtype = "D" jcode = 9 pcode = 102 /* music font oby = vpar(3) + vpar(8) if nstaves = 2 oby += 1000 end obx -= vpar(2) jscrdat = "" perform putobj obx += vpar(2) end end oby = 0 contruct superobject string for bar line supcnt = 0 * look for termination of ending a9 = ts(a1,BACK_ENDING) if a9 <> 0 if esnum > 0 ++supcnt supnums(supcnt) = esnum a6 = esnum else return 4 end esnum = 0 end * look for termination of long trill ~~~~ if bit(0,ts(a1,BAR_FLAGS)) = 0 loop for a3 = 1 to MAX_PASS if tsnum(a3) > 0 ++supcnt /* stop trill supnums(supcnt) = tsnum(a3) end repeat end * look for origination of ending if ts(a1,FORW_ENDING) > 0 ++snum esnum = snum ++supcnt supnums(supcnt) = esnum end * construct supernumber string for object out = chs(supcnt) loop for a3 = 1 to supcnt out = out // " " // chs(supnums(a3)) repeat supcnt = 0 Typeset elements of the bar line * numbered measure /* Code added 02-23-97 a3 = ts(a1,M_NUMBER) if a3 > 0 c5 = 38 perform spacepar c5 = spc(176) >> 1 /* space for small "0" if a3 > 9 c5 <<= 1 end sobl(1) = "W " // "-" // chs(c5) // " 0 38 " sobcnt = 1 if a3 > 9 c5 = a3 / 10 a3 = rem sobl(1) = sobl(1) // "\0" // chs(c5) end sobl(1) = sobl(1) // "\0" // chs(a3) end * back-repeat if bit(1,ts(a1,REPEAT)) = 1 /* backward repeat x = p + hpar(36) x += ts(a1,NODE_SHIFT) /* This line added 09/22/03 (but not fully checked) y = vpar(3) z = 44 /* music font kscrdat = "" perform subj y = vpar(5) perform subj end * first of double bar y = 0 if a14 > 3 a3 = a14 & 0x0c z = a3 / 2 + 80 /* music font x = obx - a4 kscrdat = "" perform subj end * second or single bar a3 = ts(a1,BAR_TYPE) & 0x03 z = a3 * 2 + 80 /* music font x = obx + a5 kscrdat = "" perform subj * forward-repeat if bit(0,ts(a1,REPEAT)) = 1 /* forward repeat x = obx + a10 a8 += hpar(43) y = vpar(3) z = 44 /* music font kscrdat = "" perform subj y = vpar(5) perform subj end * put out object (and sub-objects) jtype = "B" jcode = ts(a1,BAR_NUMBER) if sobcnt = 1 pcode = z /* music font else pcode = sobcnt end oby = ts(a1,NUM_STAVES) - 1 * 1000 + a14 putobjpar = 0 jscrdat = tsdata(ts(a1,TEXT_INDEX)) Strip the operative barnum from the front of jscrdat opbarnum = int(jscrdat) if jscrdat con "+" jscrdat = jscrdat{mpt+1..} end perform putobj * put out ending super-object if a9 <> 0 /* backward ending if ts(a1,FORW_ENDING) > 0 out = "-" // chs(hpar(41)) else out = "0" end out = out // " -" // chs(vpar(40)) // " " out = out // " -" // chs(ending_height) // " " /* changed 01/06/06 out = out // chs(vpar(41)) // " " if a9 > 0 /* ending stops out = out // chs(vpar(41)) else /* ending discontinues a9 = 0 - a9 out = out // "0" end ++outpnt tput [Y,outpnt] H ~a6 E ~a9 0 ~out end * put out long trill super-object if bit(0,ts(a1,BAR_FLAGS)) = 0 loop for c5 = 1 to MAX_PASS if tsnum(c5) > 0 out = "H " // chs(tsnum(c5)) // " R " // chs(ctrarrf(c5)) out = out // " 0" ++outpnt tput [Y,outpnt] ~out -~hpar(42) ~try(c5) tsnum(c5) = 0 ctrarrf(c5) = 0 end repeat end * adjust p p = obx + ts(a1,SPACING) + a8 goto ZZZ end B. Typeset Clef change, Time change, Key change if nodtype = CLEF_CHG Code added 01/17/04 to deal with time clef in measure groups if ts(a1,DOLLAR_SPN) = 6913 /* 6913 used here as a code, not a value spn = 6913 end /* otherwise don't change spn a3 = ts(a1,STAFF_NUM) + 1 /* staff number if ts(a1,NODE_SHIFT) < 0 a7 = 0 - ts(a1,NODE_SHIFT) putc backing up clef sign by amount = ~a7 p += ts(a1,NODE_SHIFT) end obx = p clef(a3) = ts(a1,CLEF_NUM) z = ts(a1,CLEF_FONT) /* music font k = ts(a1,TRANS_FLAG) oby = ts(a1,STAFF_NUM) * 1000 /* added 5-28-93 oby += ts(a1,CLEF_STAFF_POS) perform putclef (a3) p += ts(a1,SPACING) goto ZZZ end * if nodtype = DESIGNATION Code added 01/17/04 to deal with designation in measure groups if ts(a1,DOLLAR_SPN) = 6913 /* 6913 used here as a code, not a value spn = 6913 end /* otherwise don't change spn c5 = 37 perform spacepar Introducing optional conversion to ligitures in designations 04/22/04 if ligit_flag = 1 if len(ttext) > 1 and ttext{1,2} = "ff" ttext{1,2} = "f\@f" end LIGCON3: if ttext con "ffi" ttext{mpt,3} = "\0:" goto LIGCON3 end if ttext con "ffl" ttext{mpt,3} = "\0;" goto LIGCON3 end if ttext con "ff" ttext{mpt,2} = "\0<" goto LIGCON3 end if ttext con "fi" ttext{mpt,2} = "\0=" goto LIGCON3 end if ttext con "fl" ttext{mpt,2} = "\0>" goto LIGCON3 end end #if AUTOSCR #else perform kernttext /* New 04/22/04 #endif jtype = "D" jcode = 5 obx = p oby = ts(a1,STAFF_NUM) * 1000 /* added 5-28-93 oby -= tword_height * vpar(1) out = "0" sobl(1) = "" temp3 = "W 0 0 37 " // ttext temp3 = "W 0 0 " // chs(dtivfont) // " " // ttext pcode = 1 putobjpar = 0 jscrdat = "" perform putobj goto ZZZ end * if nodtype = METER_CHG Code added 01/17/04 to deal with meter changes in measure groups if ts(a1,DOLLAR_SPN) = 6913 /* 6913 used here as a code, not a value spn = 6913 end /* otherwise don't change spn tnum = ts(a1,TIME_NUM) / 100 tden = rem oby = 0 k = p loop for h = 1 to ts(a1,NUM_STAVES) p = k perform settime (a3) oby += 1000 repeat if tnum = 1 and tden = 1 tnum = 4 tden = 4 end if tnum = 0 and tden = 0 tnum = abflg tden = 2 end goto ZZZ end * if nodtype = AX_CHG Code added 01/17/04 to deal with key changes in measure groups if ts(a1,DOLLAR_SPN) = 6913 /* 6913 used here as a code, not a value spn = 6913 end /* otherwise don't change spn h = ts(a1,3) /* new key k = ts(a1,4) /* old key a3 = ts(a1,NUM_STAVES) /* number of staves a4 = 0 a5 = 0 /* added 08/23/06 perform key_change (h, k, a3, a4, a5) /* emptyspace(.,.) not set key = h /* 08/23/06 5th variable added to procedure NOTE: The following instruction was added 05/29/05 to fix a minor bug that I have never seen before. It makes perfect sense that we should go to the next element in the ts(.) array, and I can't see how this "bug" has remained hidden for so long. My worry is that there was a good reason why we wanted to "fall through" to the note processing section, although this would be very poor programming practice. I do believe, however, in light of the fact that this program has worked properly for so long, that we need to keep an eye on this situation. This "goto" instruction is a major change! goto ZZZ end C. Typeset Signs, Words and Marks which are Objects if nodtype = SIGN or nodtype = WORDS or nodtype = MARK putobjpar = 0 * obx = p a4 = ts(a1,TEXT_INDEX) ttext = tsdata(a4) ttext = trm(ttext) out = "0" determine vertical positions of object and superobject if ts(a1,SIGN_TYPE) = SEGNO oby = 0 - vpar(43) else if ts(a1,SIGN_POS) = ABOVE oby = 0 - vpar(44) else oby = vpar(45) end end oby1 = oby oby2 = oby obx1 = obx obx2 = obx Comment: 01/07/06 The code here is somewhat convoluted, but I think this addition corrects a problem with the way print suggestions interact with transpositions. Stay alert! if nodtype = MARK oby = 0 end if ts(a1,POSI_SHIFT1) > 0 a3 = ts(a1,POSI_SHIFT1) & 0xff if a3 > 0 oby1 = a3 - 0x80 * vpar(2) / 10 yposi_shift = 0 else a3 = ts(a1,POSI_SHIFT1) >> 8 yposi_shift = a3 & 0xff if yposi_shift > 0 yposi_shift = yposi_shift - 0x80 * vpar(2) / 10 end end xposi_shift = ts(a1,POSI_SHIFT1) >> 16 if xposi_shift > 0 xposi_shift = xposi_shift - 0x80 * vpar(2) / 10 end else yposi_shift = 0 xposi_shift = 0 end save_xposi_shift = xposi_shift obx1 += xposi_shift oby1 += yposi_shift if ts(a1,POSI_SHIFT2) > 0 a3 = ts(a1,POSI_SHIFT2) & 0xff if a3 > 0 oby2 = a3 - 0x80 * vpar(2) / 10 yposi_shift = 0 else a3 = ts(a1,POSI_SHIFT2) >> 8 yposi_shift = a3 & 0xff if yposi_shift > 0 yposi_shift = yposi_shift - 0x80 * vpar(2) / 10 end end xposi_shift = ts(a1,POSI_SHIFT2) >> 16 if xposi_shift > 0 xposi_shift = xposi_shift - 0x80 * vpar(2) / 10 end else yposi_shift = 0 xposi_shift = 0 end obx2 = xposi_shift oby2 += yposi_shift temp = " " // chs(oby1) temp2 = " " // chs(oby2) a2 = ts(a1,SUPER_TYPE) * construct superflags for object if a2 > 0 a3 = a2 + 1 / 2 a8 = 0 if a3 = 4 a8 = 1 a3 = 3 end if rem = 0 /* start of super-object a4 = a3 - WEDGES * 5 + ts(a1,S_TRACK_NUM) /* row element loop for a5 = 1 to 5 if smusdir(a4,1) = 0 /* must be zero to use a5 = 1000 else /* else look at others ++a4 if a4 > a3 * 5 a4 -= 5 /* in the set end end repeat if a5 <> 1000 putc Too many active ... if a3 = WEDGES putc wedges. else if a3 = DASHES putc sets of dashes. else putc transpositions of one type. end end putc Typesetting halted stop end ++snum smusdir(a4,1) = snum smusdir(a4,4) = oby2 if a3 = WEDGES smusdir(a4,2) = ts(a1,WEDGE_SPREAD) smusdir(a4,3) = ts(a1,WEDGE_OFFSET) + obx2 else if a3 = DASHES if ts(a1,FONT_NUM) = 0 c5 = mtfont else c5 = ts(a1,FONT_NUM) end smusdir(a4,3) = c5 perform wordspace smusdir(a4,2) = a5 + obx2 else smusdir(a4,3) = obx2 smusdir(a4,4) -= oby /* tricky code if a3 = OCT_UP smusdir(a4,2) = 0 end if a3 = OCT_DOWN smusdir(a4,2) = 1 end if a3 = DBL_OCT_UP smusdir(a4,2) = 2 end if a3 = DBL_OCT_DOWN smusdir(a4,2) = 3 end end end else /* end of super-object a4 = a3 - WEDGES * 5 + ts(a1,S_TRACK_NUM) /* row element loop for a5 = 1 to 5 if smusdir(a4,1) <> 0 /* must be non zero to use a5 = 1000 else /* else look at others ++a4 if a4 > a3 * 5 a4 -= 5 /* in the set end end repeat if a5 <> 1000 putc Attempt to end a ... if a3 = WEDGES putc wedge ... else if a3 = DASHES putc set of dashes ... else putc transposition of a type ... end end putc that wasn't properly started. putc Typesetting halted stop end save_a4 = a4 end out = "1 " // chs(smusdir(a4,1)) end if single character, write object a3 = ts(a1,SIGN_TYPE) if a3 = PED or a3 = END_PED pcode = 112 + a3 /* music font jtype = "S" jcode = 0 obx = obx1 oby = ts(a1,STAFF_NUM) * 1000 + oby1 if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj goto VT2 end if a3 = LETTER_DYNAM /* one letter dynamics if ttext con "Z" #if SFZ ttext{mpt,1} = "sfz" #else ttext{mpt,1} = "sf" #endif end if len(ttext) = 1 and "pf" con ttext if mpt = 1 pcode = 108 /* music font else pcode = 110 /* music font end jtype = "S" jcode = 0 obx = obx1 oby = ts(a1,STAFF_NUM) * 1000 + oby1 if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj goto VT2 end end put out segno signs (as directives) if a3 = SEGNO pcode = 106 /* music font jtype = "D" jcode = 8 + sigflag obx = obx1 oby = ts(a1,STAFF_NUM) * 1000 + vpar(45) /* oby reset here if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj jcode = 5 - sigflag oby = ts(a1,STAFF_NUM) * 1000 + oby1 if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj if sigflag = 0 sigflag = 1 end goto VT2 end This code added 10-12-96 Put out mark for tie terminator if a3 = TIE_TERM jtype = "M" jcode = 0 obx = obx1 + hpar(81) + hpar(45) /* guarenteed to put you beyond bar line oby = 0 pcode = 0 c7 = ts(a1,BACKTIE) c7 = ts(c7,BACKTIE) out = "1 " // chs(tiearr(c7,TIE_SNUM)) jscrdat = "" perform putobj Now put out the Tie Super-object compute sitf (situation flag) Description of sitf: range 1 to 16 If the range were from 0 to 15, then bits 3 to 0 would have the following meanings: zero | one -------------------------------------------- bit 3: tips down | tips up bit 2: note on space | note on line bit 1: no stem interfenence | stem interference bit 0: staff interference | no staff interference c9 = tiearr(c7,TIE_VLOC) c10 = tiearr(c7,TIE_FHDIS) /* local x-offset for first note c11 = 0 /* local x-offset for second note c12 = tiearr(c7,TIE_FORCE) /* force flag if c12 = 3 c12 = 9 end Rules for single note c5 = tiearr(c7,TIE_FSTEM) if c5 = 0 sitf = 9 /* stem up else sitf = 1 end if c12 > 0 sitf = c12 /* forced situation end if tiearr(c7,TIE_FSTEM) = UP and sitf < 9 sitf += 2 /* stem interference end Note: you won't know if there is staff interference until you know the final length of the tie c9 += tiearr(c7,TIE_STAFF) * 1000 /* New code added 04/20/03, modified 05/02/03 c13 = tiearr(c7,TIE_SUGG) & 0xff000000 /* length data c6 = tiearr(c7,TIE_SUGG) & 0xff0000 /* position flags c4 = tiearr(c7,TIE_SUGG) & 0xff00 /* x data c5 = tiearr(c7,TIE_SUGG) & 0xff /* y data c13 >>= 24 c6 >>= 16 c4 >>= 8 if c4 > 0 c4 = c4 - 128 * notesize / 10 end if c5 > 0 c5 = c5 - 128 * notesize / 10 end if bit(2,c6) = 1 c5 += 10000 end c6 = 0 if c13 > 0 c6 = c13 - 128 * notesize / 10 end /* end New code c8 = tiearr(c7,TIE_SNUM) ++outpnt tput [Y,outpnt] H ~c8 T ~c9 ~c10 ~c11 ~c4 ~c5 ~c6 ~sitf 0 tiearr(c7,TIE_SNUM) = 0 ts(a1,BACKTIE) = 0 goto VT2 end End of 10-12-96 addition if nodtype = MARK jtype = "M" jcode = 0 obx = obx1 oby = 0 pcode = 0 if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj goto VT2 end * words if nodtype = WORDS jtype = "D" jcode = 0 if ttext = "Fine" jcode = 9 end if ttext = "fine" jcode = 9 end if ttext = "[fine]" jcode = 9 end if ttext con " " if ttext{1,mpt-1} = "da" jcode = 9 end if ttext{1,mpt-1} = "dal" jcode = 9 end if ttext{1,mpt-1} = "Dal" jcode = 9 end if ttext{1,mpt-1} = "Da" jcode = 9 end if ttext con " da " jcode = 9 end end if ttext con "D.C." or ttext con "D. C." jcode = 9 end pcode = 1 a4 = ts(a1,FONT_NUM) if a4 = 0 a4 = mdirfont end This code moved to this location from below, because we need to the operative font number for spacing purposes. 10/08/08 ttext = ttext // pad(4) if ttext{1} = "!" a4 = int(ttext{2..}) if ttext{sub} = "|" /* New 01/17/04: skip over "|" ++sub end ttext = ttext{sub..} end ttext = trm(ttext) if a3 > 4 /* (a3 = SIGN_TYPE here) c5 = a4 if a3 < 7 Introducing optional conversion to ligitures in words 04/22/04 if ligit_flag = 1 if ttext = "ff" ttext = "f\@f" end LIGCON2: if ttext con "ffi" ttext{mpt,3} = "\0:" goto LIGCON2 end if ttext con "ffl" ttext{mpt,3} = "\0;" goto LIGCON2 end if ttext con "ff" ttext{mpt,2} = "\0<" goto LIGCON2 end if ttext con "fi" ttext{mpt,2} = "\0=" goto LIGCON2 end if ttext con "fl" ttext{mpt,2} = "\0>" goto LIGCON2 end end #if AUTOSCR #else perform kernttext /* New 04/22/04 #endif perform wordspace (reminder) │ Inputs: ttext = word │ │ c5 = font number │ │ curfont = currently active font │ │ │ │ Outputs: a5 = space taken up by word │ if a3 = 6 a5 /= 2 else a5 += 10 end else New code (02/03/08) for determining box size and position for Rehearsal numbers or letters (uses c10,c11,c12,c13,c14,c15,c16,c17) if a3 = REH_MARK perform wordspace c12 = 2 * font_base + zero_height / 3 /* displacement to top c13 = font_height - font_base * 2 / 3 /* displacement to bottom c14 = spc(48) / 2 /* displacement to the left c15 = a5 + (spc(48) * 3 / 5) /* displacement to the right end a5 = 0 end end if a5 > 0 temp3 = "W -" // chs(a5) else temp3 = "W 0" end This code added 10/01/03 to allow for font = 0 (no print) ttext = ttext // pad(4) if ttext{1} = "!" a4 = int(ttext{2..}) if ttext{sub} = "|" /* New 01/17/04: skip over "|" ++sub end ttext = ttext{sub..} end ttext = trm(ttext) (moved to location above on 10/08/08) More code 02/03/08 for dealing with boxes if a3 = REH_MARK and box_flag = 1 sobl(1) = temp3 // temp // " " // chs(a4) // " " // ttext c10 = 1 c11 = oby1 - c12 /* actual displacement to top c12 = oby1 + c13 /* actual displacement to bottom c13 = 0 - c14 /* actual displacement to the left c14 = c15 /* actual displacement to the right First put in horizontal lines of the box c17 = 0 if notesize = 6 c15 = c13 + 1 loop for c16 = 1 to 8 ++c10 sobl(c10) = "K " // chs(c15) // " " // chs(c11) // " 45" ++c10 sobl(c10) = "K " // chs(c15) // " " // chs(c12) // " 45" c15 += 10 if c17 = 1 c16 = 1000 end if c15 > (c14 - 9) c15 = c14 - 9 c17 = 1 end repeat else c15 = c13 loop for c16 = 1 to 8 ++c10 sobl(c10) = "K " // chs(c15) // " " // chs(c11) // " 90" ++c10 sobl(c10) = "K " // chs(c15) // " " // chs(c12) // " 90" if c17 = 1 c16 = 1000 end c15 += 30 if c15 > (c14 - 30) c15 = c14 - 30 c17 = 1 end repeat end for glyph 45 for glyph 90 for glyph 89 --------------- --------------- ----------------- notesize 6 -1 0 10 notesize 6 0 0 30 notesize 6 0 0 1 (6) notesize 14 -3 0 24 notesize 14 0 1 30 notesize 14 0 1 2 (14) notesize 16 -3 0 28 notesize 16 0 1 30 notesize 16 0 1 2 (16) notesize 18 -4 0 32 notesize 18 0 1 30 notesize 18 0 1 3 (18) notesize 21 -4 0 35 notesize 21 0 2 30 notesize 21 0 1 4 (21) Now put in vertical lines of the box c17 = 0 c15 = c11 --c14 if notesize > 6 --c14 end if notesize > 16 --c14 end if notesize > 18 --c14 end loop for c16 = 1 to 8 ++c10 sobl(c10) = "K " // chs(c13) // " " // chs(c15) // " 89" ++c10 sobl(c10) = "K " // chs(c14) // " " // chs(c15) // " 89" if c17 = 1 c16 = 1000 end c15 += notesize if c15 > (c12 - notesize) c15 = c12 - notesize c17 = 1 end repeat pcode = c10 else Need to make a cludge of a modification here 01/12/09. The problem is that when the node is isolated, any non-null xposi_shift becomes irrelevant, once mskpage takes over. In this case, if we want the word shifted horizontally, the shift must be in the Word sub-object, not in the object position. We will adjust the obx position because it is relevant when printing individual parts if ts(a1,ISOLATED) = 1 temp3 = "W " // chs(save_xposi_shift) // temp // " " // chs(a4) // " " // ttext obx1 -= save_xposi_shift else temp3 = temp3 // temp // " " // chs(a4) // " " // ttext end sobl(1) = "" end End of 02/03/08 Changes obx = obx1 oby = ts(a1,STAFF_NUM) * 1000 if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj goto VT2 end * multi-letter dynamics jtype = "S" jcode = 0 pcode = len(ttext) putc pcode = ~pcode ttext = ~ttext | obx = obx1 oby = oby1 x = obx y = oby loop for a4 = 1 to pcode if "pmfszr" con ttext{a4} z = mpt + 107 /* music font mpt += 59 kscrdat = "" perform subj x += hpar(mpt) end repeat oby = ts(a1,STAFF_NUM) * 1000 + oby if ts(a1,ISOLATED) = 1 jtype = "I" end jscrdat = "" perform putobj put out super-objects VT2: a2 = ts(a1,SUPER_TYPE) if a2 > 0 a2 /= 2 if rem = 0 and a2 >= 1 and a2 <= 6 a4 = save_a4 /* this was computed above if a2 = WEDGES * wedges line = chs(smusdir(a4,2)) // " " line = line // chs(ts(a1,WEDGE_SPREAD)) // " " line = line // chs(smusdir(a4,3)) // " " // chs(smusdir(a4,4)) // " " line = line // chs(ts(a1,WEDGE_OFFSET) + obx2) // " " // chs(smusdir(a4,4)) ++outpnt tput [Y,outpnt] H ~smusdir(a4,1) W ~line end if a2 = DASHES * dashes if ts(a1,SIGN_TYPE) = LETTER_DYNAM a6 = obx2 - (2 * hpar(46)) else a6 = obx2 end line = chs(a6) // " " // chs(smusdir(a4,4)) // " 0" a6 = smusdir(a4,3) ++outpnt tput [Y,outpnt] H ~smusdir(a4,1) D ~smusdir(a4,2) ~line ~a6 end * range shifts if chr(a2) in [OCT_UP,OCT_DOWN,DBL_OCT_UP,DBL_OCT_DOWN] if a2 = OCT_UP or a2 = DBL_OCT_UP a5 = smusdir(a4,4) + vpar(47) else a5 = smusdir(a4,4) - vpar(46) end line = chs(smusdir(a4,2)) // " " // chs(smusdir(a4,3)) // " " a6 = obx2 - hpar(47) line = line // chs(a6) // " " // chs(a5) // " " // chs(vpar(41)) ++outpnt tput [Y,outpnt] H ~smusdir(a4,1) V ~line end smusdir(a4,1) = 0 /* clear the row for next use end end if ts(a1,DINC_FLAG) > 0 inctype = ts(a1,DINC_FLAG) end goto ZZZ end D. Typeset Figures if nodtype = FIGURES obx = p We need to run a little check here. If there is an element in the ts array that has the same division number and is a note or cue-note, then the possibility exist that this object might have to be shifted to the right in order to be placed under the note (and not under some accidental to the note). if ts(a1+1,DIV) = ts(a1,DIV) if ts(a1+1,TYPE) = NOTE or ts(a1+1,TYPE) = CUE_NOTE obx += ts(a1+1,NODE_SHIFT) p += ts(a1+1,NODE_SHIFT) ts(a1+1,NODE_SHIFT) = 0 if ts(a1+1,SPACING) < ts(a1,MIN_FIG_SPAC) ts(a1+1,SPACING) = ts(a1,MIN_FIG_SPAC) end end end a3 = FIG_DATA supcnt = 0 * determine if accidentals precede any figures in this set loop for a2 = 1 to 4 mf(a2) = 0 repeat a10 = FIG_DATA loop for a2 = 1 to ts(a1,NUMBER_OF_FIG) a4 = ts(a1,a10) + 28 /* tricky code, possible rewrite Code added 11/16/03 to deal with parentheses around figures if a4 > 1000 a4 = a4 / 1000 a4 = rem end temp = chr(a4) if "1389" con temp if ts(a1,a10+1) > 0 and ts(a1,a10+1) < 20 mf(a2) = a4 - 48 end end a10 += 3 repeat * construct sub-objects oby = vpar(49) y = vpar(49) loop for a2 = 1 to ts(a1,NUMBER_OF_FIG) a6 = ts(a1,a3) Code added 11/16/03 to deal with parentheses around figures a10 = 0 if a6 > 1000 a10 = a6 / 1000 a6 = rem if a6 = 0 a10 = 0 else if a10 = 1 y -= vpar(92) x = obx - hpar(136) if mf(a2) > 0 a9 = mf(a2) + 67 a9 = hpar(a9) x -= a9 end z = 197 /* music font kscrdat = "" perform subj /* small left parenthesis y += vpar(92) else if a10 = 3 /* shift down to bracket 3 figures y += (vpar(48) >> 1) end y += vpar(93) x = obx - hpar(138) if mf(a2) > 0 a9 = mf(a2) + 67 a9 = hpar(a9) x -= a9 end z = 69 /* music font kscrdat = "" perform subj /* large left parenthesis y -= vpar(93) if a10 = 3 y -= (vpar(48) >> 1) end end end end x = obx if a6 > 0 if mf(a2) > 0 a9 = mf(a2) + 67 a9 = hpar(a9) x = obx - a9 z = mf(a2) + 210 /* music font else a9 = hpar(66) if a6 = 30 z = 220 /* music font else if a6 < 10 z = a6 + 199 else if a6 < 20 z = 200 kscrdat = "" perform subj x += a9 z = a6 + 189 else a9 = a6 + 47 a9 = hpar(a9) z = a6 + 190 end end end end kscrdat = "" perform subj x += a9 a6 = ts(a1,a3+1) if a6 > 0 a9 = hpar(66) if a6 < 10 z = a6 + 199 else if a6 < 20 z = 200 kscrdat = "" perform subj x += a9 z = a6 + 189 else a9 = a6 + 47 a9 = hpar(a9) z = a6 + 190 end end kscrdat = "" perform subj x += a9 end Code added 11/16/03 to deal with parentheses around figures if a10 > 0 x -= a9 if a10 = 1 x += hpar(137) y -= vpar(92) z = 198 /* music font kscrdat = "" perform subj /* small right parenthesis y += vpar(92) else if a10 = 3 /* shift down to bracket 3 figures y += (vpar(48) >> 1) end x += hpar(139) y += vpar(93) z = 70 /* music font kscrdat = "" perform subj /* large right parenthesis y -= vpar(93) if a10 = 3 y -= (vpar(48) >> 1) end end x += a9 end end * set up for dealing with continuation lines if ts(a1,a3+2) = 2 ++snum figarr(a2,FIG_SNUM) = snum dv4 = x - obx if a6 > 0 dv4 += (hpar(66) * 3 / 2) /* 11/16/03 Experiment: was simply hpar(66) end figarr(a2,FIG_HOFF1) = dv4 ++supcnt supnums(supcnt) = snum end if ts(a1,a3+2) = 1 figarr(a2,FIG_HOFF2) = hpar(77) figarr(a2,FIG_READY) = 1 ++supcnt supnums(supcnt) = figarr(a2,FIG_SNUM) end a3 += 3 y += vpar(48) repeat * put out object and sub-objects out = chs(supcnt) loop for a3 = 1 to supcnt out = out // " " // chs(supnums(a3)) repeat supcnt = 0 jtype = "F" jcode = 0 pcode = sobcnt oby = ts(a1,STAFF_NUM) * 1000 + oby Now look for print suggestions for this figure object putobjpar = 0 c5 = ts(a1,TSR_POINT) pcontrol = ors(tsr(c5){1}) /* 05/02/03 px = ors(tsr(c5){3}) << 8 py = ors(tsr(c5){4}) << 16 a2 = ors(tsr(c5){2}) << 24 putobjpar = a2 + px + py + pcontrol /* Note: order of data has been changed jscrdat = "" perform putobj * write out continuation line super-objects loop for a2 = 1 to MAX_FIG if figarr(a2,FIG_READY) > 0 ++outpnt tput [Y,outpnt] H ~figarr(a2,FIG_SNUM) F ~a2 ~figarr(a2,FIG_HOFF1) ~figarr(a2,FIG_HOFF2) 0 loop for a3 = 1 to 4 figarr(a2,a3) = 0 repeat end repeat a4 = ts(a1,FIG_SPACE) if a4 > 0 p += a4 end if ts(a1,DINC_FLAG) > 0 inctype = ts(a1,DINC_FLAG) end goto ZZZ end ================================================================= GENERAL SECTION COMMENT At this point, we have only notes (grace, regular and cue) and rests (regular and cue) left to typeset. This is actually where the process becomes interesting and can be quite complex. For music on the grand staff (the most complex situation) there can be as many as ten (MAX_PASS) passes and as many as six notes in a single pass (maximum chord size) We need to review the way note events are organized in the set array and how this relates to the way they are organized in the i-files. In the i-files, the basic unit of organization is the object. An object can contain a note, a set of notes (chord), or a rest. Items which normally attach to notes such as accidentals, ornaments, articulations, leger lines, etc., are included as sub-objects to the object. Items which normally connect notes such as beams, ties, and slurs, are represented by superobjects. Among the parameters associated with an object are (1) horizontal location, (2) space node number, and (3) distance increment flag. The first level of organization in the set array is by division. A division is a time-location with a measure. A division may have several note events belonging to it (as well as other types of events, which, at this point in the program have already been dealt with). All members of a division will have the same space node number. The first object in a division will have a non-zero distance increment flag. This feature is handled automatically by the putobj procedure. Within a division, we first find all of the grace notes (and grace chord notes). Since grace notes generally precede regular and cue notes, these notes can have non-zero advance-space parameters associated with them. This means that grace notes objects can advance the horizontal location pointer. On the other hand, cue-size and regular objects will generally have the same horizontal location (except for for shifts to accomodate clashes). From the above analysis, we can see that the next level of organization in the set array is by general location. In particular, grace notes will tend fall into one or more groups, each having a separate general location. All cue-size and regular notes (and rests will have the same general location. Finally the lowest level of organization in the set array is by actual object. Only notes of the same chord will share the same object. We are currently inside a big loop, which begins under the title "Processing loop (loop ends at ZZZ)". The loop itself is initiated by the instruction "loop for a1 = 1 to sct". The variable "spn", which is the space node number, is retrieved from storage at the top of this loop. It is based on division number. We do not need to process all notes and rests on a particular division at one time; we may proceed down to the next level of organization within the set array, which is the general location. The key variable in determining this grouping is the space parameter "SPACING". The first ts(.,.) ROW element of a general location group will have a non-zero space parameter, and any other element in such a group will have a space parameter = 0. In typesetting a group of notes at a general location, the following information is required. (1) The number of passes (chords or single notes) in the group (2) The number of set array elements in each of these passes (3) a4 = the spacing parameter for this group (4) a2 = index to last element in group END OF COMMENT ================================================================= E. Notes/Rests a4 = ts(a1,SPACING) if ts(a1,NODE_SHIFT) > 0 dputc shifting division number ~ts(a1,DIV) by the amount = ~ts(a1,NODE_SHIFT) p += ts(a1,NODE_SHIFT) end npasses = 1 a3 = 1 loop for a2 = a1+1 to sct if ts(a2,SPACING) <> 0 --a2 pitchcnt(npasses) = a3 goto XX1 end if ts(a2,TYPE) > NOTE_OR_REST --a2 pitchcnt(npasses) = a3 goto XX1 end if nodtype = GR_NOTE if ts(a2,TYPE) = XGR_NOTE ++a3 else pitchcnt(npasses) = a3 a3 = 1 ++npasses end else if ts(a2,TYPE) = XNOTE or ts(a2,TYPE) = XCUE_NOTE ++a3 else pitchcnt(npasses) = a3 a3 = 1 ++npasses end end repeat XX1: Create objects for this node a1 = index to first element in node a2 = index to last element in node npasses = number of passes (separate chords) in this node pitchcnt(.) = size of chord for each pass a4 = space parameter (space following this node) I. Typeset objects in this node c2 = a1 - 1 loop for a14 = 1 to npasses obx = p c1 = c2 + 1 /* top of chord c2 = c1 + pitchcnt(a14) - 1 /* bottom of chord a3 = ts(c1,STAFF_NUM) + 1 /* staff number passnum = ts(c1,PASSNUM) oby = ts(c1,OBY) ntype = ts(c1,NTYPE) ntype = ts(c1,NTYPE) & 0xff /* new 10/15/07 opt_rest_flag = ts(c1,NTYPE) >> 8 /* new 10/15/07 nodtype = ts(c1,TYPE) I. Construct Text Sub-Object (new to this position 06-26-94 ) if nodtype = NOTE c5 = ts(c1,TEXT_INDEX) if c5 > 0 ttext = tsdata(c5) // pad(1) else ttext = pad(1) end if ttext{1} in ['A'..'Z','a'..'z','!'..'(','\','='] New test for text data 09/01/03 c5 = 0 if ttext{1} in ['A'..'Z','a'..'z','!'..'(','\','='] c5 = 1 else ttext = ttext // " " loop for c4 = 1 to len(ttext) if ttext{c4} = "|" and ttext{c4+1} in ['A'..'Z','a'..'z','!'..'(','\','='] c5 = 1 c4 = len(ttext) end repeat ttext = trm(ttext) end if c5 = 1 End of test 09/01/03 c5 = mtfont perform spacepar temp2 = ttext if temp2 con "$$$$" ttext = temp2{1,sub-1} c4 = int(temp2{sub+4..}) /* x offset (calculated earlier) if sub < len(temp2) org_c4 = int(temp2{sub+1..}) /* original "unbiased" (pre 12/09/03) offset else org_c4 = c4 end else dputc Program Error end temp2 = ttext // "| " ttextcnt = 0 CCCD: if temp2 con "|" ttext = temp2{1,mpt-1} if ttext = "_" /* 09/01/03 Must flag isolated "_" ttext = "&" end temp2 = temp2{mpt+1..} ++ttextcnt ttextarr(ttextcnt) = trm(ttext) goto CCCD end loop for a7 = 1 to ttextcnt ttext = ttextarr(a7) determine values of xbytearr a6 = len(ttext) xbytearr(a7) = "* " if "-_" con ttext{a6} ttext = ttext{1,a6-1} xbytearr(a7) = "-_"{mpt} // " " if mpt = 2 a6 = len(ttext) if ",.;:!?" con ttext{a6} ttext = ttext{1,a6-1} xbytearr(a7) = ",.;:!?"{mpt} // " " end end end ttextarr(a7) = ttext repeat determine relative position of ttext x = p - c4 sobx = x - obx Code added 12/09/03 if org_c4 <> c4 a8 = p - org_c4 sobx2 = a8 - obx else sobx2 = 0 end loop for a8 = 1 to ttextcnt ttext = ttextarr(a8) if ttext <> "&" /* 09/01/03 Use flag set above ++sobcnt Code modified 12/09/03 if sobx2 <> 0 temp3 = "T " // chs(sobx) // "|" // chs(sobx2) // " " // chs(a8) // " " else temp3 = "T " // chs(sobx) // " " // chs(a8) // " " end temp3 = "T " // chs(sobx) // " " // chs(a8) // " " if ttext con "=" if mpt < 3 /* 10/19/03 Fixing corner case error ttext{mpt} = "-" else if ttext{mpt-2,3} <> "\0=" ttext{mpt} = "-" end end end Introducing optional conversion to ligitures in text 10/20/03 if ligit_flag = 1 LIGCON1: if ttext con "ffi" ttext{mpt,3} = "\0:" goto LIGCON1 end if ttext con "ffl" ttext{mpt,3} = "\0;" goto LIGCON1 end if ttext con "ff" ttext{mpt,2} = "\0<" goto LIGCON1 end if ttext con "fi" ttext{mpt,2} = "\0=" goto LIGCON1 end if ttext con "fl" ttext{mpt,2} = "\0>" goto LIGCON1 end end #if AUTOSCR #else perform kernttext /* New 04/22/04 #endif perform wordspace sobl(sobcnt) = temp3 // ttext // " " // xbytearr(a8) // chs(a5) end repeat else if ttext in [' ','~'] /* code added 02-23-95 loop for c15 = len(ttext) to 1 step -1 if ttext{c15} = "~" I'm going to try something risky here, namely to add a text sub-object to the previous note: temp variables c13,c14,c15 loop for c13 = outpnt to 1 step -1 tget [Y,c13] temp3 if temp3{1,3} = "J N" 1. Increment field 6 of record at c13 temp3 = temp3{5..} c14 = int(temp3) c14 = int(temp3{sub..}) c14 = int(temp3{sub..}) temp2 = "J N " // temp3{1..sub} c14 = int(temp3{sub..}) ++c14 temp2 = temp2 // chs(c14) // temp3{sub..} tput [Y,c13] ~temp2 2. Create space at c13+1 loop for c14 = outpnt to c13 + 1 step -1 tget [Y,c14] temp3 tput [Y,c14+1] ~temp3 repeat 3. Add pseudo text record at c13+1 temp3 = "T 0 " // chs(c15) // " ~ * 0" tput [Y,c13+1] ~temp3 4. Increment outpnt ++outpnt c13 = 1 /* end of loop end repeat end repeat end end end note_dur = ts(c1,NOTE_DUR) /* Added 11-11-93 if nodtype <= REST passtype = REG passsize = FULLSIZE if bit(16,ts(c1,SUBFLAG_1)) = 1 passsize = CUESIZE /* EXPERIMENT 06-24-94 end else passsize = CUESIZE if nodtype <= CUE_REST passtype = CUE else passtype = GRACE end end a) rests if nodtype = REST or nodtype = CUE_REST c3 = ts(c1,STAFF_NUM) * 1000 perform setrest (c9) /* OK 6-23-93 goto ZZZZ end b) arpeggios (New code 01/13/06) if nodtype = GR_NOTE and ntype = ARPEGGIO arpeg_flag = ts(c1,ARPEG_FLAG) arpeg_top = ts(c1,ARPEG_TOP) arpeg_bottom = ts(c1,ARPEG_BOTTOM) perform setarpeggio goto ZZZZ end c) notes leger lines hpar(82) = width of black note (for typesetting) hpar(83) = width of whole note (for typesetting) c7 = c2 c8 = c1 c9 = 0 stem = bit(1,ts(c1,STEM_FLAGS)) if stem = UP chord_spread = ts(c2,STAFFLOC) - ts(c1,STAFFLOC) else chord_spread = ts(c1,STAFFLOC) - ts(c2,STAFFLOC) end super_flag = 0 slur_flag = 0 loop for c3 = c1 to c2 super_flag |= ts(c3,SUPER_FLAG) slur_flag |= ts(c3,SLUR_FLAG) repeat if ntype > HALF c9 = hpar(83) - hpar(82) + 1 end perform setleger /* looks O.K. 6-24-93 accidentals loop for c3 = c1 to c2 c4 = ts(c3,AX) if c4 > 0 y = ts(c3,STAFFLOC) perform setax /* looks O.K. 6-24-93 end repeat note heads and dots z1 = 50 - ntype /* music font if z1 > 43 /* music font z1 = 43 /* music font end if passsize = CUESIZE z1 += 128 /* music font end Adding code for percussion note heads 02/19/06 c4 = ts(c1,SUBFLAG_1) & 0xf00000 if c4 > 0 c4 >>= 20 if c4 = 1 z1 = 1001 /* extended music font if passsize = CUESIZE ++z1 /* end end end loop for c3 = c1 to c2 if c3 = c1 All New code 05/02/03 At this point, we need to see if the note object position has been modified "absolutely" by a print suggestion. If this is the case, we need to make the adjustment here, AND, elimate the suggestion from the tsr string. c4 = ts(c1,TSR_POINT) c5 = ors(tsr(c4){2}) if bit(0,c5) = 1 px = ors(tsr(c4){3}) if px > 0 px = px - 128 * notesize / 10 pxx = c5 & 0x02 >> 1 if pxx = 1 ts(c1,GLOBAL_XOFF) = px tsr(c4){3} = chr(0) /* here is where suggestion is zeroed out end end end End of new code 05/02/03 obx = ts(c1,GLOBAL_XOFF) + p end x = obx + ts(c3,LOCAL_XOFF) y = ts(c3,STAFFLOC) z = z1 Adding code 11/26/06 to allow for mixed colors in chords if mixed_color_flag > 0 z = 50 - ts(c3,NTYPE) if z > 43 /* music font z = 43 /* music font end /* music font if passsize = CUESIZE z += 128 end /* music font end End of 11/26/06 Addition kscrdat = "" #if AUTOSCR perform build_note_kscrdat #endif │ │ Uses inputs: c3 = pointer into set array for this note │ y = vertical position of note │ ntype = type of note (e.g. sixteenth) │ note_dur = duration of note (in divisions) │ divspq = divspq │ nodtype = NOTE, GR_NOTE, or CUE_NOTE │ │ Output: kscrdat string │ │ Operation: Compute full values for: P2 P4 P6 P7 P10 P12 │ Compute partial values for: P5 P9 │ Not computed: P3 P8 │ perform subj c16 = y / notesize if c16 <= 0 --c16 /* guarentee c16 is above position for rem <> 0 end c10 = rem if y <= 0 - notesize if c10 <> 0 y += vpar(1) y = c16 + 1 * notesize end perform wideleger /* looks O.K. 6-24-93 end if y >= vpar(10) if c10 <> 0 y -= vpar(1) y = c16 * notesize end perform wideleger end perform setdots /* looks O.K. 6-24-93 repeat look for forward tie, slur and tuplet super-objects x = obx y = oby perform superfor /* operates on entire chord set certain articulations above or below notes or stems perform setart /* operates on entire chord if there are slurs entering or leaving this chord, adjust virtual endpoints at this time. c14 = ts(c1,SLUR_X) c8 = 0 /* slur present flag if c14 > 0 c5 = ts(c14,1) c4 = ts(c14,3) if c4 <> c5 c8 = 2 /* slur present above (usually) end if c4 < c5 c5 = c4 /* above end c4 = ts(c14,2) c6 = ts(c14,4) if c4 <> c6 c8 = 1 /* slur present below (usually) end if c6 > c4 c4 = c6 /* below end if stem = DOWN c6 = c4 c4 = c5 c5 = c6 if c8 <> 0 c8 = 3 - c8 end end loop for c6 = c1 to c2 ts(c6,VIRT_STEM) = c5 ts(c6,VIRT_NOTE) = c4 repeat else c5 = ts(c1,VIRT_STEM) c4 = ts(c1,VIRT_NOTE) end Set more indications perform setperf /* operates on entire chord Set forte and piano (New code 05/17/03) c17 = ( ts(c1,SUBFLAG_1) | ts(c1,ED_SUBFLAG_1) ) & 0x1c003c00 /* changed 10/08/08 from 0x3c00 if c17 > 0 c7 = stem px = 0 py = 0 pyy = 0 pxx = 0 c5 = 14 /* dynamics code = 14 perform getpxpy (c5,c1) if bit(0,pcontrol) = 1 if bit(1,pcontrol) = 1 if bit(2,pcontrol) = 0 c7 = 1 - stem else c7 = stem end end end c5 = ts(c1,VIRT_STEM) c4 = ts(c1,VIRT_NOTE) c13 = 0 perform yadjust if c7 = stem if stem = DOWN y = c5 + vpar(5) else y = c4 + vpar(5) end else if stem = UP y = c5 - vpar(2) else y = c4 - vpar(2) end end x = obx + px if pyy = 1 y = py else y += py end c7 = c17 >> 10 New code 10/08/08 if c7 > 15 c7 >>= 16 c7 += 15 /* potential range 1 to 23 end c17 = ts(c1,ED_SUBFLAG_1) & 0x1c003c00 /* changed 10/08/08 from 0x3c00 Case I: regular dynmaics if c17 = 0 New code 10/08/08 and 01/12/09 and 03/16/09 if c7 = 16 or c7 = 17 or c7 = 18 if c7 = 18 /* sff z = 111 /* music font kscrdat = "" perform subj x += hpar(63) z = 110 /* music font perform subj x += hpar(62) z = 110 /* music font perform subj else if c7 = 16 z = 110 kscrdat = "" perform subj /* f x += hpar(140) else z = 109 kscrdat = "" perform subj /* m x += hpar(60) z = 110 end perform subj x += hpar(140) /* f z = 108 perform subj x += hpar(62) /* p end else if c7 < 5 /* p, pp, ppp, pppp z = 108 kscrdat = "" loop while c7 > 0 perform subj x += hpar(60) --c7 repeat else if c7 < 9 /* f, ff, fff, ffff z = 110 kscrdat = "" loop while c7 > 4 perform subj x += hpar(140) --c7 repeat else if c7 < 11 /* mp, mf z = 109 /* music font kscrdat = "" perform subj x = obx + hpar(60) + px z = c7 * 2 + 90 /* music font perform subj else if c7 = 11 /* fp z = 110 /* music font kscrdat = "" perform subj x = obx + hpar(140) + px z = 108 /* music font perform subj else if c7 = 12 /* sfp z = 111 /* music font kscrdat = "" perform subj x = obx + hpar(63) + px z = 110 /* music font perform subj x += hpar(140) z = 108 /* music font perform subj else kscrdat = "" if c7 > 13 /* sfz, rfz z = c7 * 2 + 83 /* music font perform subj c8 = z - 48 x = obx + hpar(c8) + px end z = 110 /* music font perform subj #if SFZ x += hpar(62) z = 112 /* music font perform subj #endif end end end end end end else Case II: editorial dynamics Conditional code added 02/04/04 to implement Roman editorial dynamics #if ROMAN_EDIT ++sobcnt sobx = x - obx soby = y - oby New code 10/08/08 if c7 = 16 sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 ffp" else if c7 < 5 /* p, pp, ppp, pppp sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 " loop while c7 > 0 sobl(sobcnt) = sobl(sobcnt) // "p" --c7 repeat else if c7 < 9 /* f, ff, fff, ffff sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 " loop while c7 > 4 sobl(sobcnt) = sobl(sobcnt) // "f" --c7 repeat else if c7 < 11 /* mp, mf sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 m" if c7 = 9 sobl(sobcnt) = sobl(sobcnt) // "p" else sobl(sobcnt) = sobl(sobcnt) // "f" end else if c7 = 11 /* fp sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 fp" else if c7 = 12 /* sfp sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 sfp" else if c7 > 13 /* sfz, rfz if c7 = 14 sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 sf" else sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " 31 rf" end #if SFZ sobl(sobcnt) = sobl(sobcnt) // "z" #endif end end end end end end end #else Editorial dynamics using square brackets and the music font hpar(108) = width of editorial dynamic letter p chr(251) hpar(109) = width of editorial dynamic letter m chr(252) hpar(110) = width of editorial dynamic letter f chr(253) hpar(111) = width of editorial dynamic letter s chr(246) hpar(112) = width of editorial dynamic letter z chr(247) hpar(113) = width of editorial dynamic letter r chr(248) hpar(114) = backup to print square bracket for editorial p [p... chr(195) hpar(115) = backup to print square bracket for editorial m [m... hpar(116) = backup to print square bracket for editorial f [f... hpar(117) = backup to print square bracket for editorial s [sf hpar(118) = backup to print square bracket for editorial r [rf hpar(119) = shift to print square bracket following editorial f f] chr(196) hpar(120) = shift to print square bracket following editorial p p] hpar(121) = shift to print square bracket following editorial z z] vpar(84) = vertical shift up for printing square brackets for dynamics New code 10/08/08 if c7 = 16 kscrdat = "" x -= hpar(116) y -= vpar(84) z = 195 perform subj x += hpar(116) y += vpar(84) z = 253 /* editorial f perform subj /* f x += hpar(110) perform subj /* f x += hpar(110) perform subj /* p x += hpar(108) x += hpar(120) else if c7 < 5 /* p, pp, ppp, pppp kscrdat = "" x -= hpar(114) y -= vpar(84) z = 195 perform subj x += hpar(114) y += vpar(84) z = 251 /* editorial p loop while c7 > 0 perform subj x += hpar(108) --c7 repeat x += hpar(120) else if c7 < 9 /* f, ff, fff, ffff kscrdat = "" x -= hpar(116) y -= vpar(84) z = 195 perform subj x += hpar(116) y += vpar(84) z = 253 /* editorial f loop while c7 > 4 perform subj x += hpar(110) --c7 repeat x += hpar(119) else if c7 < 11 /* mp, mf kscrdat = "" x -= hpar(115) y -= vpar(84) z = 195 perform subj x += hpar(115) y += vpar(84) z = 252 /* editorial m perform subj x += hpar(109) if c7 = 9 z = 251 /* editorial p perform subj x += hpar(108) x += hpar(120) else z = 253 /* editorial f perform subj x += hpar(110) x += hpar(119) end else if c7 = 11 /* fp kscrdat = "" x -= hpar(116) y -= vpar(84) z = 195 perform subj x += hpar(116) y += vpar(84) z = 253 /* editorial f perform subj x += hpar(110) z = 251 /* editorial p perform subj x += hpar(108) x += hpar(120) else if c7 = 12 /* sfp kscrdat = "" x -= hpar(117) y -= vpar(84) z = 195 perform subj x += hpar(117) y += vpar(84) z = 246 /* editorial s perform subj x += hpar(111) z = 253 /* editorial f perform subj x += hpar(110) z = 251 /* editorial p perform subj x += hpar(108) x += hpar(120) else if c7 > 13 /* sfz, rfz kscrdat = "" if c7 = 14 x -= hpar(117) y -= vpar(84) z = 195 perform subj x += hpar(117) y += vpar(84) z = 246 /* editorial s perform subj x += hpar(111) else x -= hpar(118) y -= vpar(84) z = 195 perform subj x += hpar(118) y += vpar(84) z = 248 /* editorial r perform subj x += hpar(113) end z = 253 /* editorial f perform subj x += hpar(110) #if SFZ z = 247 /* editorial z perform subj x += hpar(112) #else x += hpar(119) #endif end end end end end end end kscrdat = "" y -= vpar(84) z = 196 perform subj #endif End of Conditional compile 02/04/04 end end End of New code 05/17/03 loop for c3 = c1 to c2 ts(c3,VIRT_NOTE) = c4 ts(c3,VIRT_STEM) = c5 repeat set stems and beams for this note if stem = UP c3 = c1 else c3 = c2 end perform setstem /* (revised for multiple notes) determine super-objects which end on this note or which contain this note (such as beams) 1) beams if ts(c1,BEAM_FLAG) > 0 ++supcnt supnums(supcnt) = beampar(passtype,passnum,BM_SNUM) end 2) ties which end on this note loop for c3 = c1 to c2 c7 = ts(c3,BACKTIE) if c7 > 0 if c7 < INT10000 /* c7 = index to ts element which starts the tie c7 = ts(c7,BACKTIE) /* c7 now points to ROW of tiearr else c7 -= INT10000 end ++supcnt supnums(supcnt) = tiearr(c7,TIE_SNUM) end ts(c3,BACKTIE) = c7 /* now set BACKTIE to point directly to ROW of tiearr repeat 3) slurs (revised for multiple notes) loop for c4 = 1 to 4 c5 = c4 * 2 - 1 if bit(c5,slur_flag) = 1 ++supcnt supnums(supcnt) = slurar(c4,SL_SNUM) end if bit(c5+16,slur_flag) = 1 ++supcnt supnums(supcnt) = slurar(c4+4,SL_SNUM) end repeat 4) tuplets (revised for multiple notes) if bit(5,super_flag) = 1 ++supcnt supnums(supcnt) = tuar(passtype,passnum,TU_SNUM) end 5) long trills (revised for multiple notes) if tsnum(passnum) > 0 and bit(3,super_flag) = 1 /* long trill ending ++supcnt supnums(supcnt) = tsnum(passnum) end New code (11-11-93) Duration attribute of note ++sobcnt sobl(sobcnt) = "A D " // chs(note_dur) // " " // chs(divspq*4) Write out Object Record and associated Sub-Objects out = chs(supcnt) loop for c4 = 1 to supcnt out = out // " " // chs(supnums(c4)) repeat if nodtype = GR_NOTE or nodtype = XGR_NOTE jtype = "G" else jtype = "N" end jcode = ntype pcode = sobcnt c10 = ts(c1,STAFF_NUM) * 1000 oby += c10 Now look for print suggestions for this note object putobjpar = 0 c4 = ts(c1,TSR_POINT) pcontrol = ors(tsr(c4){1}) /* 05/02/03 px = ors(tsr(c4){3}) << 8 py = ors(tsr(c4){4}) << 16 c8 = ors(tsr(c4){2}) << 24 putobjpar = c8 + px + py + pcontrol /* Note: order of data has been changed if xdata_flag = 1 c4 = ts(c1,STEM_FLAGS) & 0x07 /* first three flags c4 <<= 4 putobjpar |= c4 Need to add in the effects of some extra x-position modifications. 11/24/07 c4 = ts(c1,GLOBAL_XOFF) /* ???? I worry about this t1 = putobjpar >> 8 & 0xff if t1 > 0 t1 = t1 - 128 * notesize / 10 end c4 = ts(c1,GLOBAL_XOFF) + t1 /* I worry less about this /* and I think I may have it fixed. jscrdat = "" if c4 > 0 jscrdat = "| P3=" // chs(c4) else if c4 < 0 c4 = 0 - c4 jscrdat = "| P3=-" // chs(c4) end end end perform putobj oby -= c10 Write out completed Super-Objects and set up new ones 1) Tuples if bit(5,super_flag) = 1 /* (revised for multiple notes) Code added 05-31-95 to prevent tuplets over "partial" beams from being associated with those beams. if beampar(passtype,passnum,BM_TUPLE) > 0 if beampar(passtype,passnum,BM_READY) = 0 beampar(passtype,passnum,BM_TUPLE) = 0 end end c8 = 1 t2 = 0 t1 = (tuar(passtype,passnum,TU_FSTEM) & 0xff) + stem c9 = tuar(passtype,passnum,TU_Y1) c11 = 0 goto TPF(tpflag+1) TPF(1): /* default tuplet placement if beampar(passtype,passnum,BM_TUPLE) > 0 c8 |= 0x08 t2 = beampar(passtype,passnum,BM_SNUM) t1 = oby if ts(c1,MULTI_TRACK) > 0 c8 |= 0x10 else t1 += chord_spread c9 = tuar(passtype,passnum,TU_Y2) end c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket if beampar(passtype,passnum,BM_TUPLE) = 2 /* this code expanded 05/06/03 if bit(4,c8) = 1 c10 |= 0x04 /* tips up end else if bit(4,c8) = 0 c10 |= 0x04 /* tips up end end if beampar(passtype,passnum,BM_TUPLE) = 2 c10 |= 0x04 /* tips up end c8 |= c10 end goto TPFEC else if t1 = 0 goto TPFEA else goto TPFEB end end TPF(2): /* place tuplet near note heads if beampar(passtype,passnum,BM_TUPLE) > 0 c8 |= 0x08 t2 = beampar(passtype,passnum,BM_SNUM) t1 = oby + chord_spread c9 = tuar(passtype,passnum,TU_Y2) c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket if beampar(passtype,passnum,BM_TUPLE) = 1 c10 |= 0x04 /* tips up end c8 |= c10 end goto TPFEC else if t1 = 0 goto TPFEA else goto TPFEB end end TPF(3): /* place tuplet near stems if beampar(passtype,passnum,BM_TUPLE) > 0 c8 |= 0x18 t2 = beampar(passtype,passnum,BM_SNUM) t1 = oby c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket if beampar(passtype,passnum,BM_TUPLE) = 2 c10 |= 0x04 /* tips up end c8 |= c10 end goto TPFEC else if t1 > 0 goto TPFEA else c11 = hpar(82) /* shift for stems up goto TPFEB end end TPF(4): /* place all tuplets above notes if beampar(passtype,passnum,BM_TUPLE) > 0 t1 = oby if stem = UP c8 |= 0x18 else c8 |= 0x08 t1 += chord_spread c9 = tuar(passtype,passnum,TU_Y2) end t2 = beampar(passtype,passnum,BM_SNUM) c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket c8 |= c10 end goto TPFEC else if t1 = 0 c11 = hpar(82) end goto TPFEB end TPF(5): /* place all tuplets below notes if beampar(passtype,passnum,BM_TUPLE) > 0 t1 = oby if stem = UP c8 |= 0x08 t1 += chord_spread c9 = tuar(passtype,passnum,TU_Y2) else c8 |= 0x18 end t2 = beampar(passtype,passnum,BM_SNUM) c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket c10 |= 0x04 /* tips up c8 |= c10 end goto TPFEC else if t1 > 0 c11 = hpar(82) end goto TPFEA end TPFEA: c9 = tuar(passtype,passnum,TU_Y2) + notesize c9 += vpar(64) if t1 > 0 c9 += vpar(7) t1 = vpar(7) /* add distance if stem is down else t1 = 0 end c10 = notesize * 6 if c9 < c10 c9 = c10 end t1 += oby + notesize + vpar(64) /* t1 set above if t1 < c10 t1 = c10 end c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket c10 |= 0x04 /* tips up c8 |= c10 end goto TPFEC TPFEB: c9 = tuar(passtype,passnum,TU_Y2) - notesize c10 = 0 - vpar(1) /* OK 4-21-95 if t1 = 0 c9 -= vpar(7) t1 = 0 - vpar(7) /* subtract distance if stem is up else t1 = 0 end if c9 > c10 c9 = c10 end t1 += oby - notesize /* t1 set above if t1 > c10 t1 = c10 end c10 = tuar(passtype,passnum,TU_FSTEM) & 0xff00 c10 >>= 8 if bit(0,c10) = 1 /* bracket present 03-21-97 c10 >>= 1 c10 <<= 5 c10 |= 0x02 /* add bracket c8 |= c10 end TPFEC: c9 -= tuar(passtype,passnum,TU_Y1) t1 -= oby c13 = ts(c1,TUPLE) Convert c13 to 1000 * n1 + n2 and get x,y adjustments New 11/05/05 c13 = ts(c1,TUPLE) & 0xffff c17 = c13 >> 8 c13 &= 0xff c17 *= 1000 c13 += c17 c17 = ts(c1,TUPLE) & 0xff0000 /* x adjustment c17 >>= 16 if c17 > 0 c16 = c17 - 128 /* center to zero else c16 = 0 end c11 += c16 c17 = ts(c1,TUPLE) & 0xff000000 /* y adjustment c17 >>= 24 if c17 > 0 c17 = c17 - 128 /* center to zero else c17 = 0 end c9 += c17 t1 += c17 t3 = tuar(passtype,passnum,TU_SNUM) ++outpnt tput [Y,outpnt] H ~t3 X ~c8 ~c13 0 ~c9 ~c11 ~t1 ~t2 tput [Y,outpnt] H ~t3 X ~c8 ~c13 ~c16 ~c9 ~c11 ~t1 ~t2 tuar(passtype,passnum,TU_SNUM) = 0 /* 05/05/03 adding this (from s2ed) tpflag = global_tpflag end 2) Beams (O.K. for multiple notes) if beampar(passtype,passnum,BM_READY) > 0 if notesize = 6 if beampar(passtype,passnum,BM_SIZE) = CUESIZE beamfont = 102 else beamfont = 103 end end if notesize = 14 if beampar(passtype,passnum,BM_SIZE) = CUESIZE beamfont = 106 else beamfont = 108 end end if notesize = 16 /* size-16 added 12/31/08 if beampar(passtype,passnum,BM_SIZE) = CUESIZE beamfont = 107 else beamfont = 109 end end if notesize = 18 /* size-18 added 12/18/04 if beampar(passtype,passnum,BM_SIZE) = CUESIZE beamfont = 107 else beamfont = 110 end end if notesize = 21 if beampar(passtype,passnum,BM_SIZE) = CUESIZE beamfont = 109 else beamfont = 112 end end c4 = beampar(passtype,passnum,BM_CNT) c5 = 1 c6 = 0 c7 = beampar(passtype,passnum,BM_STEM) << 1 loop for c3 = 1 to c4 c7 >>= 1 if c7 & 0x01 <> 1 c6 = 1 end c5 <<= 1 repeat c7 += beampar(passtype,passnum,BM_SUGG) /* New code 05/14/03 out = chs(c7) // " " /* first stem direction c8 = beampar(passtype,passnum,BM_STEM) if c6 = 0 or c8 = 0 out = out // "0 " /* consistant stem directions else if c7 & 0x01 = UP /* New code 05/14/03 c5 -= 1 /* c5 = 111 ... for number of notes c8 = not(c8) & c5 end out = out // chs(c8) // " " end out = out // chs(beamfont) // " " out = out // chs(beampar(passtype,passnum,BM_READY)) loop for c4 = 1 to beampar(passtype,passnum,BM_READY) out = out // " " out = out // chs(beamdata(passtype,passnum,c4)) repeat ++outpnt tput [Y,outpnt] H ~beampar(passtype,passnum,BM_SNUM) B ~out beampar(passtype,passnum,BM_READY) = 0 beampar(passtype,passnum,BM_TUPLE) = 0 end 3) Ties (revised for multiple notes) tiecnt = 0 loop for c3 = c1 to c2 c7 = ts(c3,BACKTIE) if c7 > 0 compute sitf (situation flag) Description of sitf: range 1 to 16 If the range were from 0 to 15, then bits 3 to 0 would have the following meanings: zero | one -------------------------------------------- bit 3: tips down | tips up bit 2: note on space | note on line bit 1: no stem interfenence | stem interference bit 0: staff interference | no staff interference c9 = tiearr(c7,TIE_VLOC) c10 = tiearr(c7,TIE_FHDIS) /* local x-offset for first note c11 = ts(c3,LOCAL_XOFF) /* local x-offset for second note c12 = tiearr(c7,TIE_FORCE) /* force flag if c12 = 3 c12 = 9 end c8 = ts(c3,MULTI_TRACK) c6 = c8 >> 2 /* multi-track flag c8 &= 0x03 /* mcat flag Modify multi-track flag under certain conditions ADDED 9-10-93 if c6 > 0 if ts(c3,PASSNUM) = 1 and bit(1,ts(c3,STEM_FLAGS)) = DOWN c6 = 0 end end if c6 = 0 if c8 < 2 Rules for single note (or chord) of single part if bit(2,ts(c3,STEM_FLAGS)) = 0 /* single note c5 = tiearr(c7,TIE_FSTEM) + stem if c5 = 0 sitf = 9 /* both stems up else sitf = 1 end if c12 > 0 sitf = c12 /* forced situation end if tiearr(c7,TIE_FSTEM) = UP and sitf < 9 sitf += 2 /* stem interference end else /* chord if c3 < c2 sitf = 1 else sitf = 9 end if c12 > 0 sitf = c12 /* forced situation end if sitf = 1 if tiearr(c7,TIE_FSTEM) = UP if c10 = 0 sitf += 2 /* stem interference end else if stem = DOWN and c3 <> c1 if c11 = 0 sitf += 2 /* stem interference end end end else if stem = DOWN if c11 = 0 sitf += 2 /* stem interference end end end end else Rules for chords representing multiple parts if c3 = c2 /* bottom note of chord sitf = 9 else sitf = 1 end if c12 > 0 sitf = c12 /* forced situation end if c3 = c2 if stem = DOWN sitf += 2 /* stem interference end else if c3 = c1 if tiearr(c7,TIE_FSTEM) = UP sitf += 2 /* stem interference end else if tiearr(c7,TIE_FSTEM) = UP or stem = DOWN sitf += 2 /* stem interference end end end end else Rules for multiple passes on a staff if c6 = 1 sitf = 3 if c12 = 9 sitf = 11 end else if c6 = 2 sitf = 11 if c12 = 1 sitf = 3 end else if c6 = 3 if stem = UP sitf = 1 if c12 > 0 sitf = c12 /* forced situation end if tiearr(c7,TIE_FSTEM) = UP sitf += 2 end else sitf = 11 if c12 = 1 sitf = 3 end end end end end end c5 = c9 / notesize if rem = 0 sitf += 4 /* note on line end Note: you won't know if there is staff interference until you know the final length of the tie c9 += tiearr(c7,TIE_STAFF) * 1000 /* New code added 04/20/03, modified 05/02/03 c13 = tiearr(c7,TIE_SUGG) & 0xff000000 /* length data c6 = tiearr(c7,TIE_SUGG) & 0xff0000 /* position flags c4 = tiearr(c7,TIE_SUGG) & 0xff00 /* x data c5 = tiearr(c7,TIE_SUGG) & 0xff /* y data c13 >>= 24 c6 >>= 16 c4 >>= 8 if c4 > 0 c4 = c4 - 128 * notesize / 10 end if c5 > 0 c5 = c5 - 128 * notesize / 10 end if bit(2,c6) = 1 c5 += 10000 end c6 = 0 if c13 > 0 c6 = c13 - 128 * notesize / 10 end /* end New code c8 = tiearr(c7,TIE_SNUM) ++outpnt tput [Y,outpnt] H ~c8 T ~c9 ~c10 ~c11 ~c4 ~c5 ~c6 ~sitf 0 tiearr(c7,TIE_SNUM) = 0 ts(c3,BACKTIE) = 0 end If there is a tie leaving this note, build up a new ROW element of tiearr if bit(0,ts(c3,SUPER_FLAG)) = 1 * identify free slice of tiearr loop for c7 = 1 to MAX_TIES if tiearr(c7,TIE_SNUM) = 0 goto X2 end repeat Here is where tiearr is built X2: ++tiecnt tiearr(c7,TIE_SNUM) = tv4(tiecnt) tiearr(c7,TIE_NTYPE) = ts(c3,TYPE) tiearr(c7,TIE_VLOC) = ts(c3,STAFFLOC) tiearr(c7,TIE_FHDIS) = ts(c3,LOCAL_XOFF) tiearr(c7,TIE_FSTEM) = bit(1,ts(c3,STEM_FLAGS)) tiearr(c7,TIE_NDX) = c3 tiearr(c7,TIE_STAFF) = ts(c3,STAFF_NUM) tiearr(c7,TIE_FOUND) = 0 tiearr(c7,TIE_FORCE) = ts(c3,SLUR_FLAG) >> 24 /* New code 04/20/03 c4 = ts(c3,TSR_POINT) tiearr(c7,TIE_SUGG) = ors(tsr(c4){69,4}) ts(c3,BACKTIE) = c7 /* not used here as a back pointer end repeat 4) Slurs (revised for multiple notes) loop for c4 = 1 to 8 c5 = c4 * 2 - 1 if c4 > 4 c5 += 8 end end-slurs first element ──────────────────── bit 27: start/end flag (0 = start, 1 = end) bits 24-26: slur number - 1 (0 to 7) bits 17-23: curvature information (end only) bit 16: up/down flag (0 = tips up, 1 = tips down) (end only) bits 0-15: x-offset + 1000 (always a positive number) second element ───────────────────── y position relative to the staff third element (05/06/03) ───────────────────── print suggestion for this end of the slur if bit(c5,slur_flag) = 1 c14 = ts(c1,SLUR_X) loop for c13 = 7 to 31 step 2 loop for c13 = 7 to (TS_SIZE - 2) step 3 /* 05/06/03 c12 = ts(c14,c13) c11 = c12 >> 24 if c11 = c4 + 0x0f /* c4 - 1 + 0x10 (end of slur) c11 = c12 & 0xffff - 1000 /* x-offset c10 = bit(16,c12) /* up/down flag c9 = c12 & 0x000e0000 >> 17 /* curvature (1 to 4) c8 = ts(c14,c13+1) - ts(c1,OBY) /* y-offset c15 = ts(c14,c13+2) /* print suggestion at end of slur (05/06/03) c13 = 100 /* end of loop end repeat if c13 < 100 putc Program error at slur recovery examine stop end sitf = 0 if in_line_edslur > 0 /* New condition 01/12/09 if c4 > 2 sitf = 1 /* dotted slur end else if c4 > 4 sitf = 1 /* dotted slur end end if c10 = UP sitf += 12 end c10 = slurar(c4,SL_SNUM) /* slur number c7 = slurar(c4,SL_YSHIFT) /* starting y-shift c6 = slurar(c4,SL_XSHIFT) /* starting x-shift c9 -= 1 c13 = slurar(c4,SL_BEAMF) /* 0 = slur doesn't start on a beam /* 1 = slur starts on a stem up beam /* 2 = slur starts on a stem down beam c16 = slurar(c4,SL_SUGG) /* print sugg. from beginning of slur (05/06/03) c12 = 0 if c13 > 0 if bit(1,ts(c1,BEAM_FLAG)) = 1 if stem = UP and c8 < 0 - vpar(6) c12 = 1 end if stem = DOWN and c8 > vpar(6) c12 = 2 end end if c12 <> c13 c12 = 0 end end Incorporate print suggestions for slur (05/06/03) if c16 <> 0 putc Suggestions from beginning of slur c17 = c16 & 0xff000000 >> 24 putc .w6x ~c17 ... c17 = c16 & 0xff0000 >> 16 putc .w6x ~c17 ... c17 = c16 & 0xff00 >> 8 putc .w6x ~c17 ... c17 = c16 & 0xff putc .w6x ~c17 getc end if c15 <> 0 putc Suggestions from end of slur c17 = c15 & 0xff000000 >> 24 putc .w6x ~c17 ... c17 = c15 & 0xff0000 >> 16 putc .w6x ~c17 ... c17 = c15 & 0xff00 >> 8 putc .w6x ~c17 ... c17 = c15 & 0xff putc .w6x ~c17 getc end Code added 04/26/05 to implement suppression of slur printing if c16 = -1 sitf = 32 c16 = 0 end c17 = c16 >> 24 /* relative x start c17 &= 0xff if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 c6 += c17 end c17 = c16 & 0xff0000 >> 16 /* relative y start if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 c7 += c17 end c17 = c15 >> 24 /* relative x end c17 &= 0xff if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 c11 += c17 end c17 = c15 & 0xff0000 >> 16 /* relative y end if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 c8 += c17 end c17 = c15 & 0xff00 >> 8 /* change to curvature if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 c9 += c17 end c17 = c16 & 0xff00 >> 8 /* global X shift if c17 > 0 c17 = c17 - 128 * notesize + 5 / 10 end c16 = c16 & 0xff /* global Y shift if c16 > 0 c16 = c16 - 128 * notesize + 5 / 10 end ++outpnt tput [Y,outpnt] H ~c10 S ~sitf ~c6 ~c7 ~c11 ~c8 ~c9 ~c12 ~c17 ~c16 end beginning-slurs --c5 if bit(c5,slur_flag) = 1 c14 = ts(c1,SLUR_X) loop for c13 = 7 to 31 step 2 loop for c13 = 7 to (TS_SIZE - 2) step 3 /* 05/06/03 c12 = ts(c14,c13) c11 = c12 >> 24 if c11 = c4 - 1 /* c4 - 1 (beginning of slur) c11 = c12 & 0xffff - 1000 /* x-offset c8 = ts(c14,c13+1) - ts(c1,OBY) /* y-offset c15 = ts(c14,c13+2) /* print suggestion at beginning of slur c13 = 100 /* end of loop end repeat if c13 < 100 putc Problem finding the end of a slur putc Possible causes: putc 1. A slur has not been closed properly putc 2. Overlapping slurs using the same code putc examine stop end c12 = 0 if ts(c1,BEAM_FLAG) > 1 if stem = UP and c8 < 0 - vpar(6) c12 = 1 end if stem = DOWN and c8 > vpar(6) c12 = 2 end end slurar(c4,SL_SNUM) = slurar(c4,SL_NEXTSNUM) slurar(c4,SL_YSHIFT) = c8 slurar(c4,SL_XSHIFT) = c11 slurar(c4,SL_BEAMF) = c12 /* 0 = slur doesn't start on a beam /* 1 = slur starts on a stem up beam /* 2 = slur starts on a stem down beam slurar(c4,SL_SUGG) = c15 /* (05/06/03) end repeat 5) Long Trills if bit(3,super_flag) = 1 and tsnum(passnum) > 0 out = "H " // chs(tsnum(passnum)) // " R " // chs(ctrarrf(passnum)) out = out // " 0" ++outpnt if nodtype = GR_NOTE or nodtype = XGR_NOTE tput [Y,outpnt] ~out 0 ~try(passnum) else tput [Y,outpnt] ~out -~hpar(42) ~try(passnum) end tsnum(passnum) = 0 ctrarrf(passnum) = 0 end if pre_tsnum(passnum) > 0 /* substitute preliminary values tsnum(passnum) = pre_tsnum(passnum) ctrarrf(passnum) = pre_ctrarrf(passnum) try(passnum) = pre_try(passnum) pre_tsnum(passnum) = 0 end ZZZZ: repeat p += a4 Now that you are all done with the notes and rests of this node, you may set the new inctype if ts(a1,DINC_FLAG) > 0 inctype = ts(a1,DINC_FLAG) end a1 = a2 ZZZ: repeat End of processing loop ************************************************************* return ┌──────────────────────────────────────────────────────────────────────┐ │ 2a. getpxpy (code,index) 04-08-97 added index variable │ │ │ │ Purpose: Save space; get values of px, py, pxx, pyy for │ │ position modification │ │ │ │ Inputs: code = type of subobject referred to │ │ index = index into ts array │ │ │ │ Outputs: pcontrol │ │ px │ │ py │ │ pxx (1 = absolute, 0 = relative) │ │ pyy (1 = absolute, 0 = relative) │ │ │ └──────────────────────────────────────────────────────────────────────┘ procedure getpxpy (code,index) int t2,t3 int code,index getvalue code,index ++code /* all New code 05/02/03 code <<= 2 px = 0 py = 0 pxx = 0 pyy = 0 t2 = ts(index,TSR_POINT) pcontrol = ors(tsr(t2){code-3}) t3 = ors(tsr(t2){code-2}) if bit(0,t3) = 1 px = ors(tsr(t2){code-1}) if px > 0 px = px - 128 * notesize / 10 pxx = t3 & 0x02 >> 1 end py = ors(tsr(t2){code}) if py > 0 py = py - 128 * notesize / 10 pyy = t3 & 0x04 >> 2 end end return ┌──────────────────────────────────────────────────────────────────────┐ │P 3. setstem │ │ │ │ Purpose: Generate subobjects for note stem, or construct │ │ beamdata parameters for setting beam. When beam │ │ is complete, this procedure will call guessbeam. │ │ │ │ Inputs: stem = stem direction (0=UP, 1=DOWN) │ │ ntype = type of note │ │ passtype = type of pass (reg,cue,grace,cuegrace) │ │ passsize = size of notes (full size vs. cue-size) │ │ passnum = pass number │ │ obx = x co-ordinate of object │ │ oby = y co-ordinate of object │ │ c1 = pointer to top note head in array │ │ c2 = pointer to bottom note head in array │ │ c3 = pointer to note head at top of stem │ │ super_flag = composite of SUPER_FLAGs for this chord │ │ │ └──────────────────────────────────────────────────────────────────────┘ procedure setstem str temp.80 int t2,t3,t4,t5,t11,t12,t13,t14,t15 int bcount Determine number of repeaters in "single note" case t11 = 0 if ts(c1,BEAM_FLAG) = NO_BEAM and ts(c1,BEAM_CODE) > 0 t12 = ts(c1,BEAM_CODE) loop t12 /= 10 ++t11 repeat while t12 > 0 end if ntype >= WHOLE if t11 > 0 y = ts(c1,STAFFLOC) - vpar(3) z = 127 kscrdat = "" loop for t12 = 1 to t11 perform subj y -= vpar(2) repeat end else x = obx z = 59 + stem /* music font if passsize = CUESIZE z += 128 /* music font end Connect notes of chord if c1 <> c2 if stem = UP y = ts(c2,STAFFLOC) kscrdat = "" loop while y > ts(c1,STAFFLOC) perform subj y -= vpar(4) repeat else y = ts(c1,STAFFLOC) kscrdat = "" loop while y < ts(c2,STAFFLOC) perform subj y += vpar(4) repeat end end y = ts(c3,STAFFLOC) if ntype > EIGHTH Quarter notes and larger if ts(c1,BEAM_FLAG) = NO_BEAM t3 = y / vpar(1) + 2 c16 = y + vpar20 * 2 + 1 / vpar(2) - 20 t3 = c16 + 2 if stem = UP if t11 = 0 t2 = 8 if t3 <= 0 t2 = t3 - 3 else if t3 < 7 t2 = t3 - 4 else if t3 < 13 t2 = t3 - 5 end end if passsize = CUESIZE ++t2 end end t2 *= vpar(1) t2 = t2 + 20 * vpar(2) / 2 - vpar20 else t13 = y / notesize t14 = rem if t14 = 0 t15 = 3 /* tricky code else t15 = 2 end t2 = y - vpar(t15) - vpar(79) loop for t13 = t15 to t11 t2 -= vpar(2) repeat t12 = vpar(77) + vpar(6) if t2 > t12 t2 = t12 end if t14 <> 0 and t11 = 1 t14 = y y = t2 - vpar(80) kscrdat = "" perform subj y = t14 end end Raise bottom of stem if percussion note head 02/19/06 t13 = ts(c1,SUBFLAG_1) & 0xf00000 if t13 > 0 t13 >>= 20 if t13 = 1 y -= (vpar(1) - 1) end end kscrdat = "" loop while y > t2 perform subj y -= vpar(4) repeat y = t2 perform subj if t11 > 0 y -= vpar(81) if ts(c1,TUPLE) > 0 t13 = ts(c1,TUPLE) New 11/05/05 Convert tuple to 1000 * n1 + n2 t13 = ts(c1,TUPLE) & 0xffff t14 = t13 >> 8 t13 &= 0xff t14 *= 1000 t13 += t14 t14 = x + hpar(102) t15 = y - vpar(82) perform typeset_tuple (t13,t14,t15) end z = 125 /* music font (repeater quarters) kscrdat = "" loop for t2 = 1 to t11 perform subj y += vpar(2) repeat end else if t11 = 0 t2 = 0 if t3 > 11 t2 = t3 - 1 else if t3 > 6 t2 = t3 else if t3 >= 0 t2 = t3 + 1 end end if passsize = CUESIZE --t2 end end t2 = t2 * notesize / 2 else t13 = y / notesize t14 = rem if t14 = 0 t15 = 3 /* tricky code else t15 = 2 end t2 = y + vpar(t15) + vpar(79) loop for t13 = t15 to t11 t2 += vpar(2) repeat t12 = vpar(78) - vpar(4) if t2 < t12 t2 = t12 end if t14 <> 0 and t11 = 1 t14 = y y = t2 + vpar(80) kscrdat = "" perform subj y = t14 end end Adding code (12/10/03) to decrease down stem for music with text for notes where note is on middle line of staff or one step above that. t15 = ts(c3,TEXT_INDEX) if t15 > 0 temp = trm(tsdata(t15)) if temp <> "" t13 = ts(c3,STAFFLOC) t14 = notesize << 1 t15 = notesize + 1 if t13 <= t14 and t13 > t15 t2 -= (notesize >> 1) end end end Lower top of stem if percussion note head 02/19/06 t13 = ts(c1,SUBFLAG_1) & 0xf00000 if t13 > 0 t13 >>= 20 if t13 = 1 y += (vpar(1) - 1) end end kscrdat = "" loop while y < t2 perform subj y += vpar(4) repeat y = t2 perform subj if t11 > 0 if ts(c1,TUPLE) > 0 t13 = ts(c1,TUPLE) New 11/05/05 Convert tuple to 1000 * n1 + n2 t13 = ts(c1,TUPLE) & 0xffff t14 = t13 >> 8 t13 &= 0xff t14 *= 1000 t13 += t14 t14 = x + hpar(103) t15 = ts(c1,STAFFLOC) - vpar(82) perform typeset_tuple (t13,t14,t15) end y += vpar(81) z = 125 /* music font (repeater quarters) x -= hpar(101) kscrdat = "" loop for t2 = 1 to t11 perform subj y -= vpar(2) repeat x += hpar(101) end end else * 2) Beams if ts(c1,BEAM_FLAG) = START_BEAM bcount = 1 ++snum beampar(passtype,passnum,BM_SNUM) = snum if bit(4,super_flag) = 1 beampar(passtype,passnum,BM_TUPLE) = 1 + stem end beampar(passtype,passnum,BM_STEM) = stem beampar(passtype,passnum,BM_SIZE) = passsize t2 = ts(c1,TSR_POINT) /* New code 05/14/03 t3 = 28 /* 28 = code for beam suggestion ++t3 t3 <<= 2 /* 116 py = ors(tsr(t2){t3-2}) t4 = 0 if py > 0 py = py - 128 if py > 0 t4 = INT100 * py else py = 0 - py t4 = INT100 * INT100 * py end end beampar(passtype,passnum,BM_SUGG) = t4 /* End new code 05/14/03 else bcount = beampar(passtype,passnum,BM_CNT) + 1 beampar(passtype,passnum,BM_STEM) <<= 1 beampar(passtype,passnum,BM_STEM) += stem if passsize < beampar(passtype,passnum,BM_SIZE) beampar(passtype,passnum,BM_SIZE) = passsize end end beamdata(passtype,passnum,bcount) = ts(c1,BEAM_CODE) beampar(passtype,passnum,BM_CNT) = bcount if ts(c1,BEAM_FLAG) = END_BEAM beampar(passtype,passnum,BM_READY) = bcount end end else Eighth notes or smaller if ts(c1,BEAM_FLAG) = NO_BEAM * 1) Flags if passtype = GRACE and ntype = SLASH8 if stem = UP z = 179 /* music font else z = 180 /* music font end y = ts(c3,STAFFLOC) kscrdat = "" perform subj else if stem = UP if ntype = EIGHTH t3 = 53 /* music font (eighth flag) if y <= vpar(4) and passtype = REG and t11 = 0 t3 = 51 /* music font (shortened eighth flag) end t2 = 10 * notesize / 2 else t3 = 55 /* music font (sixteenth flag) t2 = 0 - ntype * 2 + 20 * notesize / 2 end z = 59 /* music font (standard up stem) t4 = notesize t5 = 57 /* music font (extra flag: 32nds, etc) if passsize = CUESIZE t2 -= vpar(1) t3 += 128 /* music font z += 128 /* music font t4 = vpar(36) t5 += 128 /* music font end kscrdat = "" loop while y > t2 perform subj y -= vpar(4) repeat t2 += vpar(1) c16 = t2 * 2 / vpar(2) if rem <> 0 ++t2 end t2 += vpar(1) y = ts(c3,STAFFLOC) if t11 = 0 /* no repeaters z = t3 /* music font (flag character) if y > t2 y = t2 end kscrdat = "" perform subj if ntype < 5 z = t5 /* music font (extra flag) loop for t3 = 1 to 5-ntype y -= t4 perform subj repeat end else t12 = y / notesize t2 += t11 - 1 * notesize if y > t2 or rem <> 0 /* note on space t13 = t11 - 1 * notesize + vpar(67) t14 = vpar(69) else /* note on line t13 = t11 - 1 * notesize + vpar(68) t14 = vpar(70) end t13 = amount to "lengthen" stem t14 = location of first repeater if y > t2 y = t2 end t15 = y kscrdat = "" loop perform subj y -= vpar(4) repeat while y > t15 - t13 y = t15 - t13 z = t3 perform subj if ntype < 5 z = t5 /* music font (extra flag) loop for t3 = 1 to 5-ntype y -= t4 perform subj repeat end y = t15 - t14 z = 126 /* music font (repeater for eights) x = x - hpar(99) loop for t12 = 1 to t11 perform subj y -= notesize repeat x = x + hpar(99) if ts(c1,TUPLE) > 0 t13 = ts(c1,TUPLE) New 11/05/05 Convert tuple to 1000 * n1 + n2 t13 = ts(c1,TUPLE) & 0xffff t14 = t13 >> 8 t13 &= 0xff t14 *= 1000 t13 += t14 t14 = x + hpar(102) t15 = y - vpar(83) perform typeset_tuple (t13,t14,t15) end end else if ntype = EIGHTH t3 = 54 /* music font (eighth flag) if y >= vpar(5) and passtype = REG and t11 = 0 t3 = 52 /* music font (shortened eighth flag) end t2 = 0 - 2 * notesize / 2 else t3 = 56 /* music font (sixteenth flag) t2 = 2 * ntype - 12 * notesize / 2 end z = 60 /* music font (standard down stem) t4 = notesize t5 = 58 /* music font (extra flag) if passsize = CUESIZE t2 += vpar(1) t3 += 128 /* music font z += 128 /* music font t4 = vpar(36) t5 += 128 /* music font end kscrdat = "" loop while y < t2 perform subj y += vpar(4) repeat t2 -= vpar(1) t2 -= vpar(1) c16 = t2 * 2 / vpar(2) if rem <> 0 --t2 end y = ts(c3,STAFFLOC) if t11 = 0 z = t3 /* music font (flag character) if y < t2 y = t2 end kscrdat = "" perform subj if ntype < 5 z = t5 /* music font loop for t3 = 1 to 5-ntype y += t4 perform subj repeat end else t12 = y / notesize t2 -= t11 - 1 * notesize if y < t2 or rem <> 0 /* note on space if t11 = 2 t13 = notesize - vpar(71) else t13 = t11 - 1 * notesize - vpar(72) end t14 = vpar(75) else /* note on line if t11 = 2 t13 = notesize - vpar(73) else t13 = t11 - 1 * notesize - vpar(74) end t14 = vpar(76) end t13 = amount to "lengthen" stem t14 = location of first repeater if y < t2 y = t2 end t15 = y kscrdat = "" loop perform subj y += vpar(4) repeat while y < t15 + t13 y = t15 + t13 z = t3 perform subj if ntype < 5 z = t5 /* music font (extra flag) loop for t3 = 1 to 5-ntype y += t4 perform subj repeat end y = t15 + t14 z = 126 /* music font (repeater for eights) x = x - hpar(100) loop for t12 = 1 to t11 perform subj y += notesize repeat x = x + hpar(100) if ts(c1,TUPLE) > 0 t13 = ts(c1,TUPLE) New 11/05/05 Convert tuple to 1000 * n1 + n2 t13 = ts(c1,TUPLE) & 0xffff t14 = t13 >> 8 t13 &= 0xff t14 *= 1000 t13 += t14 t14 = x + hpar(103) t15 = ts(c1,STAFFLOC) - vpar(82) perform typeset_tuple (t13,t14,t15) end end end end else * 2) Beams if ts(c1,BEAM_FLAG) = START_BEAM bcount = 1 ++snum beampar(passtype,passnum,BM_SNUM) = snum if bit(4,super_flag) = 1 beampar(passtype,passnum,BM_TUPLE) = 1 + stem end beampar(passtype,passnum,BM_STEM) = stem beampar(passtype,passnum,BM_SIZE) = passsize t2 = ts(c1,TSR_POINT) /* New code 05/14/03 t3 = 28 /* 28 = code for beam suggestion ++t3 t3 <<= 2 /* 116 py = ors(tsr(t2){t3-2}) t4 = 0 if py > 0 py = py - 128 if py > 0 t4 = INT100 * py else py = 0 - py t4 = INT100 * INT100 * py end end beampar(passtype,passnum,BM_SUGG) = t4 /* End new code 05/14/03 else bcount = beampar(passtype,passnum,BM_CNT) + 1 beampar(passtype,passnum,BM_STEM) <<= 1 beampar(passtype,passnum,BM_STEM) += stem if passsize < beampar(passtype,passnum,BM_SIZE) beampar(passtype,passnum,BM_SIZE) = passsize end end beamdata(passtype,passnum,bcount) = ts(c1,BEAM_CODE) beampar(passtype,passnum,BM_CNT) = bcount if ts(c1,BEAM_FLAG) = END_BEAM beampar(passtype,passnum,BM_READY) = bcount end end end end return ┌───────────────────────────────────────────────────────────────┐ │P 4. setax │ │ │ │ Purpose: Set accidental │ │ │ │ Inputs: c3 = index into ts array │ │ c4 = accident flag │ │ passsize = note size (full, cue-size) │ │ obx = x co-ordinate of object │ │ oby = y co-ordinate of object │ │ y = y co-ordinate of note head │ │ │ │ Internal: x,y,z sent to subj │ │ │ │ │ └───────────────────────────────────────────────────────────────┘ procedure setax int t1,t2,t3,t4 /* 02/25/97 shift changed from 4 to 8 t2 = c4 >> 8 /* x-offset (to the left) t1 = c4 & 0x0f /* accidental only t4 = 19 /* New code 05/02/03 accidentals code = 19 perform getpxpy (t4,c3) if pxx = 1 x = obx + px else x = obx - t2 + px end /* end New code if bit(2,t1) = 1 /* case: flat-flat or natural-(flat/sharp) z = bit(3,t1) + 64 /* flat or natural t2 = hpar(40) if passsize = CUESIZE z += 128 /* cue size t2 = t2 * 8 / 10 end kscrdat = "" perform subj x += t2 end if t1 & 0x03 = 2 if bit(3,t1) = 1 z = 66 /* double sharp else z = 63 /* regular sharp end else z = bit(1,t1) + 64 /* flat or natural end if passsize = CUESIZE z += 128 /* cue size end kscrdat = "" if bit(4,c4) = 0 perform subj else perform subj2 /* Addition to Code 02/25/97 end return ┌───────────────────────────────────────────────────────────────────┐ │P 5. superfor (operates on an entire chord at once) │ │ │ │ Purpose: Get new snums for forward tie, forward slurs and │ │ forward tuplet │ │ │ │ Inputs: c1 = pointer to top of chord │ │ c2 = pointer to bottom of chord │ │ passtype = type of pass (reg,cue,grace,cuegrace) │ │ passnum = pass number │ │ x = x co-ordinate of object │ │ y = y co-ordinate of object │ │ super_flag = composite of SUPER_FLAGs for this chord │ │ slur_flag = composite of SLUR_FLAGs for this chord │ │ stem = stem direction │ │ │ │ Function: If there is a forward tie, this procedure increments │ │ snum and puts result in tv4(). If there are │ │ forward slurs, this procedure increments snum and │ │ stores results in the appropriate │ │ slurar(.,SL_NEXTSNUM). If there is a forward │ │ tuplet, this procedure increments snum and │ │ constructs the tuar for this tuplet. For all │ │ cases, the procedure increments supcnt and adds │ │ the new super-object number to supnums(.) for later │ │ output in the object record. │ └───────────────────────────────────────────────────────────────────┘ procedure superfor int t1,t2 tiecnt = 0 loop for c3 = c1 to c2 if bit(0,ts(c3,SUPER_FLAG)) = 1 /* if tie starts ++snum ++supcnt supnums(supcnt) = snum ++tiecnt tv4(tiecnt) = snum end repeat loop for t1 = 1 to 8 t2 = t1 * 2 - 2 if t1 > 4 t2 += 8 end if bit(t2,slur_flag) = 1 /* if slur starts ++snum ++supcnt supnums(supcnt) = snum slurar(t1,SL_NEXTSNUM) = snum else slurar(t1,SL_NEXTSNUM) = 0 end repeat if bit(4,super_flag) = 1 ++snum ++supcnt supnums(supcnt) = snum tuar(passtype,passnum,TU_SNUM) = snum tuar(passtype,passnum,TU_Y1) = y if stem = UP tuar(passtype,passnum,TU_Y2) = y else tuar(passtype,passnum,TU_Y2) = ts(c1,STAFFLOC) end tuar(passtype,passnum,TU_FSTEM) = stem t1 = super_flag & 0x3c0 /* bits 6,7,8,9 03-21-97 t1 <<= 2 tuar(passtype,passnum,TU_FSTEM) |= t1 /* tuplet flags 03-21-97 end return ┌──────────────────────────────────────────────────────────────────┐ │P 6. setart (operates on an entire chord at once) │ │ │ │ Purpose: create sub-objects for dots, spiccato and legato. │ │ │ │ Inputs: obx = x-position of object │ │ oby = y-position of object │ │ c1 = pointer to top note of chord │ │ c2 = pointer to bottom note of chord │ │ stem = stem direction (UP or DOWN) │ │ │ │ Outputs: Program may modify virtual endpoints in the ts │ │ array. │ │ │ │ Operation: There are two rules that can be followed │ │ Rule 1: (chord = single note, or dot on middle note │ │ of chord, or more than one dot) │ │ If there is a slur, and slur starts (ends) near │ │ the dot, put dot under (over) slur; │ │ otherwise, if multi-track > 0, put dot on stem; │ │ otherwise put dot on note head. │ │ │ │ Rule 2: (all other situations) │ │ If dot on note at stem end, put dot on stem; │ │ otherwise, put dot at head end of chord. │ │ │ │ If there is a slur into or out of this chord, then │ │ information on the placement of dot/legato or │ │ spiccato has already been compiled and is stored │ │ in the SLUR_X ROW element. Otherwise, the place- │ │ ment needs to be computed here. │ │ │ │ Virtual endpoints are modified in all cases. │ │ │ └──────────────────────────────────────────────────────────────────┘ procedure setart int t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13 int dot_xshift /* New 05/14/05 t2 = 0 t9 = 0 loop for t1 = c1 to c2 t10 = ts(t1,SUBFLAG_2) & 0x3c /* 05/17/03 Editorial arts not yet supported if t10 > 0 ++t2 t3 = t1 t9 |= t10 /* composite flag for chord end Using grace dot to typeset editorial staccato 02/06/04 t10 = ts(t1,ED_SUBFLAG_2) & 0x0c /* editorial staccato & spiccato if t10 > 0 t10 <<= 8 /* put this in higher order byte ++t2 t3 = t1 t9 |= t10 end repeat if t2 = 0 return end Step 1: determine starting position for dot/legatos or spiccatos t13 = 0 /* 03/24/97 potential modification to x position of articulation if c1 = c2 or (t3 <> c1 and t3 <> c2) or t2 > 1 /* follow rule 1 t4 = ts(c1,SLUR_X) if t4 > 0 and ts(t4,6) > 0 /* there is a slur effecting dot y = ts(t4,5) t5 = ts(t4,6) /* above/below flag t8 = 0 /* no adjustment to virtual end points else t10 = ts(c1,MULTI_TRACK) >> 2 if t10 > 0 /* CHANGED from = 3 on 03/24/97 if ts(c1,PASSNUM) = 1 and stem = DOWN t10 = 0 end if ts(c1,PASSNUM) = 2 and stem = UP t10 = 0 end end Code added 03/24/97 to check for print suggestions for articulations t12 = 1 /* articulation code = 1 if t9 & 0x04 > 0 /* spiccato code = 2 05/02/03 ++t12 end perform getpxpy (t12,c1) if pcontrol & 0x03 = 0x03 /* major location change flag if bit(2,pcontrol) = 1 /* place below t5 = BELOW if stem = UP y = ts(c1,VIRT_NOTE) t8 = notesize else y = ts(c1,VIRT_STEM) t8 = vpar(1) if ts(c1,BEAM_FLAG) > NO_BEAM t8 = vpar(2) end end else t5 = ABOVE if stem = UP y = ts(c1,VIRT_STEM) t8 = vpar(1) if ts(c1,BEAM_FLAG) > NO_BEAM t8 = vpar(2) end else y = ts(c1,VIRT_NOTE) t8 = notesize end end else End of 03/24/97 addition if t10 > 0 y = ts(c1,VIRT_STEM) if stem = UP t5 = ABOVE else t5 = BELOW end t8 = vpar(1) if ts(c1,BEAM_FLAG) > NO_BEAM t8 = vpar(2) end else y = ts(c1,VIRT_NOTE) if stem = UP t5 = BELOW else t5 = ABOVE end t8 = notesize end New 11/10/07 We need some code here which disables the interference section below when there is a y-position modifier, if pcontrol & 0x01 > 0 if (py = 0 and pyy = 0) or pyy = 1 t8 = 0 end end end if pyy > 0 y = py else y += py end t13 = px end else /* follow rule 2 Code added 03/24/97 to check for print suggestions for articulations t12 = 1 /* articulation code = 1 if t9 & 0x04 > 0 /* spiccato code = 2 05/02/03 ++t12 end perform getpxpy (t12,c1) if pcontrol & 0x03 = 0x03 /* major location change flag if bit(2,pcontrol) = 1 /* place below t5 = BELOW if stem = UP y = ts(c1,VIRT_NOTE) t8 = notesize else y = ts(c1,VIRT_STEM) t8 = vpar(1) end else t5 = ABOVE if stem = UP y = ts(c1,VIRT_STEM) t8 = vpar(1) else y = ts(c1,VIRT_NOTE) t8 = notesize end end else End of 03/24/97 addition if stem = UP if t3 = c1 /* top note t5 = ABOVE y = ts(c1,VIRT_STEM) t8 = vpar(1) else t5 = BELOW y = ts(c1,VIRT_NOTE) t8 = notesize end else if t3 = c1 /* top note t5 = ABOVE y = ts(c1,VIRT_NOTE) t8 = notesize else t5 = BELOW y = ts(c1,VIRT_STEM) t8 = vpar(1) end end New 11/10/07 We need some code here which disables the interference section below when there is a y-position modifier, if pcontrol & 0x01 > 0 if (py = 0 and pyy = 0) or pyy = 1 t8 = 0 end end end if pyy > 0 y = py else y += py end t13 = px end New (05/14/05) code to set value of dot_xshift for staccato over (under) stem dot_xshift = 0 if t5 = ABOVE if stem = UP dot_xshift = hpar(19) if ts(c1,BEAM_FLAG) <= NO_BEAM y -= vpar(1) end end else if stem = DOWN dot_xshift = 0 - hpar(19) if ts(c1,BEAM_FLAG) <= NO_BEAM y += vpar(1) end end end check for interference in cases where y is based on VIRT_ if t8 <> 0 if (stem = DOWN and t5 = ABOVE) or (stem = UP and t5 = BELOW) t11 = HEAD else t11 = TAIL end if t9 & 0x04 > 0 /* spiccato is special case if (t9 & 0x04 > 0) or (t9 & 0x400 > 0) /* spiccato is special case (02/06/04) if stem = DOWN if t5 = ABOVE /* note if y > vpar(1) y = vpar(1) end y -= 5 * notesize / 4 else if y < vpar(8) y = vpar(8) end y += vpar(1) + vpar(50) /* OK 4-22-95 end else /* UP if t5 = ABOVE if y > 0 y = 0 end y -= vpar(1) y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end else /* note if y < vpar(7) y = vpar(7) end y += 5 * notesize / 4 + vpar(50) end end else t6 = 1 if t5 = ABOVE y -= t8 if y >= 0 t6 = y / notesize t6 = rem else y = 0 - notesize / 4 + y end t7 = -1 else y += t8 if y <= vpar(8) t6 = y / notesize t6 = rem else y = notesize / 4 + y end t7 = 1 end adjust for interference with staff if t6 = 0 y = vpar(1) * t7 + y c16 = t7 + 20 * vpar(2) / 2 - vpar20 y += c16 end end end Step 2: write out articulations Code addition 01/06/06: If art_flag = 48, then please set all staccatos and/or legatos above the note and above the staff lines. if art_flag = 48 if t9 & 0x38 > 0 if y > (0 - vpar(1)) y = 0 - vpar(1) end end end x = obx + t13 kscrdat = "" if t9 & 0x18 > 0 /* staccato z = 96 /* music font x += dot_xshift /* New 05/14/05 perform subj x -= dot_xshift /* New 05/14/05 y = notesize * t7 + y end if t9 & 0x30 > 0 /* legato z = 99 /* music font x += dot_xshift /* New 05/14/05 perform subj x -= dot_xshift /* New 05/14/05 y = notesize * t7 + y end Using grace dot to typeset editorial staccato 02/06/04 if t9 & 0x800 > 0 z = 172 /* grace dot used as editorial staccato x += vpar(1) / 2 x += dot_xshift / 2 /* New 05/14/05 and 09/22/05 kscrdat = "" perform subj x -= dot_xshift / 2 /* New 05/14/05 and 09/22/05 x -= vpar(1) / 2 y = notesize * t7 + y end Using ordinary spiccato for the moment to typeset editorial spiccato 02/06/04 if t9 & 0x400 > 0 /* spiccato z = 98 /* music font if t5 = ABOVE --z /* music font end x += dot_xshift /* New 05/14/05 Code added 05/26/05 to implement arbitrary placement of editorial spiccatos kscrdat = "" if bit(2,art_flag) = 1 t13 = y if stem = UP y = oby + vpar(4) else y = oby - (vpar(5) / 2) end perform subj y = t13 else perform subj end x -= dot_xshift /* New 05/14/05 if t5 = BELOW y -= vpar(50) end if y >= 0 y = y * 2 + 1 / vpar(2) else y = y * 2 - 1 / vpar(2) end y = y * vpar(2) / 2 else if t9 & 0x04 > 0 /* spiccato z = 98 /* music font if t5 = ABOVE --z /* music font end x += dot_xshift /* New 05/14/05 Code added 05/26/05 to implement arbitrary placement of spiccatos kscrdat = "" if bit(2,art_flag) = 1 t13 = y if stem = UP y = oby + vpar(4) else y = oby - (vpar(5) / 2) end perform subj y = t13 else perform subj end x -= dot_xshift /* New 05/14/05 if t5 = BELOW y -= vpar(50) end y = y / vpar(1) * vpar(1) if y >= 0 y = y * 2 + 1 / vpar(2) else y = y * 2 - 1 / vpar(2) end y = y * vpar(2) / 2 else y -= notesize * t7 end end Step 3: adjust virtual end points if t8 <> 0 if t11 = HEAD loop for t8 = c1 to c2 ts(t8,VIRT_NOTE) = y repeat else loop for t8 = c1 to c2 ts(t8,VIRT_STEM) = y repeat end end return ┌────────────────────────────────────────────────────────────────────┐ │P 7. setperf (operates on an entire chord at once) │ │ │ │ Purpose: create sub-objects for turns, trills, shakes, │ │ mordents, horizontal accents, thumb positions, │ │ open string, numbers, harmonics, down-bows, │ │ up-bows, fermatas. (and tremulos as of 01/07/06) │ │ │ │ Inputs: obx = x-position of object │ │ oby = y-position of object │ │ c1 = pointer to top of chord │ │ c2 = pointer bottom of chord │ │ c4 = virtual vertical position of controlling │ │ note head │ │ c5 = virtual vertical position of end of stem │ │ c8 = slur present flag │ │ 0 = not present (usually) │ │ 1 = present at head │ │ 2 = present at stem │ │ stem = stem direction 0 = up │ │ 1 = down │ │ super_flag = composite of SUPER_FLAGs for this chord │ │ │ │ Operation: If multi-track > 0, put indications at the stem │ │ end of the chord; │ │ else, put indications above the chord │ │ │ │ Internal: c4,c5,c7,c9,c13 used to communicate with yadjust │ │ │ │ 04-08-97 Modification. │ │ │ │ It turns out that for turns, trill, shakes, and mordents, │ │ and tremulos, as of 01/07/06, │ │ we want to allow multiple ornaments on a chord. Therefore, │ │ these ornaments need to be processed individually, and not │ │ grouped, as are accents, numbers, up and down bows, fermatas, │ │ etc. │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ procedure setperf str temp.100 /* 04/24/03 bstr bs.600,bt.600 int t1,t2,t3,t4,t5,t7,t8,t9,t10 int ed_subflag_1,ed_subflag_2 /* New variables 05/17/03 int merged_subflag_1,merged_subflag_2 int lsqx,rsqx,sqy,glyph,sq_glyph 1. Determine placement: c7 = situation flag: 0 = place on note head 1 = place on stem if ts(c1,MULTI_TRACK) >> 2 > 0 c7 = 1 else c7 = 1 - stem end 2. Long trill if super_flag & 0x06 > 0 /* if begin ~~~~~ subflag_1 = 0 loop for t8 = c1 to c2 /* loop added 11/05/05 to accomodate all ornaments subflag_1 = subflag_1 | ts(t8,SUBFLAG_1) /* on notes of a chord repeat t5 = ts(c1,PASSNUM) ++snum pre_tsnum(t5) = snum ++supcnt supnums(supcnt) = snum c13 = vpar(53) pre_ctrarrf(t5) = bit(2,super_flag) /* tr. trill if pre_ctrarrf(t5) = 0 c13 = vpar(51) end if pre_ctrarrf(t5) = 1 /* tr. present t3 = subflag_1 & 0x70 >> 4 /* t3 = 0 to 7 (05/17/03 editorial not supported yet) t3 = int("01312311"{t3+1}) pre_ctrarrf(t5) += t3 if subflag_1 & 0x80000 > 0 /* bit 19 is set 11/05/05 pre_ctrarrf(t5) += 3 /* add 3 to R super-object parameter 4 end end ++pre_ctrarrf(t5) perform yadjust pre_try(t5) = y - oby /* Code added 02/24/97 t2 = 4 /* ornament code = 4 perform getpxpy (t2,c1) if pyy > 0 pre_try(t5) = py else pre_try(t5) += py end /* End of 02/24/97 addition else 3. Back ties (sub-objects) New code 04/22/08 Note: Back ties are handled like ornaments. This means that a note with a back tie can have at most one ornament attached to it. Limitation?? sugg_flg2 = 0 /* added 05/02/03 for ornaments, use also /* with back ties loop for t8 = c1 to c2 /* loop accomodates back ties on all chord notes subflag_1 = ts(t8,SUBFLAG_1) t5 = subflag_1 & 0x03000000 /* 00000011 00000000 00000000 00000000 if t5 > 0 t2 = 4 + sugg_flg2 /* ornament code = 4 if sugg_flg2 = 0 /* New code 05/02/03 ++sugg_flg2 end x = obx - vpar(4) t5 >>= 24 if t5 = 1 /* overhand back tie y = 0 - vpar(2) z = 2036 /* overhand tie character else y = vpar(2) z = 2164 /* underhand tie charachter end y += oby perform getpxpy (t2,t8) x += px if pyy > 0 py -= y pyy = 0 end y += py kscrdat = "" #if AUTOSCR #else perform subj /* this feature not implemented in autoscr yet #endif end repeat 4+5. Ornaments and their accidentals need to be handled together New code rewrite 05/17/03 to accommodate editorial ornaments and their accidentals loop for t8 = c1 to c2 /* loop added 04-08-97 to accomodate all ornaments subflag_1 = ts(t8,SUBFLAG_1) /* on notes of a chord subflag_2 = ts(t8,SUBFLAG_2) ed_subflag_1 = ts(t8,ED_SUBFLAG_1) ed_subflag_2 = ts(t8,ED_SUBFLAG_2) merged_subflag_1 = subflag_1 | ed_subflag_1 merged_subflag_2 = subflag_2 | ed_subflag_2 t5 = merged_subflag_1 & 0x0f /* turn,tr,shake,mordent, etc. if t5 > 0 and t5 < 6 /* 5 ornaments at the moment if t5 > 0 and t5 < 7 /* 6 ornaments as of 01/07/06 Raise (lower) turn, if slur and turn are present on note head if c7 = 0 and c8 = 1 if t5 = 1 /* turn if stem = UP c16 = c4 * 2 / vpar(2) if rem <> 0 ++c4 end c4 += vpar(1) else c4 -= vpar(1) c16 = c4 * 2 / vpar(2) if rem <> 0 --c4 end end end end a. We must know definitively whether ornament goes above or below notes, and we must determine whether there is an "intervening" accidental. t7 = c7 /* save c7 t2 = 4 + sugg_flg2 /* ornament code = 4 if sugg_flg2 = 0 /* New code 05/02/03 ++sugg_flg2 end perform getpxpy (t2,t8) if bit(0,pcontrol) = 1 if bit(1,pcontrol) = 1 if bit(2,pcontrol) = 0 c7 = 1 - stem else c7 = stem end end end t1 = c7 + stem /* t1 = 1 means ornament goes above t2 = 0 t3 = merged_subflag_1 & 0x3f0 >> 4 t9 = ed_subflag_1 & 0x3f0 >> 4 t10 = 0 /* 0 will mean actual, as opposed to editorial if t3 > 0 if t1 = 1 if t3 > 7 /* ax under on ornament above t2 = 1 if t9 > 7 t10 = 1 /* and this is editorial end end else if t3 & 0x07 > 0 /* ax over on ornament below t2 = 2 if t9 & 0x07 > 0 t10 = 1 /* and this is editorial end end end end if t2 > 0 /* put accidental first if t2 = 1 t4 = t3 >> 3 else t4 = t3 & 0x07 end c13 = vpar(56) perform yadjust if c9 <> 1 y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end end x = obx if t2 = 1 and (t5 = 1 or t5 = 5) x += hpar(70) end x += px if pyy > 0 py -= y pyy = 0 end y += py kscrdat = "" Deal with case where ornament is real, but accidental is editorial if subflag_1 & 0x0f > 0 and t10 = 1 x -= hpar(124) y -= vpar(86) z = 244 /* open square bracket perform subj x += hpar(124) y += vpar(86) end Put out "first" accidental z = int("39389"{t4}) /* music font z += 210 /* music font perform subj if t4 < 3 z = int("39"{t4}) /* music font x += hpar(z+67) /* hpar(70) or hpar(76) z += 210 /* music font if t2 = 1 and (t5 = 1 or t5 = 5) x += hpar(70) end perform subj end Deal with case where ornament is real, but accidental is editorial if subflag_1 & 0x0f > 0 and t10 = 1 x += hpar(125) y -= vpar(86) z = 245 /* close square bracket perform subj end end b. Now put out turn, tr., shake, mordent, delayed turn tremulo added 01/07/06 (primary only) t3 = t5 if c3 = 5 c3 = 1 end c13 = 51 + t3 c13 = vpar(c13) 01/07/06 for tremulos if t3 = 6 c13 = vpar(4) end perform yadjust if c9 <> 1 y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end end x = obx x += px if pyy > 0 py -= y pyy = 0 end y += py kscrdat = "" Deal with case where ornament is editorial if ed_subflag_1 & 0x0f > 0 if t3 = 1 or t3 = 5 /* turn and delayed turn lsqx = hpar(126) rsqx = hpar(127) sqy = vpar(87) glyph = 242 /* turn ornament sq_glyph = 244 /* small square bracket else if t3 = 2 /* tr. trill Conditional code added 02/04/04 to implement Roman editorial trills #if ROMAN_EDIT y -= vpar(1) ++sobcnt sobx = x - obx soby = y - oby sobl(sobcnt) = "W " // chs(sobx) // " " // chs(soby) // " " sobl(sobcnt) = sobl(sobcnt) // "31 tr" goto SETP01 #else lsqx = hpar(122) rsqx = hpar(123) sqy = vpar(85) glyph = 254 /* editorial trill ornament sq_glyph = 195 /* cue square bracket #endif else if t3 = 3 /* shake lsqx = hpar(128) rsqx = hpar(129) sqy = vpar(88) glyph = 239 /* shake ornament sq_glyph = 244 /* small square bracket else /* mordant lsqx = hpar(130) rsqx = hpar(131) sqy = vpar(89) glyph = 238 /* mordant ornament sq_glyph = 244 /* small square bracket end end end x -= lsqx y -= sqy z = sq_glyph /* open square bracket perform subj x += lsqx y += sqy z = glyph perform subj x += rsqx y -= sqy z = sq_glyph + 1 /* close square bracket perform subj else Deal with case where ornament is primary 01/07/06 Adding code to deal with tremulo ornament (T) z = int("71437"{t3}) /* music font z += 235 /* music font perform subj if t3 < 6 z = int("71437"{t3}) /* music font z += 235 /* music font perform subj else c16 = y z = 127 perform subj y -= vpar(3) / 2 perform subj y -= vpar(3) / 2 perform subj y = c16 end end c. Put out remaining accidentals above or below notes. SETP01: /* t1 = 1 means ornament goes above t2 = 0 t3 = merged_subflag_1 & 0x3f0 >> 4 t9 = ed_subflag_1 & 0x3f0 >> 4 t10 = 0 /* 0 will mean actual, as opposed to editorial if t3 > 0 if t1 = 1 if t3 & 0x07 > 0 /* ax over on ornament above t2 = 1 if t9 & 0x07 > 0 t10 = 1 /* and this is editorial end end else if t3 > 7 /* ax under on ornament below t2 = 2 if t9 > 7 t10 = 1 /* and this is editorial end end end end if t2 > 0 /* put accidental if t2 = 1 t4 = t3 & 0x07 else t4 = t3 >> 3 end c13 = vpar(56) perform yadjust if c9 <> 1 y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end end x = obx if t2 = 2 and (t5 = 1 or t5 = 5) x += hpar(70) end x += px if pyy > 0 py -= y pyy = 0 end y += py kscrdat = "" Deal with case where ornament is real, but accidental is editorial if subflag_1 & 0x0f > 0 and t10 = 1 x -= hpar(124) y -= vpar(86) z = 195 /* open square bracket perform subj x += hpar(124) y += vpar(86) end Put out "second" accidental z = int("39389"{t4}) /* music font z += 210 /* music font perform subj if t4 < 3 z = int("39"{t4}) /* music font x += hpar(z+67) /* hpar(70) or hpar(76) z += 210 /* music font if t2 = 2 and (t5 = 1 or t5 = 5) x += hpar(70) end perform subj end Deal with case where ornament is real, but accidental is editorial if subflag_1 & 0x0f > 0 and t10 = 1 x += hpar(125) y -= vpar(86) z = 196 /* close square bracket perform subj end end c7 = t7 /* restore "real" c7 end repeat end End of code rewrite for editorial ornaments and their accidentals 6. Construct composite subflag_1 and subflag_2, ed_subflag_1 and ed_subflag_2 New code rewrite 05/17/03 to accommodate other editorial marks subflag_1 = ts(c1,SUBFLAG_1) subflag_2 = ts(c1,SUBFLAG_2) ed_subflag_1 = ts(c1,ED_SUBFLAG_1) ed_subflag_2 = ts(c1,ED_SUBFLAG_2) if c2 > c1 t5 = ts(c1,TSR_POINT) bs = cbi(tsr(t5){5..68}) /* 04/24/03 merge only subobj suggs. loop for t3 = c1+1 to c2 subflag_1 |= ts(t3,SUBFLAG_1) subflag_2 |= ts(t3,SUBFLAG_2) ed_subflag_1 |= ts(t3,ED_SUBFLAG_1) ed_subflag_2 |= ts(t3,ED_SUBFLAG_2) t4 = ts(t3,TSR_POINT) bt = cbi(tsr(t4){5..68}) /* 04/24/03 merge only subobj suggs. bs = bor(bs,bt) repeat temp = cby(bs) t3 = TSR_LENG tsr(t5) = tsr(t5){1,4} // temp // tsr(t5){69..t3} /* 05/02/03 end merged_subflag_1 = subflag_1 | ed_subflag_1 merged_subflag_2 = subflag_2 | ed_subflag_2 7. Horizontal and vertical accents if merged_subflag_2 & 0x01c0 > 0 Lower (raise) horizontal accent, if it and slur are present on note head if c7 = 0 and c8 = 1 if bit(6,merged_subflag_2) = 1 /* horizontal accent if stem = UP c4 -= vpar(1) c16 = c4 * 2 / vpar(2) if rem <> 0 --c4 end else c16 = c4 * 2 / vpar(2) if rem <> 0 ++c4 end c4 += vpar(1) end end end t7 = c7 t2 = 3 /* accent code = 3 perform getpxpy (t2,c1) if bit(0,pcontrol) = 1 if bit(1,pcontrol) = 1 if bit(2,pcontrol) = 0 c7 = 1 - stem else c7 = stem end end end x = obx + px if bit(6,subflag_2) = 1 if bit(6,merged_subflag_2) = 1 /* 01/26/08 Fixing a small bug c13 = vpar(57) glyph = 93 /* horizontal accent lsqx = hpar(132) rsqx = hpar(133) sqy = vpar(90) sq_glyph = 195 /* cue square bracket end if bit(7,subflag_2) = 1 if bit(7,merged_subflag_2) = 1 /* 01/26/08 Fixing a small bug c13 = vpar(58) glyph = 94 /* vertical accent--point up lsqx = hpar(134) rsqx = hpar(135) sqy = vpar(91) sq_glyph = 244 /* small square bracket end if bit(8,subflag_2) = 1 if bit(8,merged_subflag_2) = 1 /* 01/26/08 Fixing a small bug c13 = vpar(58) glyph = 95 /* vertical accent--point down lsqx = hpar(134) rsqx = hpar(135) sqy = vpar(91) sq_glyph = 244 /* small square bracket end perform yadjust if c9 <> 1 y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end end if pyy > 0 y = py else y += py end kscrdat = "" if ed_subflag_2 & 0x01c0 > 0 x -= lsqx y -= sqy z = sq_glyph /* open square bracket perform subj x += lsqx y += sqy end z = glyph perform subj if ed_subflag_2 & 0x01c0 > 0 x += rsqx y -= sqy z = sq_glyph + 1 /* close square bracket perform subj end c7 = t7 end 8. harmonics if merged_subflag_2 & 0x0200 > 0 t2 = 7 /* harmonics code = 7 perform getpxpy (t2,c1) x = obx + px z = 123 /* music font c13 = vpar(59) t7 = c7 if stem = 0 c7 = 1 else c7 = 0 end perform yadjust /* c9 set by yadjust c7 = t7 if pyy > 0 y = py else y += py end kscrdat = "" perform subj end 9. thumb positions, open string c9 = merged_subflag_2 & 0x0c00 if c9 > 0 t2 = 8 /* thumb-open code = 8 perform getpxpy (t2,c1) x = obx + px if bit(10,merged_subflag_2) = 1 z = 124 /* music font c13 = vpar(60) else z = 199 /* music font c13 = vpar(48) end t7 = c7 if stem = 0 c7 = 1 else c7 = 0 end perform yadjust /* c9 set by yadjust c7 = t7 if pyy > 0 y = py else y += py end kscrdat = "" perform subj end 10. fingerings (above staff for the moment) Note: suggestions for fingerings not yet implemented here. c9 = merged_subflag_2 >> 12 if c9 > 0 If above the staff, reverse the flags t4 = 0 VVV2: t1 = 0x0f t3 = 4 VVV1: t2 = c9 & t1 if t2 > t1 >> 1 t1 = t1 << 4 + t1 t3 += 4 goto VVV1 end t4 <<= t3 t4 += t2 c9 >>= t3 if c9 > 0 goto VVV2 end t5 = t4 VVV4: t1 = 0x0f t3 = 4 VVV3: t2 = t5 & t1 if t2 > t1 >> 1 t1 = t1 << 4 + t1 t3 += 4 goto VVV3 end Typeset t2 c13 = vpar(48) perform yadjust /* c9 set by yadjust t4 = t3 - 1 >> 2 * (hpar(73) / 2) x = obx - t4 VVV5: t4 = t2 & 0x0f z = t4 & 0x07 + 199 /* music font kscrdat = "" perform subj if t4 > 7 x += hpar(73) z = 220 /* music font perform subj x += hpar(73) t2 >>= 4 goto VVV5 end t5 >>= t3 if t5 > 0 goto VVV4 end end 11. up-bows, down-bows if merged_subflag_2 & 0x03 > 0 t2 = 6 /* bowing code = 6 perform getpxpy (t2,c1) x = obx + px if bit(0,merged_subflag_2) = 1 c13 = vpar(61) z = 117 /* music font else c13 = vpar(62) z = 116 /* music font end t7 = c7 if stem = 0 c7 = 1 else c7 = 0 end perform yadjust c7 = t7 if c9 <> 1 y -= vpar(1) c16 = y * 2 / vpar(2) if rem <> 0 --y end end if pyy > 0 y = py else y += py end kscrdat = "" perform subj end 12. fermatas if bit(14,merged_subflag_1) = 1 t2 = 15 /* upright fermata code = 15 perform getpxpy (t2,c1) x = obx + px c13 = vpar(63) z = 101 /* music font perform yadjust if pyy > 0 y = py else y += py end kscrdat = "" perform subj end if bit(15,merged_subflag_1) = 1 t2 = 16 /* inverted fermata code = 16 perform getpxpy (t2,c1) x = obx + px c13 = vpar(63) z = 102 /* music font t7 = c7 if stem = 0 c7 = 0 else c7 = 1 end perform yadjust c7 = t7 y -= vpar(63) if pyy > 0 y = py else y += py end kscrdat = "" perform subj end return ┌────────────────────────────────────────────────────────────────────┐ │P 9. yadjust (operates on an entire chord at once) │ │ │ │ Purpose: to work in conjunction with setperf to adjust │ │ the y position so that the indication will │ │ fall on c4/c5 or above/below the staff line, │ │ whichever is higher/lower. Procedure also │ │ determines a new value of the virtual endpoints, │ │ c4/c5 based on the y position and the vertical │ │ space parameter, c13, which is passed to the │ │ procedure. │ │ │ │ Inputs: c4 = virtual vertical position of controlling │ │ note head │ │ c5 = virtual vertical position of end of stem │ │ stem = stem direction 0 = up │ │ 1 = down │ │ c7 = situation flag 0 = place on note head │ │ 1 = place on stem │ │ c13 = vertical space of next character to set │ │ │ │ Outputs: c4 = updated vertical position of controlling │ │ note head │ │ c5 = updataed vertical position of end of stem │ │ c9 = position flag (1 = place on top of staff) │ │ │ └────────────────────────────────────────────────────────────────────┘ procedure yadjust int t1 if c7 = 0 if stem = DOWN if c4 > vpar(1) c4 = vpar(1) end else if c4 < vpar(7) c4 = vpar(7) end end else if stem = DOWN if c5 < vpar(8) c5 = vpar(8) end else if c5 > 0 c5 = 0 end end end * determine y location c9 = stem + c7 t1 = 1 if c9 = 1 t1 = -1 end if c7 = 0 y = 5 * notesize / 4 * t1 + c4 if stem = UP y += c13 end else y = vpar(2) * t1 + c5 /* was vpar(1) if stem = DOWN y += c13 end end * compute new vertual endpoints if c7 = 1 c5 += c13 * t1 else c4 += c13 * t1 end return ┌────────────────────────────────────────────────────────┐ │P 10. setleger │ │ │ │ Purpose, set leger lines for a chord (object) │ │ │ │ Inputs: obx = x-position of object │ │ passsize = note size (full, cue-size) │ │ c7 = pointer to lowest note in chord │ │ c8 = pointer to highest note in chord │ │ c9 = extra width of leger lines │ │ stem = stem direction 0 = up, 1 = down │ │ │ │ Internal: x,y,z sent to subj │ │ │ └────────────────────────────────────────────────────────┘ procedure setleger z = passsize * 128 + 45 /* music font x = obx if stem = UP ++x end if ts(c8,STAFFLOC) < 0 y = 0 - notesize kscrdat = "" loop while y >= ts(c8,STAFFLOC) perform subj if c9 > 0 x += c9 perform subj x -= c9 end y -= notesize repeat end if ts(c7,STAFFLOC) > vpar(9) y = vpar(10) kscrdat = "" loop while y <= ts(c7,STAFFLOC) perform subj if c9 > 0 x += c9 perform subj x -= c9 end y += notesize repeat end return ┌──────────────────────────────────────────────────────────────────┐ │P 11. wideleger │ │ │ │ Purpose: set wide a leger line for a note head located on, │ │ above, or below a leger line │ │ │ │ Inputs: obx = x-position of object │ │ oby = y-position of object │ │ x = x-position of note head │ │ y = y-position of note head │ │ passsize = note size (full size, cue size) │ │ c10 = note-on-line flag: 0 = on line, 1 = on space │ │ │ │ Internal: x,y,z sent to subj │ │ │ └──────────────────────────────────────────────────────────────────┘ procedure wideleger int t1 z = passsize * 128 + 45 /* music font t1 = x if c10 = 0 --x end kscrdat = "" perform subj if c10 = 0 x += hpar(106) else x += hpar(107) end perform subj x = t1 return ┌────────────────────────────────────────────────────┐ │P 12. number │ │ │ │ Purpose: Create subobject for number │ │ │ │ Inputs: a = number │ │ dv2 = center position for number │ │ │ │ Outputs: dv3 = right boundary of number │ │ │ │ x,z sent to subj │ │ │ └────────────────────────────────────────────────────┘ procedure number x = dv2 - hpar(21) if a > 99 x = dv2 + hpar(21) else if a > 9 x = dv2 end end dv3 = x + hpar(20) kscrdat = "" NU1: a /= 10 z = rem + 71 /* music font perform subj if a = 0 return end x -= hpar(20) goto NU1 ┌──────────────────────────────────────────────────────────────┐ │P 13. setdots │ │ │ │ Purpose: typeset sub-object dot(s) │ │ │ │ Inputs: c3 = pointer into set array for this note │ │ obx = horizontal position of object │ │ oby = vertical position of object │ │ passsize = note size (full size, cue size) │ │ │ └──────────────────────────────────────────────────────────────┘ procedure setdots int t1,t2,t3,t4,t5,t6 t4 = ts(c3,DOT) if t4 > 0 t1 = t4 >> 4 /* code modified 12-24-96 t1 /= INT10000 t2 = rem if t2 > (INT10000 >> 1) t2 -= INT10000 ++t1 end t6 = 18 /* New code 05/02/03 extension dot code = 18 perform getpxpy (t6,c3) if pxx = 1 x = obx + px else x = obx + t1 + px end if pyy = 1 y = oby + py else y = oby + t2 + py end /* end New code z = 128 * passsize + 44 /* music font kscrdat = "" perform subj /* first dot if t4 & 0x03 = 3 t3 = hpar(91) if passsize = CUESIZE t3 = t3 * 8 / 10 end x += t3 perform subj /* second dot end added code 12-24-96 if t4 & 0x04 = 4 t3 = hpar(91) if passsize = CUESIZE t3 = t3 * 8 / 10 end x += t3 perform subj /* third dot end if t4 & 0x08 = 8 t3 = hpar(91) if passsize = CUESIZE t3 = t3 * 8 / 10 end x += t3 perform subj /* fourth dot end end return ┌────────────────────────────────────────────────────────────────┐ │P 14. setrest (t6) │ │ │ │ Purpose: write object rest │ │ │ │ Inputs: c1 = pointer into set array for this rest │ │ obx = horizontal position of rest │ │ oby = vertical position of rest │ │ c3 = oby offset (for grand staff) │ │ ntype = type of note (e.g. sixteenth) │ │ passsize = rest type (full size, cue size) │ │ passtype = type of pass (reg,cue,grace,cuegrace) │ │ passnum = pass number for this rest │ │ inctype = increment type for next node │ │ with a new spn (used in putobj) │ │ opt_rest_flag = put out rest with small r │ │ │ │ Output: t6 = amount of space taken up │ │ │ │ Operation: In addition to writing the object rest, this │ │ procedure must also check to see if the rest is │ │ the beginning or end of a tuplet group. In the │ │ former case, the tuplet array, tuar, must be │ │ constructed; in the latter case, the tuplet │ │ super-object must be compiled and written out. │ └────────────────────────────────────────────────────────────────┘ procedure setrest (t6) str temp.100 int t1,t2,t3,t4,t5,t6,t7,t8,t9 int t10 int staff,track,pri_staff,p21,p22,p4,p5,p6,p71,p72,p8,p12 if scr_flag = 1 pri_staff = 0 track = ts(c1,TRACK_NUM) staff = ts(c1,STAFF_NUM) + 1 if track > 0 pri_staff = trackstave(opbarnum,track,3) end Compute values for P2 P4 P5 P6 P7 P8 and P12 p21 = staff p22 = track t1 = oby P4 may be modified by print suggestions t4 = ts(c1,TSR_POINT) t8 = ors(tsr(t4){2}) /* 05/02/03 code revised if bit(0,t8) = 1 t5 = ors(tsr(t4){4}) if t5 > 0 t5 = t5 - 128 * notesize if t5 >= 0 t5 = t5 + 5 / 10 else t5 = t5 - 5 / 10 /* verified as working properly end if bit(2,t8) = 1 /* position is "absolute" t1 = t5 else /* position is "relative" t1 = t1 + t5 end end end Assumed defaults for rests ============================ rest MUSED SCORE w 28 0 h 28 0 q 28 0 e 28 0 s 28 0 t 14 0 x 14 0 p4 = (0 - t1) / vpar(1) + 4 if ntype < SIXTEENTH p4 -= 2 end p5 = 7 - ntype /* MUSEDATA q = 7, SCORE q = 0 if ts(c1,CLAVE) = 200 p6 = -1 else p6 = 0 t3 = ts(c1,DOT) t8 = t3 & 0x0f if t8 > 0 p6 = int("1.2...3.......4"{t8}) end end p71 = 10000 * note_dur / divspq p71 = p71 / 10000 p72 = rem p8 = 0 if bit(14,ts(c1,SUBFLAG_1)) = 1 p8 = 1 /* actually -1 end p12 = 0 if pri_staff > 0 if pri_staff = 1 and staff = 2 p12 = 2 end if pri_staff = 2 and staff = 1 p12 = 1 end p21 = pri_staff /* set P2 to primary staff end if ts(c1,CLAVE) = 200 and pri_staff > 0 p12 = 0 /* force "silent" rests to primary staff end kscrdat = " | P2=" // chs(p21) // "." // chs(p22) // " P4=" // chs(p4) kscrdat = kscrdat // " P5=" // chs(p5) // " P6=" // chs(p6) kscrdat = kscrdat // " P7=" // chs(p71) // "." if p72 < 10 kscrdat = kscrdat // "0" end if p72 < 100 kscrdat = kscrdat // "0" end if p72 < 1000 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(p72) if p8 = 0 kscrdat = kscrdat // " P8=" else kscrdat = kscrdat // " P8=-" end kscrdat = kscrdat // chs(p8) // " P12=" // chs(p12) end t10 = c3 x = obx y = oby t1 = 0 if ts(c1,CLAVE) = 200 and scr_flag = 1 t6 = 0 z = 0 perform subj kscrdat = "" goto SRST1 end if ntype > QUARTER t6 = hpar(87) /* total horizontal space taken else t6 = hpar(88) /* total horizontal space taken end if ntype > SIXTEENTH z = 128 * passsize + 55 - ntype /* music font perform subj kscrdat = "" else y += notesize if ntype < THIRTY_SECOND y = 4 - ntype * notesize + y end z = 128 * passsize + 49 /* music font perform subj kscrdat = "" ++z if passsize = FULLSIZE t3 = notesize t4 = hpar(54) else t3 = vpar(65) t4 = hpar(89) end t2 = ntype loop while t2 < EIGHTH y -= t3 x += t4 t6 += t4 /* total horizontal space taken ++t1 perform subj ++t2 repeat end if ts(c1,DOT) > 0 t3 = ts(c1,DOT) t8 = t3 & 0x0f /* actual DOT code (modified 12-24-96) t3 >>= 4 /* code modified 12-24-96 t3 /= INT10000 t7 = rem if t7 > (INT10000 >> 1) t7 -= INT10000 ++t3 end y = oby + t7 x += t3 t6 = vpar(1) if passsize = CUESIZE t6 = t6 * 8 / 10 /* space for dot end t6 += t3 z = 128 * passsize + 44 /* music font perform subj /* first dot if t8 & 0x02 = 2 t5 = hpar(91) x += t5 perform subj /* second dot t6 += t5 end code added 12-24-96 if t8 & 0x04 = 4 t5 = hpar(91) x += t5 perform subj /* third dot t6 += t5 end if t8 & 0x08 = 8 t5 = hpar(91) x += t5 perform subj /* fourth dot t6 += t5 end end SRST1: passback t6 /* total horizontal space taken New 10/15/07 jtype = "R" if opt_rest_flag = 0 jtype = "R" else jtype = "r" end jcode = ntype out = "0" if bit(4,ts(c1,SUPER_FLAG)) = 1 /* if begin tuplet ++snum tuar(passtype,passnum,TU_SNUM) = snum tuar(passtype,passnum,TU_Y1) = y tuar(passtype,passnum,TU_Y2) = y tuar(passtype,passnum,TU_FSTEM) = DOWN /* (default) t7 = 0 if bit(6,ts(c1,SUPER_FLAG)) = 1 /* tuplet has a bracket t7 = ts(c1,SUPER_FLAG) & 0x3c0 /* bits 6,7,8,9 03-21-97 t7 <<= 2 end tuar(passtype,passnum,TU_FSTEM) += t7 /* tuplet flags 03-21-97 out = "1 " // chs(snum) end if bit(5,ts(c1,SUPER_FLAG)) = 1 /* if end tuplet t7 = tuar(passtype,passnum,TU_FSTEM) & 0xff goto TPFF(tpflag+1) TPFF(1): /* default tuplet placement TPFF(2): /* place tuplet near note heads if t7 = UP goto TPFFA else goto TPFFB end TPFF(3): /* place tuplet near stems if t7 = UP goto TPFFB else goto TPFFA end TPFF(4): /* place all tuplets above notes goto TPFFB TPFF(5): /* place all tuplets below notes goto TPFFA TPFFA: t3 = tuar(passtype,passnum,TU_Y2) + notesize + vpar(64) t4 = notesize * 6 if t7 <> UP t3 += vpar(7) end if t3 < t4 t3 = t4 end t9 = 4 /* tips up 03-21-97 goto TPFFC TPFFB: t3 = tuar(passtype,passnum,TU_Y2) - notesize t4 = 0 - vpar(1) if t7 = UP t3 -= vpar(7) end if t3 > t4 t3 = t4 end t9 = 0 /* tips down 03-21-97 TPFFC: t3 -= tuar(passtype,passnum,TU_Y1) t5 = t4 - oby out = "1 " // chs(tuar(passtype,passnum,TU_SNUM)) end fermata over rest kscrdat = "" if bit(14,ts(c1,SUBFLAG_1)) = 1 t2 = 15 /* upright fermata code = 15 perform getpxpy (t2,c1) x = obx + px if pyy > 0 y = py else y = py - vpar(1) end z = 101 /* music font perform subj end if bit(15,ts(c1,SUBFLAG_1)) = 1 t2 = 16 /* inverted fermata code = 16 perform getpxpy (t2,c1) x = obx + px z = 102 /* music font y = vpar(10) /* changed 05/02/03 if pyy > 0 y = py else y += py end perform subj end New code (11-11-93) Duration attribute of rest ++sobcnt sobl(sobcnt) = "A D " // chs(note_dur) // " " // chs(divspq*4) if sobcnt = 1 pcode = z else pcode = sobcnt end t7 = inctype if ts(c1,CLAVE) = 101 /* if movable rest inctype = 10000 end New code add 01/03/04 to deal with special case of type 7 whole rests if ts(c1,CLAVE) = 102 /* flag whole rest as potentially "removable" inctype = 10001 end oby += t10 Now look for print suggestions for this note object putobjpar = 0 t4 = ts(c1,TSR_POINT) pcontrol = ors(tsr(t4){1}) /* 05/02/03 px = ors(tsr(t4){3}) << 8 py = ors(tsr(t4){4}) << 16 t1 = ors(tsr(t4){2}) << 24 putobjpar = t1 + px + py + pcontrol /* Note: order of data has been changed jscrdat = "" perform putobj inctype = t7 if bit(5,ts(c1,SUPER_FLAG)) = 1 /* if end tuplet t1 = tuar(passtype,passnum,TU_FSTEM) >> 8 /* tuplets flags 03-21-97 if t1 > 0 t1 >>= 1 /* remove bracket present flag t1 <<= 5 t9 |= t1 t9 |= 0x02 /* bracket present flag else t9 = 1 end ++outpnt New 11/05/05 Convert TUPLE to 1000 * n1 + n2 format and get x,y adjustments t1 = ts(c1,TUPLE) & 0xffff t2 = t1 >> 8 t1 &= 0xff t2 *= 1000 t1 += t2 t6 = ts(c1,TUPLE) & 0xff0000 /* x adjustment t6 >>= 16 if t6 > 0 t6 = t6 - 128 /* center to zero else t6 = 0 end t4 = ts(c1,TUPLE) & 0xff000000 /* y adjustment t4 >>= 24 if t4 > 0 t4 = t4 - 128 /* center to zero else t4 = 0 end t3 += t4 t5 += t4 tput [Y,outpnt] H ~tuar(passtype,passnum,TU_SNUM) X ~t9 ~ts(c1,TUPLE) 0 ~t3 0 ~t5 0 tput [Y,outpnt] H ~tuar(passtype,passnum,TU_SNUM) X ~t9 ~t1 ~t6 ~t3 ~t6 ~t5 0 tuar(passtype,passnum,TU_SNUM) = 0 /* New added from s2ed tpflag = global_tpflag end return ┌─────────────────────────────────────────────────────────────────────┐ │P 15. putobj │ │ │ │ Purpose: write object and sub-objects to intermediate list │ │ │ │ Inputs: jtype = object type (field 2) │ │ jcode = object code (field 3) │ │ obx = object offset from staff x-position (field 4) │ │ oby = object offset form staff y-position (field 5) │ │ pcode = print code (field 6) (or sobl counter) │ │ spn = space node (field 7) │ │ inctype = increment type for next node with a new spn │ │ out = fields 9 -- │ │ temp3 = occationally temp3 is used in place of │ │ sobl(1) when there is only 1 subobject │ │ sobl() = subobject line │ │ jscrdat = SCORE data appended to end of object (03/21/03) │ c1,c2 = pointer to first and last elements in │ │ ts(.,.) array for this object │ │ │ │ putobjpar = parameters modifying operation of putobj │ │ │ │ putobjpar & 0x01 = control 0 = no modifications │ │ in this byte │ │ 1 = possible mods in │ │ this byte │ │ │ │ putobjpar & 0x06 = blank flag 0 = no blanking │ │ 2 = blank all sub-obj │ │ 4 = replace all sub-obj│ │ with one │ │ extension dot │ │ │ │ putobjpar & 0xf0 = (four) various flags │ │ For Notes, Grace Notes, Cue Notes ("NGQ" con jtype)│ │ 0x10 = stem present │ │ 0 = no stem │ │ 1 = stem │ │ 0x20 = stem direction │ │ 0 = UP │ │ 1 = DOWN │ │ 0x40 = note/chord │ │ 0 = single note │ │ 1 = chord │ │ │ │ │ │ putobjpar & 0x00ff00 = x position data + 128 │ │ (in tenths of notesize) │ │ 0 = no data │ │ │ │ putobjpar & 0xff0000 = y position data + 128 │ │ (in tenths of notesize) │ │ 0 = no data │ │ │ │ putobjpar & 0xff000000 = position data flags │ │ │ │ 0x01 = data active flag │ │ 0x02 = x data flag │ │ 1 = x location relative to │ │ obx │ │ 0 = modification to │ │ x location as calculated│ │ 0x04 = y data flag │ │ 1 = y location on staff │ │ 0 = modification to │ │ y location as calculated│ │ │ │ fix_next_inctype = static variable initialized at BIG, │ New 01/19/04 │ set and used only by putobj. │ │ Variable provides a means for putobj │ │ to "remember" when it has altered an │ │ inctype, and a way to "add back" any │ │ amount taken away. │ │ │ │ Outputs: sobcnt set to 0 │ │ supcnt set to 0 │ │ │ │ Internal variable: oldspn = spn from previous object │ └─────────────────────────────────────────────────────────────────────┘ procedure putobj str temp.180,super.180 str params.30(20) int oldspn,t int t1,t2,t3,t4,t5,t6,t7,t8,t9 int s1,s2,s3,s4,s5,s6,s7,s8,s9 int stem,chord int high,low,highpoint,lowpoint int highstem,lowstem,stemlength int nflags,slash,pcnt int grflag This code added 01/19/04 to fix the accumulation of inctypes if fix_next_inctype > 0 and inctype > 0 putc Attempting to adjust the next Inctype from ~inctype ... inctype -= fix_next_inctype if inctype < 0 inctype = 0 end putc to ~inctype fix_next_inctype = 0 end New Code 09/14/03 ----------------- If jtype = "I", then inctype may need to be recalculated from the ts(.) array if jtype = "I" and a1 > 1 t3 = 10000 loop for t1 = a1 - 1 to 1 step -1 t2 = ts(t1,DIV) if t2 < ts(a1,DIV) t3 = ts(a1,DIV) - t2 * 576 / divspq t1 = 1 end repeat if t3 <> 10000 and t3 <> inctype putc Caution Inctype for "I" type object changed from ~inctype to ~t3 fix_next_inctype = t3 - inctype /* fix_next_inctype set 01/19/04 inctype = t3 end end t = inctype if t <> 10000 and t <> 10001 /* 10001 added 01/03/04 if spn = oldspn t = 0 end if spn = 1 t = 0 end end stem = 0 if "NGQ" con jtype and jcode < WHOLE stem = putobjpar & 0xf0 stem >>= 4 putobjpar &= 0xffffff0f /* strip stem codes from putobjpar end Determine: t1 = final obx as modified by print suggestions t2 = final oby 05/02/03 px = putobjpar >> 8 & 0xff py = putobjpar >> 16 & 0xff if px > 0 px = px - 128 * notesize / 10 end t1 = obx + px if py > 0 py = py - 128 * notesize / 10 t4 = putobjpar >> 24 & 0xff if bit(2,t4) = 1 t2 = py if oby > 700 t2 += 1000 end else t2 = oby + py end else t2 = oby end If putobjpar & 0x01 = 1, then we are dealing with certain rennaisance notation which allows a note duration to extend beyond a bar line. In this case, the note beyond the barline may be blanked entirely (putobjpar & 0x02 = 1), or it may be replaced with an extension dot (putobjpar & 0x04 = 1). if (bit(0,putobjpar)) = 1 putobjpar &= 0xff t3 = pcode t4 = putobjpar >> 1 if t4 = 1 or t4 = 2 if t3 > 0 and t3 < 32 if sobl(1) = "" t3 = 0 else t6 = 0 if t4 = 2 ++t6 t8 = t2 / vpar(2) if rem = 0 t8 = vpar(1) - notesize else t8 = 0 end t9 = DOT_CHAR sobl(t6) = "K 0 " // chs(t8) // " " // chs(t9) end loop for t5 = 1 to t3 if sobl(t5){1} = "A" ++t6 sobl(t6) = sobl(t5) end repeat t3 = t6 end end end else t3 = pcode end ++outpnt 11/20/06 This code added for special case of a slur terminating on a non-printed note. if jtype = "N" and jcode = 0 t3 = 0 end End of 11/20/06 addition if scr_flag = 1 tput [Y,outpnt] J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out ~jscrdat #if OBJ_REPORT dputc J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out ~jscrdat #endif else tput [Y,outpnt] J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out #if OBJ_REPORT dputc J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out #endif end Look for marks that could be incorporated with this object super = "" if jtype = "N" tget [Y,outpnt-1] temp .t5 s1 s2 s3 s4 s5 s6 s7 s8 if temp{1} = "H" super = temp tget [Y,outpnt-2] temp .t5 s1 s2 s3 s4 s5 s6 s7 s8 end if temp{1,3} = "J M" and s2 = t1 and s5 = spn and s7 = 1 if super = "" --outpnt else outpnt -= 2 end out = trm(out) out = out // " " s9 = int(out) ++s9 out = chs(s9) // out{sub..} // chs(s8) t = s6 if scr_flag = 1 tput [Y,outpnt] J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out ~jscrdat else tput [Y,outpnt] J ~jtype ~jcode ~t1 ~t2 ~t3 ~spn ~t ~out end else super = "" end end oldspn = spn if t3 > 0 and t3 < 32 if sobl(1) = "" ++outpnt tput [Y,outpnt] ~temp3 #if OBJ_REPORT dputc ~temp3 #endif else if scr_flag = 1 We are going to get a little fancy here. At this point, we can determine some information that SCORE would like to have. A. For NOTE heads: By having information on stem direction and note vs. chord, by looking at the note-object record and by searching through the sub-objects, we can determine: 1. whether the note/chord has a separate stem or is allied with a beam 2. if the note/chord has a separate stem, a) which notehead is at the note-end of the chord b) the stem direction, stem length, and number of flags for this chord (elements of P5, P8, and P9), which can be attached to this notehead sub-object. 3. if the note/chord is allied with a beam, a) whether this is a single note or a chord b) if a chord, which notehead is at the note-end of the chord and the stem direction (number of flags is zero), both of which can be attached to this notehead sub-object. Note: In theory, autoscr had this information at the time it typeset the sub-objects, but I looked through the code and found it problematic to deduce precisely what autoscr is doing. We could do this, but it would take quite a while to get everything right. Instead, why not just analyze what autoscr actually did in each situation and report this to SCORE. if "GNQ" con jtype and jcode < WHOLE grflag = mpt & 0x01 if bit(0,stem) = 0 putc stem = ~stem putc No stem direction specified for half note or less dputc Program needs fixing, and so does the stage2 file. stop end chord = stem >> 2 /* 1 = chord stem &= 0x02 /* just look at this bit stem >>= 1 /* 0 = UP 1 = DOWN nflags = 0 slash = 0 stemlength = 0 highstem = 10000 lowstem = -10000 high = 10000 low = -10000 loop for sobcnt = 1 to t3 temp = sobl(sobcnt) temp = temp // pad(80) if temp{1} = "K" sub = 2 t4 = int(temp{sub..}) t5 = int(temp{sub..}) t6 = int(temp{sub..}) if chr(t6) in [42,43,170,171] if t5 < high highpoint = sobcnt high = t5 end if t5 > low lowpoint = sobcnt low = t5 end end if chr(t6) in [51..62,179..190] t7 = t5 t8 = t5 if t6 = 59 /* 59 full length up t7 = t5 - 28 goto POJ1 end if t6 = 60 /* 60 full length down t8 = t5 + 29 goto POJ1 end if t6 < 55 nflags = 1 if t6 = 53 /* 53 up-eighth t7 = t5 - 47 goto POJ1 end if t6 = 54 /* 54 down-eighth t8 = t5 + 47 goto POJ1 end if t6 = 51 /* 51 short up-eighth t7 = t5 - 40 goto POJ1 end if t6 = 52 /* 52 short down-eighth t8 = t5 + 40 goto POJ1 end end if t6 < 59 if t6 = 55 /* 55 up-sixteenth t7 = t5 - 51 nflags = 2 goto POJ1 end if t6 = 56 /* 56 down-sixteenth t8 = t4 + 51 nflags = 2 goto POJ1 end if t6 = 57 /* 57 up-add-eighth t7 = t5 - 51 ++nflags goto POJ1 end if t6 = 58 /* 58 down-add-eighth t8 = t4 + 51 ++nflags goto POJ1 end end if t6 = 61 /* 61 notesize up t7 = t5 - 14 goto POJ1 end if t6 = 62 /* 62 notesize down t8 = t5 + 15 goto POJ1 end if t6 = 179 /* 179 up-eight + slash t7 = t5 - 38 nflags = 1 slash = 1 goto POJ1 end if t6 = 181 /* 181 up-eighth t7 = t5 - 38 nflags = 1 goto POJ1 end if t6 = 180 /* 180 down-eight + slash t8 = t5 + 38 nflags = 1 slash = 1 goto POJ1 end if t6 = 182 /* 182 down-eighth t8 = t5 + 38 nflags = 1 goto POJ1 end if t6 = 183 /* 183 up-sixteenth nflags = 2 t7 = t5 - 41 end if t6 = 184 /* 184 down-sixteenth nflags = 2 t8 = t5 + 41 end if t6 = 185 /* 185 up-add-eighth ++nflags t7 = t5 - 41 end if t6 = 186 /* 186 down-add-eighth ++nflags t8 = t5 + 37 end if t6 = 187 /* 187 full length up t7 = t5 - 28 end if t6 = 188 /* 188 full length down t8 = t5 + 29 end if t6 = 189 /* 189 notesize up t7 = t5 - 14 end if t6 = 190 /* 190 notesize down t8 = t5 + 15 end POJ1: if t7 < highstem highstem = t7 end if t8 > lowstem lowstem = t8 end end end repeat stemlength = lowstem - highstem t8 = low - high /* t8 = spread if t8 + vpar(3) >= stemlength - 2 /* then this unit is under a beam stemlength = 100000 /* P8 for notes under a beam else stemlength *= 100 /* work in 100ths if grflag = 1 /* a fudge, but it may work stemlength += (260 * vpar(1)) end if jcode >= EIGHTH t8 = 700 * vpar(1) /* set zero to 7 scale steps else t8 = 793 * vpar(1) /* set zero to 7.93 scale steps end /* SCORE printing style stemlength -= t8 stemlength /= vpar(1) /* reduce to scale steps now end if stem = UP t8 = lowpoint else t8 = highpoint end temp = sobl(t8) // pad(120) loop for t7 = 1 to 20 params(t7) = "" repeat sub = 1 POJ2: if temp{sub..} con "P" t4 = sub t7 = int(temp{sub+1..}) if temp{sub..} con " " t5 = sub end params(t7) = temp{t4..t5} goto POJ2 end Note: The code below is potentially in ERROR because it may need to be applied to all notes in the chord, not just the controlling note. (07/28/03) if temp con "Dots" t4 = sub-1 if temp{sub..} con " " t5 = sub end params(20) = temp{t4..t5} end if "GQ" con jtype t4 = int(params(4){4..}) params(4) = "P4=" 07/28/03 if t4 < 0 This code is in the wrong t4 = 0 - t4 place. It must be applied params(4) = params(4) // "-" to all notes on a chord, not end just the controlling note. t4 += 100 See new code below. params(4) = params(4) // chs(t4) // " " end if params(5) = "" t5 = stem + 1 * 10 params(5) = "P5=" // chs(t5) // " " else t5 = stem + 1 params(5) = "P5=" // chs(t5) // params(5){4..} end if stemlength < 0 stemlength = 0 - stemlength params(8) = "P8=-" else params(8) = "P8=" end t4 = stemlength / 100 t5 = rem if slash = 1 stemlength += 100 end params(8) = params(8) // chs(t4) // "." if t5 < 10 params(8) = params(8) // "0" end params(8) = params(8) // chs(t5) if nflags > 0 if params(9) = "" params(9) = "P9=" // chs(nflags) // ".00" else t5 = int(params(9){4..}) t6 = sub t5 += nflags params(9) = "P9=" // chs(t5) // params(9){t6..} end end if temp con "|" temp = temp{1,mpt} end loop for t7 = 1 to 9 params(t7) = trm(params(t7)) if params(t7) <> "" temp = temp // " " // params(t7) end repeat params(20) = trm(params(20)) if params(20) <> "" temp = temp // " " // params(20) end loop for t7 = 10 to 19 params(t7) = trm(params(t7)) if params(t7) <> "" temp = temp // " " // params(t7) end repeat sobl(t8) = temp If note is Grace or Cue, you must modify P4 for all notes in a chord (07/28/03) if "GQ" con jtype loop for sobcnt = 1 to t3 temp = sobl(sobcnt) temp = temp // pad(170) if temp{1} = "K" if temp con "P4=" t4 = sub if temp{sub..} con " " t5 = sub end params(4) = temp{t4..t5} /* e.g. "P4=12 " t7 = int(params(4){4..}) params(4) = "P4=" if t7 < 0 t7 = 0 - t7 params(4) = params(4) // "-" end t7 += 100 params(4) = params(4) // chs(t7) // " " /* e.g. "P4=112 " temp = temp{1..t4-1} // params(4) // temp{t5+1..} if jcode = 0 dputc Line = ~temp if temp con "P8=" t4 = sub if temp{sub..} con " " t5 = sub end params(8) = temp{t4..t5} /* e.g. "P8=0.09 " t7 = int(params(8){4..}) if params(8){sub} = "." t8 = int(params(8){sub+1..}) /* e.g. t8 = 9 else t8 = 0 end params(8) = "P8=" if t7 < 0 t7 = 0 - t7 params(8) = params(8) // "-" end t7 += 100 params(8) = params(8) // chs(t7) if t8 > 0 if t8 < 10 params(8) = params(8) // ".0" /* e.g. "P8=100.09 " else params(8) = params(8) // "." end params(8) = params(8) // chs(t8) // " " else params(8) = params(8) // " " end temp = temp{1..t4-1} // params(8) // temp{t5+1..} end dputc New Line = ~temp end sobl(sobcnt) = trm(temp) end end repeat end end End of 07/28/03 addition end New 03/18/06 constructing "A" type records 1. First identify all ties connected to notes if xdata_flag = 1 and scr_flag = 0 if "NGR" con jtype s5 = mpt s2 = 0 if s5 < 3 s3 = 0 loop for s1 = c1 to c2 if bit(0,ts(s1,SUPER_FLAG)) = 1 /* if tie starts ++s2 end ++s3 repeat 2. Append "tie" digit to "A D" record s4 = 0 if s2 > 0 s4 = 1 if s2 < s3 s4 = 2 end end sobl(t3) = sobl(t3) // " " // chs(s4) else sobl(t3) = sobl(t3) // " 0" end 3. Construct "A P" records for this node loop for s1 = c1 to c2 ++t3 s6 = ts(s1,TRACK_NUM) if s6 = 0 if tracknum_flag = 0 s6 = 1 else putc Missing track number. Possible error in stage2 file. putc Run program again with measure numbers (Pxsm) to see putc this might be. putc putc Program Halted putc stop end end sobl(t3) = "A P " // chs(s6) // " " // chs(ts(s1,BASE_40)) if s5 < 3 if bit(0,ts(s1,SUPER_FLAG)) = 1 /* if tie starts sobl(t3) = sobl(t3) // " 1" else sobl(t3) = sobl(t3) // " 0" end rest_flag(s6) = 0 else sobl(t3) = sobl(t3) // " 0" /* tricky code s7 = rest_flag(s6) if s7 > 0 /* fixup previous rest for this track tget [Y,s7] temp s8 = int(temp{5..}) if temp{1,3} <> "A P" or s8 <> s6 putc Program error. No rest fixup possible else temp = trm(temp) temp{..} = "1" tput [Y,s7] ~temp --s7 tget [Y,s7] temp temp = trm(temp) temp{..} = "1" tput [Y,s7] ~temp end end rest_flag(s6) = outpnt + t3 end repeat end end End of 03/18/06 addition loop for sobcnt = 1 to t3 ++outpnt tput [Y,outpnt] ~sobl(sobcnt) #if OBJ_REPORT dputc ~sobl(sobcnt) #endif repeat end end sobcnt = 0 supcnt = 0 if super <> "" ++outpnt tput [Y,outpnt] ~super end return ┌────────────────────────────────────────────────────────────┐ │P 16. subj │ │ │ │ Purpose: write sub-object to intermediate list │ │ │ │ Inputs: x = horizontal position of sub-object │ │ y = vertical position of sub-object │ │ z = character number │ │ obx = object offset from staff x-position │ │ oby = object offset from staff y-position │ │ sobcnt = counter in intermediate list │ │ kscrdat = SCORE info to append to end of │ │ sub-object record │ └────────────────────────────────────────────────────────────┘ procedure subj ++sobcnt sobx = x - obx soby = y - oby sobl(sobcnt) = "K " // chs(sobx) // " " // chs(soby) // " " if scr_flag = 1 sobl(sobcnt) = sobl(sobcnt) // chs(z) // kscrdat else sobl(sobcnt) = sobl(sobcnt) // chs(z) end return ┌────────────────────────────────────────────────────────────┐ │P 16a. subj2 /* Addition to Code 02/25/97 │ │ │ │ Purpose: write "invisible" sub-object to │ │ intermediate list │ │ │ │ Inputs: x = horizontal position of sub-object │ │ y = vertical position of sub-object │ │ z = character number │ │ obx = object offset from staff x-position │ │ oby = object offset from staff y-position │ │ sobcnt = counter in intermediate list │ └────────────────────────────────────────────────────────────┘ procedure subj2 ++sobcnt sobx = x - obx soby = y - oby sobl(sobcnt) = "k " // chs(sobx) // " " // chs(soby) // " " sobl(sobcnt) = sobl(sobcnt) // chs(z) return ┌────────────────────────────────────────────────────────────────┐ │P 17. cancelsig (m, j, h, klave) │ │ │ │ Purpose: Write out cancellation of sharps or flats │ │ │ │ Inputs: obx = object location │ │ oby = " " │ │ x = x starting point │ │ h = number of sharps or flats to cancel │ │ j = one less than starting point in zak(.,.) │ │ m = selection 1 = sharps │ │ 2 = flats │ │ 3 = sharps (clef = tenor) │ │ klave = line on which to start calcellations │ │ (from which y is computed) │ └────────────────────────────────────────────────────────────────┘ procedure cancelsig (m, j, h, klave) int m,j,h,klave,tenor getvalue m, j, h, klave tenor = 0 if m = 3 m = 1 tenor = 1 /* exception for sharps in the tenor cler end z = 64 kscrdat = "" loop for g = 1 to h if tenor = 0 or klave >= 0 y = klave + 20 * notesize / 2 - vpar20 else y = klave + 27 * notesize / 2 - vpar20 end perform subj ++j y += zak(m,j) klave += zak(m,j) x += hpar(11) repeat passback klave return ┌────────────────────────────────────────────────────────────────┐ │P 18. setmrest │ │ │ │ Purpose: Set multiple rests and terminating bar line │ │ │ │ Inputs: p = horizontal starting point │ │ mrest = number of rests to set │ │ measnum = measure number for terminating bar line │ │ wrest = optional type 7 whole rest flag (01/03/04) │ │ jscrdat = SCORE info to append to end of │ │ terminating bar line │ │how_much_mrest(2) = divspq, divspm │ │ │ │ Outputs: p = new horizontal point │ │ mrest = 0 │ │ │ │ Operation: For multiple rests we need to communicate │ │ P7 = rest's rhythmic duration │ │ │ └────────────────────────────────────────────────────────────────┘ procedure setmrest str temp.80 int i,j int a2,a3,a4 int t1 /* New 10/29/08 if scr_flag = 1 temp = jscrdat /* save measure object's jscrdat string i = how_much_mrest(1) j = how_much_mrest(2) j = j * 10000 / i j /= 10000 i = rem jscrdat = " | P7=" // chs(j) // "." if i < 10 jscrdat = jscrdat // "0" end if i < 100 jscrdat = jscrdat // "0" end if i < 1000 jscrdat = jscrdat // "0" end jscrdat = jscrdat // chs(i) end putobjpar = 0 if mrest > 1 p += hpar(22) obx = p oby = vpar(3) x = obx y = oby z = 62 kscrdat = "" perform subj y = oby + vpar(11) perform subj z = 92 x = obx y = vpar(4) loop for i = 1 to 3 perform subj x += 30 p += 30 repeat y = oby z = 62 perform subj y = oby + vpar(11) perform subj dv2 = p - 45 a = mrest Slight code modification 11/18/08 In the case of musical parts, for notesize 21 anyway, I think the number above a multiple rest is easier to read if it is 2 dots above the middle line. Admittedly, this is a magic number at the moment. if notesize = 21 y = vpar(4) - 2 else y = vpar(4) end perform number jtype = "S" jcode = 4 out = "0" pcode = sobcnt spn = mrest perform putobj p += hpar(23) t1 = 1 /* New 10/29/08: 1 was the old value for J B (field 8) else obx = p + hpar(24) oby = vpar(4) ++outpnt New code 01/03/04, modified 03/13/06 to remove type 6 and type 7 Symbol objects if scr_flag = 1 if wrest = 1 tput [Y,outpnt] J R 9 ~obx ~oby 46 1 10001 0 ~jscrdat else tput [Y,outpnt] J R 9 ~obx ~oby 46 1 10000 0 ~jscrdat end else if wrest = 1 tput [Y,outpnt] J S 7 ~obx ~oby 46 0 0 0 tput [Y,outpnt] J R 9 ~obx ~oby 46 1 10001 0 else tput [Y,outpnt] J S 6 ~obx ~oby 46 0 0 0 tput [Y,outpnt] J R 9 ~obx ~oby 46 1 10000 0 end end p += hpar(25) New 10/29/08 We need to try to compute a J B (field 8) value that mirrors the expected distance increment flag in a normal measure. We will use the data in: how_much_mrest(2) = divspq, divspm t1 = 576 * how_much_mrest(2) / how_much_mrest(1) end obx = p + hpar(36) if scr_flag = 1 jscrdat = temp /* restore measure object's jscrdat string else jscrdat = "" end 03/07/06 Adding capability of setmrest to set "mdotted", "mdouble", "mheavy2", "mheavy3", in addition to "measure". No repeat dots, endings, or other signs are allowed here. if mrest_line{2,6} = "easure" ++outpnt tput [Y,outpnt] J B ~measnum ~obx 1 82 6913 1 0 ~jscrdat /* Line below is new 10/29/08 tput [Y,outpnt] J B ~measnum ~obx 1 82 6913 ~t1 0 ~jscrdat p = obx + hpar(37) end if mrest_line{2,6} = "dotted" ++outpnt tput [Y,outpnt] J B ~measnum ~obx 3 86 6913 1 0 ~jscrdat /* Line below is new 10/29/08 tput [Y,outpnt] J B ~measnum ~obx 3 86 6913 ~t1 0 ~jscrdat p = obx + hpar(37) end hpar(44) = actual white space between two light lines hpar(45) = actual white space between heavy/light, light/heavy and heavy/heavy combinations hpar(79) = thickness of light line hpar(81) = thickness of heavy line if mrest_line{2,6} = "double" a2 = hpar(44) + hpar(79) a4 = obx + a2 ++outpnt tput [Y,outpnt] J B ~measnum ~a4 5 2 6913 1 0 ~jscrdat /* Line below is new 10/29/08 tput [Y,outpnt] J B ~measnum ~a4 5 2 6913 ~t1 0 ~jscrdat ++outpnt tput [Y,outpnt] K -~a2 0 82 ++outpnt tput [Y,outpnt] K 0 0 82 p = a4 + hpar(37) end if mrest_line{2,6} = "heavy3" a2 = hpar(45) + hpar(81) ++outpnt tput [Y,outpnt] J B ~measnum ~obx 9 2 6913 1 0 ~jscrdat /* Line below is new 10/29/08 tput [Y,outpnt] J B ~measnum ~obx 9 2 6913 ~t1 0 ~jscrdat ++outpnt tput [Y,outpnt] K 0 0 84 ++outpnt tput [Y,outpnt] K ~a2 0 82 p = obx + hpar(37) + a2 end if mrest_line{2,6} = "heavy2" a2 = hpar(45) + hpar(81) + hpar(79) - 1 a3 = hpar(81) - 1 a4 = obx + a2 ++outpnt tput [Y,outpnt] J B ~measnum ~a4 6 2 6913 1 0 ~jscrdat /* Line below is new 10/29/08 tput [Y,outpnt] J B ~measnum ~a4 6 2 6913 ~t1 0 ~jscrdat ++outpnt tput [Y,outpnt] K -~a2 0 82 ++outpnt tput [Y,outpnt] K -~a3 0 84 p = a4 + hpar(37) end loop for i = 1 to MAX_STAFF loop for j = 1 to 45 emptyspace(i,j) = hpar(37) repeat repeat mrest = 0 return ┌─────────────────────────────────────────────────────────────────────┐ │P 19. getspace │ │ │ │ Purpose: Determine space parameter for particular note value │ │ │ │ Inputs: a5 = pointer into set array │ │ │ │ Outputs: a6 = space parameter │ └─────────────────────────────────────────────────────────────────────┘ procedure getspace int t1, t2, t3 int gsp_ntype /* new 10/15/07 if scr_flag = 1 if ts(a5,CLAVE) = 200 /* silent rest gets no space a6 = 1 /* 10/13/07 TEST return end end if ts(a5,CLAVE) = 101 or ts(a5,CLAVE) = 102 /* movable rest (altered 01/03/04) a6 = hpar(24) + hpar(25) - hpar(37) return end a6 = ts(a5,NTYPE) * 3 gsp_ntype = ts(a5,NTYPE) & 0xff /* new 10/15/07 a6 = gsp_ntype * 3 /* new 10/15/07 if a6 = 0 a6 = 3 end --a6 if ts(a5,DOT) > 0 ++a6 else if ts(a5,TUPLE) > 2 if (ts(a5,TUPLE) & 0xffff) > 2 /* New 11/05/05 --a6 end end a6 = nsp(a6) * make extra space for up-flags if ts(a5,TYPE) = NOTE and bit(1,ts(a5,STEM_FLAGS)) = UP if ts(a5,BEAM_FLAG) = NO_BEAM and ts(a5,NTYPE) < QUARTER if ts(a5,BEAM_FLAG) = NO_BEAM and gsp_ntype < QUARTER /* new 10/15/07 a6 += hpar(28) t3 = hpar(26) + hpar(28) + hpar(82) if a6 < t3 loop for t1 = a5+1 to sct if ts(t1,DIV) > ts(a5,DIV) loop for t2 = t1 to sct if ts(t2,DIV) = ts(t1,DIV) if ts(t2,TYPE) <= NOTE_OR_REST if ts(t2,STAFF_NUM) = ts(a5,STAFF_NUM) if ts(t2,CLAVE) >= ts(a5,CLAVE) a6 = t3 t2 = sct end end end else t2 = sct end repeat t1 = sct end repeat end end end * allow mininum extra space if next note on staff has stem-down repeaters * make extra space for sixteenth and smaller rests if ts(a5,TYPE) = REST and ts(a5,NTYPE) < EIGHTH if ts(a5,TYPE) = REST and gsp_ntype < EIGHTH /* new 10/15/07 a6 = 6 - ts(a5,NTYPE) * hpar(54) + a6 a6 = 6 - gsp_ntype * hpar(54) + a6 /* new 10/15/07 end * shrink space if cue-size flag is set if bit(16,ts(a5,SUBFLAG_1)) = CUESIZE a6 = a6 * 8 / 10 end return ┌────────────────────────────────────────────────────┐ │P 20. wordspace │ │ │ │ Purpose: Calculate length of word │ │ │ │ Inputs: ttext = word │ │ c5 = font number │ │ curfont = currently active font │ │ │ │ Outputs: a5 = space taken up by word │ │ │ │ curfont possibly modified │ └────────────────────────────────────────────────────┘ procedure wordspace int t1,t2,d1 a5 = 0 * get new spacing parameters, if needed perform spacepar Rewriting this section 04/22/04 loop for t2 = 1 to len(ttext) if ttext{t2} = "\" if t2 = len(ttext) return 5 end if "!@#$%^&*(-=" con ttext{t2+1} if mpt < 10 ++t2 a5 += mpt goto NXC else ++t2 a5 -= (mpt - 9) goto NXC end end New 02/02/09 if ttext{t2+1} = "+" ++t2 a5 += spc(32) goto NXC end if t2 + 1 = len(ttext) return 5 end ++t2 if ttext{t2} = "0" t1 = ors(ttext{t2+1}) + 128 if chr(t1) in [160,206,212,224] return 5 end ++t2 a5 += spc(t1) goto NXC end if ttext{t2} = "\" t1 = ors(ttext{t2}) a5 += spc(t1) goto NXC end if ttext{t2} in ['a'..'z','A'..'Z'] d1 = ors(ttext{t2}) if "1345789" con ttext{t2+1} t1 = ors(ttext{t2}) else if ttext{t2+1} = "2" if ttext{t2} = "s" t1 = 244 /* German ss else t1 = ors(ttext{t2}) end else return 5 end end ++t2 else --t2 t1 = ors(ttext{t2}) end else t1 = ors(ttext{t2}) end a5 += spc(t1) NXC: repeat loop for t2 = 1 to len(ttext) * adjust for backslash (\) sequence if ttext{t2} = "\" if t2 + 2 > len(ttext) return 5 end ++t2 if ttext{t2} in ['0'..'9'] or ttext{t2+1} in ['0'..'9'] if ttext{t2,2} con ['0'..'9'] if ttext{t2} in ['0'..'9'] t1 = ors(ttext{t2+1}) if ttext{t2} = "0" t1 += 128 end else t1 = ors(ttext{t2}) if ttext{t2+1} = "0" t1 += 128 end end ++t2 else return 5 end else t1 = ors(ttext{t2}) end a5 += spc(t1) if t1 = 171 a5 -= hpar(57) end repeat End of 04/22/04 rewrite return ┌────────────────────────────────────────────────────┐ │P 20a. kernttext NEW 04/22/04 │ │ │ │ Purpose: Apply kerning to ttext │ │ │ │ Inputs: ttext = word │ │ c5 = current font │ │ │ │ Outputs: revised ttext │ │ │ └────────────────────────────────────────────────────┘ procedure kernttext str tline.300 int t1,t2,t3,t4 if ttext = "" return end ttext = ttext // " " tline = "" loop for t1 = 1 to len(ttext) if "abcdefghijklmnopqrstuvwxyz" con ttext{t1} t2 = mpt if "abcdefghijklmnopqrstuvwxyz" con ttext{t1+1} t3 = mpt if kernmap(t2,t3) = 0 tline = tline // ttext{t1} else if kernmap(t2,t3) = -1 tline = tline // ttext{t1} // "\-" else if kernmap(t2,t3) = 1 tline = tline // ttext{t1} // "\!" end end end else if t1 < len(ttext) - 2 and ttext{t1+1,2} = "\0" and ":=;><" con ttext{t1+3} if mpt < 3 t3 = 9 /* i else if mpt < 5 t3 = 12 /* l else t3 = 6 /* f end end if kernmap(t2,t3) = 0 tline = tline // ttext{t1} else if kernmap(t2,t3) = -1 tline = tline // ttext{t1} // "\-" else if kernmap(t2,t3) = 1 tline = tline // ttext{t1} // "\!" end end end else tline = tline // ttext{t1} end end else if "ABCDEFGHIJKLMNOPQRSTUVWXYZ" con ttext{t1} t2 = mpt + 26 if "abcdefghijklmnopqrstuvwxyz" con ttext{t1+1} t3 = mpt if kernmap(t2,t3) = 0 tline = tline // ttext{t1} else if kernmap(t2,t3) = -1 tline = tline // ttext{t1} // "\-" else if kernmap(t2,t3) = -2 tline = tline // ttext{t1} // "\=" end end end else if t1 < len(ttext) - 2 and ttext{t1+1,2} = "\0" and ":=;><" con ttext{t1+3} if mpt < 3 t3 = 9 /* i else if mpt < 5 t3 = 12 /* l else t3 = 6 /* f end end if kernmap(t2,t3) = 0 tline = tline // ttext{t1} else if kernmap(t2,t3) = -1 tline = tline // ttext{t1} // "\-" else if kernmap(t2,t3) = 1 tline = tline // ttext{t1} // "\!" end end end else tline = tline // ttext{t1} end end else /* ffi,fi,ffl,fl,ff if t1 < len(ttext) - 2 and ttext{t1,2} = "\0" and ":=;><" con ttext{t1+2} if mpt < 3 t2 = 9 /* i else if mpt < 5 t2 = 12 /* l else t2 = 6 /* f end end if "abcdefghijklmnopqrstuvwxyz" con ttext{t1+3} t3 = mpt if kernmap(t2,t3) = 0 tline = tline // ttext{t1,3} t1 += 2 else if kernmap(t2,t3) = -1 tline = tline // ttext{t1,3} // "\-" t1 += 2 else if kernmap(t2,t3) = 1 tline = tline // ttext{t1,3} // "\!" t1 += 2 end end end else tline = tline // ttext{t1} end else tline = tline // ttext{t1} end end end repeat t1 = len(tline) - 1 ttext = tline{1,t1} return ┌──────────────────────────────────────────────────────────────┐ │P 21. spacepar │ │ │ │ Purpose: Be sure that proper space parameters are loaded │ │ │ │ Inputs: c5 = font number │ │ │ │ Outputs: valid spc(.) array for this font │ │ font_base, font_height, zero_height │ │ for this font (new 02/03/08) │ │ valid kernmap(.,.) for this font │ │ updated value of curfont │ │ │ │ Internal Variables: │ │ │ │ int bfont(4,4) Spacepar keeps a record of past calls │ │ together with the number of times │ │ a particular font has been asked for. │ │ If the number of fonts exceeds 4, │ │ spacepar will replace the space data │ │ from the memory block [bspc(.,.)] │ │ least current. │ │ int bspc(4,255) Four memory blocks for space data │ │ int bfont_specs(4,3) 4 x (font parameters) (02/03/08) │ │ int bkernmap(4,52,26) │ │ Four memory blocks for backup kernmap │ │ int time pseudo timer │ │ │ │ │ └──────────────────────────────────────────────────────────────┘ procedure spacepar str file.200 str line.120,kfile1.80,kfile2.80 int bfont(4,4),bspc(4,255),time int bfont_specs(4,3) /* New 02/03/08 int bkernmap(4,52,26) int t1,t2,t3,t4,t5,t6,t7 if c5 <> curfont font_base = 0 /* New 02/03/08 font_height = 0 /* New 02/03/08 zero_height = 0 /* New 02/03/08 t2 = 1000000 loop for t1 = 1 to 4 if c5 = bfont(t1,1) /* font found in reserve ++time bfont(t1,2) = time loop for t3 = 1 to 255 spc(t3) = bspc(t1,t3) repeat New code 04/22/04 loop for t3 = 1 to 52 loop for t5 = 1 to 26 kernmap(t3,t5) = bkernmap(t1,t3,t5) repeat repeat New code 02/03/08 font_base = bfont_specs(t1,1) font_height = bfont_specs(t1,2) zero_height = bfont_specs(t1,3) curfont = c5 return end if bfont(t1,2) < t2 t2 = bfont(t1,2) t7 = t1 /* t7 is the oldest block end repeat New code 02/03/08 if box_flag = 1 file = DISP_DISK // ":/musprint/new/xfonts/tms/fonthite" open [4,1] file t1 = c5 - 29 /* 1 <= t1 <= 19 t2 = XFonts(sizenum,t1) - 50 /* 1 <= t2 <= 90 (text font) --t2 loop for t1 = 1 to t2 getf [4] repeat getf [4] font_base font_height zero_height close [4] end bfont_specs(t7,1) = font_base bfont_specs(t7,2) = font_height bfont_specs(t7,3) = zero_height New code 03/19/04 file = DISP_DISK // ":/musprint/new/xfonts/tms/fontspac" open [4,1] file t1 = c5 - 29 /* 1 <= t1 <= 19 t2 = XFonts(sizenum,t1) - 50 /* 1 <= t2 <= 90 (text font) t2 = Fspacex(t2) - 1 /* t2 = offset in fontspac loop for t1 = 1 to t2 getf [4] repeat t3 = 61 loop for t2 = 1 to 31 spc(t2) = 0 repeat loop for t2 = 32 to 127 if t3 = 61 t3 = 1 getf [4] line end spc(t2) = int(line{t3,2}) t3 += 3 repeat loop for t2 = 128 to 159 spc(t2) = 0 repeat t3 = 61 loop for t2 = 160 to 255 if t3 = 61 t3 = 1 getf [4] line end spc(t2) = int(line{t3,2}) t3 += 3 repeat close [4] loop for t1 = 1 to 255 bspc(t7,t1) = spc(t1) repeat bfont(t7,1) = c5 ++time bfont(t7,2) = time curfont = c5 New code 04/22/04 t1 = c5 - 29 /* 1 <= t1 <= 19 t2 = XFonts(sizenum,t1) - 50 /* 1 <= t2 <= 90 (text font) t3 = t2 * 4 - 3 if t2 <= 30 kfile1 = DISP_DISK // ":/musprint/new/xfonts/tms/stnd/kmaps/" // kernfiles{t3,4} kfile2 = DISP_DISK // ":/musprint/new/xfonts/tms/stnd/kmaps2/" // kernfiles{t3,4} else if t2 <= 60 kfile1 = DISP_DISK // ":/musprint/new/xfonts/tms/bold/kmaps/" // kernfiles{t3,4} kfile2 = DISP_DISK // ":/musprint/new/xfonts/tms/bold/kmaps2/" // kernfiles{t3,4} else kfile1 = DISP_DISK // ":/musprint/new/xfonts/tms/italic/kmaps/" // kernfiles{t3,4} kfile2 = DISP_DISK // ":/musprint/new/xfonts/tms/italic/kmaps2/" // kernfiles{t3,4} end end open [4,1] kfile1 getf [4] getf [4] loop for t4 = 1 to 26 getf [4] line t6 = 0 loop for t5 = 5 to 55 step 2 ++t6 if line{t5} = " " kernmap(t4,t6) = 0 else if line{t5} = "1" kernmap(t4,t6) = -1 else if line{t5} = "0" kernmap(t4,t6) = 1 else putc kernmap file error stop end end end repeat getf [4] line if t4 = 16 getf [4] line getf [4] line end repeat close [4] open [4,1] kfile2 getf [4] getf [4] loop for t4 = 1 to 26 getf [4] line t6 = 0 loop for t5 = 5 to 55 step 2 ++t6 if line{t5} = " " kernmap(t4+26,t6) = 0 else if line{t5} = "1" kernmap(t4+26,t6) = -1 else if line{t5} = "2" kernmap(t4+26,t6) = -2 else putc kernmap file error stop end end end repeat getf [4] line if t4 = 16 getf [4] line getf [4] line end repeat close [4] loop for t3 = 1 to 52 loop for t5 = 1 to 26 bkernmap(t7,t3,t5) = kernmap(t3,t5) repeat repeat end return ┌─────────────────────────────────────────────────────────────────┐ │P 22. newnsp │ │ │ │ Purpose: Calculate new nsp array │ │ │ │ Inputs: scnt = next logical record in input table │ │ divspq = number of divisions per quarter note │ │ xmindist = minimum distance between notes (x100) │ │ mindist = minimum distance between notes │ │ │ │ Outputs: new nsp array for this section │ │ │ │ Internal variables: t1,t2,t3,t4,t5,t6 │ │ mtot │ │ │ │ Strategy: (1) read through file until the next time │ │ signature change or until the end │ │ (2) count number of measures where shortest │ │ duration occurs │ │ (3) if this represents more than xx% of the │ │ outstanding measures, then this is │ │ the shortest note │ │ (4) otherwise, the shortest note is the │ │ next one up; i.e. │ │ triplets --> regular │ │ regular --> double regular │ │ │ │ nsp(32) will be space for longa │ │ nsp(29) will be space for breve │ │ nsp(26) will be space for whole │ │ ... │ │ nsp(5) will be space for 128th note │ │ nsp(2) will be space for 256th note │ └─────────────────────────────────────────────────────────────────┘ procedure newnsp int t1,t2,t3,t4,t5,t6,t7 int mtot str line.120 t6 = scnt /* temporary counter in input loop for t1 = 1 to 33 nsp(t1) = xmindist /* New 12/16/03 nsp(t1) = mindist repeat if minshort <> 0 t1 = minshort * 4 rem = 0 /* sloppy code goto NOCALC end t2 = 100 mtot = 0 t7 = 0 /* "durations found" flag (initialize at 0) loop t1 = 0 tget [X,t6] line .t6 t1 ++t6 /* increment temporary counter line = line // pad(4) if line{1,4} = "/END" or line{1,4} = "/FIN" goto NW1 end if line{1} = "$" and line con "T:" and t7 = 1 goto NW1 end if t6 > 9990 putc putc FAULT CONDITION putc putc In searching for something, like for example, the end of a slur, putc AUTOSET has searched past the end of the file. There definitely putc is an error in the stage2 file. Please find and correct. putc putc Program Halted putc stop end if line{1,3} = "mea" ++mtot t4 = 0 end * if line{1} in ['A'..'G','r'] and t1 > 0 /* positive dur t7 = 1 if t1 < t2 t2 = t1 /* new shortest note t3 = 0 t4 = 0 end if t1 = t2 and t4 = 0 t4 = 1 ++t3 /* inc number of measures end end repeat t2 = shortest note value t3 = number of measures where this note occurs NW1: if t7 = 0 /* No durations found (unusual case) mtot = 1 t2 = 1 t3 = 1 end t5 = divspq * 16 / t2 if t5 > 96 t4 = 0 /* case 1: always double shortest note else if t5 > 48 t4 = 5 /* case 2: double if less than 16% else if t5 > 24 t4 = 8 /* case 3: double if less than 11% else t4 = 10 /* case 4: double if less than 9% end end end * t1 = mtot / t3 if t1 > t4 t1 = divspq / 3 if rem = 0 t1 = t2 / 2 if rem = 0 t2 = t1 * 3 else t2 *= 2 end else t2 *= 2 end end * t1 = divspq * 16 / t2 if t1 = 1, shortest note is longa if t1 = 2, shortest note is breve if t1 = 4, shortest note is whole if t1 = 8, shortest note is half, etc t2 = t1 / 3 if rem = 0 t1 = t2 * 2 end NOCALC: t5 = 32 /* 32 = code for longa t4 = 160 * t1 >>= 1 loop while t1 > 0 /* i.e., if t1 started as 16th (t1 = 64), loop 6 times t5 -= 3 t4 -= 20 t1 >>= 1 repeat * if rem = 0 /* sloppy code. See up 100 lines for expl. nsp(t5) = xmindist * 10 / 9 /* New 12/16/03 nsp(t5) = mindist * 10 / 9 end if t4 > 100 nsp(t5) = nsp(t5) * t4 / 100 end nsp(t5+1) = nsp(t5) * 12 / 10 t1 = 13 * loop while t5 < 31 t4 = t5 + 3 nsp(t4) = nsp(t5) * t1 / 10 ++t1 t5 = t4 nsp(t5-1) = nsp(t5) * 9 / 10 nsp(t5+1) = 2 * nsp(t5) - nsp(t5-3) repeat Now reduce all nsp(.) numbers by factor of 100 (12/16/03) loop for t1 = 1 to 33 nsp(t1) = nsp(t1) + 50 / 100 repeat return ┌────────────────────────────────────────────────┐ │P 23. settime (t1) │ │ │ │ Purpose: Set time signature │ │ │ │ Inputs: tnum = time numerator │ │ tden = time denominator │ │ p = current x position │ │ oby = 0 or 1000 (staff 0 or 1) │ │ spn = space node (obj field 7) │ 01/17/04 │ │ │ Outputs: p = new x position │ │ t1 = amount of empty space │ │ │ │ Internal variables: @e,a,dv2,dv3,dv4 │ └────────────────────────────────────────────────┘ procedure settime (t1) int t1 jcode = tnum * 100 + tden putobjpar = 0 @e = 0 if tnum = 1 and tden = 1 @e = 1 end if tnum = 0 and tden = 0 @e = 2 end * putc Time = ~tnum :~tden * set time signature jtype = "T" out = "0" if @e > 0 obx = p oby += vpar(6) pcode = 1 a = 36 + @e sobl(1) = "K 0 0 " // chs(a) jscrdat = "" perform putobj p += hpar(14) t1 = hpar(14) - hpar(92) oby -= vpar(6) else dv2 = p + hpar(16) if tden < 10 and tnum < 10 dv2 = p + hpar(17) end * obx = dv2 * y = vpar(4) + oby a = tnum perform number dv4 = dv3 y = vpar(8) + oby a = tden perform number pcode = sobcnt jscrdat = "" perform putobj if dv3 > dv4 dv3 = dv4 end p = dv3 + hpar(18) t1 = hpar(18) end passback t1 return ┌──────────────────────────────────────────────────────┐ │P 24. process_section │ │ │ │ Purpose: Set parameters for new section │ │ │ │ Inputs: @b = new key │ │ divspq = divisions per quarter │ │ @e = time signature flag │ │ tnum = time numerator │ │ tden = time denominator │ │ @n = set array counter (for │ │ changes within measure) │ │ line = "$" control code line │ │ │ │ Outputs: p = new x position │ │ │ │ Internal variables: @e,a,dv2,dv3,dv4 │ └──────────────────────────────────────────────────────┘ procedure process_section int h, hh, pp, qq int @spn /* New 01/17/04 ┌─────────────────────────────────────────┐ │ BEGINNING OF SECTION PROCESSING │ └──-──────────────────────────────────────┘ New code for single line staff 12/18/05 if line con "C:0" single_line = 1 end if @n > 0 Code changed and added 01/17/04 to fix time change bug if @n > 0 or outslurs <> "00000000" if @n = 0 @spn = 6913 else @spn = 0 /* code for "don't use this information" end examine if line con "I:" vflag = int(line{mpt+2..}) if vflag < 1 vflag = 1 end if vflag > 3 vflag = 3 end end if line con "S:" nstaves = int(line{mpt+2..}) if nstaves < 1 nstaves = 1 end if nstaves > 2 nstaves = 2 end end if line con "C:" or line con "C1:" ++@n tv1(@n) = CLEF_CHG if line{mpt+2} = ":" ++mpt end tv2(@n) = int(line{mpt+2..}) tv3(@n) = 0 /* staff number if line con "D:" or line con "D1:" or large_clef_flag > 0 /* New 02/02/09 tcode(@n) = "0" /* music font else tcode(@n) = "128" /* music font end tv5(@n) = @spn /* added 01/17/04 end if line con "C2:" ++@n tv1(@n) = CLEF_CHG tv2(@n) = int(line{mpt+3..}) tv3(@n) = 1 /* staff number if line con "D2:" or large_clef_flag > 0 /* New 02/02/09 tcode(@n) = "0" /* music font else tcode(@n) = "128" /* music font end nstaves = 2 tv5(@n) = @spn /* added 01/17/04 end if line con "D:" or line con "D1:" ++@n tv1(@n) = DESIGNATION tv2(@n) = 0 tv3(@n) = 0 /* staff number tcode(@n) = "" if line{mpt+1} <> ":" ++mpt end line2 = trm(line{mpt+2..}) tdata(@n,1) = mrt(line2) tv5(@n) = @spn /* added 01/17/04 end if line con "D2:" ++@n tv1(@n) = DESIGNATION tv2(@n) = 0 tv3(@n) = 1 /* staff number tcode(@n) = "" line2 = trm(line{mpt+3..}) tdata(@n,1) = mrt(line2) nstaves = 2 tv5(@n) = @spn /* added 01/17/04 end Another change on 05/29/05. In this case, I am moving the keychange "K:" code from below the "Q:" code to above the time "T:" code. This conforms with the normal way sections are introduced. What I don't know, however, is whether this conflicts with some other convention, or whether the program code depended in some way on the old order. Again, we must watch this and see if it produces strange results in the future. if line con "K:" ++@n tv1(@n) = AX_CHG tv2(@n) = int(line{mpt+2..}) tv3(@n) = nstaves tcode(@n) = "" tv5(@n) = @spn /* added 01/17/04 end if line con "T:" ++@n tv1(@n) = METER_CHG tnum = int(line{mpt+2..}) if line con "/" tden = int(line{mpt+1..}) else return 6 end tv2(@n) = 100 * tnum + tden tv3(@n) = nstaves tcode(@n) = "" tv5(@n) = @spn /* added 01/17/04 end if line con "Q:" ++@n tv1(@n) = DIV_CHG tv2(@n) = int(line{mpt+2..}) tv3(@n) = 0 tcode(@n) = "" tv5(@n) = @spn /* added 01/17/04 end Moving this code to above the time "T:" code (05/29/05) if line con "K:" ++@n tv1(@n) = AX_CHG tv2(@n) = int(line{mpt+2..}) tv3(@n) = nstaves tcode(@n) = "" tv5(@n) = @spn /* added 01/17/04 end /* old system; better to use print suggestions if line con "P:" mindist = int(line{mpt+2..}) * notesize / 16 end return end * spn = 6913 "P:" is the old system; it's actually better to use the new system of print suggestions to change note spacing if line con "P:" mindist = int(line{mpt+2..}) * notesize / 16 end if line con "I:" vflag = int(line{mpt+2..}) if vflag < 1 vflag = 1 end if vflag > 3 vflag = 3 end end if line con "S:" nstaves = int(line{mpt+2..}) if nstaves < 1 nstaves = 1 end if nstaves > 2 nstaves = 2 end end if line con "D2:" nstaves = 2 end (1) clef if line con "C:" or line con "C1:" or line con "C2:" i = 0 h = 0 if line con "C:" or line con "C1:" if line{mpt+1} = ":" i = mpt + 2 else i = mpt + 3 end end if line con "C2:" h = mpt + 3 nstaves = 2 end if i*h = 0 /* Case1: only one clef designator if i > 0 k = 1 else i = h k = 2 end clef(k) = int(line{i..}) Special code for single line instruments 12/18/05 if single_line = 1 clef(1) = 4 end perform zjcline (k) if p > 0 p -= hpar(37) end p += hpar(5) * print clef obx = p oby = 5 - j * notesize oby = (k - 1) * 1000 + oby if single_line = 0 /* New condition 12/18/05 perform putclef (k) end else /* Case2: two clef designators k = 1 clef(k) = int(line{i..}) perform zjcline (k) if p > 0 p -= hpar(37) end p += hpar(5) * print clef on staff 1 obx = p oby = 5 - j * notesize perform putclef (k) k = 2 clef(k) = int(line{h..}) perform zjcline (k) * print clef on staff 2 obx = p oby = 5 - j * notesize oby += 1000 perform putclef (k) end * advance horizontal pointer p += hpar(8) pp = hpar(8) - hpar(86) loop for h = 1 to MAX_STAFF loop for hh = 1 to 45 emptyspace(h,hh) = pp repeat repeat end (2) key signature if line con "K:" @b = int(line{mpt+2..}) if line{sub} = "(" /* new code 08/23/06 if line{sub+1} = "+" h = int(line{sub+2..}) else h = int(line{sub+1..}) end else h = 0 end hh = 1 perform key_change (@b, key, nstaves, hh, h) /* fifth variable added 08/23/06 /* this sets key = @b and resets claveax(.), emptyspace(.,.) etc. end (3) divisions per quarter if line con "Q:" olddivspq = int(line{mpt+2..}) end (4) time word if line con "D:" or line con "D1:" or line con "D2:" a1 = 6913 if line not_con "T:" a1 = 1 f4 is set when a directive is placed with spn = 1. This directive takes its position from the next controlling object in the part. Therefore, it must not be followed by a multiple rest. f4 = 1 end if line con "D:" temp3 = trm(line{mpt+2..}) temp3 = mrt(temp3) oby = 0 - tword_height * vpar(1) ++outpnt tput [Y,outpnt] J D 5 ~p ~oby 1 ~a1 0 0 ++outpnt tput [Y,outpnt] W 0 0 ~dtivfont ~temp3 end if line con "D1:" temp3 = trm(line{mpt+2..}) temp3 = mrt(temp3) oby = 0 - tword_height * vpar(1) ++outpnt tput [Y,outpnt] J D 5 ~p ~oby 1 ~a1 0 0 ++outpnt tput [Y,outpnt] W 0 0 ~dtivfont ~temp3 end if line con "D2:" temp3 = trm(line{mpt+2..}) temp3 = mrt(temp3) oby = 0 - tword_height * vpar(1) oby += 1000 ++outpnt tput [Y,outpnt] J D 5 ~p ~oby 1 ~a1 0 0 ++outpnt tput [Y,outpnt] W 0 0 ~dtivfont ~temp3 end end (5) time signature (also new note spacing calculations) if line con "T:" tnum = int(line{mpt+2..}) if line con "/" tden = int(line{mpt+1..}) else return 6 end oby = 0 pp = p loop for hh = 1 to nstaves p = pp perform settime (h) Actually, we will set emptyspace to hpar(29), the mimimum space space allowed before an accidental. This way, no note-type objects will be able to crowd the time signature. If this works, we can remove the code that returns the value (h) from settime. (We actually shouldn't be interested in this value anyway, because we do NOT want to get too close to the time signature.) loop for qq = 1 to 45 emptyspace(hh,qq) = min_space /* replaces hpar(29) 11/19/07 repeat oby += 1000 repeat if tnum = 1 and tden = 1 tnum = 4 tden = 4 end if tnum = 0 and tden = 0 tnum = abflg tden = 2 end determine note spacing ---------------------- divspq = olddivspq perform newnsp end return ┌───────────────────────────────┐ │ END OF SECTION PROCESSING │ └───────────────────────────────┘ ┌──────────────────────────────────────────────────────┐ │P 25. key_change (newkey, oldkey, nstaves, t1, t2) │ │ │ │ Purpose: Typeset a key change │ │ │ │ Inputs: int newkey new key │ │ int oldkey old key │ │ int nstaves number of staves │ │ int t1 operation code │ │ 1 = change emptyspace │ │ 0 = don't do it │ │ int t2 part of new key in │ │ parenthesis 08/23/06 │ │ │ │ Global variables: │ │ │ │ sobcnt subobject counter │ │ p x position pointer │ │ x actual x-coordinate │ │ y actual y-coordinate │ │ z font number │ │ obx object x-coordinate │ │ oby object y-coordinate │ │ clef(.) current clef │ │ measax(.,.) current measure ax array │ │ claveax(.) global ax array │ │ jtype object type │ │ jcode object code │ │ pcode number of sub objects │ │ out ASCII string │ │ │ │ Outputs: p = new x position │ │ emptyspace(.,.) changed (if t1 = 1) │ │ │ └──────────────────────────────────────────────────────┘ procedure key_change (newkey, oldkey, nstaves, t1, t2) /* t2 added 08/23/06 int newkey, oldkey, nstaves int save_oldkey /* added 11/05/05 int sy int a, m, h, i, j, k int hh int t1,t2,t3 /* t2,t3 added 08/23/06 int klave,sklave int tenor int m1,m2,m3,m4,m5,m6 /* added 08/23/06 getvalue newkey, oldkey, nstaves, t1, t2 if t2 <> 0 /* magic numbers for editorial [] 08/23/06 m1 = (2 * notesize + 3 / 6) m2 = (4 * notesize + 3 / 6) m3 = (7 * notesize + 3 / 6) m4 = notesize + 3 / 6 m5 = (5 * notesize + 3 / 6) m6 = notesize end t3 = newkey /* added 08/23/06 newkey = newkey + t2 /* added 08/23/06 This code added 11/26/06 to allow reprint of existing key signature if newkey = oldkey and key_reprint_flag > 0 oldkey = 0 end End of 11/26/06 addition New code. 10/15/07. It used to be the case that a non key change in an orchestra part (such as horns) simply returned at this point. No i-file entry was generated because none was needed. The problem created by this was that if the mskpage program was looking for a key change node (because other parts had one) and didn't find one, this could cause a misalignment of control node. It turns out that the program crashed only when the key change came at the end of a line, so nothing was done about it. (The bug was rare, and difficult to identify). The advent of justification made the bug more likely to occur, and it did (once too often). So I decided on this fix, namely: From now on, all key changes will generate a "J K" node, even if there is none to be printed. In this case, the node will have no sub-objects and will therefore be "silent." This seems to have caused no other problems with the programs. if newkey = oldkey loop for hh = 1 to nstaves putobjpar = 0 sobcnt = 0 oby = 0 obx = p x = obx jtype = "K" jcode = newkey pcode = 0 out = "0" oby = (hh - 1) * 1000 jscrdat = "" perform putobj repeat return end End of 10/15/07 addition New code. 11/02/07. Another situation has come up, which I believe can be dealt with here. In the case where the timpani plays on the notes B-flat and F, the notation shows these two pitches without a key signature. In order to make this work, the encoder used the pitches B-natural and F, and a key signature of 0 (no sharps or flats). This of course would wreck havoc in a midi file. It would be far better to encode the key as -1 (one flat) and then encode the pitches B-flat and F, as they would actually sound. The problem with this is that the key signature would appear at the beginning of every line. We need to have a way to suppress this. I propose a new global flag, suppress_key, which can be set by the "k" global suggestion. The following code deals with this situation. if suppress_key > 0 save_oldkey = oldkey loop for hh = 1 to nstaves * set up new global accidentals for claveax oldkey = newkey loop for i = 1 to 50 claveax(i) = 0 repeat h = newkey if h > 0 k = 4 loop for i = 1 to h loop for a = k to 50 step 7 claveax(a) = 2 repeat k += 4 if k > 7 k -= 7 end repeat end if h < 0 h = 0 - h k = 7 loop for i = 1 to h loop for a = k to 50 step 7 claveax(a) = 3 repeat k -= 4 if k < 1 k += 7 end repeat end oldkey = save_oldkey putobjpar = 0 sobcnt = 0 oby = 0 obx = p x = obx jtype = "K" jcode = 0 pcode = 0 out = "0" oby = (hh - 1) * 1000 jscrdat = "" perform putobj repeat loop for i = 1 to 50 loop for h = 1 to 4 /* 06/04/08 was 3 measax(h,i) = claveax(i) repeat repeat oldkey = newkey /* moved 11/05/05 passback oldkey return end End of 11/02/07 addition putobjpar = 0 save_oldkey = oldkey /* added 11/05/05 loop for hh = 1 to nstaves sobcnt = 0 oby = 0 i = clef(hh) / 10 klave = rem - 1 * 2 i /= 3 k = 2 - rem * 3 klave -= k obx = p x = obx tenor = 0 if clef(hh) = 12 tenor = 2 end * sharps if newkey > 0 * cancellations? sy = y sklave = klave if oldkey > newkey loop for j = 1 to newkey y += zak(1,j) klave += zak(1,j) repeat h = oldkey - newkey m = 1 + tenor perform cancelsig (m,j,h,klave) end if oldkey < 0 h = 0 - oldkey y += vpar(4) klave += 4 j = 0 m = 2 perform cancelsig (m,j,h,klave) end y = sy klave = sklave * set new key kscrdat = "" if t2 = 0 loop for j = 1 to newkey z = 63 if tenor = 0 or klave >= 0 y = klave + 20 * notesize / 2 - vpar20 else y = klave + 27 * notesize / 2 - vpar20 /* exception for tenor clef end perform subj y += zak(1,j) klave += zak(1,j) x += hpar(9) repeat else This code added 08/23/06 to deal with editorial additions of sharps if t2 > 0 loop for j = 1 to t3 z = 63 if tenor = 0 or klave >= 0 y = klave + 20 * notesize / 2 - vpar20 else y = klave + 27 * notesize / 2 - vpar20 /* exception for tenor clef end y = klave + 20 * notesize / 2 - vpar20 perform subj klave += zak(1,j) x += hpar(9) repeat loop for j = t3 + 1 to newkey x += m1 /* magic number z = 67 if tenor = 0 or klave >= 0 y = klave + 20 * notesize / 2 - vpar20 else y = klave + 27 * notesize / 2 - vpar20 /* exception for tenor clef end y = klave + 20 * notesize / 2 - vpar20 perform subj x += m2 /* magic number z = 63 perform subj x += m3 /* magic number z = 68 perform subj klave += zak(1,j) x += (hpar(9) - m3) /* magic number repeat end End of 08/23/06 addition end end * no sharps or flats if newkey = 0 * cancellations? j = 0 if oldkey > 0 h = oldkey m = 1 + tenor perform cancelsig (m,j,h,klave) end if oldkey < 0 h = 0 - oldkey m = 2 y += vpar(4) klave += 4 perform cancelsig (m,j,h,klave) end end * flats if newkey < 0 * cancellations? sy = y sklave = klave if oldkey < newkey h = 0 - newkey y += vpar(4) klave += 4 loop for j = 1 to h y += zak(2,j) klave += zak(2,j) repeat h = newkey - oldkey m = 2 perform cancelsig (m,j,h,klave) end if oldkey > 0 h = oldkey j = 0 m = 1 + tenor perform cancelsig (m,j,h,klave) end y = sy + vpar(4) klave = sklave + 4 * set new key kscrdat = "" if t2 = 0 h = 0 - newkey loop for j = 1 to h z = 65 y = klave + 20 * notesize / 2 - vpar20 Code added 09/13/06 to fix flats in soprano clef if y > vpar(8) y -= vpar(7) end perform subj y += zak(2,j) klave += zak(2,j) x += hpar(11) repeat else This code added 08/23/06 to deal with editorial additions of flats if t2 < 0 t3 = 0 - t3 h = 0 - newkey loop for j = 1 to t3 z = 65 y = klave + 20 * notesize / 2 - vpar20 Code added 09/13/06 to fix flats in soprano clef if y > vpar(8) y -= vpar(7) end perform subj klave += zak(2,j) x += hpar(9) repeat loop for j = t3 + 1 to h x += m4 /* magic number z = 67 y = klave + 20 * notesize / 2 - vpar20 Code added 09/13/06 to fix flats in soprano clef if y > vpar(8) y -= vpar(7) end perform subj x += m5 /* magic number z = 65 perform subj x += m6 /* magic number z = 68 perform subj klave += zak(2,j) x += (hpar(11) - m6) /* magic number repeat end End of 08/23/06 addition end end * Write out object and subobjects jtype = "K" jcode = newkey pcode = sobcnt out = "0" oby = (hh - 1) * 1000 jscrdat = "" perform putobj * if newkey = 0 and oldkey = 0 i = hpar(13) if t1 = 1 loop for j = 1 to 45 emptyspace(hh,j) += i repeat end else i = hpar(12) if t1 = 1 loop for j = 1 to 45 emptyspace(hh,j) = i repeat end end if hh = nstaves p = x + i end * set up new global accidentals for claveax oldkey = newkey loop for i = 1 to 50 claveax(i) = 0 repeat h = newkey if h > 0 k = 4 loop for i = 1 to h loop for a = k to 50 step 7 claveax(a) = 2 repeat k += 4 if k > 7 k -= 7 end repeat end if h < 0 h = 0 - h k = 7 loop for i = 1 to h loop for a = k to 50 step 7 claveax(a) = 3 repeat k -= 4 if k < 1 k += 7 end repeat end oldkey = save_oldkey /* changed 11/05/05 (was oldkey = newkey) repeat loop for i = 1 to 50 loop for h = 1 to 4 /* 06/04/08 was 3 measax(h,i) = claveax(i) repeat repeat oldkey = newkey /* moved 11/05/05 passback oldkey return ┌──────────────────────────────────────────────────────┐ │P 26. display_ts │ │ │ │ Purpose: Display parameters in ts(.,.) array │ │ │ └──────────────────────────────────────────────────────┘ procedure display_ts str temp.TSR_LENG int t1,t2,t3 putc TYPE DIV CLAV AX NTYP DOT TPLE VLOC SPAC STEM BMFG BMCD ... putc SUPF SLUR SUB1 SUB2 YSH SRT2 TEXT PASS BTIE NDUR DINC MULT loop for t2 = 1 to TS_SIZE putc .t2w4 ~t2 ... repeat putc putc ... loop for t2 = 1 to 6 putc ==== ==== ==== ==== ==== ==== ... repeat putc loop for t1 = 1 to sct loop for t2 = 1 to TS_SIZE putc .t2w4 ~ts(t1,t2) ... repeat putc repeat DTS1: putc putc Type a number (pointer value in col 34) to see the tsr string for an item. t3 = 0 getc t3 if t3 = 0 return end temp = tsr(t3) putc TSR string at pointer ~t3 putc Item byte1 byte2 byte3 byte4 loop for t1 = 1 to (TSR_LENG >> 2) putc .w4 ~t1 ... loop for t2 = -3 to 0 step 1 t3 = ors(temp{t1*4+t2}) putc .w7x ~t3 ... repeat putc repeat goto DTS1 return ┌────────────────────────────────────────────────────────────────────┐ │P 27. zjcline (staff) │ │ │ │ Purpose: Compute values of z, j, and cline from clef │ │ │ │ Inputs: staff = staff number (1 or 2) │ │ clef(.) = clef flag │ │ │ │ Outputs: z = clef font │ │ j = vertical postion of clef │ │ cline(.) = location of middle C │ └────────────────────────────────────────────────────────────────────┘ procedure zjcline (staff) int g,h,i,k,m int staff getvalue staff i = clef(staff) / 10 j = 6 - rem k = i / 3 h = rem if rem = 0 z = 33 else z = 34 + h end m = j * 2 + 20 g = 0 if k > 0 if k = 1 g = 7 else g = -7 end end cline(staff) = h - 1 * 4 + m + g return ┌───────────────────────────────────────────────────────┐ │P 28. putclef (staff) │ │ │ │ Purpose: write clef sign to intermediate file │ │ │ │ Inputs: staff = staff number (1 or 2) │ │ clef(.) = clef code │ │ obx = x offset │ │ oby = y offset │ │ z = clef font │ └───────────────────────────────────────────────────────┘ procedure putclef (staff) int staff int g,h,i,k,m getvalue staff i = clef(staff) / 10 k = i / 3 h = rem jtype = "C" jcode = clef(staff) out = "0" kscrdat = "" if h = 0 x = obx y = oby perform subj ++z perform subj if k = 1 x = obx + hpar(52) y = oby + vpar(23) z = 234 perform subj end pcode = sobcnt else pcode = z end putobjpar = 0 jscrdat = "" perform putobj return ┌─────────────────────────────────────────────────────────────────┐ │P 29. rotate_array (t1,t2) │ │ │ │ Purpose: Move ts array elements at t2 to t1 position. │ │ Rotate all other elements down one │ │ │ │ Inputs: t1 = top of rotation │ │ t2 = bottom of rotation (t2 > t1) │ │ │ └─────────────────────────────────────────────────────────────────┘ procedure rotate_array (t1,t2) int temp(TS_SIZE) int t1,t2,t3,t4 getvalue t1,t2 if t2 = t1 return end if t2 < t1 putc Program error at rotate examine stop end loop for t3 = 1 to TS_SIZE temp(t3) = ts(t2,t3) /* create hole at the bottom (save bottom) repeat loop for t4 = t2 to t1+1 step -1 /* loop in backwards order loop for t3 = 1 to TS_SIZE ts(t4,t3) = ts(t4-1,t3) /* copy each row from the one above it repeat repeat loop for t3 = 1 to TS_SIZE ts(t1,t3) = temp(t3) /* store bottem piece at top repeat return ┌─────────────────────────────────────────────────────────────────┐ │P 30. get_topbottom (t1,t2,t3) │ │ │ │ Purpose: If t1 points to a ts row element which is a note │ │ head, then t2 will point to the ts row element │ │ which is the top of the chord, and t3 will point │ │ to the ts row element which is the bottom of the │ │ chord │ │ │ │ Inputs: t1 = index to ts row element │ │ │ │ Outputs: t2 = index to top of chord │ │ t3 = index to bottom of chord │ │ │ │ Note: Do not call this procedure before GLOBAL_XOFF is set │ │ │ └─────────────────────────────────────────────────────────────────┘ procedure get_topbottom (t1,t2,t3) int t1,t2,t3,t4 getvalue t1 t4 = ts(t1,GLOBAL_XOFF) if t4 > INT10000 t2 = t4 / INT10000 t3 = rem else t4 = ts(t1+1,GLOBAL_XOFF) if t4 > INT10000 t2 = t4 / INT10000 t3 = rem else t2 = t1 t3 = t1 end end passback t2,t3 return PROCEDURES FOR PSEUDO-TYPESETTING ┌─────────────────────────────────────────────────────────────────┐ │P 31. ps_setchord (p1,p2,p3) │ │ │ │ Purpose: Add a chord to the simultaneity │ │ │ │ Inputs: p1 = pass number (chord number) │ │ p2 = second chord number (for unisons) or 100 │ │ p3 = initialize parameter (0 = initialize) │ │ │ │ Outputs: p3 = initialize parameter (1 = don't initialize) │ │ printpos(.) = print position for this chord │ │ │ │ Method: construct the left boundary of the new chord. │ │ Move the chord to the right until it bumps │ │ with previous chords. │ │ │ │ Output: when a note for a chord is set, ndata(*,PASS) │ │ for that note is set to zero. │ │ │ │ printpos(p1) and maybe printpos(p2) │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ procedure ps_setchord (p1,p2,p3) int a,b,c,d,e,x int aa,bb,cc,dd int tr(2,45),tl(2,45) int pseudo_tr(2,45) int pseudo_tl(2,45) int f,g,h,i,j,k int ff,gg,hh int p1, p2, p3 int ps_width int stem_up_flag int stem_down_flag getvalue p1,p2,p3 if p3 = 0 p3 = 1 x = 10000 else x = 0 end passback p3 putc Calling ps_setchord pass = ~p1 pass2 = ~p2 putc ff = 0 hh = 0 loop for j = 1 to 45 tl(1,j) = 200 tr(1,j) = -200 pseudo_tr(1,j) = -200 pseudo_tl(1,j) = 200 tl(2,j) = 200 tr(2,j) = -200 pseudo_tr(2,j) = -200 pseudo_tl(2,j) = 200 repeat stem_up_flag = 0 stem_down_flag = 0 repeater_case = 0 c = 100 loop for i = 1 to pcnt if ndata(i,PS_PASS) = p1 or ndata(i,PS_PASS) = p2 b = ndata(i,PS_XPOS) a = ndata(i,PS_PITCH) putc set note ~i pitch = ~ndata(i,PS_PITCH) ... putc shift = ~ndata(i,PS_XPOS) if a = 100 ndata(i,PS_PASS) = 0 return end if c = 100 c = ndata(i,PS_STAFF) + 1 /* staff number d = ndata(i,PS_COLOR) if d < 3 ps_width = hpar(82) else if d = 3 ps_width = hpar(83) else ps_width = hpar(84) end end if ndata(i,PS_NSIZE) = CUESIZE ps_width = ps_width * 8 / 10 end end if bit(0,ndata(i,PS_STEM)) = UP /* stem up if b = 0 if tl(c,a) > 0 tl(c,a) = 0 end if tl(c,a+1) > hpar(95) tl(c,a+1) = hpar(95) end if pseudo_tl(c,a) > 0 pseudo_tl(c,a) = 0 end if pseudo_tl(c,a+1) > 0 pseudo_tl(c,a+1) = 0 end if tr(c,a) < ps_width - hpar(95) tr(c,a) = ps_width - hpar(95) end if tr(c,a+1) < ps_width tr(c,a+1) = ps_width end if pseudo_tr(c,a) < ps_width pseudo_tr(c,a) = ps_width end if pseudo_tr(c,a+1) < ps_width pseudo_tr(c,a+1) = ps_width end else dd = ps_width << 1 - hpar(90) if tr(c,a) < dd - hpar(95) tr(c,a) = dd - hpar(95) end if tr(c,a+1) < dd tr(c,a+1) = dd end if pseudo_tr(c,a) < dd + hpar(49) pseudo_tr(c,a) = dd + hpar(49) end if pseudo_tr(c,a+1) < dd + hpar(49) pseudo_tr(c,a+1) = dd + hpar(49) end end if ff = 0 ff = a + 8 /* 8 = length of stem end stem_up_flag |= ndata(i,PS_STEM) >> 2 else if b = 0 if tr(c,a) < ps_width - hpar(95) tr(c,a) = ps_width - hpar(95) end if tr(c,a+1) < ps_width tr(c,a+1) = ps_width end if pseudo_tr(c,a) < ps_width pseudo_tr(c,a) = ps_width end if pseudo_tr(c,a+1) < ps_width pseudo_tr(c,a+1) = ps_width end if tl(c,a) > 0 tl(c,a) = 0 end if tl(c,a+1) > hpar(95) tl(c,a+1) = hpar(95) end if pseudo_tl(c,a) > 0 pseudo_tl(c,a) = 0 end if pseudo_tl(c,a+1) > 0 pseudo_tl(c,a+1) = 0 end else if tl(c,a) > hpar(90) - ps_width tl(c,a) = hpar(90) - ps_width end if tl(c,a+1) > hpar(90) - ps_width + hpar(95) tl(c,a+1) = hpar(90) - ps_width + hpar(95) end if pseudo_tl(c,a) > hpar(90) - ps_width - hpar(49) pseudo_tl(c,a) = hpar(90) - ps_width - hpar(49) end if pseudo_tl(c,a+1) > hpar(90) - ps_width - hpar(49) pseudo_tl(c,a+1) = hpar(90) - ps_width - hpar(49) end end if hh = 0 hh = a - 1 end stem_down_flag |= ndata(i,PS_STEM) >> 2 end repeater_case |= bit(1,ndata(i,PS_STEM)) if ndata(i,PS_PASS) = p1 ndata(i,PS_PASS) = 0 end if ndata(i,PS_PASS) = p2 ndata(i,PS_PASS) = 0 end end repeat if hh > 45 hh = 45 end if ff > 0 /* put in stem up restraints e = ps_width - hpar(90) /* OLD ps_width - hpar(85) d = ps_width /* OLD ps_width + hpar(85) if repeater_case = 1 aa = e - hpar(98) bb = d + hpar(98) else aa = e bb = d end if stem_up_flag > 0 if stem_up_flag > 2 ff += stem_up_flag - 2 << 1 end dd = d + hpar(26) else dd = d end if ff > 45 ff = 45 end loop for i = ff - 6 to ff if tl(c,i) > aa tl(c,i) = aa end if tr(c,i) < bb tr(c,i) = bb end if pseudo_tr(c,i) < dd pseudo_tr(c,i) = dd end repeat loop for i = a + 2 to ff - 7 if tl(c,i) > e tl(c,i) = e end if tr(c,i) < d tr(c,i) = d end repeat end if hh > 0 /* put in stem down restraints a = a - 7 if stem_down_flag > 0 if stem_down_flag > 2 a -= stem_down_flag - 2 << 1 end dd = hpar(90) + hpar(26) else dd = hpar(90) end if a < 1 a = 1 end Fixing the left border on stems down with repeaters 06/04/08 plus bug correction 11/23/09 #if XPOS_FIXED loop for i = a + 4 to hh if tl(c,i) > 0 /* aa tl(c,i) = 0 /* aa end if tr(c,i) < hpar(90) /* bb tr(c,i) = hpar(90) /* bb end if pseudo_tr(c,i) < dd pseudo_tr(c,i) = dd end repeat #else loop for i = a + 4 to hh if tl(c,i) > 0 /* aa tl(c,i) = 0 /* aa end if tr(c,i) < bb tr(c,i) = bb end if pseudo_tr(c,i) < dd pseudo_tr(c,i) = dd end repeat #endif if repeater_case = 1 aa = 0 - hpar(98) bb = hpar(90) + hpar(98) else aa = 0 bb = hpar(90) end loop for i = a to a + 3 /* 4 is magic number if tl(c,i) > aa /* Repeaters only at bottom tl(c,i) = aa end if tr(c,i) < bb tr(c,i) = bb end if pseudo_tr(c,i) < dd pseudo_tr(c,i) = dd end repeat end if x = 10000 loop for i = 1 to 45 gr(c,i) = tr(c,i) gl(c,i) = tl(c,i) pseudo_gr(c,i) = pseudo_tr(c,i) repeat x = 0 /* amount shifted to the right else ff = 1000 loop for i = 1 to 45 gg = 1000 - gr(c,i) + tl(c,i) - 5 if gg < ff ff = gg end repeat x = 1000 - ff /* amount shifted to the right loop for i = 1 to 45 gg = x + tr(c,i) if gg > gr(c,i) and tr(c,i) <> -200 gr(c,i) = gg end gg = x + pseudo_tr(c,i) if gg > pseudo_gr(c,i) and pseudo_tr(c,i) <> -200 pseudo_gr(c,i) = gg end gg = x + tl(c,i) if gg < gl(c,i) gl(c,i) = gg end repeat end loop for j = 1 to 45 if pseudo_gl(1,j) > pseudo_tl(1,j) pseudo_gl(1,j) = pseudo_tl(1,j) end if pseudo_gl(2,j) > pseudo_tl(2,j) pseudo_gl(2,j) = pseudo_tl(2,j) end repeat loop for j = 1 to 1 putc Left Right Pseudo Left Pseudo Right loop for i = 45 to 1 step -1 putc .w5 ~gl(j,i) ~gr(j,i) ~pseudo_gl(j,i) ~pseudo_gr(j,i) repeat putc ═════════════════════════════════════ repeat getc printpos(p1) = x if p2 <> 100 printpos(p2) = x end putc print position equals ~x putc return ┌──────────────────────────────────────────────────────────────────────────────┐ │P 32. guessbeam (slope, t12) │ │ │ │ │ │ Purpose: Make a guess about the position of a beam │ │ │ │ Inputs: int c6 = number of notes under beam │ │ int mf(.) = y-position of note │ │ int beamcode(.) = beam code │ │ int stem = stem direction (UP/DOWN) │ │ int c5 = size: 0 = regular; 1 = small │ │ │ │ Outputs: int slope = BHPAR1 * slope of beam │ │ int t12 = end point of first stem (relative to top of staff) │ │ │ │ Internal variables: beamfy = y coordinate of first note under beam │ │ vrange = vertical range of note set │ │ zstaff = top of staff line │ │ slope = slope of beam │ │ ypiv = temporary variable │ │ (x1,y1) = temporary coordinates │ │ (x2,y2) = temporary coordinates │ └──────────────────────────────────────────────────────────────────────────────┘ procedure guessbeam (slope, t12) int t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 int zstaff,ypiv,slope int x1,x2,y1,y2,vrange,beamfy int xf(100) int beamh,beamt,bthick int beamtype int loopcnt * if c5 = 0 beamh = bvpar(16) beamt = bvpar(32) bthick = vpar(2) * 6 / 14 else beamh = bvpar(16) * 4 / 5 beamt = bvpar(32) * 4 + 3 / 5 bthick = vpar(2) * 5 / 14 end t6 = 0 loop for t5 = 1 to c6 xf(t5) = t6 t6 += vpar(6) /* average x increment (a guess) repeat beamfy = mf(1) * reverse if stem down t3 = 0 if stem = DOWN t3 = 300 * vpar(1) - vpar(8) t3 = 150 * vpar(2) - vpar(8) loop for t6 = 1 to c6 mf(t6) = 300 * vpar(1) - mf(t6) mf(t6) = 150 * vpar(2) - mf(t6) repeat end zstaff = t3 * determine slope and pivot of beam t9 = 0 x1 = 5000 y1 = 5000 t11 = 6 t1 = 0 t4 = 0 /* changes in absolute height t2 = 0 t5 = mf(1) identify: t9 = 6 - smallest note type under beam (x1,y1) = position of note closest to beam (x2,y2) = position of note next closest to beam t1 = y coordinate of note furthest from beam loop for t6 = 1 to c6 * also compute sum of absolute changes in vertical height t8 = t5 - mf(t6) testfor t8 < 0 if t2 = 0 t2 = -1 end if t2 = 1 t2 = 2 end t8 = 0 - t8 else (>) if t2 = 0 t2 = 1 end if t2 = -1 t2 = 2 end end t5 = mf(t6) t4 += t8 * t8 = 0 /* number of additional beams on this note loop while beamcode(t6) > 9 ++t8 beamcode(t6) /= 10 repeat if t8 > t9 t9 = t8 /* max number of additional beams end if t8 < t11 t11 = t8 /* min number of additional beams end t8 = mf(t6) if t8 > t1 t1 = t8 /* lowest y co-ord of notes in beam set end if t8 < y1 y2 = y1 x2 = x1 y1 = t8 /* nearest y co-ord x1 = xf(t6) else if t8 < y2 y2 = t8 x2 = xf(t6) end end repeat Check point one: (x1,y1); (x2,y2); t1 set vrange = t1 - y1 Formula for initial stem length note t9 y1-t8 ─────── ────── ─────── 8th: 0 beamh 16th: 1 beamh + (1 * notesize / 4) 32th: 2 beamh + (4 * notesize / 4) 64th: 3 beamh + (7 * notesize / 4) 128th: 4 beamh + (10 * notesize / 4) 256th: 5 beamh + (13 * notesize / 4) beamtype = t9 if t9 = 0 t8 = y1 - beamh else t8 = t9 * 3 - 2 t8 = 0 - notesize * t8 / 4 - beamh + y1 end t1 = x1 * deal with case of severe up-down pattern if t2 = 2 t4 /= c6 if t4 > bvpar(18) slope = 0 goto GSB1 end end * slope = y1 - y2 * 2 * BHPAR1 t7 = x1 - x2 slope /= t7 Comment: slope is (2*BHPAR1) times slope between two notes nearest the beam t7 = mf(c6) - mf(1) * 2 * BHPAR1 t6 = xf(c6) if t6 < vpar(5) t6 = vpar(5) end t7 /= t6 Comment: t7 is (2*BHPAR1) times slope between outside notes Formula: slope = (slope + t7) / 6 provided |slope| must be equal to or less than |t7| t6 = abs(slope) - abs(t7) if t6 > 0 if slope > 0 slope -= t6 else slope += t6 end end * slope = slope + t7 / 6 GSB1: t7 = abs(slope) if t7 > BHPAR1 / 2 t7 = BHPAR1 / 2 end * Soften slant for thirty-seconds and smaller if t9 > 2 and t7 > 5 t7 = 0 - t9 / 2 + t7 end if t7 < 0 t7 = 0 end set reduce slant if end note are closer than vpar(6) t4 = xf(c6) if t4 <= vpar(6) and t7 > bvpar(35) t7 = bvpar(35) end shorten shortest stem, if gradual slope and large vertical range and relatively high note if vrange > vpar(3) t4 = t9 * beamt + t8 - zstaff t4 = 0 - t4 if t4 > vpar(3) if t7 < 6 if x1 > 0 and x1 < xf(c6) t8 += bvpar(17) end if c6 = 2 t8 += bvpar(17) end end end end * if slope < 0 slope = 0 - t7 else slope = t7 end slope = BHPAR1 * slope of beam t8 = y coordinate of pivot point (on highest note) of first beam t7 = absolute value of @m t3 = y coordinate of top of staff line (x1,y1) = coordinate of note closest to beam (highest note) (x2,y2) = coordinate of second closest note to beam (2nd highest note) t9 = 6 - smallest note type number (number of beams - 1 t11 = 6 - largest note type number ypiv = t8 ++t9 Check point two: t9 = number of beams, current slope = slope Adjust slope and t8 so that beams will fall properly on staff lines Case I: slope = 0 GCSI: if slope = 0 t2 = t9 - 1 * notesize + t8 if t2 >= t3 Adjust flat beam height t5 = t2 - t3 / notesize if t9 = 1 and rem <= bvpar(20) rem += bvpar(20) end if t9 = 2 if rem <= bvpar(20) rem += bvpar(34) else rem = rem - notesize + bvpar(20) end end if t9 = 3 rem += bvpar(34) end if t9 = 4 if t5 = 3 beamt = bvpar(33) end if t5 < 3 t5 = rem t5 -= vpar(1) / 2 rem = t5 end end t8 -= rem * (*) extremely low notes if t9 = 1 t2 = vpar(4) + zstaff else t2 = 4 - t9 * vpar(2) + zstaff end if t8 > t2 t8 = t2 if t9 > 3 and c5 = 0 beamt = bvpar(33) end end end else Case II: slope <> 0 loopcnt = 0 GCSII: ++loopcnt t6 = 0 - x1 * slope / BHPAR1 + t8 t5 = xf(c6) * slope / BHPAR1 + t6 t2 = t5 + t6 / 2 if t9 > 1 if t11 > 0 t2 += beamt if t9 = 2 t2 += 2 end end t10 = bvpar(22) else t10 = bvpar(23) end t6 = starting point of top beam t5 = stopping point of top beam t2 = average height of beam (second beam if always 2 or more) t10 = fudge factor t4 = t3 t3 -= notesize if t9 > 2 t3 -= notesize end if t2 > t3 Adjust slanted beam height if t9 > 2 if t2 > t4 beamt = bvpar(33) else t2 -= 2 end end t4 = abs(t5 - t6) t5 = t2 - t3 / notesize t5 = rem t4 = rise/fall of beam t5 = amount by which the average beam height lies below a line if t4 < bvpar(24) if t5 >= t10 t5 -= notesize if t9 = 1 ++t5 end else if t9 = 1 --t5 end end t8 -= t5 goto GCV end if t4 < beamt if loopcnt > 4 goto GCV end if t7 > 1 goto GCSJJ end ++t7 if slope < 0 slope = 0 - t7 else slope = t7 end goto GCSII end if t4 < bvpar(25) t5 += vpar(1) c16 = t5 * 2 / vpar(2) if rem <> 0 ++t5 end t5 += vpar(1) if t5 > t10 t5 -= notesize end t8 -= t5 goto GCV end if t4 > bvpar(26) if t5 > t10 t5 -= notesize end t8 -= t5 goto GCV end if t7 = 2 t5 += vpar(1) c16 = t5 * 2 / vpar(2) if rem <> 0 ++t5 end t5 += vpar(1) if t5 > t10 t5 -= notesize end t8 -= t5 goto GCV end if loopcnt > 4 goto GCV end GCSJJ: --t7 if slope < 0 slope = 0 - t7 else slope = t7 end goto GCSII else if t9 < 4 t8 = notesize / 3 + t8 end end * Check for extra low notes GCV: t4 = 0 - x1 * slope / BHPAR1 + t8 t6 = xf(c6) - x1 * slope / BHPAR1 + t8 t5 = 0 if t9 = 1 t2 = vpar(4) + zstaff - 2 else t2 = 4 - t9 * notesize + zstaff - 2 end if slope > 0 if t4 > t2 t5 = 1 t4 = t2 + 1 end else if t6 > t2 t5 = 1 t6 = t2 + 1 end end t2 = t2 + bvpar(20) + 2 if slope > 0 if t6 > t2 t5 = 1 t6 = t2 end else if t4 > t2 t5 = 1 t4 = t2 end end if t5 = 1 * Correction necessary t7 = xf(c6) slope = t6 - t4 * BHPAR1 / t7 t8 = x1 * slope / BHPAR1 + t4 t7 = abs(slope) end t8 -= vpar(1) / 2 end * t12 = slope * t1 t12 = t8 * BHPAR1 - t12 Check point three: beam slope = slope; y intercept (times BHPAR1) = t12 Post adjustment: sometimes the stems of sixteenths are too short. This will be the case when (y2-t8) - ((t9-1)*beamt) < xxx where xxx is some number. In this case, we should raise the beam by some small amount, yyy. t6 = 0 - (t9 - 1) * beamt + y2 - t8 if t6 < bvpar(29) t12 -= bvpar(30) * BHPAR1 end In the case where c6 = 4, compare sum of the first two notes verses the last two notes. If the direction is different from the slope, then the slope should be zero. if c6 = 4 t2 = mf(1) + mf(2) t3 = mf(3) + mf(4) if t2 > t3 if slope > 0 goto GSB2 end end t2 = t2 - t3 * slope if t2 > 0 goto GSB2 end goto GSB3 GSB2: slope = 0 t3 = zstaff t8 = ypiv goto GCSI end GSB3: slope = BHPAR1 * slope of beam t12 = y-intercept of beam (times BHPAR1) t8 = vpar(6) / 7 if beamtype > 0 t8 = vpar(5) / 4 end t12 /= BHPAR1 if stem = DOWN t12 = 300 * vpar(1) - t12 + bthick - t8 t12 = 150 * vpar(2) - t12 + bthick - t8 slope = 0 - slope else t12 += t8 end passback slope, t12 return ┌──────────────────────────────────────────────────────────────┐ │P 33. display_array │ │ │ │ │ │ Purpose: Print out the current state of the ts array │ │ Used for debugging │ └──────────────────────────────────────────────────────────────┘ procedure display_array int g g = measnum - 1 if bit(2,pmode) = 1 and g >= debug_point Condition changed 01/01/06 if (bit(2,pmode) = 1 or debug_flag = 1) and g >= debug_point putc Set Array at procedure call: measure ~g putc Look? getc jtype if jtype = "y" perform display_ts end end return ┌──────────────────────────────────────────────────────────────┐ │P 34. rest_occupy_space (t1,t2) │ │ │ │ │ │ Purpose: For a given location on the staff line and │ │ a given type of rest, set the gr(.,.) and │ │ gl(.,.) arrays to reflect the placement │ │ of the rest in this spot │ │ │ │ Inputs: ntype = type of rest │ │ t1 = position on staff (0 = top line) │ │ (i.e.,STAFFLOC) │ │ t2 = staff number │ │ │ └──────────────────────────────────────────────────────────────┘ procedure rest_occupy_space (t1,t2) int t1,t2,t3,t4,t5,t6,t7,t8 getvalue t1,t2 t1 = 0 - t1 / vpar(1) + 23 c16 = t1 + vpar20 * 2 + 1 / vpar(2) - 20 t1 = 23 - c16 t5 = ntype << 1 - 1 t3 = int("1008060402020402030303"{t5,2}) t4 = int("0505050505030301000101"{t5,2}) if ntype > WHOLE t6 = hpar(87) * 4 / 3 else if ntype > QUARTER t6 = hpar(87) else if ntype > EIGHTH t6 = hpar(88) else t6 = EIGHTH - ntype * hpar(54) + hpar(88) end end end t6 += hpar(85) t7 = t1 - t4 if t7 < 1 t7 = 1 end t8 = t1 + t3 if t8 > 45 t8 = 45 end loop for t5 = t7 to t8 gr(t2,t5) = t6 gl(t2,t5) = 0 repeat return ┌───────────────────────────────────────────────────────────────────────┐ │P 35. place_accidental (t1,t2,t3,t4) │ │ │ │ │ │ Purpose: Determine the absolute x-location of an │ │ accidental, given gl(.,.) and the imputs: │ │ │ │ Inputs: t1 = staff number │ │ t2 = position on staff (23 = top line) │ │ t3 = accidental code │ │ t4 = note size (full size vs. cue size) │ │ │ │ Output: t4 = absolute x location │ │ t3 = SCORE P5 data: │ │ t3 & 0x00ff = P5 fractional position data │ │ t3 & 0x0f00 = P5 one's data │ │ t3 & 0xff0000 = left shift (dots) for natural │ │ │ └───────────────────────────────────────────────────────────────────────┘ procedure place_accidental (t1,t2,t3,t4) int t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,savet3,savet4,t14 getvalue t1, t2, t3, t4 t14 = t4 if t2 > 42 or t2 < 3 or t3 = 10 /* use old system t5 = t2 - int("221002200100001"{t3}) /* lower limit t6 = t2 + int("333003300200003"{t3}) /* upper limit t8 = 200 loop for t7 = t5 to t6 if t7 > 0 and t7 <= 45 if gl(t1,t7) < t8 t8 = gl(t1,t7) end end repeat t9 = hpar(t3) if t14 = CUESIZE t9 = t9 * 8 / 10 /* cue or grace size end t4 = t8 - t9 /* absolute x position loop for t7 = t5 to t6 if t7 > 0 and t7 <= 45 gl(t1,t7) = t4 /* new global left boundary end repeat passback t4 t10 = 0 if t3 = 6 or t3 = 7 t10 = 0 - t4 /* relative leftward position of CODE-9 natural In SCORE, the position of an ax is the right, not left boundary if t14 = CUESIZE t10 -= (hpar(1) * 8 / 10) else t10 -= hpar(1) end t3 -= 4 /* remove natural from code end t8 = 0 - t8 if t8 < 0 t8 = 0 end New 10/25/07 In SCORE, the shifting of an accidental to the left is coded as .25 units per accidental width. Dmuse units are in dots, so there needs to be a conversion. The formula would be something like this: 14 dots = 25 units t8 (in units) = t8 (in dots) * 25 / vpar(2) t8 = t8 * 25 / vpar(2) t3 = int("321......5....4"{t3}) /* converting form MUSEDATA code to SCORE code t3 = t3 << 8 t3 += (t10 << 16) t3 += t8 passback t3 return end hpar(1) = shift following accidental natural hpar(2) = shift following accidental sharp hpar(3) = shift following accidental flat hpar(6) = shift following accidental natural-sharp hpar(7) = shift following accidental natural-flat hpar(10) = shift following accidental double sharp hpar(15) = shift following accidental double flat (1) determine absolute x location if chr(t3) in [3,7,15] t5 = hpar(3) * 7 / 10 t6 = gl(t1,t2+3) + t5 loop for t7 = t2 - 1 to t2 + 2 if gl(t1,t7) < t6 t6 = gl(t1,t7) end repeat if t3 = 7 and gl(t1,t2-2) + hpar(3) < t6 t6 = gl(t1,t2-2) + hpar(3) end else if chr(t3) in [2,6] t5 = hpar(2) * 2 / 10 t6 = gl(t1,t2+3) + t5 loop for t7 = t2 - 1 to t2 + 2 if gl(t1,t7) < t6 t6 = gl(t1,t7) end repeat if t6 > gl(t1,t2-2) + t5 t6 = gl(t1,t2-2) + t5 end else t5 = hpar(3) * 6 / 10 t6 = gl(t1,t2+3) + t5 loop for t7 = t2 - 2 to t2 + 2 if gl(t1,t7) < t6 t6 = gl(t1,t7) end repeat end end t5 = hpar(t3) if t14 = CUESIZE t5 = t5 * 8 / 10 /* cue or grace size end t4 = t6 - t5 /* absolute x position passback t4 savet3 = t3 t10 = 0 if t3 = 6 or t3 = 7 t10 = 0 - t4 /* relative leftward position of CODE-9 natural In SCORE, the position of an ax is the right, not left boundary if t14 = CUESIZE t10 -= (hpar(1) * 8 / 10) else t10 -= hpar(1) end t3 -= 4 /* remove natural from code end t6 = 0 - t6 if t6 < 0 t6 = 0 end New 10/25/07 In SCORE, the shifting of an accidental to the left is coded as .25 units per accidental width. Dmuse units are in dots, so there needs to be a conversion. The formula would be something like this: 14 dots = 25 units t6 (in units) = t6 (in dots) * 25 / vpar(2) t6 = t6 * 25 / vpar(2) t3 = int("321......5....4"{t3}) /* converting from MUSEDATA code to SCORE code t3 = t3 << 8 t3 += (t10 << 16) t3 += t6 passback t3 t3 = savet3 (2) determine new values for gl(.,.) if chr(t3) in [1,6,7] loop for t7 = t2 - 1 to t2 + 3 gl(t1,t7) = t4 /* new global left boundary repeat gl(t1,t2-2) = hpar(1) / 2 + t4 else if chr(t3) in [3,15] loop for t7 = t2 - 1 to t2 + 3 gl(t1,t7) = t4 /* new global left boundary repeat else t5 = hpar(2) / 10 gl(t1,t2+3) = t4 + t5 loop for t7 = t2 - 1 to t2 + 2 gl(t1,t7) = t4 /* new global left boundary repeat gl(t1,t2-2) = t4 + t5 end end return ┌──────────────────────────────────────────────────────────────┐ │P 36. typeset_tuple (t1,t2,t3) │ │ │ │ Purpose: Typeset tuple companion to repeater │ │ │ │ Inputs: t1 = tuple number │ │ t2 = centered x-location to place tuple │ │ t3 = y-location to place tuple │ │ │ └──────────────────────────────────────────────────────────────┘ procedure typeset_tuple (t1,t2,t3) int t1,t2,t3 int savex,savey,savez getvalue t1,t2,t3 savex = x savey = y savez = z x = t2 y = t3 kscrdat = "" if t1 > 9 x -= hpar(104) z = t1 / 10 + 221 t1 = rem perform subj x += hpar(105) z = t1 + 221 perform subj else z = t1 + 221 perform subj end x = savex y = savey z = savez return #if AUTOSCR ┌────────────────────────────────────────────────────────────────┐ │P 37. build_note_kscrdat │ │ │ │ Purpose: build the kscrdat string for note heads │ │ │ │ Inputs: c3 = pointer into set array for this note │ │ y = vertical position of notehead on staff │ │ ntype = type of note (e.g. sixteenth) │ │ note_dur = duration of note (in divisions) │ │ divspq = divspq │ │ nodtype = NOTE, GR_NOTE, or CUE_NOTE │ │ │ │ Output: kscrdat string │ │ │ │ Operation: Compute full values for: P2 P4 P6 P7 P10 P12 │ │ Compute partial values for: P5 P9 │ │ Not computed here: P3 P8 │ │ │ └────────────────────────────────────────────────────────────────┘ procedure build_note_kscrdat int t1,t2,t3,t4 int staff,track,pri_staff,p21,p22,p4,p5,p61,p62,p71,p72,p8,p9,p10,p12 pri_staff = 0 track = ts(c3,TRACK_NUM) staff = ts(c3,STAFF_NUM) + 1 if track > 0 pri_staff = trackstave(opbarnum,track,3) end Compute values for P2 P4 P5 P6 P7 P8 P9 P10 P12 p12 = 0 if pri_staff > 0 if pri_staff = 1 and staff = 2 p12 = 2 end if pri_staff = 2 and staff = 1 p12 = 1 end p21 = pri_staff else p21 = staff end p22 = track p4 = (0 - y) / vpar(1) + 11 kscrdat = " | P2=" // chs(p21) // "." // chs(p22) // " P4=" // chs(p4) t1 = ts(c3,AX_DISP) if t1 = 0 kscrdat = kscrdat // " P5=0" else t2 = t1 & 0xff t3 = t1 & 0xff00 >> 8 kscrdat = kscrdat // " P5=" // chs(t3) // "." if t2 < 10 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(t2) t1 >>= 16 if t1 <> 0 kscrdat = kscrdat // "+Nat@" // chs(t1) // "<-" end end if ntype < 8 p61 = 0 else p61 = ntype - 7 end p62 = ts(c3,BASE_40) p62 = ts(c3,BASE_40) + pitch_mod /* New 11/27/09 kscrdat = kscrdat // " P6=" // chs(p61) // "." if p62 < 10 kscrdat = kscrdat // "0" end if p62 < 100 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(p62) if nodtype = NOTE or nodtype = CUE_NOTE p71 = 10000 * note_dur / divspq p71 = p71 / 10000 p72 = rem kscrdat = kscrdat // " P7=" // chs(p71) // "." if p72 < 10 kscrdat = kscrdat // "0" end if p72 < 100 kscrdat = kscrdat // "0" end if p72 < 1000 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(p72) else /* GR_NOTE kscrdat = kscrdat // " P7=-1.0000" /* needs further clarification kscrdat = kscrdat // " P7=65.00" end t1 = ts(c3,AUG_DOTS) if t1 > 0 t2 = t1 >> 24 if t2 = 0 t3 = t1 & 0xff t2 = t1 & 0xff00 >> 8 kscrdat = kscrdat // " P9=" // chs(t2) // "." if t3 < 10 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(t3) else kscrdat = kscrdat // " " // chs(t2) // "Dots@x+" t1 &= 0xffffff t1 /= INT10000 if rem > (INT10000 >> 1) t2 = INT10000 - rem ++t1 kscrdat = kscrdat // chs(t1) // "y-" // chs(t2) else kscrdat = kscrdat // chs(t1) // "y" // chs(rem) end end end t1 = ts(c3,NOTE_DISP) /* can be 100,0,-100 or large t2 = ts(c3,LOCAL_XOFF) if t2 > 0 /* set t2 to 100,0,or -100 t2 = 100 end if t2 < 0 t2 = -100 end if t2 + t1 <> 0 if t2 + t1 = 100 kscrdat = kscrdat // " P10=10" else if t2 + t1 = -100 kscrdat = kscrdat // " P10=20" else if t2 + t1 = 200 kscrdat = kscrdat // " P10=6" else if t2 + t1 = -200 kscrdat = kscrdat // " P10=-6" else t1 = t1 / INT10000 if rem > (INT10000 >> 1) t3 = INT10000 - rem ++t1 else t3 = rem end t3 = t3 * 300 / t1 /* 100 times too big t2 *= 3 /* 100 times too big t3 += t2 if t3 > 0 t3 = t3 / 100 t1 = rem kscrdat = kscrdat // " P10=" // chs(t3) // "." else t3 = 0 - t3 t3 = t3 / 100 t1 = rem kscrdat = kscrdat // " P10=-" // chs(t3) // "." end if t1 < 10 kscrdat = kscrdat // "0" end kscrdat = kscrdat // chs(t1) end end end end end kscrdat = kscrdat // " P12=" // chs(p12) return #endif ┌────────────────────────────────────────────────────────────────┐ │P 38. setarpeggio (New 01/13/06) │ │ │ │ Purpose: write object arpeggio │ │ │ │ Inputs: c1 = pointer into set array for arpeggio │ │ obx = horizontal position of arpeggio │ │ arpeg_top = top of arpeggio │ │ arpeg_bottom = bottom of arpeggio │ │ arpeg_flag = extra length to span grand staff │ │ ntype = ARPEGGIO │ │ passnum = pass number for this arpeggio │ │ inctype = increment type for next node │ │ with a new spn (used in putobj) │ │ │ └────────────────────────────────────────────────────────────────┘ procedure setarpeggio int t1,t2,t3,t4,t5,t6,t7,t8,t9 t3 = ts(c1,STAFF_NUM) * 1000 oby = arpeg_top * 2 - 1 * vpar(2) / 2 sobcnt = 0 x = obx y = oby t1 = arpeg_bottom * 2 - 1 * vpar(2) / 2 if arpeg_flag > 0 t1 += arpeg_flag end z = 120 /* music font for arpeggio perform subj t2 = t1 - vpar(4) loop while y <= t2 perform subj y += vpar(4) repeat y -= vpar(2) if y <= t2 perform subj end jtype = "G" jcode = EIGHTH out = "0" Duration attribute of arpeggio ++sobcnt sobl(sobcnt) = "A D 1 8" pcode = sobcnt oby += t3 putobjpar = 0 t4 = ts(c1,TSR_POINT) pcontrol = ors(tsr(t4){1}) /* 05/02/03 px = ors(tsr(t4){3}) << 8 py = ors(tsr(t4){4}) << 16 t1 = ors(tsr(t4){2}) << 24 putobjpar = t1 + px + py + pcontrol /* Note: order of data has been changed perform putobj oby -= t3 return ┌────────────────────────────────────────────────────────────────┐ │P 39. survay_file │ │ │ │ Purpose: Survay the entire file and make a map of the │ │ number of tracks in each measure and of their staff │ │ position; also determine divspm and divspq for each │ │ measure; also determine if and where there are any time │ │ gaps. │ │ │ │ │ └────────────────────────────────────────────────────────────────┘ procedure survay_file str line2.200 int i,j loop for i = 1 to MAX_MEAS loop for j = 1 to 9 trackstave(i,j,1) = 0 trackstave(i,j,2) = 0 trackstave(i,j,3) = 0 repeat repeat loop for i = 1 to 15000 timegaps(i,1) = 0 timegaps(i,2) = 0 timegaps(i,3) = 0 repeat scnt = 11 /* the first record better be a $ record or else! GET_DOLLAR: tget [X,scnt] line ++scnt if line{1} = "P" or line{1} = "@" goto GET_DOLLAR end line = line // pad(100) if line{1} <> "$" putc Program error, or file error: expecting initial $ record. putc putc This is most likely a file error. The most common error putc is a misrepresentation of the group membership structure putc in lines 11ff. of the data file. putc stop end if line con "C2:" staves = 2 else staves = 1 end if line con "Q:" divspq = int(line{mpt+2..}) else putc Program error, or file error: divspq not specified. putc Record ~(scnt+12) ~line stop end MMPR: ++barnum measuremap(barnum,1) = 0 measuremap(barnum,2) = 0 measuremap(barnum,3) = 0 measuremap(barnum,4) = 0 measuremap(barnum,5) = divspq durflag = 0 divpoint = 0 loop for i = 1 to 9 trackdivpnt(i) = 0 repeat track = 1 staff = 1 if track_flag = 1 loop for i = 1 to 9 trackstave(barnum,i,3) = track_assign(i) repeat end MPR: tget [X,scnt] line ++scnt line = line // pad(80) if line{8} <> " " d = int(line{6,3}) /* possible duration end g = int(line{9,4}) /* possible measure number if line{1} = "$" if line con "Q:" divspq = int(line{mpt+2..}) if durflag = 0 measuremap(barnum,5) = divspq /* divspq can be set before durations in a meas. end end sugg_flg = 0 goto MPR end if line{1} = "P" goto MPR end if line{1} = "@" if line con "track assignment:" line2 = line{mpt+17..} line2 = line2 // " *" loop while line2 con "(" a1 = int(line2{mpt+1..}) a2 = int(line2{sub+1..}) line2 = line2{sub+1..} trackstave(barnum,a1,3) = a2 /* re-assign track a1 to staff a2 track_assign(a1) = a2 /* and make change in assignment array repeat end if line con "instrument number:" line2 = line{mpt+18..} line2 = line2 // " *" instrument_number = int(line2) end if line con "transposition:" line2 = line{mpt+14..} line2 = line2 // " *" transposition = int(line2) end goto MPR end if "ABCDEFGri" con line{1} /* note or rest durflag = 1 if line{8} = " " putc File error: expecting a duration for this record putc Record ~(scnt+12) ~line stop end if "123456789" con line{15} track = mpt else track = 1 end if "123456789" con line{24} staff = mpt else staff = 1 end if trackdivpnt(track) <> divpoint /* time gap exists here if trackdivpnt(track) > divpoint putc File format error: track events out of time order putc Record ~(scnt+12) ~line stop end ++tgpnt if measuremap(barnum,2) = 0 measuremap(barnum,3) = tgpnt end ++measuremap(barnum,2) timegaps(tgpnt,1) = track timegaps(tgpnt,2) = trackdivpnt(track) timegaps(tgpnt,3) = divpoint - trackdivpnt(track) trackdivpnt(track) = divpoint end trackdivpnt(track) += d divpoint += d trackstave(barnum,track,staff) += d goto MPR end if line{1} = " " /* chord? if "123456789" con line{15} if track = mpt /* true chord goto MPR end track = mpt else goto MPR /* true chord end if "123456789" con line{24} staff = mpt end if trackdivpnt(track) <> divpoint - d /* time gap exists here if trackdivpnt(track) > divpoint - d putc File format error: track events out of time order putc Record ~(scnt+12) ~line stop end ++tgpnt timegaps(tgpnt,1) = track timegaps(tgpnt,2) = trackdivpnt(track) timegaps(tgpnt,3) = divpoint - d - trackdivpnt(track) trackdivpnt(track) = divpoint - d end trackdivpnt(track) += d trackstave(barnum,track,staff) += d goto MPR end if line{1} = "c" putc Warning: cue notes may not be handled properly in this program goto MPR end if line{1} = "b" /* backup command divpoint -= d goto MPR end if line{1} = "m" loop for i = 1 to 9 if trackdivpnt(i) > divpoint putc File error: time pointer not fully advanced at end of measure putc Record ~(scnt+12) ~line stop end if trackdivpnt(i) > 0 and trackdivpnt(i) < divpoint /* time gap exists here ++tgpnt if measuremap(barnum,2) = 0 measuremap(barnum,3) = tgpnt end ++measuremap(barnum,2) timegaps(tgpnt,1) = i timegaps(tgpnt,2) = trackdivpnt(i) timegaps(tgpnt,3) = divpoint - trackdivpnt(i) trackdivpnt(i) = divpoint end repeat measuremap(barnum,4) = divpoint loop for i = 1 to 9 if trackstave(barnum,i,1) > 0 or trackstave(barnum,i,2) > 0 ++measuremap(barnum,1) end repeat goto MMPR end if line{1} <> "/" goto MPR end --barnum Check for time gaps loop for i = 1 to barnum if measuremap(i,2) > 0 i = MAX_MEAS * 10 end repeat if i > MAX_MEAS * 9 putc putc A survay of this stage2 file detected some time gaps, which may putc be perfectly legal in terms of the MUSEDATA stage2 format, but putc which introduce added complexity in music searching and in score putc conversion. These applications require that the time gaps be putc filled before proceeding any further with the i-file compilation putc process. The report below shows the bar numbers where the time putc gaps occur. Be sure to use the correct track number when you putc add irests (the most common solution to filling time gaps). putc You will probably also need to make use of the backup command putc (back # record) to keep the division pointer in the right place. putc putc ╔═══════════════╗ putc ║ R E P O R T ║ putc ╚═══════════════╝ putc putc This movement has ~barnum bars. Note: Some of these may putc be double bars or heavy bars within normal bars, and may not putc have bar numbers. In this situation, the bar number column putc below will not correspond to actual meausure numbers. putc putc Active Time putc Bar number │ Tracks Gaps divspm divspq putc ─────────────┼───────────────────────────────────── loop for i = 1 to barnum putc .w6 ~i │~measuremap(i,1) ~measuremap(i,2) ~measuremap(i,4) ~measuremap(i,5) repeat putc ─┼─ putc putc Detail on Time Gaps putc ═══════════════════════ putc putc Gap starts Lasts # putc Bar number │ Track at div # divisions putc ─────────────┼───────────────────────────────────── loop for i = 1 to barnum k = measuremap(i,3) - 1 loop for j = 1 to measuremap(i,2) ++k putc .w6 ~i │~timegaps(k,1) ~timegaps(k,2) ~timegaps(k,3) repeat repeat putc ─────────────┼───────────────────────────────────── putc putc ┌──────────────────┐ putc │ Program Halted │ putc └──────────────────┘ putc stop end if staves = 2 and track_flag = 0 putc putc This stage2 file displays music on the grand staff. This putc means that it is possible for tracks to jump between staves. putc SCORE requires that every musical track be assigned to a putc "primary" staff, on a measure-by-measure basis. Most tracks putc will live their entire lives on the top or the bottom stave, putc but some will jump around. In many of these cases, it is putc still possible that the "primary" staff will remain the same putc throughout the movement. However, there are some cases putc where the primary staff really does change. Where this putc happens is not always easy to determine. There are many putc factors to consider, such as voice range, what else is on putc the staff, and the presence of ties. Perhaps some day putc autoscr will be able to make these decisions automatically, putc but for the time being, we must ask you, the user, to help putc us with this. putc putc The report below shows the track activity for the first 6 tracks putc on a bar-by-bar basis. Only those tracks that appear on both putc staves are in question. putc putc Type "Enter" getc putc ╔═══════════════╗ putc ║ R E P O R T ║ putc ╚═══════════════╝ putc putc T R A C K A C T I V I T Y putc ════════════════════════════════ putc putc Track-1 Track-2 Track-3 Track-4 Track-5 Track-6 putc Bar │ S1 S2 S1 S2 S1 S2 S1 S2 S1 S2 S1 S2 putc ───────┼──────────────────────────────────────────────────────────────────── loop for i = 1 to barnum putc .w3 ~i │ ~trackstave(i,1,1) ~trackstave(i,1,2) │ ... putc .w3 ~trackstave(i,2,1) ~trackstave(i,2,2) │ ... putc .w3 ~trackstave(i,3,1) ~trackstave(i,3,2) │ ... putc .w3 ~trackstave(i,4,1) ~trackstave(i,4,2) │ ... putc .w3 ~trackstave(i,5,1) ~trackstave(i,5,2) │ ... putc .w3 ~trackstave(i,6,1) ~trackstave(i,6,2) │ repeat putc ─┼──────────────────────────────────────────────────────────────────── putc Type "Enter" getc putc loop for i = 1 to 9 h = 0 k = 0 loop for j = 1 to barnum if trackstave(j,i,1) > 0 ++h end if trackstave(j,i,2) > 0 ++k end repeat if h > 0 and k = 0 putc Track ~i will be assigned to stave 1 loop for j = 1 to barnum trackstave(j,i,3) = 1 repeat end if h = 0 and k > 0 putc Track ~i will be assigned to stave 2 loop for j = 1 to barnum trackstave(j,i,3) = 2 repeat end if h > 0 and k > 0 AQQQ: a3 = 1 putc We need help with Track ~i putc Which staff should be primary staff at the start of the piece? (1 or 2) getc a1 putc Track ~i will start with staff ~a1 as primary AQQ: a2 = 3 - a1 putc putc At what bar number should track ~i change its primary staff to staff ~a2 ? putc If no change, enter 1000. (or any number greater than total number of meas + 1) getc a4 if a4 > barnum + 1 a4 = barnum + 1 end loop for j = a3 to a4 - 1 trackstave(j,i,3) = a1 repeat if a4 < barnum + 1 a1 = a2 a3 = a4 goto AQQ end putc You have designated the following pattern for the primary staves of track ~i putc putc Track-~i putc Bar │ S1 S2 putc ───────┼───────────── loop for j = 1 to barnum if trackstave(j,i,3) = 1 putc .w3 ~j │ ~trackstave(j,i,1) ~trackstave(j,i,2) else putc .w3 ~j │ ~trackstave(j,i,1) ~trackstave(j,i,2) end repeat putc ─┼───────────── putc putc Type Enter to accept. A non-empty line will allow you to enter the data again. getc line line = trm(line) if line <> "" goto AQQQ end end repeat end Now check to see that every active track is assigned to a stave if staves = 2 a3 = 0 loop for a1 = 1 to barnum loop for a2 = 1 to 9 if trackstave(a1,a2,1) + trackstave(a1,a2,2) > 0 if trackstave(a1,a2,3) = 0 if a3 = 1 putc There are some measures where an active track is not assigned to a staff putc The problem can be corrected by either: putc (1) adding @ SCORECON track assignment records at the putc measures in question, or putc (2) deleting all @ SCORECON track assignment records from putc the stage2 file putc end a3 = 1 putc Track ~a2 in measure ~a1 is unassigned end end repeat repeat if a3 = 1 putc putc Program Halted putc stop end end To re-cap at this point, we now have gathered the following information to help us develop the parameters necessary to convert stage2 data to Score data: 1. The total number of barlines in this movement is barnum 2. number of staves for this stage2 file is staves 3. For each measure, we know a) the number of active tracks in this measure is measuremap(.,1) b) there are no time gaps c) number of divisions in this measure is measuremap(.,4) d) governing divspq for this measure is measuremap(.,5) e) if staves = 2, the primary staff for each track is trackstave(.,.,3) f) a track is active if trackstave(.,.,1) + trackstave(.,.,2) > 0 g) a track spans both staves if trackstave(.,.,1) > 0 and trackstave(.,.,2) > 0 return ┌──────────────────────────────────────────────────────────────────────────────┐ │P. XXX check_for_lib (slib,nlib │ │ │ │ Operation: This procedure looks into the directory "slib" for the │ │ sub-directory "nlib". │ │ │ │ if nlib does not appear in the sub-diretory, │ │ it is created as a sub-directory │ │ else │ │ if nlib does appear in the sub-diretory, and │ │ if it appears as a FILE, │ │ an error message is printed and a stop command issued. │ │ else │ │ the procedure returns with no action taken. │ │ end │ │ end │ │ end │ │ │ │ Inputs: slib = directory to look into │ │ nlib = sub-directory to look for, and possibly create │ │ │ │ Possible Outcomes: │ │ nlib is there, no action │ │ nlib is not there, and is created │ │ nlib is there, but as a FILE. Error and stop │ └──────────────────────────────────────────────────────────────────────────────┘ procedure check_for_lib (slib,nlib) str slib.200,nlib.80 str fname.200 getvalue slib,nlib nlib = trm(nlib) open [7,1] slib loop getf [7] line fname = line{33..} fname = trm(fname) if fname = nlib if line{1,5} = "<dir>" /* this is a directory, not a file close [7] return else putc ~nlib already exists as a FILE and cannot be created as a directory putc For purposes of this program, this is unexpected and must be considered putc an ERROR. putc Program Halted putc stop end end repeat eof7: close [7] line = slib // "/" // nlib createdir line return run Extra Lines for Debugging perform display_array /* DEBUG if measnum - 1 >= 291 examine end