Commit 87f67c8f authored by Chris Wraight's avatar Chris Wraight Committed by ROOL
Browse files

Improvements to tie handling

-Ties can be now be over or under the note.
-Only notes in the current or next bar are checked for being tied to.
-The tie sprite is scaled to match the gap between notes.
-Ties can no longer be attached to rests.
-Deleting the second note also deletes the tie.

Version 2.14. Tagged as 'Maestro-2_14'
parent e5b5e114
No preview for this file type
No preview for this file type
No preview for this file type
......@@ -173,6 +173,7 @@ AH17:key signature
AH18:\Sopen the key signatures menu.
AH19:time signature
AH20:\Sopen the time signatures menu.
AH23:tie
B0:bar line
B1:double bar line
......
/* (2.13)
/* (2.14)
*
* This file is automatically maintained by srccommit, do not edit manually.
*
*/
#define Module_MajorVersion_CMHG 2.13
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 01 Jun 2019
#define Module_MajorVersion_CMHG 2.14
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 04 Nov 2020
#define Module_MajorVersion "2.13"
#define Module_Version 213
#define Module_MajorVersion "2.14"
#define Module_Version 214
#define Module_MinorVersion ""
#define Module_Date "01 Jun 2019"
#define Module_Date "04 Nov 2020"
#define Module_ApplicationDate "01-Jun-19"
#define Module_ApplicationDate "04-Nov-20"
#define Module_ComponentName "Maestro"
#define Module_FullVersion "2.13"
#define Module_HelpVersion "2.13 (01 Jun 2019)"
#define Module_LibraryVersionInfo "2:13"
#define Module_FullVersion "2.14"
#define Module_HelpVersion "2.14 (04 Nov 2020)"
#define Module_LibraryVersionInfo "2:14"
......@@ -329,7 +329,7 @@ CASE window% OF
ENDIF
WHEN SharpsPane_h%:
CASE icon% OF
WHEN 2,3,4,5,6,7,8,9,10,11,12,17,19:
WHEN 2,3,4,5,6,7,8,9,10,11,12,17,19,23:
text$=FNmessage_lookup(Messages_h%,"AH"+STR$icon%)
text$=FNmessage_lookupN(Messages_h%,"SelectObject",text$,"","","")
WHEN 14,16,18,20:
......@@ -1544,9 +1544,11 @@ BPUT#FILE%,6
BPUT#FILE%,Tempo%
ENDPROC
DEF PROCsprite(s%,X%,Y%) : REM plot sprite S%(s%) at X%,Y%
SYS "OS_SpriteOp", SprPlot%, SprBlk%, S%(s%), X%-x%(s%),Y%-y%(s%), 8, factors%, pixtrans%
REM overwrite screen colour, but using sprite mask
DEF PROCsprite(s%,sx%,sy%)
REM Plot sprite S%(s%) at sx%,sy%
sx%=sx%-x%(s%)
sy%=sy%-y%(s%)
SYS "OS_SpriteOp",SprPlot%,SprBlk%,S%(s%),sx%,sy%,8,factors%,pixtrans%
ENDPROC
DEF PROCfloat (s%,sx%,sy%)
......@@ -1646,15 +1648,15 @@ ENDPROC
REM PROCEDURE: note_type(Channel C%, Type T%)
DEF PROCnote_type(C%,T%)
N%(C%)?1=N%(C%)?1AND&1F ORT%<<5
N%(C%)?1=N%(C%)?1 AND &1F OR T%<<5
ENDPROC
DEF PROCnote_dots(C%,D%)
N%(C%)?1=N%(C%)?1AND&E7 ORD%<<3
N%(C%)?1=N%(C%)?1 AND &E7 OR D%<<3
ENDPROC
DEF PROCnote_accidental(C%,A%)
N%(C%)?1=N%(C%)?1AND&F8 ORA%
N%(C%)?1=N%(C%)?1 AND &F8 OR A%
ENDPROC
DEF PROCnote_line (c%,l%,type%)
......@@ -1672,12 +1674,17 @@ ELSE
ENDIF
ENDPROC
DEF PROCnote_tie(C%,T%)
?N%(C%)=?N%(C%)AND&FB OR(T%<>0)AND4
ENDPROC
DEF PROCnote_join(C%,J%)
?N%(C%)=?N%(C%)AND&FD OR(J%<>0)AND2
DEF PROCnote_tie (c%,type%)
REM Add/remove a tie from a note
CASE type% OF
WHEN 0:REM Remove tie
?N%(c%)=?N%(c%) AND NOT (2<<1)
WHEN 1:REM Add an over-note tie
?N%(c%)=?N%(c%) AND NOT (1<<1)
?N%(c%)=?N%(c%) OR (1<<2)
WHEN 2:REM Add an under-note tie
?N%(c%)=?N%(c%) OR (3<<1)
ENDCASE
ENDPROC
DEF PROCnote_stem(C%,D%)
......@@ -2022,6 +2029,36 @@ IF (H% AND &18) THEN
ENDIF
ENDPROC
DEF FNbound_tie (pos%)
REM Scans ahead to check that a valid second note exists
REM to tie to. If the scan passes more than one barline, or
REM hits the end of the score, return 0. Otherwise, return
REM the x position of the gate that contains the note.
LOCAL gp%,px%,bar%,sline%,xpos%,bline%
REM Get first note's staveline
sline%=(?N%(C%) AND &F8)>>3
REM Store current score and bar pointers
PROCsavp
bar%=BAR%
REM Scan for a note on the same channel and staveline
WHILE GP%<GATE%+1 AND bline%<2
PROCskip_gate
pos%+=1
REM Check for barline
IF GP%?0=0 AND GP%?1=&20 THEN bline%+=1
REM Check for note
IF (?GP% AND (1<<C%)) AND bline%<2 THEN
IF ((?N%(C%) AND &F8)>>3)=sline% THEN
xpos%=pos%
GP%=GATE%+1
ENDIF
ENDIF
ENDWHILE
REM Restore score and bar pointers
PROCrstp
BAR%=bar%
=xpos%
DEF PROCposition_staves
LOCAL y%,s%
Score_Height%=(PERC%+1+3*(STAVE%+1)+1)*Stave_Height%
......@@ -2081,6 +2118,7 @@ CASE window% OF
IF icon%=18 THEN CurrentMenu%=FNwimp_popup(SharpsPane_h%,KeyMenu%,icon%)
IF icon%=19 THEN PROCattach(time%,%1) :REM time signature
IF icon%=20 THEN PROCtimesig_init(icon%)
IF icon%=23 THEN PROCattach(tie%+1,%1101000)
ENDIF
WHEN ScoreWind_h%:
IF button%=4 THEN
......@@ -2160,7 +2198,7 @@ Block%!0=ScoreWind_h%
SYS "Wimp_GetWindowState",,Block%
bar%=FNFindBar(Block%!20)
IF bar%<1 THEN bar%=1
PROCwimp_seticontext(Bar_h%,0,STR$bar%)
PROCwimp_seticontext(Bar_h%,0,STR$(bar%))
PROCwimp_seticontext(Bar_h%,2,STR$(NBars%-1))
ENDPROC
......@@ -2239,27 +2277,35 @@ REM PROCEDURE: draw_score(Based X%,Y%, PX bounds A%,B%)
REM
REM DESCRIPTION: Write current section of music score that appears between A%
REM and B%
:
DEF PROCdraw_score(X%,Y%,A%,B%)
LOCALPX%
BAR%=0
REM must be subtle about redrawing last note (or other item) of score to prevent picking up rubbish data after end
LOCAL PX%
REM Must be subtle about redrawing last note (or other item) of
REM score to prevent picking up rubbish data after end
IF A%>PX%(PXn%(NBars%)) THEN
IF A%>PX%(PXn%(NBars%))+2*Pgap% ENDPROC ELSE A%=PX%(PXn%(NBars%))
ENDIF
REM ensure bar numbers are always completely updated; but don't lose 1st-note draw
ENDIF
REM Ensure bar numbers are always completely updated,
REM but don't lose first note draw
BAR%=0
IF NBars%>2 THEN
WHILE PX%(PXn%(BAR%+2))<A% AND BAR%<=NBars%-1
BAR%+=1
ENDWHILE :REM get to drawstart quickly
IF BAR%>NBars% ENDPROC
PROCGetBarInfo(BAR%)
IF GP%>=GATE% ENDPROC
WHILEPX%(PX%+3)<A%ANDPX%<EX%
PROCskip_gate
ENDWHILE:REM Skip music until A%
REM Move to the first bar to draw from
WHILE PX%(PXn%(BAR%+2))<A% AND BAR%<=NBars%-1
BAR%+=1
ENDWHILE
IF BAR%>NBars% THEN ENDPROC
REM Move back two bars to ensure any note ties are picked up,
REM then get bar pointers and update clipping window
IF BAR%>2 THEN BAR%-=2
PROCGetBarInfo(BAR%)
IF PX%<A% THEN A%=PX%
IF GP%>=GATE% THEN ENDPROC
REM Skip music until A%
WHILE PX%(PX%+3)<A% AND PX%<EX%
PROCskip_gate
ENDWHILE
ELSE
PROCstart_music
PROCstart_music
ENDIF
WHILEPX%(PX%)<=B%ANDGP%<GATE%
IF?GP% PROCdraw_notes(?GP%):GP%+=1 ELSEPROCdraw_attribute(GP%?1):GP%+=2:IF PLAYING% PROCCheckQ
......@@ -2307,17 +2353,36 @@ REPEAT
ELSE
REM Draw rest
s%=rest% OR NC1%>>5
l%=(NC1% AND &7)
IF l%<>0 THEN l%-=4
y%+=(Li%*2)*l%
y%+=(Li%*2)*FNrest_getline(NC1%)
PROCsprite(s%,x%,y%)
ENDIF
IF NC1% AND 24 PROCsprite(dot%+(NC1%>>3AND3),x%+x%(s%),y%)
IF NC0% AND 4 PROCsprite(tie%,x%,y%)
REM Draw a tie
IF (NC0% AND &4) THEN PROCdraw_tie(tie%+((NC0% AND &2)>>1),x%,y%)
N%(C%)+=2:REM Pull from note queue
UNTIL(2<<C%)>G%:REM Until no more notes (1 bits)
ENDPROC
DEF PROCdraw_tie (s%,sx%,sy%)
REM Plot a scaled tie sprite
LOCAL span%,swidth%
LOCAL oldx0%,oldx1%,scale,scale%
sx%=sx%-x%(s%)
sy%=sy%-y%(s%)
swidth%=x%(s%)+X%(s%)
span%=X%+PX%(FNbound_tie(PX%))-sx%+Pgap%
oldx0%=factors%!0
oldx1%=factors%!8
scale=span%/swidth%
IF scale<0.6 THEN scale=0.6
scale%=scale*10
factors%!0=oldx0%*scale%
factors%!8=oldx1%*10
SYS "OS_SpriteOp",SprPlot%,SprBlk%,S%(s%),sx%,sy%,8,factors%,pixtrans%
factors%!0=oldx0%
factors%!8=oldx1%
ENDPROC
DEF PROCdraw_attribute(A%)
LOCALx%,N%
N%=TRUE:REPEATN%-=TRUE:UNTILA%AND%1<<N%
......@@ -2380,16 +2445,16 @@ DEF PROCskip_gate
IF?GP% PROCskip_notes(?GP%):GP%+=1 ELSEPROCskip_attribute(GP%?1):GP%+=2
ENDPROC
DEF PROCskip_notes(G%)
DEF PROCskip_notes(g%)
LOCAL c%
PX%+=1
LOCALC%
C%=-1
c%=-1
REPEAT
REPEAT
C%+=1
UNTILG%AND%1<<C%
N%(C%)+=2
UNTIL(2<<C%)>G%
c%+=1
UNTIL (g% AND %1<<c%)
N%(c%)+=2
UNTIL (2<<c%)>g%
ENDPROC
DEF PROCskip_attribute(A%)
......@@ -2547,6 +2612,13 @@ IF X%=PX%(PX%+1) THEN
REM Only notes delete notes/rests delete rests
IF ((?N%(C%) AND &F8) AND type%=note%) OR ((?N%(C%) AND &F8)=0 AND type%=rest%) THEN
PROCdelete_note(C%)
REM Check if previous Note has a tie; if so, remove it
IF N%(C%)>MUSIC%(C%) THEN
N%(C%)-=2
IF (?N%(C%) AND &4) THEN PROCnote_tie(C%,0)
N%(C%)+=2
ENDIF
REM If no Notes left in chord, delete the Gate
IF ?GP% THEN
PROCupdate_note(S%,s%,X%,Y%)
ELSE
......@@ -2556,8 +2628,8 @@ IF X%=PX%(PX%+1) THEN
PROCdelete_gate(2)
ENDWHILE
ENDIF
PROCrescore(PX%)
ENDIF
PROCrescore(0)
ENDIF
ENDIF
ELSE
......@@ -2600,17 +2672,34 @@ UNTIL conflict% OR c%<0
=c%-(conflict%<>0)
DEF PROCput_tie
IF?N%(C%)AND4 THEN
PROCnote_tie(C%,FALSE)
PROCscore_update(X%+24,Y%+12,X%+70,Y%+24)
LOCAL c%,tx%
IF (?N%(C%) AND &4) THEN
REM Remove a tie from the note and redraw
PROCnote_tie(C%,0)
tx%=FNbound_tie(SCRIBE%(posx%)+1)
PROCscore_update(X%,Y%-26,X%+PX%(tx%),Y%+28)
ELSE
LOCALI%
PROCnote_tie(C%,TRUE)
PROCskip_notes(?GP%):GP%+=1
PROCarrange_stave(S%)
GP%=SCRIBE%(sgp%)
FORI%=0TO7:N%(I%)=SCRIBE%(I%):NEXT
IFN%(C%)+2>=FINE%(C%)OR(?N%(C%)EORN%(C%)?2)AND&F8 PROCnote_tie(C%,FALSE) ELSEPROCscore_update(X%+24,Y%+12,X%+70,Y%+24)
REM Check that first note isn't a rest
IF (?N%(C%) AND &F8)=0 THEN ENDPROC
REM Place a tie on the first note
PROCnote_tie(C%,SCRIBE%(sprite%)-(tie%-1))
REM Arrange channel distribution on the stave so that the next note
REM appearing on the same stave line (if present) is also the next
REM note in the Note queue for that channel
PROCskip_notes(?GP%):GP%+=1
PROCarrange_stave(S%)
REM Check that there's a second note on the same staveline to tie to.
REM If there is, mark the area to redraw; if not, remove the tie.
GP%=SCRIBE%(sgp%)
FOR c%=0 TO 7
N%(c%)=SCRIBE%(c%)
NEXT
tx%=FNbound_tie(SCRIBE%(posx%)+1)
IF tx% THEN
PROCscore_update(X%,Y%-26,X%+PX%(tx%)+70,Y%+28)
ELSE
PROCnote_tie(C%,0)
ENDIF
ENDIF
ENDPROC
......@@ -2722,7 +2811,6 @@ ENDPROC
DEF PROCupdate_note(S%,N%,X%,Y%)
LOCALlx0%,lx1%,ly0%,ly1%
PROCbound_note(N%):REM Get minimum bounding rectangle of note
IFN%AND4 lx1%=X%(tie%):IFY%(tie%)>ly1% ly1%=Y%(tie%):REM Tie sets suffix and may be higher (Tie bounds only apply to updating)
IFABS(Y%-Y_STAVE%(S%))>Li%*5 THEN
IFx%(dot%)>lx0% lx0%=x%(dot%)
IFX%(dot%)>lx1% lx1%=X%(dot%):REM Extend to ledger extent
......@@ -2850,8 +2938,8 @@ IF (V% AND &7) THEN
T%=-V%<<1 AND &6
REM Repeat until distance increases or no more positions
REPEAT
REM Save previous distance, pointers etc
PROCsavp
REM Save score pointers and distance
PROCsavp:d%=D%
REM Move to next bar PX%
REPEAT
PROCskip_gate
......@@ -2881,8 +2969,8 @@ ELSE
X%-=X%(2)>>1
REM Repeat until distance increases or no more notes
REPEAT
REM Save previous distance, pointers etc
PROCsavp
REM Save score pointers and distance
PROCsavp:d%=D%
REM Move to next symbol
PROCskip_gate
REM Skip any attribute types
......@@ -2927,7 +3015,7 @@ C%=-1 :REM Initially no channel
L%=0 :REM Initially centre line
res%=1 :REM Resolution setting for Rest placement
IF (V% AND &40) AND ?GP%>0 THEN
REM Set y position of accidentals, dots, etc
REM Set y position of Accidentals, Dots and Ties
REM Find nearest symbol at gate
LOCAL G%,c%:REM Gate mask copy, Previous channel counter
c%=C%
......@@ -2943,7 +3031,7 @@ IF (V% AND &40) AND ?GP%>0 THEN
D%=ABS(D%-Li%*((?N%(C%)>>3)-16))
ELSE
REM Rest
D%=ABS(D%)
D%=ABS(D%-Li%*FNrest_getline(N%(C%)?1))
ENDIF
IF D%<d% THEN d%=D%:c%=C%
UNTIL (2<<C%)>G%
......@@ -2954,7 +3042,7 @@ IF (V% AND &40) AND ?GP%>0 THEN
L%=(?N%(C%)>>3)-16
ELSE
REM Rest
L%=(N%(C%)?1 AND &7)-4
L%=FNrest_getline(N%(C%)?1)
res%=2
ENDIF
ELSE
......@@ -3005,9 +3093,14 @@ REM Set Y% to centre line of stave, +/- offset, * resolution
Y%=Y_STAVE%(S%)+L%*(Li%*res%)
ENDPROC
DEF FNrest_getline (n%)
LOCAL line%
line%=(n% AND &7)
IF line%>0 THEN line%-=4
=line%
DEF PROCsavp
n%()=N%()
d%=D%
px%=PX%
gp%=GP%
clef%()=CLEF%()
......@@ -3453,7 +3546,7 @@ DATA Natural,8,6,7,12,Natural,8,6,7,12,Sharp,10,6,9,13,Flat,8,3,8,11
DATA Sharp2,9,2,10,5,Flat2,14,3,16,11,NSharp,17,6,17,12,NFlat,15,6,16,14
DATA Treble,0,14,23,31,Alto,0,8,23,17,Alto,0,4,23,17,Bass,0,5,24,14
DATA ldg5,2,28,16,17,ldg4,2,24,16,13,ldg3,2,20,16,9,ldg2,2,16,16,5,ldg1,2,12,16,1
DATA Dot1,-14,1,4,2,Dot2,-14,1,9,2,Dot3,-14,1,14,2,Tie,-12,-3,20,4,Tie,-12,-3,20,4
DATA Dot1,-14,1,4,2,Dot2,-14,1,9,2,Dot3,-14,1,14,2,Tie,-8,-3,20,4,Tie2,-8,7,20,4
DATA ldg1,2,-12,16,1,ldg2,2,-12,16,5,ldg3,2,-12,16,9,ldg4,2,-12,16,13,ldg5,2,-12,16,17
DATA Bar,-1,8,4,16,DBar,-1,8,6,16,Bar,-2,8,1,16,Bar,-2,8,1,16
DATA Time,1,9,14,16,Key,0,8,9,17
......@@ -4330,16 +4423,16 @@ REM ENDIF
PROCprint_sprite(s%,xs+Pgap%, y%, note_factors%)
checkstagger% = FALSE
IF NC1% AND 24 PROCprint_sprite(dot%+(NC1%>>3 AND 3), xs + x%(s%) + Pgap%, y%, note_factors%)
IF NC0% AND 4 PROCprint_sprite(tie%, xs + Pgap%, y%, note_factors%)
IF (NC0% AND &4) THEN PROCprint_tie(xs,y%)
ELSE
PROCprint_sprite(s%, xs, y%, note_factors%)
IF NC1% AND 24 PROCprint_sprite(dot%+(NC1%>>3 AND 3), xs + x%(s%), y%, note_factors%)
IF NC0% AND 4 PROCprint_sprite(tie%, xs, y%, note_factors%)
IF (NC0% AND &4) THEN PROCprint_tie(xs,y%)
ENDIF
ELSE
PROCprint_sprite(s%, xs, y%, note_factors%)
IF NC1% AND 24 PROCprint_sprite(dot%+(NC1%>>3 AND 3), xs + x%(s%), y%, note_factors%)
IF NC0% AND 4 PROCprint_sprite(tie%, xs, y%, note_factors%)
IF (NC0% AND &4) THEN PROCprint_tie(xs,y%)
checkstagger%=TRUE
ENDIF
lasty% = y%
......@@ -4491,6 +4584,31 @@ FOR s%=0 TO STAVE%+PERC%
NEXT
ENDPROC
DEF PROCprint_tie (sx%,sy%)
LOCAL s%,g%,span%,oldx%
IF (NC0% AND &2) THEN s%=tie%+1 ELSE s%=tie%
sx%=sx%-(x%(s%))
sy%=sy%-y%(s%)
g%=gp%+1
span%=1
WHILE g%<=GATE%
IF ?g% THEN
IF ?g% AND (1<<C%) THEN
g%=GATE%+1
ELSE
span%+=1
g%+=1
ENDIF
ELSE
g%+=2
ENDIF
ENDWHILE
oldx%=factors%!0
factors%!0=span%
SYS "OS_SpriteOp",SprPlot%,SprBlk%,S%(s%),sx%,sy%,8,factors%,pixtrans%
factors%!0=oldx%
ENDPROC
DEF PROCprint_sprite(s%, X%, Y%, scale_factors%) : REM plot sprite S%(s%) at X%,Y%
LOCAL spr_y, scaled_y, y_add, x_add
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment