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
=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