<> <> <> <> <> DIRECTORY Beam USING [Height, InVoice], MusicDefs, Note USING [Delete, Delta, FindChord], Piece USING [CleanUpSyncs, Length, RemoveSync], Real USING [FixI], Score USING [GetKey, ShowPitch], Sheet USING [FindLine, FindSection, Height, NearestTime, NextLine], Sync USING [GetScoreIndex, Octava], Utility USING [FreeSync]; PieceImplA: CEDAR PROGRAM IMPORTS Beam, MusicDefs, Note, Piece, Real, Score, Sheet, Sync, Utility EXPORTS MusicDefs, Piece = BEGIN OPEN MusicDefs; dataStructureInFlux: PUBLIC BOOL _ FALSE; Length: PROC[p: PiecePTR] RETURNS[NAT] = { IF p=NIL THEN RETURN[0]; IF p=MusicDefs.score THEN RETURN[scoreLength]; FOR i: NAT IN [0..maxPieceLength] DO IF i=maxPieceLength THEN RETURN[i]; IF p[i]=NIL THEN RETURN[i]; ENDLOOP; ERROR; }; <<****************************************************************************>> <> <> <> <> <> <<****************************************************************************>> AddSync: PUBLIC PROC[p: PiecePTR, s: SyncPTR] = { <> length: CARDINAL=Piece.Length[p]; IF s=NIL THEN RETURN; <> IF p=score AND length+1=maxScoreLength THEN Overflow[score]; IF p#score AND length+1=maxPieceLength THEN Overflow[piece]; <> IF p=score THEN dataStructureInFlux _ TRUE; FOR i: CARDINAL DECREASING IN [0..length) DO IF p[i]=NIL THEN LOOP; IF p[i].time < s.time THEN {p[i+1] _ s; s _ NIL; EXIT}; IF p[i].time = s.time AND ~LessThan[s.type, p[i].type] THEN {p[i+1] _ s; s _ NIL; EXIT}; p[i+1] _ p[i]; ENDLOOP; IF s#NIL THEN p[0] _ s; IF p=score THEN scoreLength _ scoreLength+1; IF p=score THEN dataStructureInFlux _ FALSE; }; LessThan: PROC[a, b: EventType] RETURNS[BOOL] = INLINE { SELECT TRUE FROM a=staves => RETURN[TRUE]; b=staves => RETURN[FALSE]; a=keySignature => RETURN[TRUE]; b=keySignature => RETURN[FALSE]; Measure[a] => RETURN[TRUE]; Measure[b] => RETURN[FALSE]; a=metrenome => RETURN[TRUE]; b=metrenome => RETURN[FALSE]; a=timeSignature => RETURN[TRUE]; b=timeSignature => RETURN[FALSE]; a IN SheetSwitch => RETURN[TRUE]; b IN SheetSwitch => RETURN[FALSE]; ENDCASE => RETURN[TRUE]; }; RemoveSync: PUBLIC PROC[p: PiecePTR, s: SyncPTR] = { <> <> i, j: CARDINAL _ 0; length: CARDINAL _ Piece.Length[p]; FOR i IN [0..length) DO IF p[i]=s THEN LOOP; IF i#j THEN p[j] _ p[i]; j _ j+1; ENDLOOP; FOR i IN [0..syncLength) DO IF s.event[i]=NIL THEN EXIT; s.event[i].sync _ NIL; ENDLOOP; length _ j; p[length] _ NIL; IF p=score THEN scoreLength _ length; }; DeleteSync: PUBLIC PROC[s: SyncPTR] = { octava: SyncPTR _ NIL; index: CARDINAL _ Sync.GetScoreIndex[s]; IF s.type IN [octava1..octava2] THEN octava _ Sync.Octava[s]; Piece.RemoveSync[score, s]; IF octava#NIL THEN { SetDirty[octava.time, octava.time]; Piece.RemoveSync[score, octava]; Utility.FreeSync[@octava]}; Utility.FreeSync[@s]; }; Sort: PUBLIC PROC[p: PiecePTR] = <> i, j: CARDINAL; temp: SyncPTR; length: CARDINAL = Piece.Length[p]; FOR i IN [0..length) DO FOR j IN (i..length) DO IF p[j] = NIL THEN LOOP; IF p[i] = NIL THEN {p[i] _ p[j]; p[j] _ NIL; LOOP}; IF p[i].time > p[j].time THEN {temp _ p[i]; p[i] _ p[j]; p[j] _ temp}; IF p[i].time= p[j].time THEN {IF p[i].event[0]=NIL OR p[j].event[0]=NIL THEN LOOP; IF p[i].event[0].toc> <> <<****************************************************************************>> NearestSync: PUBLIC PROC[p: PiecePTR, t: Time, notesOnly: BOOL _ FALSE] RETURNS[index: CARDINAL]= { delta: Time _ 10000; length: CARDINAL = Piece.Length[p]; index _ 0; FOR binary: CARDINAL _ 8192, binary/2 UNTIL binary=0 DO IF index+binary>=length THEN LOOP; IF p[index+binary].time<=t THEN index _ index+binary; IF p[index].time=t THEN EXIT; ENDLOOP; <> FOR i: CARDINAL IN [(IF index<5 THEN 0 ELSE index-5)..MIN[index+5, length]) DO IF notesOnly AND p[i].type#notes THEN LOOP; IF ABS[p[i].time-t] > delta THEN LOOP; index _ i; delta _ ABS[p[i].time-t]; ENDLOOP; IF notesOnly AND index#length AND p[index].type#notes THEN index _ length; }; NearestNote: PUBLIC PROC[x, y: INTEGER] RETURNS[p: NotePTR] = { n: NotePTR; key: INTEGER; time, dt, t: Time _ 11; i, j, k, l, next: CARDINAL; height, dy, show: INTEGER _ 8; [time, height] _ Sheet.NearestTime[x, y]; next _ Sheet.FindLine[time]; time _ time - (staffLength - sheet[next].x); l _ Sheet.FindLine[time]; height _ height + (sheet[next].y - sheet[l].y); FOR k IN [0..2] DO FOR i IN [0..scoreLength) DO IF score[i].time< time - 40 THEN LOOP; IF score[i].time> time + 40 THEN EXIT; IF score[i].time=sheet[next].time THEN EXIT; FOR j IN [0..syncLength) DO IF (n _ score[i].event[j]) = NIL THEN EXIT; IF voice AND n.voice#selectedVoice THEN LOOP; t _ ABS[score[i].time+5+Note.Delta[n]-time]; key _ Score.GetKey[n.sync.time]; show _ Score.ShowPitch[n.pitch, n.spelled, key]; y _ ABS[height-Sheet.Height[n.sync.time, show, n.staff]]; IF y+t>dy+dt THEN LOOP; IF y+t=dy+dt AND t>dt THEN LOOP; dt _ t; dy _ y; p _ n; ENDLOOP; ENDLOOP; time _ time+ (staffLength - sheet[next].x); height _ height- (sheet[next].y - sheet[l].y); l _ next; next _ Sheet.NextLine[l]; ENDLOOP; IF dt>10 OR dy>7 THEN p _ NIL; }; NearestObject: PUBLIC PROC[x, y: INTEGER] RETURNS[obj: ObjectType, p: UnspecifiedPTR _ NIL] = { n: NotePTR; l: CARDINAL; key: INTEGER; staves: StavesPTR; i, j, k, s, next: CARDINAL _ 0; time, dt, t: Time _ 11; height, dy, show: INTEGER _ 8; [time, height] _ Sheet.NearestTime[x, y]; next _ Sheet.FindLine[time]; time _ time - (staffLength - sheet[next].x); l _ Sheet.FindLine[time]; height _ height + (sheet[next].y - sheet[l].y); FOR k IN [0..2] DO <> FOR i IN [0..beamHeapLength) DO IF beamHeap[i].beam#NIL AND beamHeap[i].beam.beamed THEN LOOP; IF beamHeap[i].sync1.time-5 > time THEN LOOP; IF beamHeap[i].sync2.time+5 < time THEN LOOP; IF voice AND ~Beam.InVoice[beamHeap[i], selectedVoice] THEN LOOP; y _ Beam.Height[beamHeap[i], time]; IF ABS[y-height]+4 > dt+dy THEN LOOP; IF ABS[y-height]+4 = dt+dy THEN IF y>height THEN LOOP; dt _ 4; dy _ ABS[y-height]; IF time < (beamHeap[i].sync1.time+beamHeap[i].sync2.time+4)/2 THEN obj _leftBeam ELSE obj _rightBeam; p _ beamHeap[i]; ENDLOOP; <> FOR i IN [s..scoreLength) DO IF score[i].time< time - 300 THEN LOOP; IF score[i].time> time + 300 THEN {s _ i; EXIT}; IF score[i].timetime THEN LOOP; t _ ABS[(n.sync.time+n.tie.sync.time)/2-time]; key _ Score.GetKey[n.sync.time]; show _ Score.ShowPitch[n.pitch, n.spelled, key]; y _ ABS[height-(Sheet.Height[n.sync.time, show, n.staff]+n.tieHeight/2)]; IF y+t>dy+dt THEN LOOP; IF y+t=dy+dt THEN IF t>dt THEN LOOP; dt _ t; dy _ y; obj _ tie; p _ n; ENDLOOP; IF score[i].time>=sheet[next].time THEN LOOP; IF ABS[score[i].time-time]>40 THEN LOOP; IF score[i].type IN SheetSwitch AND score[i].type#staves THEN { octava: SyncPTR _ NIL; staff, top, bottom: INTEGER _ score[i].value; t _ score[i].time; IF score[i].type=clef THEN t _ t+6; IF ABS[t-time]+6> dt + dy THEN LOOP; IF ABS[t-time]+6=dt+dy AND t