DIRECTORY Beam USING [AddItem, Free, GetHeapIndex, RemoveItem, SetSyncs, Sort, time], Chord USING [SetBeam, Sort], MusicDefs USING [BeamHeapPTR, BeamPTR, BeamRec, ChordPTR, NotePTR, noVoice, ScorePTR, SheetPTR, SyncPTR, Time, VariousPTR], Real USING [FixI], Sheet USING [Height]; BeamImplA: CEDAR PROGRAM IMPORTS Beam, Chord, Real, Sheet EXPORTS Beam = BEGIN OPEN MusicDefs; time: PUBLIC PROC[chord: VariousPTR] RETURNS[Time] ~ { WITH chord SELECT FROM n: NotePTR => RETURN[n.sync.time]; c: ChordPTR => RETURN[c.note[0].sync.time]; b: BeamPTR => { s: SyncPTR ~ GetSyncs[b].sync1; RETURN[IF s#NIL THEN s.time ELSE 0] }; ENDCASE => ERROR; }; AddItem: PUBLIC PROC[score: ScorePTR, beam: BeamPTR, item: VariousPTR] = { oldBeam: BeamPTR; sync1, sync2: SyncPTR _ NIL; FOR i: CARDINAL IN [0..beam.length) DO IF beam.chord[i] = item THEN RETURN; ENDLOOP; WITH item SELECT FROM n: NotePTR => { sync1 _ sync2 _ n.sync; oldBeam _ n.beam; n.beam _ beam }; b: BeamPTR => { sync1 _ b.sync1; sync2 _ b.sync2; oldBeam _ b; b.beam _ beam }; c: ChordPTR => { sync1 _ sync2 _ c.note[0].sync; oldBeam _ c.note[0].beam; FOR i: NAT IN[0..c.length) DO c.note[i].beam _ beam ENDLOOP; }; ENDCASE => ERROR; IF oldBeam = beam THEN ERROR; IF oldBeam#NIL THEN Beam.RemoveItem[score, oldBeam, item]; beam.chord[beam.length] _ item; beam.length _ beam.length + 1; IF sync1=NIL OR sync2=NIL THEN RETURN; -- for forward references during FileIn IF beam.sync1=NIL THEN beam.sync1 _ sync1; IF beam.sync2=NIL THEN beam.sync2 _ sync2; IF sync1.time < beam.sync1.time THEN beam.sync1 _ sync1; IF sync2.time > beam.sync2.time THEN beam.sync2 _ sync2; Sort[beam]; IF beam.beam#NIL THEN Beam.SetSyncs[beam.beam]; }; RemoveItem: PUBLIC PROC[score: ScorePTR, beam: BeamPTR, item: VariousPTR, free: BOOLEAN] = { found: BOOLEAN _ FALSE; sync1, sync2: SyncPTR _ NIL; IF beam=NIL THEN RETURN; FOR i: NAT IN[0..beam.length) DO IF beam.chord[i]=item THEN { FOR j: NAT IN[i..beam.length) DO beam.chord[j] _ beam.chord[j+1]; ENDLOOP; beam.length _ beam.length - 1; EXIT; }; REPEAT FINISHED => RETURN; ENDLOOP; WITH item SELECT FROM n: NotePTR => { sync1 _ sync2 _ n.sync; n.beam _ NIL }; c: ChordPTR => { sync1 _ sync2 _ c.note[0].sync; Chord.SetBeam[c, NIL] }; b: BeamPTR => { sync1 _ b.sync1; sync2 _ b.sync2; b.beam _ NIL }; ENDCASE => ERROR; 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]; IF free AND beam.length < 2 THEN Beam.Free[score, beam]; }; New: PUBLIC PROC[score: ScorePTR, length: CARDINAL] RETURNS[beam: BeamPTR] = { beam _ NEW[BeamRec[length] _ [chord: ]]; score.beamHeap[score.beamHeap.length] _ beam; score.beamHeap.length _ score.beamHeap.length + 1; }; Free: PUBLIC PROC[score: ScorePTR, b: BeamPTR] = { index: NAT ~ Beam.GetHeapIndex[score.beamHeap, b]; score.beamHeap[index] _ NIL; { -- pack the beamHeap score.beamHeap.length _ score.beamHeap.length - 1; score.beamHeap[index] _ score.beamHeap[score.beamHeap.length] }; IF b.beam#NIL THEN { -- put everything in the higher beam highBeam: BeamPTR _ b.beam; Beam.RemoveItem[score, highBeam, b, b.length = 0]; -- don't free beam if length > 0 FOR i: NAT DECREASING IN[0..b.length) DO -- add item to high beam Beam.AddItem[score, highBeam, b.chord[i]]; ENDLOOP; }; FOR i: NAT IN[0..b.length) DO WITH b.chord[0] SELECT FROM n: NotePTR => n.beam _ NIL; c: ChordPTR => Chord.SetBeam[c, NIL]; b: BeamPTR => b.beam _ NIL; ENDCASE; ENDLOOP; FOR i: NAT IN[0..3) DO IF score.cache.beamQueue[i]=b THEN score.cache.beamQueue[i] _ NIL; ENDLOOP; }; Sort: PUBLIC PROC[b: BeamPTR] = { FOR i: CARDINAL IN [0..b.length) DO FOR j: CARDINAL IN (i..b.length) DO IF Beam.time[b.chord[i]]>Beam.time[b.chord[j]] THEN { temp: VariousPTR ~ b.chord[i]; b.chord[i] _ b.chord[j]; b.chord[j] _ temp; }; ENDLOOP; ENDLOOP; }; SetSyncs: PUBLIC PROC[b: BeamPTR] = { sync1, sync2: SyncPTR; b.sync1 _ b.sync2 _ NIL; FOR i: NAT IN [0..b.length) DO WITH b.chord[i] SELECT FROM n: NotePTR => sync1 _ sync2 _ n.sync; c: ChordPTR => sync1 _ sync2 _ c.note[0].sync; b: BeamPTR => { sync1 _ b.sync1; sync2 _ b.sync2; }; ENDCASE; IF b.sync1 = NIL THEN b.sync1 _ sync1; IF b.sync2 = NIL THEN b.sync2 _ sync2; 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]; }; GetSyncs: PUBLIC PROC[b: BeamPTR] RETURNS[sync1, sync2: SyncPTR _ NIL] = { IF b.length = 0 THEN RETURN[NIL, NIL]; WITH b.chord[0] SELECT FROM n: NotePTR => sync1 _ n.sync; c: ChordPTR => IF c.length > 0 THEN sync1 _ c[0].sync; b: BeamPTR => sync1 _ GetSyncs[b].sync1; ENDCASE => ERROR; WITH b.chord[b.length-1] SELECT FROM n: NotePTR => sync2 _ n.sync; c: ChordPTR => IF c.length > 0 THEN sync2 _ c[0].sync; b: BeamPTR => sync2 _ GetSyncs[b].sync2; ENDCASE => ERROR; }; SetStems: PUBLIC PROC[sheet: SheetPTR, 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[sheet, b.sync1.time, , b.staff]; FOR i IN [0..b.length) DO WITH b.chord[i] SELECT FROM n: NotePTR => { heighti _ Sheet.Height[sheet, n.sync.time, n.pitch, n.staff]; timei _ Beam.time[b.chord[i]]; height _ Real.FixI[heightb+b.tilt*(timei-time1)]; n.stemUp _ (height > heighti); b.staff _ n.staff; }; c: ChordPTR => { [] _ Chord.Sort[c, FALSE]; heighti _ Sheet.Height[sheet, c.note[0].sync.time, c.note[0].pitch, c.note[0].staff]; timei _ Beam.time[b.chord[i]]; height _ Real.FixI[heightb+b.tilt*(timei-time1)]; c.stemUp _ (height > heighti); b.staff _ c.note[0].staff; }; b: BeamPTR => { b.tilt _ b.tilt; height _ Real.FixI[heightb+b.tilt*(b.sync1.time-time1)]; b.height _ height-Sheet.Height[sheet, 0, , b.staff]; SetStems[sheet, b]; b.staff _ b.staff; }; ENDCASE; ENDLOOP; b.height _ heightb - Sheet.Height[sheet, b.sync1.time, , b.staff]; }; Grace: PUBLIC PROC[b: BeamPTR] RETURNS[BOOL] = { FOR i: NAT IN[0..b.length) DO IF b.chord[i] = NIL THEN EXIT; WITH b.chord[i] SELECT FROM n: NotePTR => IF ~n.grace THEN RETURN[FALSE]; c: ChordPTR => FOR j: NAT IN [0..c.length) DO IF ~c.note[j].grace THEN RETURN[FALSE]; ENDLOOP; b: BeamPTR => IF ~Grace[b] THEN RETURN[FALSE]; ENDCASE; ENDLOOP; RETURN[TRUE]; }; InVoice: PUBLIC PROC[b: BeamPTR, voice: CARDINAL] RETURNS[BOOL] = { IF voice = noVoice THEN RETURN[TRUE]; FOR i: NAT IN [0..b.length) DO IF b.chord[i] = NIL THEN EXIT; WITH b.chord[i] SELECT FROM n: NotePTR => IF n.voice = voice THEN RETURN[TRUE]; c: ChordPTR => FOR j: NAT IN [0..c.length) DO IF c.note[j].voice = voice THEN RETURN[TRUE]; ENDLOOP; b: BeamPTR => IF InVoice[b, voice] THEN RETURN[TRUE]; ENDCASE; ENDLOOP; RETURN[FALSE]; }; GetHeapIndex: PUBLIC PROC[heap: BeamHeapPTR, p: BeamPTR] RETURNS[NAT] = { FOR i: NAT IN[0..heap.length) DO IF heap.beam[i] = p THEN RETURN[i]; ENDLOOP; RETURN[heap.length]; }; Height: PUBLIC PROC[sheet: SheetPTR, b: BeamPTR, time: Time] RETURNS[h: INTEGER] = { sync1: SyncPTR _ GetSyncs[b].sync1; h _ b.height+Sheet.Height[sheet, sync1.time, , b.staff]; IF time # sync1.time THEN h _ h + Real.FixI[(time-sync1.time)*b.tilt]; }; END. €BeamImplA.mesa Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved. Author: John Maxwell Last Edited by: Maxwell, November 22, 1983 10:12 am Last Edited by: Doug Wyatt, June 13, 1984 3:57:56 pm PDT ************************************************************************** data abstractions for a beam CONSTRAINT: b.chord[i] # NIL for all i < b.length CONSTRAINT: b.chord[i].sync.time <= b.chord[i+1].sync.time for all i < b.length CONSTRAINT: b.sync1.time <= b.chord[i].sync.time for all i < b.length CONSTRAINT: b.sync2.time >= b.chord[i].sync.time for all i < b.length ************************************************************************** IF NOT beam.lengthJ™NJ™—J™—Jšœ™—Jšœ˜J˜—šžœœœ˜!šœœœ˜#šœœœ˜#šœ-œ˜5J˜J˜J˜J˜—Jšœ˜—Jšœ˜—Jšœ˜J˜—šžœœœ˜%J˜Jšœœ˜šœœœ˜šœ œ˜J˜%Jšœ.˜.Jšœ4˜4Jšœ˜—Jšœ œœ˜&Jšœ œœ˜&Jšœœ˜2Jšœœ˜3Jšœ˜—J˜ Jšœ œœ˜'Jšœ˜J˜—š žœœœ œœ˜JJš œœœœœ˜&šœ œ˜J˜Jšœœœ˜6J˜(Jšœœ˜—šœœ˜$J˜Jšœœœ˜6J˜(Jšœœ˜—Jšœ˜J˜—šžœœœ!˜6Jšœ=™=Jšœœ˜ Jšœœ˜"J˜"Jšœœ œœ˜Jšœ™J˜@šœœ˜šœ œ˜˜J˜=J˜J˜1J˜J˜J˜—˜Jšœœ˜J˜UJ˜J˜1J˜J˜J˜—˜J˜J˜8J˜4J˜J˜J˜—Jšœ˜—Jšœ˜—J˜CJšœ˜J˜—JšœJ™JJšœ™JšœJ™JJ˜š žœœœ œœ˜0Jšœ-™-šœœœ˜Jšœœœœ˜šœ œ˜Jš œœ œœœ˜-šœœœœ˜-Jšœœœœ˜'Jšœ˜—Jš œœ œœœ˜.Jšœ˜—Jšœ˜—Jšœœ˜ Jšœ˜J˜—š žœœœœœœ˜CJšœœœœ˜%šœœœ˜Jšœœœœ˜šœ œ˜Jš œœœœœ˜3šœœœœ˜-Jšœœœœ˜-Jšœ˜—Jš œœœœœ˜5Jšœ˜—Jšœ˜—Jšœœ˜Jšœ˜J˜—š ž œœœ œœ˜Išœœœœ˜!Jšœœœ˜$Jšœ˜ —Jšœ˜šœ˜J˜——š žœœœ*œœ˜TJšœ#˜#J˜8Jšœœ-˜FJšœ˜J˜—J˜Jšœ˜J˜—…—0