<> <> <> <> <> DIRECTORY Graphics USING [DisplayContext, Vec, ScreenToUser], InlineDefs USING [LowHalf], MusicDefs, Note USING [Delta], Real USING [FixI], Score USING [GetKey, KeyHeight, ShowPitch], Sheet USING [default, FindLine, FindSection, Height, NextLine, PriorLine]; SheetImplB: CEDAR PROGRAM IMPORTS Graphics, InlineDefs, MusicDefs, Note, Real, Score, Sheet EXPORTS Sheet = BEGIN OPEN MusicDefs, Sheet; <<****************************************************************************>> <> <<****************************************************************************>> MapNote: PUBLIC PROC[n: NotePTR] RETURNS[x, y: INTEGER]= { l: Section; show: INTEGER; t: Time _ n.sync.time; IF n.rest AND n.value=whole THEN t _ t-7; l _ sheet[FindSection[t]]; x _ InlineDefs.LowHalf[t-l.time+l.x+Note.Delta[n]]; show _ Score.ShowPitch[n.pitch, n.spelled, l.key]; RETURN[x, l.y-top+PitchHeight[t, show, l.staves.staff[n.staff]]]; }; Map: PUBLIC PROC[t: Time, pitch: INTEGER, staff: CARDINAL] RETURNS[x, y: INTEGER]= { l: Section _ sheet[FindSection[t]]; RETURN[InlineDefs.LowHalf[t-l.time+l.x], l.y-top + PitchHeight[t, pitch, l.staves.staff[staff]]]; }; MapHeight: PUBLIC PROC[t: Time, height: INTEGER] RETURNS[x, y: INTEGER]= { l: Section _ sheet[FindSection[t]]; RETURN[InlineDefs.LowHalf[t-l.time+l.x], l.y-top + height]; }; Height: PUBLIC PROC[t: Time, pitch: INTEGER, staff: CARDINAL] RETURNS[INTEGER]= { l: Section _ sheet[FindSection[t]]; RETURN[PitchHeight[t, pitch, l.staves.staff[staff]]]; }; Pitch: PUBLIC PROC[t: Time, height: INTEGER, staff: CARDINAL] RETURNS[INTEGER]= { i: CARDINAL; key: INTEGER _ Score.GetKey[t]; pitch: INTEGER _ 12; keyPitch: INTEGER _ (44+key*7) MOD 12; octave: INTEGER; l: Section _ sheet[FindSection[t]]; height _ height - PitchHeight[t, keyPitch, l.staves.staff[staff]]; IF height<0 THEN octave_ height/28-1 ELSE octave _ height/28; octave _ height/28 - (IF height<0 THEN 1 ELSE 0); height _ Mod[height, 28]; FOR i IN [0..12) DO IF pitchHeight[i] >= height THEN { pitch _ i; EXIT; }; ENDLOOP; RETURN[pitch + keyPitch + 12*octave]; }; PitchHeight: PROC[t: Time, pitch: INTEGER, staff: Staff] RETURNS[INTEGER]= { <> <100 use the staff's pitch>> height, octave, key: INTEGER; IF pitch>100 THEN RETURN[staff.y]; IF NOT show.accidental THEN RETURN[CrackHeight[t, pitch, staff]]; key _ Score.GetKey[t]; octave _ (pitch-Mod[pitch, 12]-staff.pitch+Mod[staff.pitch, 12])/12; height _ 28*octave + Score.KeyHeight[key, pitch] - Score.KeyHeight[key, staff.pitch]; RETURN[staff.y+height]; }; CrackHeight: PROC[t: Time, pitch: INTEGER, staff: Staff] RETURNS[INTEGER]= { <> height: INTEGER; octave: INTEGER; ms: CARDINAL _ Mod[staff.pitch, 12]; mp: CARDINAL _ Mod[pitch, 12]; octave _ (pitch-mp-staff.pitch+ms)/12; height _ 28*octave + crackHeight[mp] - crackHeight[ms]; RETURN[staff.y+height]; }; crackHeight: ARRAY[0..12) OF INTEGER = [0, 4, 6, 8, 10, 12, 14, 16, 20, 22, 24, 26]; pitchHeight: ARRAY [0..12) OF INTEGER = [0, 1, 4, 5, 8, 12, 13, 16, 17, 20, 21, 24]; <<****************************************************************************>> <> <<****************************************************************************>> ScreenPoint: PUBLIC PROC RETURNS[x, y: INTEGER] = { sp, p: Graphics.Vec; sp.x _ MouseX^; sp.y _ MouseY^; p _ Graphics.ScreenToUser[context, sp]; x _ Real.FixI[p.x]; y _ Real.FixI[p.y]+top; }; NearestTime: PUBLIC PROC[x, y: INTEGER] RETURNS[time: Time, height: INTEGER]= { line, next: CARDINAL _ 0; IF x=default THEN [x, y] _ ScreenPoint[]; WHILE sheet[next].y>=y DO line _ next; next _ Sheet.NextLine[line]; ENDLOOP; IF y<((sheet[line].y+Sheet.Height[sheet[line].time,, 3]+8)/2+sheet[next].y/2) THEN line _ next; IF x < sheet[line].x THEN x _ sheet[line].x; IF x > staffLength THEN x _ staffLength; time _ sheet[line].time+ x- sheet[line].x; height_ y- sheet[line].y; }; AlternateTime: PUBLIC PROC[t1: Time, h1: INTEGER, lines: INTEGER] RETURNS[time: Time, height: INTEGER] = { next, prior, l: CARDINAL; time _ t1; height _ h1; l _ Sheet.FindLine[time]; IF lines>0 THEN FOR i: CARDINAL IN [0..ABS[lines]) DO next _ Sheet.NextLine[l]; time _ time + (staffLength - sheet[next].x); height _ height - (sheet[next].y - sheet[l].y); l _ next; ENDLOOP; IF lines<0 THEN FOR i: CARDINAL IN [0..ABS[lines]) DO prior _ Sheet.PriorLine[l]; time _ time - (staffLength - sheet[l].x); height _ height + (sheet[l].y - sheet[prior].y); l _ prior; ENDLOOP; RETURN[time, height]; }; NearestStaff: PUBLIC PROC[t: Time, height: INTEGER] RETURNS[CARDINAL] = { i, j, k: CARDINAL _ 10; staves: StavesPTR = sheet[Sheet.FindSection[t]].staves; FOR i IN [0..staves.sl] DO IF i<2 AND staves.staff[i]=staves.staff[i+1] THEN LOOP; IF height< staves.staff[i].y THEN { j _ i; LOOP; }; IF j=10 THEN RETURN[i]; IF height<(staves.staff[j].y+staves.staff[i].y+34)/2 THEN RETURN[i] ELSE RETURN[j]; ENDLOOP; RETURN[staves.sl]; }; END. GetStaves: PROC[time: Time] RETURNS[StavesPTR] = { sync: SyncPTR _ NIL; FOR i: CARDINAL IN [0..cacheLength) DO IF cache[i]=NIL THEN EXIT; IF cache[i].type#staves THEN LOOP; IF cache[i].time>time AND sync=NIL THEN sync _ cache[i]; IF cache[i].time>time THEN EXIT; sync _ cache[i]; ENDLOOP; IF sync=NIL THEN { Sheet.SetStaves[2, 0, EndOfScore[]]; RETURN[GetStaves[time]]; }; RETURN[LOOPHOLE[@sync.event]]; }; Reset: PUBLIC PROC= { staves: Staves; page: INTEGER _ 2; i, j: CARDINAL _ 0; sync: SyncPTR _ NIL; time, break, top, cacheTime: Time _ 0; height, x, sc, sheetHeight: INTEGER _ 0; Score.BuildCache[]; MakeSheetConsistent[]; IF scale=2 THEN sc _ 3 ELSE sc _ 2*scale; FOR i IN [0..cacheLength] DO IF i#cacheLength AND cache[i].type NOT IN SheetSwitch THEN LOOP; IF i=cacheLength AND sync=NIL THEN RETURN; IF i=cacheLength THEN cacheTime _ 400000 ELSE cacheTime _ cache[i].time; IF sync=NIL THEN {sync _ cache[i]; staves _ LOOPHOLE[sync.event]}; WHILE time(650*sc)/2 THEN { top _ height; sheet[j].page _ page; page _ page+1; }; SELECT TRUE FROM x=0 => {x_ ABS[8*(sheet[j].key)]; IF x=0 THEN x _ 8}; ENDCASE => x_ x + InlineDefs.LowHalf[time-sheet[j-1].time]; sheet[j].x _ x; IF time>=break THEN break _ break+staffLength-x; time _ MIN[cacheTime, break]; IF time>=break THEN { sheetHeight _ -staves.staff[staves.sl].y; height _ height - sheetHeight - staves.offset; x _ 0; }; j _ j+1; IF j=sheetLength THEN RETURN; ENDLOOP; IF i=cacheLength THEN EXIT; sync _ cache[i]; staves _ LOOPHOLE[sync.event]; ENDLOOP; FOR i: CARDINAL IN [0..beamHeapLength) DO Beam.SetStems[beamHeap[i]]; ENDLOOP; };