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 }; 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. @BeamImplA.mesa Copyright (C) 1981, 1984 Xerox Corporation. All rights reserved. Author: John Maxwell last modified: November 28, 1981 8: 35 AM Edited by Doug Wyatt, June 14, 1984 3:32:49 pm PDT ************************************************************************** data abstractions for a beam CONSTRAINT: IF b.chord[i]=NIL THEN b.chord[j]=NIL for all j>i CONSTRAINT: b.chord[i].sync.time<=b.chord[i+1].sync.time for all i ************************************************************************** reset beamsyncs if needed make the chord stems consistent with the position of the beam determine the staff ************************************************************************** beam attributes ************************************************************************** a grace beam doesn't have ANY non-grace notes Ê ¨˜šœ™Jšœ@™@Jšœ™Jšœ*™*J™2J˜—šÏk ˜ Jšœœ ˜*Jšœœ˜J˜ Jšœœ˜Jšœœ ˜Jšœœ ˜J˜—Jšœ œ˜Jšœ.˜5Jšœ˜Jšœœœ˜ J˜š Ïn œœœ œœœ˜<š œœœœœ˜&Jšœœœ˜!Jšœ˜ Jšœ˜J˜——š žœœœœ˜A˜3Jšœœ0˜IJ˜——š žœœ œœ˜.šœœœœ˜!Jšœœœ˜Jšœœœ˜'Jšœ˜Jšœ˜J˜——šœœœœ ˜;šœœœ˜Jšœœ˜"Jšœœ˜+Jš œœœ œœœ˜>Jšœ˜—šœ˜J˜——JšœJ™JJšœ™Jšœ>™>JšœC™CJšœJ™JJ˜šžœœœ"˜2šœœ˜J˜J˜!J˜Jšœœ˜—J˜J˜—šžœœ˜)J˜Jšœœ˜Jšœœœœœœœ˜AJšœ œœ˜%Jšœ œœ˜%Jšœœ˜4Jšœœ˜4šœœ˜Jšœœ œ˜.Jšœ#œ˜0Jšœœœ˜Jšœ˜—Jšœ!œ˜7šœ œœ˜&J˜Jšœ˜—J˜J˜ Jš œ œœ œœœ˜CJšœœœ˜)Jšœ˜—J˜šžœœ˜+Jšœœ˜J˜!Jšœœœœœœœ˜AJšœ œœ˜-Jšœ œœ˜-Jšœ$œ˜DJšœ$œ˜Dšœœ˜Jšœœ œ˜.Jšœ+œ˜8Jšœœœ˜Jšœ˜—Jšœ!œ˜7šœ œœ˜&J˜Jšœ˜—J˜šœœœ˜Jšœ œœœ˜J˜Jšœ˜—Jš œ œœ œœœ˜DJšœœœ˜)Jšœ˜—J˜J˜šžœœ˜+J˜Jšœœ˜Jšœœœœœœœ˜CJšœ œœ˜(Jšœ œœ˜(Jšœœ˜:Jšœœ˜:šœœ˜Jšœœ œ˜.Jšœ&œ˜3Jšœœœ˜Jšœ˜—Jšœ!œ˜7šœ œœ˜&J˜Jšœ˜—J˜J˜ Jš œ œœ œœœ˜FJšœœœ˜)Jšœ˜—J˜J˜šžœœœ8˜KJšœœ˜Jšœœœ˜Jšœœ˜Jšœœœœ˜šœœ˜Jšœœœ˜%šœœ˜*Jšœœœ˜—Jšœœ œ˜%Jšœœ œ˜%š œœœœ˜4Jšœ œœœ˜Jšœœ˜Jšœ˜—šœœ˜J˜ Jšœ˜—J˜%Jšœœ˜ Jšœ˜—Jšœœœœ˜Jšœœœ˜:Jšœ™Jšœœœ˜Jšœœœ˜%Jšœœœ'˜4Jšœœœœ˜>Jšœœœœ˜>Jš œ œœ œœ˜=Jšœ˜—J˜šžœœœ˜!Jšœœ˜J˜šœœ˜Jšœœœ˜$šœœ˜Jšœœœ˜$Jšœ0œœ˜