╔═══════════════════════╗ ║ 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 │