DIRECTORY Beam USING [RemoveItem], Chord USING [RemoveNote], Event USING [GetScoreIndex, RemoveNote, Sync], MusicDefs, Note USING [default, Width], Real USING [Fix], Score USING [ShowPitch], Selection USING [RemoveNote], Sheet USING [FindLine, Height, Map, MapNote], Utility USING [DrawBox, DrawChar, DrawCubic, DrawLine, SetColor, SetCP]; NoteImpl: CEDAR PROGRAM IMPORTS Beam, Chord, Event, MusicDefs, Note, Real, Score, Selection, Sheet, Utility EXPORTS Note = BEGIN OPEN MusicDefs; Free: PUBLIC PROC[score: ScorePTR, n: NotePTR] = { IF n.chord # NIL THEN Chord.RemoveNote[score, n.chord, n]; -- sets n.beam to NIL IF n.beam # NIL THEN Beam.RemoveItem[score, n.beam, n]; IF n.tie # NIL THEN {n.tie.tied _ FALSE; n.tie _ NIL}; IF n.tied THEN {GetBackTie[score, n].tie _ NIL; n.tied _ FALSE}; Event.RemoveNote[score, n.sync, n, TRUE]; -- frees s if s.length = 0. Selection.RemoveNote[n]; }; SetAccidental: PUBLIC PROC[score: ScorePTR, n: NotePTR, a: Accidental] = { IF score.sheet.voice # noVoice AND n.voice # score.sheet.voice THEN RETURN; score.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; score.flash _ FALSE; n.spelled _ a; SetDirty[score, n.sync.time, n.sync.time]; }; SetEmbellishment: PUBLIC PROC[score: ScorePTR, n: NotePTR, e: Embellishment] = { IF score.sheet.voice # noVoice AND n.voice # score.sheet.voice THEN RETURN; IF n.rest THEN RETURN; n.embellish _ e; SetDirty[score, n.sync.time, n.sync.time]; }; Duration: PUBLIC PROC[n: NotePTR, metrenome: INTEGER] RETURNS[d: Time] = { 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; }; GetBackTie: PUBLIC PROC[score: ScorePTR, n: NotePTR] RETURNS[t: NotePTR] = { sync: SyncPTR; IF n = NIL THEN RETURN[NIL]; IF n.sync = NIL THEN RETURN[NIL]; IF ~n.tied THEN RETURN[NIL]; FOR i: CARDINAL IN [Event.GetScoreIndex[score, n.sync]..score.length) DO IF score.event[i].type # sync THEN LOOP; sync _ Event.Sync[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO IF sync.note[j].tie = n THEN RETURN[sync.note[j]]; ENDLOOP; ENDLOOP; ERROR; }; GetSyncIndex: PUBLIC PROC[s: SyncPTR, p: NotePTR] RETURNS[NAT] = { FOR i: NAT IN[0..s.length) DO IF s.note[i] = p THEN RETURN[i]; ENDLOOP; ERROR; }; d: CARDINAL = 8; Draw: PUBLIC PROC[score: ScorePTR, n: NotePTR, stem: INTEGER] = { w: REAL = 1; -- width of ledger line two: REAL = 2; flag: NoteValue; sheet: SheetPTR = score.sheet; x, y, mid, width: INTEGER _ 0; width _ Note.Width[n]; [x, y] _ Sheet.MapNote[sheet, n]; DrawHead[score, n, x, y, x+width+2]; -- includes x delta IF n.rest OR NOT sheet.notehead THEN RETURN; mid _ Sheet.Map[sheet, n.sync.time, , n.staff].y+16; FOR i: INTEGER IN [3..9] WHILE y-mid >= i*d DO IF ~n.grace THEN Utility.DrawBox[sheet.context, [x-3, mid+w+i*d, x+width+3, mid-w+i*d]] ELSE Utility.DrawBox[sheet.context, [x-3, mid+w/two+i*d, x+width+3, mid-w/two+i*d]] ENDLOOP; FOR i: INTEGER IN [3..9] WHILE mid-y >= i*d DO IF ~n.grace THEN Utility.DrawBox[sheet.context, [x-3, mid+w-i*d, x+width+3, mid-w-i*d]] ELSE Utility.DrawBox[sheet.context, [x-3, mid+w/two-i*d, x+width+3, mid-w/two-i*d]] ENDLOOP; IF n.value = whole OR n.value = unknown THEN RETURN; flag _ n.value; IF stem#Note.default THEN { stem _ (IF n.stemUp THEN stem+1 ELSE stem-1); flag _ quarter } ELSE IF n.grace THEN { IF n.stemUp THEN stem _ y+2*d ELSE stem _ y-2*d } ELSE { IF n.stemUp THEN stem _ MAX[y+(7*d)/2, mid] ELSE stem _ MIN[y-(7*d)/2, mid] }; IF n.stemUp THEN Utility.DrawLine[sheet.context, x+width, y, x+width, stem] ELSE Utility.DrawLine[sheet.context, x, y, x, stem]; IF n.grace THEN Utility.SetCP[sheet.context, x, IF n.stemUp THEN stem-17 ELSE stem+17] ELSE Utility.SetCP[sheet.context, x, IF n.stemUp THEN stem-24 ELSE stem+24]; SELECT TRUE FROM flag = quarter => NULL; n.grace => Utility.DrawChar[sheet.context, IF n.stemUp THEN 133C ELSE 134C]; flag = eighth => Utility.DrawChar[sheet.context, IF n.stemUp THEN 153C ELSE 163C]; flag = sixteenth => Utility.DrawChar[sheet.context, IF n.stemUp THEN 152C ELSE 162C]; flag = thirtysecond => Utility.DrawChar[sheet.context, IF n.stemUp THEN 151C ELSE 161C]; flag = sixtyfourth => Utility.DrawChar[sheet.context, IF n.stemUp THEN 151C ELSE 161C]; ENDCASE; }; DrawHead: PUBLIC PROC[score: ScorePTR, n: NotePTR, x, y, dotX: INTEGER] = { inVoice: BOOL; width, dotY: INTEGER; sheet: SheetPTR _ score.sheet; inVoice _ score.sheet.voice = noVoice OR n.voice = score.sheet.voice; Utility.SetColor[sheet.context, IF inVoice THEN black ELSE light]; IF NOT sheet.notehead THEN {DrawPhysical[sheet, n, x, y]; RETURN}; IF n.tie # NIL THEN DrawTie[score, n]; Utility.SetCP[sheet.context, x, y]; IF n.grace THEN IF n.rest THEN SELECT n.value FROM ENDCASE => Utility.DrawChar[sheet.context, 172C] ELSE SELECT n.value FROM ENDCASE => Utility.DrawChar[sheet.context, 132C] ELSE IF n.rest THEN SELECT n.value FROM whole => {Utility.SetCP[sheet.context, x, y+(IF sheet.printing THEN -5 ELSE 3)] ; Utility.DrawChar[sheet.context, 145C]}; half => {IF sheet.printing THEN Utility.SetCP[sheet.context, x, y-9]; Utility.DrawChar[sheet.context, 145C]}; quarter => Utility.DrawChar[sheet.context, 144C]; eighth => Utility.DrawChar[sheet.context, 143C]; sixteenth => Utility.DrawChar[sheet.context, 142C]; thirtysecond => Utility.DrawChar[sheet.context, 141C]; ENDCASE => Utility.DrawChar[sheet.context, 114C] ELSE SELECT n.value FROM whole => Utility.DrawChar[sheet.context, 156C]; half => Utility.DrawChar[sheet.context, 155C]; ENDCASE => Utility.DrawChar[sheet.context, 154C]; width _ Note.Width[n]; IF DottedOnLine[sheet, n] THEN dotY _ y+4 ELSE dotY _ y; IF n.dotted THEN { Utility.SetCP[sheet.context, dotX, dotY]; Utility.DrawChar[sheet.context, 056C]; dotX _ dotX+3; }; IF n.doubleDotted THEN { Utility.SetCP[sheet.context, dotX, dotY]; Utility.DrawChar[sheet.context, 056C]; dotX _ dotX+3; Utility.SetCP[sheet.context, dotX, dotY]; Utility.DrawChar[sheet.context, 056C]; }; IF n.embellish # none THEN { sy: INTEGER; sy _ MAX[y, Sheet.Map[sheet, n.sync.time, , n.staff].y+28]; IF n.embellish = trill THEN Utility.SetCP[sheet.context, x, sy+10] ELSE Utility.SetCP[sheet.context, x-2, sy+10]; SELECT n.embellish FROM trill => Utility.DrawChar[sheet.context, 'U]; mordent1 => Utility.DrawChar[sheet.context, 'V]; mordent2 => Utility.DrawChar[sheet.context, 'W]; ENDCASE; }; IF n.rest OR NOT sheet.accidental THEN RETURN; x _ x-9+(IF sheet.display = graphical THEN n.accDelta ELSE 0); Utility.SetCP[sheet.context, x, y]; SELECT n.shown FROM -- n.shown is set by EventImpl.Adjust's GetAccidental doubleFlat => {Utility.SetCP[sheet.context, x-4, y]; Utility.DrawChar[sheet.context, 110C]}; flat => Utility.DrawChar[sheet.context, 111C]; natural => Utility.DrawChar[sheet.context, 112C]; sharp => Utility.DrawChar[sheet.context, 113C]; doubleSharp => Utility.DrawChar[sheet.context, 114C]; ENDCASE; }; DottedOnLine: PROC[sheet: SheetPTR, n: NotePTR] RETURNS[BOOL] = INLINE { IF NOT n.dotted THEN RETURN[FALSE]; RETURN[Mod[Sheet.Height[sheet, n.sync.time, Score.ShowPitch[sheet, n.pitch, n.spelled, 0], n.staff]- Sheet.Height[sheet, n.sync.time , , n.staff ], 8] = 0]; }; Mod: PROC[k, m: INTEGER] RETURNS[n: INTEGER] = { n _ k MOD m; IF n < 0 THEN n _ n+m; }; DrawPhysical: PROC[sheet: SheetPTR, n: NotePTR, x, y: INTEGER] = { duration: INTEGER; IF n.rest THEN RETURN; IF sheet.display # physical THEN duration _ 7*(Duration[n, 128]/8)/sheet.density; IF sheet.display = physical OR n.value = unknown THEN duration _ n.duration/sheet.density; Utility.DrawBox[sheet.context, [x, y-2, MIN[x+duration, sheet.width+12], y+1]]; }; DrawTie: PUBLIC PROC[score: ScorePTR, n: NotePTR] = { temp: NotePTR; oneTie: BOOL; sheet: SheetPTR _ score.sheet; x1, x2, y1, y2, xe, ye: INTEGER; IF n.sync.time < n.tie.sync.time THEN { -- swap the notes temp _ n.tie; IF n.tied THEN GetBackTie[score, n].tie _ n.tie; temp.tied _ n.tied; n.tied _ TRUE; n.tie _ temp.tie; temp.tie _ n; n _ temp; }; x1 _ Sheet.Map[sheet, n.tie.sync.time, n.tie.pitch, n.tie.staff].x; x2 _ Sheet.Map[sheet, n.sync.time, n.pitch, n.staff].x; [xe, y1] _ Sheet.MapNote[sheet, n.tie]; x1 _ MAX[x1, xe]; [xe, y2] _ Sheet.MapNote[sheet, n]; x2 _ MIN[x2, xe]; IF n.tieHeight > 0 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 { oneTie _ FALSE; xe _ sheet.width; ye _ y1; } ELSE { oneTie _ TRUE; xe _ x2-2; ye _ y2; }; x1 _ x1 + 10; IF n.tie.sync.time >= sheet.begin THEN Utility.DrawCubic[sheet.context, x1, y1, xe, ye, n.tieHeight]; IF oneTie THEN RETURN; IF n.sync.time <= sheet.endTime THEN { xe _ sheet.section[Sheet.FindLine[sheet, n.sync.time]].x-6; ye _ y2; Utility.DrawCubic[sheet.context, xe, ye, x2, y2, n.tieHeight]; }; }; END. DrawStem: PUBLIC PROC[x, y1, y2, stem, staff: INTEGER, stemUp, grace: BOOL, flag: NoteValue] = { 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 Utility.DrawBox[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 Utility.DrawBox[context, [x-3, middle+line-n*d, x+w, middle-line-n*d]]; ENDLOOP; IF flag = whole OR flag = unknown THEN RETURN; Utility.SetCP[context, x, IF stemUp THEN tail-24 ELSE tail+24]; SELECT flag FROM eighth => IF stemUp THEN Utility.DrawChar[context, 153C] ELSE Utility.DrawChar[context, 163C]; sixteenth => IF stemUp THEN Utility.DrawChar[context, 152C] ELSE Utility.DrawChar[context, 162C]; thirtysecond => IF stemUp THEN Utility.DrawChar[context, 151C] ELSE Utility.DrawChar[context, 161C]; ENDCASE; IF stemUp THEN x _ x+8; Utility.DrawLine[x, head, x, tail]; }; Vector: TYPE = RECORD[x, y: INTEGER]; DisplayAcc: PROC[x, y: INTEGER, n: NotePTR] = { c: Accidental; Utility.SetCP[context, x, y]; c _ GetAccidental[n]; SELECT c FROM doubleFlat => { Utility.SetCP[context, x-4, y]; Utility.DrawChar[context, 110C]; }; flat => Utility.DrawChar[context, 111C]; natural => Utility.DrawChar[context, 112C]; sharp => Utility.DrawChar[context, 113C]; doubleSharp => Utility.DrawChar[context, 114C]; ENDCASE; }; VNoteImpl.mesa Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved. Author: John Maxwell Last Edited by: Maxwell, November 22, 1983 11:43 am Last Edited by: Doug Wyatt, June 19, 1984 10:22:21 am PDT **************************************************************************** note procedures **************************************************************************** NILs out all pointers to n. a note can be pointed at by a sync, a chord, a beam, a tie, and the selection zone.FREE[@n]; **************************************************************************** drawing notes **************************************************************************** draw the ledger lines note above mid note below mid draw the stem draw the flag draw notehead (physical, rest, or normal), dot, and accidental **************************************************************************** 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) note above middle note below middle ʦ˜šœ ™ J™@Jšœ™Jšœ3™3Jšœ9™9—J˜šÏk ˜ Jšœœ˜Jšœœ˜Jšœœ$˜/J˜ Jšœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœœ#˜.Jšœœ;˜HJ˜—Jšœ œ˜JšœL˜SJšœ˜ Jšœœœ ˜J˜JšœL™LJšœ™JšœL™LJ˜šÏnœœœ!˜2Jšœ™JšœM™MJšœ œœ&Ïc˜PJšœ œœ#˜7Jš œ œœœ œ˜6Jšœœœ œ˜@Jšœ#œŸ˜EJ˜Jšœœ™Jšœ˜J˜—šž œœœ0˜JJšœœœœ˜KJšœœ˜šœ œ˜Jš œœœ œœ˜1Jš œœ œœœ˜1Jš œœœ œœ˜3Jš œœ œ œœ˜+Jš œœœ œœœ ˜NJš œœ œ œœ˜+Jš œœ œœœ˜4Jš œœœ œœ˜1Jš œœ œœœ˜1Jš œœœ œœ˜3Jš œœ œ œœ˜,Jš œœ œœœ˜4Jšœ˜—Jšœœ˜J˜J˜*Jšœ˜J˜—šžœœœ3˜PJšœœœœ˜KJšœœœ˜J˜J˜*Jšœ˜J˜—š žœœœœœ ˜JJ˜Jšœœ˜ J˜ Jšœœ%œ ˜Išœœ ˜J˜5Jšœ#œ˜0—Jšœ œ ˜J˜šœœœ˜'Jšœœœ˜J˜J˜Jšœœ œ˜8Jšœ˜—Jšœ˜J˜—šž œœœœ˜LJ˜Jš œœœœœ˜Jš œ œœœœ˜!Jšœ œœœ˜šœœœ4˜HJšœœœ˜(J˜"šœœœ˜&Jšœœœ˜2Jšœ˜—Jšœ˜—Jšœ˜Jšœ˜J˜—š ž œœœœœ˜Bšœœœœ˜Jšœœœ˜!Jšœ˜ —Jšœ˜šœ˜J˜——J˜JšœL™LJšœ ™ JšœL™LJ˜Jšœœ˜J˜šžœœœ$œ˜AJšœœŸ˜$Jšœœ˜J˜J˜Jšœœ˜J˜J˜!Jšœ%Ÿ˜8Jš œœœœœ˜,Jšœ™J˜4š œœœœœœ ˜™>Jšœ&œ˜GJšœ œ œœ˜BJšœœœ œ˜BJšœ œœ˜&Jšœ#˜#šœ˜ šœœ˜šœœ ˜Jšœ)˜0—šœœ ˜Jšœ)˜0——šœœ˜šœœ ˜šœ-œœœ˜RJšœ(˜(—šœ œœ'˜FJšœ(˜(—Jšœ8˜8Jšœ9˜9Jšœ9˜9Jšœ9˜9Jšœ.˜5—šœœ ˜Jšœ1˜1Jšœ1˜1Jšœ+˜2———J˜Jšœœ œ ˜8šœ œ˜Jšœ)˜)Jšœ&˜&J˜Jšœ˜—šœœ˜Jšœ_˜_JšœP˜PJšœ˜—šœœ˜Jšœœ˜ Jšœœ3˜;šœ˜Jšœ(˜,Jšœ*˜.—šœ ˜Jšœ0˜0Jšœ0˜0Jšœ0˜0Jšœ˜—Jšœ˜—Jš œœœœœ˜.Jšœ œœ œ˜>Jšœ#˜#šœ œŸ5˜IJšœ\˜\Jšœ1˜1Jšœ1˜1Jšœ1˜1Jšœ7˜7Jšœ˜—Jšœ˜J˜—š ž œœœœœ˜HJš œœ œœœ˜#Jšœ–˜œJšœ˜J˜—Jšžœœœœœ œœœ ˜WJ˜šž œœ$œ˜BJšœ œ˜Jšœœœ˜Jšœœ1˜QJšœœœ%˜ZJšœ(œ$˜OJšœ˜J˜—šžœœœ!˜5J˜Jšœœ˜ J˜Jšœœ˜ šœœŸ˜9J˜Jšœœ"˜0Jšœœ˜"J˜J˜ Jšœ˜—J˜CJ˜7Jšœ-œ ˜9Jšœ)œ ˜5Jšœœ œ ˜1Jšœœ œ ˜1šœœ#œ˜/J˜Jšœœ œ ˜1Jšœœ œ ˜2—šœ œ œ˜>Jšœ œ˜,—J˜ šœ ˜&Jšœ>˜>—Jšœœœ˜šœœ˜&J˜;J˜Jšœ>˜>Jšœ˜—Jšœ˜J˜—Jšœ˜J˜JšœL™LJ™Jš žœœœœœ˜_Jšœ˜Jšœ ™ JšœD™DJšœK™KJšœœ˜ Jšœœ˜šœŸ˜-Jšœ œœœ˜/šœ8˜Jšœ!˜%—šœœœ ˜>Jšœ!˜%—šœœœ ˜>Jšœ!˜%—Jšœ˜—Jšœœ ˜Jšœ#˜#Jšœ˜J˜Jšœœœœ˜%J˜Jšž œœœ˜.Jšœ˜J˜Jšœ˜J˜šœ˜ JšœS˜SJšœ+˜+Jšœ+˜+Jšœ+˜+Jšœ1˜1Jšœ˜—Jšœ˜J˜J˜—…—,â?Þ