--Author: John Maxwell --last modified: November 21, 1981 11:33 AM 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:PROGRAM IMPORTS Graphics, InlineDefs, MusicDefs, Note, Real, Score, Sheet EXPORTS Sheet = BEGIN OPEN MusicDefs, Sheet; --**************************************************************************** --procedures that map from note to screen --**************************************************************************** MapNote:PUBLIC PROCEDURE[n:NotePTR] RETURNS[x,y:INTEGER]= BEGIN 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]]]; END; Map:PUBLIC PROCEDURE[t:Time,pitch:INTEGER,staff:CARDINAL] RETURNS[x,y:INTEGER]= BEGIN l:Section _ sheet[FindSection[t]]; RETURN[InlineDefs.LowHalf[t-l.time+l.x],l.y-top + PitchHeight[t,pitch,l.staves.staff[staff]]]; END; MapHeight:PUBLIC PROCEDURE[t:Time,height:INTEGER] RETURNS[x,y:INTEGER]= BEGIN l:Section _ sheet[FindSection[t]]; RETURN[InlineDefs.LowHalf[t-l.time+l.x],l.y-top + height]; END; Height:PUBLIC PROCEDURE[t:Time,pitch:INTEGER,staff:CARDINAL] RETURNS[INTEGER]= BEGIN l:Section _ sheet[FindSection[t]]; RETURN[PitchHeight[t,pitch,l.staves.staff[staff]]]; END; Pitch:PUBLIC PROCEDURE[t:Time,height:INTEGER,staff:CARDINAL] RETURNS[INTEGER]= BEGIN 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 BEGIN pitch _ i; EXIT; END; ENDLOOP; RETURN[pitch + keyPitch + 12*octave]; END; PitchHeight:PROCEDURE[t:Time,pitch:INTEGER,staff:Staff] RETURNS[INTEGER]= --return the y height of the pitch relative to the top of the staves --if pitch>100 use the staff's pitch BEGIN 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]; END; CrackHeight:PROCEDURE[t:Time,pitch:INTEGER,staff:Staff] RETURNS[INTEGER]= BEGIN --pitches with accidentals are placed between lines and spaces 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]; END; 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]; --**************************************************************************** --procedures that map from screen back --**************************************************************************** ScreenPoint:PUBLIC PROCEDURE RETURNS[x,y:INTEGER] = BEGIN 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; END; NearestTime:PUBLIC PROCEDURE[x,y:INTEGER] RETURNS[time:Time,height:INTEGER]= BEGIN 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; END; AlternateTime:PUBLIC PROCEDURE[t1:Time,h1:INTEGER,lines:INTEGER] RETURNS[time:Time,height:INTEGER] = BEGIN 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]; END; NearestStaff:PUBLIC PROCEDURE[t:Time,height:INTEGER] RETURNS[CARDINAL] = BEGIN 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 BEGIN j_i; LOOP; END; 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; END..(0,3648)(1,4288)(2,4939)(3,6048)\554i39I81b7B341b3B219b9B168b7B172b5B653i13I6i85I928i36I81b11B187b11B471b13B589b13B GetStaves:PROCEDURE[time:Time] RETURNS[StavesPTR] = BEGIN 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 BEGIN Sheet.SetStaves[2,0,EndOfScore[]]; RETURN[GetStaves[time]]; END; RETURN[LOOPHOLE[@sync.event]]; END; Reset:PUBLIC PROCEDURE= BEGIN 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 BEGIN top _ height; sheet[j].page_page; page_page+1; END; 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 BEGIN sheetHeight _ -staves.staff[staves.sl].y; height _ height - sheetHeight - staves.offset; x_0; END; 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; END; (0,65535)(1,65535)(2,65535)\1b9B430b5B242i1I