--Author: John Maxwell --last modified: December 18, 1981 8:51 AM DIRECTORY Beam USING [Remove], Chord USING [RemoveNote], Graphics USING [MoveTo, DrawRectangle, SetTexture], InlineDefs USING [LowHalf], MusicDefs, Note USING [default, DrawHead, DrawTie, Duration, GetBackTie, FindChord, Width], Piece USING [NearestSync], Real USING [Fix], Score USING [GetAccidental, ShowPitch], Sheet USING [FindLine, Height, Map, MapNote], Sync USING [RemoveNote], Utility USING [DrawChar, DrawCubic, DrawLine, FreeNote, FreeSync]; NoteImpl: PROGRAM IMPORTS Beam, Chord, Graphics, InlineDefs, MusicDefs, Note, Piece, Real, Score, Sheet, Sync, Utility EXPORTS Note = BEGIN OPEN Graphics, MusicDefs, Note, Utility; Error:SIGNAL; --**************************************************************************** --note procedures --**************************************************************************** Delete:PUBLIC PROCEDURE[n:NotePTR,free:BOOLEAN] = BEGIN s:SyncPTR = n.sync; c:ChordPTR = Note.FindChord[n]; Sync.RemoveNote[s,n]; IF c#NIL THEN Chord.RemoveNote[c,n]; IF c=NIL AND n.beam#NIL THEN Beam.Remove[n.beam,n,NIL,NIL]; IF NOT free THEN RETURN; IF s.event[0]=NIL THEN Utility.FreeSync[@n.sync]; Utility.FreeNote[@n]; END; SetAccidental:PUBLIC PROCEDURE[n:NotePTR,a:Accidental] = BEGIN IF voice AND n.voice#selectedVoice THEN RETURN; flash _ TRUE; SELECT n.pitch MOD 12 FROM 0 => IF a=doubleFlat OR a=sharp THEN RETURN; 1 => IF a=flat OR a=doubleSharp THEN RETURN; 2 => IF a=doubleFlat OR a=natural THEN RETURN; 3 => IF a=flat OR a=sharp THEN RETURN; 4 => IF a=doubleFlat OR a=natural OR a=doubleSharp THEN RETURN; 5 => IF a=flat OR a=sharp THEN RETURN; 6 => IF a=natural OR a=doubleSharp THEN RETURN; 7 => IF a=doubleFlat OR a=sharp THEN RETURN; 8 => IF a=flat OR a=doubleSharp THEN RETURN; 9 => IF a=doubleFlat OR a=natural THEN RETURN; 10=> IF a=flat OR a=sharp THEN RETURN; 11=> IF a=natural OR a=doubleSharp THEN RETURN; ENDCASE; flash _ FALSE; n.spelled _ a; SetDirty[n.sync.time,n.sync.time]; END; SetEmbellishment:PUBLIC PROCEDURE[n:NotePTR,e:Embellishment] = BEGIN IF voice AND n.voice#selectedVoice THEN RETURN; IF n.rest THEN RETURN; n.embellish _ e; SetDirty[n.sync.time,n.sync.time]; END; Duration:PUBLIC PROCEDURE[n:NotePTR,metrenome:INTEGER] RETURNS[d:Time] = BEGIN m,t,rem:Time; l:REAL_1; b:BeamPTR; IF metrenome#128 THEN m_Real.Fix[128*(l*256/metrenome)] ELSE m_256; d _ SELECT n.value FROM whole=>64, half=>32, quarter=>16, eighth=>8, sixteenth=>4, thirtysecond=>2, ENDCASE=>1; IF n.dotted THEN d _ (d*3)/2; d _ d*m; FOR b_n.beam,b.beam WHILE b#NIL DO IF b.ntuple=0 THEN LOOP; t _ (d*b.against)/b.ntuple; rem _ d*(b.against)-t*b.ntuple; IF b.sync2.time=n.sync.time THEN d _ t+rem ELSE d _ t; ENDLOOP; END; GetBackTie:PUBLIC PROCEDURE[n:NotePTR] RETURNS[t:NotePTR] = BEGIN i,j:CARDINAL; start:CARDINAL; IF n=NIL THEN RETURN[NIL]; IF n.sync=NIL THEN RETURN[NIL]; IF ~n.tied THEN RETURN[NIL]; start _ Piece.NearestSync[p:score,t:n.sync.time,notesOnly:TRUE]; FOR i IN [start..scoreLength) DO FOR j IN [0..syncLength) DO IF score[i].event[j]=NIL THEN EXIT; IF score[i].event[j].tie=n THEN RETURN[score[i].event[j]]; ENDLOOP; ENDLOOP; Error; END; --**************************************************************************** --drawing notes --**************************************************************************** Draw:PUBLIC PROCEDURE[n:NotePTR,stem:INTEGER] = BEGIN two:REAL = 2; flag:NoteValue; x,y,mid,width:INTEGER_0; width _ Note.Width[n]; [x,y] _ Sheet.MapNote[n]; Note.DrawHead[n,x,y,x+width+2]; --includes x delta IF n.rest OR NOT show.notehead THEN RETURN; --draw the ledger lines mid _ Sheet.Map[n.sync.time,,n.staff].y+16; FOR i:INTEGER IN [3..9] WHILE y-mid >= i*d DO IF ~n.grace --note above mid THEN DrawRectangle[context,[x-3,mid+1+i*d],[x+width+3,mid-1+i*d]] ELSE DrawRectangle[context,[x-3,mid+1/two+i*d],[x+width+3,mid-1/two+i*d]] ENDLOOP; FOR i:INTEGER IN [3..9] WHILE mid-y >= i*d DO IF ~n.grace --note below mid THEN DrawRectangle[context,[x-3,mid+1-i*d],[x+width+3,mid-1-i*d]] ELSE DrawRectangle[context,[x-3,mid+1/two-i*d],[x+width+3,mid-1/two-i*d]] ENDLOOP; IF n.value=whole OR n.value=unknown THEN RETURN; --draw the stem flag _ n.value; IF stem#default -- drawing part of or beam THEN {stem_(IF n.stemUp THEN stem+1 ELSE stem-1); flag_quarter} ELSE SELECT TRUE FROM n.grace AND n.stemUp => stem _ y+2*d; n.grace AND ~n.stemUp => stem _ y-2*d; n.stemUp => stem _ MAX[y+(7*d)/2,mid]; ~n.stemUp => stem _ MIN[y-(7*d)/2,mid]; ENDCASE; IF n.stemUp THEN DrawLine[x+width,y,x+width,stem] ELSE DrawLine[x,y,x,stem]; --draw the flag IF n.grace THEN MoveTo[context,[x,IF n.stemUp THEN stem-17 ELSE stem+17]] ELSE MoveTo[context,[x,IF n.stemUp THEN stem-24 ELSE stem+24]]; SELECT TRUE FROM flag=quarter => NULL; n.grace => IF n.stemUp THEN DrawChar[context,133C] ELSE DrawChar[context,134C]; flag=eighth => IF n.stemUp THEN DrawChar[context,153C] ELSE DrawChar[context,163C]; flag=sixteenth => IF n.stemUp THEN DrawChar[context,152C] ELSE DrawChar[context,162C]; flag=thirtysecond => IF n.stemUp THEN DrawChar[context,151C] ELSE DrawChar[context,161C]; flag=sixtyfourth => IF n.stemUp THEN DrawChar[context,151C] ELSE DrawChar[context,161C]; ENDCASE; END; DrawHead:PUBLIC PROCEDURE[n:NotePTR,x,y,dotX:INTEGER] = BEGIN inVoice:BOOLEAN; width,dotY:INTEGER; --draw notehead (physical, rest, or normal), dot, and accidental inVoice_ ~(voice AND n.voice#selectedVoice); Graphics.SetTexture[context,IF inVoice THEN black ELSE light]; IF NOT show.notehead THEN {DrawPhysical[n,x,y]; RETURN}; IF n.tie#NIL THEN Note.DrawTie[n]; MoveTo[context,[x,y]]; IF n.grace THEN IF n.rest THEN SELECT n.value FROM ENDCASE => DrawChar[context,172C] ELSE SELECT n.value FROM ENDCASE => DrawChar[context,132C] ELSE IF n.rest THEN SELECT n.value FROM whole => {MoveTo[context,[x,y+(IF print THEN -5 ELSE 3)]] ; DrawChar[context,145C]}; half => {IF print THEN MoveTo[context,[x,y-9]]; DrawChar[context,145C]}; quarter => DrawChar[context,144C]; eighth => DrawChar[context,143C]; sixteenth => DrawChar[context,142C]; thirtysecond => DrawChar[context,141C]; ENDCASE => DrawChar[context,114C] ELSE SELECT n.value FROM whole => DrawChar[context,156C]; half => DrawChar[context,155C]; ENDCASE => DrawChar[context,154C]; width _ Note.Width[n]; IF DottedOnLine[n] THEN dotY_y+4 ELSE dotY_y; IF n.dotted THEN BEGIN MoveTo[context,[dotX,dotY]]; DrawChar[context,056C]; dotX_dotX+3; END; IF n.doubleDotted THEN BEGIN MoveTo[context,[dotX,dotY]]; DrawChar[context,056C]; dotX_dotX+3; MoveTo[context,[dotX,dotY]]; DrawChar[context,056C]; END; IF n.embellish#none THEN BEGIN sy:INTEGER; sy _ MAX[y,Sheet.Map[n.sync.time,,n.staff].y+28]; IF n.embellish=trill THEN MoveTo[context,[x,sy+10]] ELSE MoveTo[context,[x-2,sy+10]]; SELECT n.embellish FROM trill => DrawChar[context,'U]; mordent1 => DrawChar[context,'V]; mordent2 => DrawChar[context,'W]; ENDCASE; END; IF n.rest OR NOT show.accidental THEN RETURN; x _ x-9+(IF show.display=graphical THEN n.accDelta ELSE 0); MoveTo[context,[x,y]]; SELECT Score.GetAccidental[n] FROM doubleFlat => {MoveTo[context,[x-4,y]]; DrawChar[context,110C]}; flat => DrawChar[context,111C]; natural => DrawChar[context,112C]; sharp => DrawChar[context,113C]; doubleSharp => DrawChar[context,114C]; ENDCASE; END; DottedOnLine:PROCEDURE[n:NotePTR] RETURNS[BOOLEAN]=INLINE BEGIN IF NOT n.dotted THEN RETURN[FALSE]; RETURN[Mod[Sheet.Height[n.sync.time, Score.ShowPitch[n.pitch, n.spelled, 0], n.staff]- Sheet.Height[n.sync.time , ,n.staff ], 8]=0]; END; Mod:PROCEDURE[k,m:INTEGER] RETURNS[n:INTEGER] = BEGIN n _ k MOD m; IF n<0 THEN n_n+m; END; DrawPhysical:PROCEDURE[n:NotePTR,x,y:INTEGER] = BEGIN duration:INTEGER; IF n.rest THEN RETURN; IF show.display#physical THEN duration _ InlineDefs.LowHalf[7*(Note.Duration[n,128]/8)/TF]; IF show.display=physical OR n.value=unknown THEN duration _ n.duration/TF; DrawRectangle[context,[x,y-2],[MIN[x+duration,staffLength+12],y+1]]; END; DrawTie:PUBLIC PROCEDURE[n:NotePTR] = BEGIN temp:NotePTR; oneTie:BOOLEAN; x1,x2,y1,y2,xe,ye:INTEGER; IF n.sync.time0 THEN y1 _ y1+2 ELSE y1 _ y1-2; IF n.tieHeight>0 THEN y2 _ y2+2 ELSE y2 _ y2-2; IF ABS[n.sync.time-n.tie.sync.time]<28 THEN { x1 _ x1-5; x2 _ x2+5; IF n.tieHeight>0 THEN y1 _ y1+4 ELSE y1 _ y1-4; IF n.tieHeight>0 THEN y2 _ y2+4 ELSE y2 _ y2-4}; IF x1>x2 THEN BEGIN oneTie_FALSE; xe _ staffLength; ye _ y1; END ELSE BEGIN oneTie_TRUE; xe _ x2-2; ye _ y2; END; x1 _ x1 + 10; IF n.tie.sync.time>=begin THEN DrawCubic[x1,y1,xe,ye,n.tieHeight]; IF oneTie THEN RETURN; IF n.sync.time<=endTime THEN BEGIN xe _ sheet[Sheet.FindLine[n.sync.time]].x-6; ye _ y2; DrawCubic[xe,ye,x2,y2,n.tieHeight]; END; END; d:CARDINAL = 8; END.. (0,3810)\839i15I81b6B323i1bI13B841i1bI16B182b8B544b10B515i13I82b4B188i17I175i11I221i11I1319b8B93i63I2939b7B138i19I DrawStem:PUBLIC PROCEDURE[x,y1,y2,stem,staff:INTEGER,stemUp,grace:BOOLEAN,flag:NoteValue] = BEGIN -- x is the left edge of the note, -- y1 & y2 are the y coordinates of the top and bottom notes of a chord -- stem is the y coordinate (stem=default is a request for the default stem) n:INTEGER; line:REAL_1; IF stem#default -- drawing part of or beam THEN stem_(IF stemUp THEN stem+1 ELSE stem-1) ELSE {[,middle] _ Sheet.Map[n.sync.time,1000,n.staff]+16; IF stemUp THEN stem _ MAX[y+(7*d)/2,middle] ELSE stem _ MIN[y-(7*d)/2,middle]}; FOR n IN [3..9] WHILE MAX[head,head2]-middle >= n*d DO --note above middle DrawRectangle[context,[x-3,middle+line+n*d],[x+w,middle-line+n*d]]; ENDLOOP; FOR n IN [3..9] WHILE middle-MIN[head,head2] >= n*d DO --note below middle DrawRectangle[context,[x-3,middle+line-n*d],[x+w,middle-line-n*d]]; ENDLOOP; IF flag=whole OR flag=unknown THEN RETURN; MoveTo[context,[x,IF stemUp THEN tail-24 ELSE tail+24]]; SELECT flag FROM eighth => IF stemUp THEN DrawChar[context,153C] ELSE DrawChar[context,163C]; sixteenth => IF stemUp THEN DrawChar[context,152C] ELSE DrawChar[context,162C]; thirtysecond => IF stemUp THEN DrawChar[context,151C] ELSE DrawChar[context,161C]; ENDCASE; IF stemUp THEN x _ x+8; DrawLine[x,head,x,tail]; END; Vector:TYPE = RECORD[x,y:INTEGER]; DisplayAcc:PROCEDURE[x,y:INTEGER,n:NotePTR] = BEGIN c:Accidental; MoveTo[context,[x,y]]; c _ GetAccidental[n]; SELECT c FROM doubleFlat => BEGIN MoveTo[context,[x-4,y]]; DrawChar[context,110C]; END; flat => DrawChar[context,111C]; natural => DrawChar[context,112C]; sharp => DrawChar[context,113C]; doubleSharp => DrawChar[context,114C]; ENDCASE; END; \3b8B604i17I157i17I