<> <> <> <> <> DIRECTORY Beam USING [Remove, SetSyncs, Sort, time], Chord USING [Beam, Sort], MusicDefs, Real USING [FixI], Sheet USING [Height], Utility USING [FreeBeam]; BeamImplA: CEDAR PROGRAM IMPORTS Beam, Chord, MusicDefs, Real, Sheet, Utility EXPORTS Beam, MusicDefs = BEGIN OPEN MusicDefs, Utility; GetHeapIndex: PUBLIC PROC[p: BeamPTR] RETURNS[NAT] = INLINE {FOR i: NAT IN [0..beamHeapLength) DO IF beamHeap[i]=p THEN RETURN[i]; ENDLOOP; RETURN[beamHeapLength]}; Height: PROC[b: BeamPTR, time: Time] RETURNS[h: INTEGER] = INLINE {h _ b.height+Sheet.Height[b.sync1.time,, b.staff]; IF time#b.sync1.time THEN h _ h + Real.FixI[(time-b.sync1.time)*b.tilt]}; Length: PROC[b: BeamPTR] RETURNS[NAT] = INLINE {FOR i: NAT IN [0..beamLength] DO IF i=beamLength THEN RETURN[i]; IF b.chord[i]=endOfBeam THEN RETURN[i]; ENDLOOP; ERROR}; time: PUBLIC PROC[chord: VariousPTR] RETURNS[Time] = INLINE {WITH chord SELECT FROM n: NotePTR => RETURN[n.sync.time]; c: ChordPTR => RETURN[c.note[0].sync.time]; b: BeamPTR => RETURN[IF b.sync1#NIL THEN b.sync1.time ELSE 0]; ENDCASE => ERROR }; <<**************************************************************************>> <> <i >> <> <<**************************************************************************>> Add: PUBLIC PROC[beam: BeamPTR, x: VariousPTR] ~ { WITH x SELECT FROM n: NotePTR => AddNote[beam, n]; c: ChordPTR => AddChord[beam, c]; b: BeamPTR => AddBeam[beam, b]; ENDCASE => ERROR; }; AddNote: PROC[b: BeamPTR, n: NotePTR] = { oldBeam: BeamPTR=n.beam; i, j: CARDINAL _ beamLength-1; FOR i IN [0..beamLength) DO IF b.chord[i]=n THEN RETURN; ENDLOOP; IF b.sync1=NIL THEN b.sync1 _ n.sync; IF b.sync2=NIL THEN b.sync2 _ n.sync; IF n.sync.time < b.sync1.time THEN b.sync1 _ n.sync; IF n.sync.time > b.sync2.time THEN b.sync2 _ n.sync; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN { j _ i; EXIT; }; IF Beam.time[b.chord[i]]>n.sync.time THEN j _ i; IF j#beamLength-1 THEN EXIT; ENDLOOP; IF b.chord[beamLength-1]#endOfBeam THEN Overflow[beam]; FOR i DECREASING IN (j..beamLength) DO b.chord[i] _ b.chord[i-1]; ENDLOOP; b.chord[j] _ n; n.beam _ b; IF oldBeam#NIL AND oldBeam#b THEN Beam.Remove[n.beam, n, NIL, NIL]; IF b.beam#NIL THEN Beam.SetSyncs[b.beam]; }; AddChord: PROC[b: BeamPTR, c: ChordPTR] = { i, j: CARDINAL _ beamLength-1; oldBeam: BeamPTR = Chord.Beam[c]; FOR i IN [0..beamLength) DO IF b.chord[i]=c THEN RETURN; ENDLOOP; IF b.sync1=NIL THEN b.sync1 _ c.note[0].sync; IF b.sync2=NIL THEN b.sync2 _ c.note[0].sync; IF c.note[0].sync.time < b.sync1.time THEN b.sync1 _ c.note[0].sync; IF c.note[0].sync.time > b.sync2.time THEN b.sync2 _ c.note[0].sync; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN { j _ i; EXIT; }; IF Beam.time[b.chord[i]]>c.note[0].sync.time THEN j _ i; IF j#beamLength-1 THEN EXIT; ENDLOOP; IF b.chord[beamLength-1]#endOfBeam THEN Overflow[beam]; FOR i DECREASING IN (j..beamLength) DO b.chord[i] _ b.chord[i-1]; ENDLOOP; b.chord[j] _ c; FOR i IN [0..chordLength) DO IF c.note[i]=NIL THEN EXIT; c.note[i].beam _ b; ENDLOOP; IF oldBeam#NIL AND oldBeam#b THEN Beam.Remove[oldBeam, NIL, c, NIL]; IF b.beam#NIL THEN Beam.SetSyncs[b.beam]; }; AddBeam: PROC[b: BeamPTR, new: BeamPTR] = { oldBeam: BeamPTR=b.beam; i, j: CARDINAL _ beamLength-1; FOR i IN [0..beamLength) DO IF b.chord[i]=new THEN RETURN; ENDLOOP; IF b.sync1=NIL THEN b.sync1 _ new.sync1; IF b.sync2=NIL THEN b.sync2 _ new.sync2; IF new.sync1.time < b.sync1.time THEN b.sync1 _ new.sync1; IF new.sync2.time > b.sync2.time THEN b.sync2 _ new.sync2; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN { j _ i; EXIT; }; IF Beam.time[b.chord[i]]>new.sync1.time THEN j _ i; IF j#beamLength-1 THEN EXIT; ENDLOOP; IF b.chord[beamLength-1]#endOfBeam THEN Overflow[beam]; FOR i DECREASING IN (j..beamLength) DO b.chord[i] _ b.chord[i-1]; ENDLOOP; b.chord[j] _ new; new.beam _ b; IF oldBeam#NIL AND oldBeam#b THEN Beam.Remove[oldBeam, NIL, NIL, new]; IF b.beam#NIL THEN Beam.SetSyncs[b.beam]; }; Remove: PUBLIC PROC[beam: BeamPTR, n: NotePTR, c: ChordPTR, b: BeamPTR] = { i, j: CARDINAL; found: BOOL _ FALSE; sync1, sync2: SyncPTR _ NIL; IF beam=NIL THEN RETURN; FOR i IN [0..beamLength) DO IF beam.chord[i]=endOfBeam THEN EXIT; IF beam.chord[i]#b AND beam.chord[i]#c AND beam.chord[i]#n THEN LOOP; IF beam.chord[i]=n THEN n.beam _ NIL; IF beam.chord[i]=b THEN b.beam _ NIL; IF beam.chord[i]=c THEN FOR j IN [0..chordLength) DO IF c.note[j]=NIL THEN EXIT; c.note[j].beam _ NIL; ENDLOOP; FOR j IN [i..beamLength-1) DO beam.chord[j] _ beam.chord[j+1]; ENDLOOP; beam.chord[beamLength-1] _ endOfBeam; found _ TRUE; ENDLOOP; IF NOT found THEN RETURN; IF beam.chord[1]=endOfBeam THEN {FreeBeam[@beam]; RETURN}; <> IF n#NIL THEN sync1 _ n.sync; IF c#NIL THEN sync2 _ c.note[0].sync; IF b#NIL THEN { sync1 _ b.sync1; sync2 _ b.sync2; }; IF beam.sync1=sync1 OR beam.sync1=sync2 THEN beam.sync1 _ NIL; IF beam.sync2=sync2 OR beam.sync2=sync1 THEN beam.sync2 _ NIL; IF beam.sync1=NIL OR beam.sync2=NIL THEN Beam.SetSyncs[beam]; }; Sort: PUBLIC PROC[b: BeamPTR] = { i, j: CARDINAL; temp: VariousPTR; FOR i IN [0..beamLength) DO IF b.chord[i] = endOfBeam THEN EXIT; FOR j IN (i..beamLength) DO IF b.chord[j] = endOfBeam THEN EXIT; IF Beam.time[b.chord[i]] <= Beam.time[b.chord[j]] THEN LOOP; temp _ b.chord[i]; b.chord[i] _ b.chord[j]; b.chord[j] _ temp; ENDLOOP; ENDLOOP; }; SetSyncs: PUBLIC PROC[b: BeamPTR] = { i: CARDINAL; sync1, sync2: SyncPTR; b.sync1 _b.sync2 _ NIL; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN EXIT; sync1 _ sync2 _ NIL; WITH ev: b.chord[i] SELECT FROM note => sync1 _ ev.n.sync; chord=> sync2 _ ev.c.note[0].sync; beam => { sync1 _ ev.b.sync1; sync2 _ ev.b.sync2; }; ENDCASE; IF sync1=NIL THEN sync1 _ sync2; IF sync2=NIL THEN sync2 _ sync1; IF b.sync1=NIL THEN b.sync1 _ sync1; IF b.sync2=NIL THEN b.sync2 _ sync2; IF sync1=NIL OR sync2=NIL THEN LOOP; IF b.sync1.time>sync1.time THEN b.sync1 _ sync1; IF b.sync2.time<=sync2.time THEN b.sync2 _ sync2; ENDLOOP; Beam.Sort[b]; IF b.beam # NIL THEN SetSyncs[b.beam]; }; SetStems: PUBLIC PROC[b: BeamPTR] = { <> i: CARDINAL; height, heighti, heightb: INTEGER; time1, timei: Time _ b.sync1.time; IF NOT b.beamed THEN RETURN; <> heightb _ b.height+Sheet.Height[b.sync1.time,, b.staff]; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN EXIT; WITH ev: b.chord[i] SELECT FROM note => { heighti _ Sheet.Height[ev.n.sync.time, ev.n.pitch, ev.n.staff]; timei _ Beam.time[b.chord[i]]; height _ Real.FixI[heightb+b.tilt*(timei-time1)]; ev.n.stemUp _ (height > heighti); b.staff _ ev.n.staff}; chord=> { [] _ Chord.Sort[ev.c, FALSE]; heighti _ Sheet.Height[ev.c.note[0].sync.time, ev.c.note[0].pitch, ev.c.note[0].staff]; timei _ Beam.time[b.chord[i]]; height _ Real.FixI[heightb+b.tilt*(timei-time1)]; ev.c.stemUp _ (height > heighti); b.staff _ ev.c.note[0].staff}; beam => { ev.b.tilt _ b.tilt; height _ Real.FixI[heightb+b.tilt*(ev.b.sync1.time-time1)]; ev.b.height _ height-Sheet.Height[0,, ev.b.staff]; SetStems[ev.b]; b.staff _ ev.b.staff}; ENDCASE; ENDLOOP; b.height _ heightb - Sheet.Height[b.sync1.time,, b.staff]; }; <<**************************************************************************>> <> <<**************************************************************************>> Grace: PUBLIC PROC[b: BeamPTR] RETURNS[BOOL] = { <> i, j: CARDINAL; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN EXIT; WITH ev: b.chord[i] SELECT FROM note => IF ~ev.n.grace THEN RETURN[FALSE]; chord => FOR j IN [0..chordLength) DO IF ev.c.note[j]=NIL THEN EXIT; IF ~ev.c.note[j].grace THEN RETURN[FALSE]; ENDLOOP; beam => IF ~Grace[ev.b] THEN RETURN[FALSE]; ENDCASE; ENDLOOP; RETURN[TRUE]; }; InVoice: PUBLIC PROC[b: BeamPTR, voice: CARDINAL] RETURNS[BOOL] = { i, j: CARDINAL; FOR i IN [0..beamLength) DO IF b.chord[i]=endOfBeam THEN EXIT; WITH ev: b.chord[i] SELECT FROM note => IF ev.n.voice=voice THEN RETURN[TRUE]; chord => FOR j IN [0..chordLength) DO IF ev.c.note[j]=NIL THEN EXIT; IF ev.c.note[j].voice=voice THEN RETURN[TRUE]; ENDLOOP; beam => IF InVoice[ev.b, voice] THEN RETURN[TRUE]; ENDCASE; ENDLOOP; RETURN[FALSE]; }; END.