FilerImpl.mesa
Copyright (C) 1981, 1984 Xerox Corporation. All rights reserved.
Author: John Maxwell
last modified: December 16, 1981 7: 58 AM
Edited by Doug Wyatt, June 14, 1984 1:07:22 pm PDT
DIRECTORY
Beam USING [GetHeapIndex, Length, SetSyncs],
Chord USING [GetHeapIndex, Length],
MusicDefs,
MusicFileDefs,
Note USING [GetSyncIndex],
Piece USING [MaxToc],
Score USING [FileStats, Look, SetKey, SetMetrenome, Test],
Sheet USING [Reset, SetBegin],
StreamDefs USING [Append, DiskHandle, NewWordStream, Read, ReadBlock, WriteBlock, Write],
Sync USING [AddTimes, GetScoreIndex, Length],
Utility USING [InitStorage, NewBeam, NewChord, NewNote, NewSync];
FilerImpl: CEDAR PROGRAM
IMPORTS Beam, Chord, MusicDefs, Note, Piece, Score, Sheet, StreamDefs, Sync, Utility
EXPORTS Score
= BEGIN OPEN MusicDefs, MusicFileDefs;
Error: SIGNAL;
****************************************************************************
filein, fileout
****************************************************************************
version: INTEGER;
FileIn: PUBLIC PROC[s: STRING, append: BOOLEAN] = BEGIN
tie: TieFormat;
temp: SyncPTR;
note: NoteFormat;
view: ViewFormat;
event: EventFormat;
beam: BeamFormat;
chord: ChordFormat;
pointer: RelativePTR;
inputStream: StreamDefs.DiskHandle;
n: NotePTR; c: ChordPTR; last, lastP: Time ← 0;
i, j, k, length, oldBHLength, oldSLength, oldCHLength: CARDINAL;
inputStream ← StreamDefs.NewWordStream[s, StreamDefs.Read];
inputStream.reset[inputStream];
[] ← GetBlock[inputStream, NIL, 0]; --signal to fill up buffer
version ← Get[inputStream];
prepare for append
IF NOT append THEN Utility.InitStorage[];
oldBHLength ← beamHeapLength;
oldSLength ← scoreLength;
oldCHLength ← chordHeapLength;
IF scoreLength#0 THEN last ← score[scoreLength-1].time+20;
IF scoreLength#0 THEN lastP ← Piece.MaxToc[score, last-50, last, TRUE];
file in score
IF Get[inputStream]#scoreID THEN Error;
length ← Get[inputStream];
FOR i IN [oldSLength..oldSLength+length) DO
[] ← GetBlock[inputStream,@event, SIZE[EventFormat]];
BuildEvent[(score[i] ← Utility.NewSync[]),@event];
FOR j IN [0..event.length) DO
[] ← GetBlock[inputStream,@note, SIZE[NoteFormat]];
BuildNote[(score[i].event[j] ← Utility.NewNote[]),@note];
score[i].event[j].sync ← score[i];
IF NOT note.tie THEN LOOP;
[] ← GetBlock[inputStream,@tie, SIZE[TieFormat]];
score[i].event[j].tie ← score[tie.heap+oldSLength].event[tie.index];
score[i].event[j].tieHeight ← tie.height;
score[i].event[j].tie.tied ← TRUE;
ENDLOOP;
IF event.exception THEN
{
sheet: Staves ← [, 0, 0, 0,,];
[] ← GetBlock[inputStream,@sheet, SIZE[SheetFormat]];
BuildSheet[score[i],@sheet];
};
temp ← score[i];
IF score[i].time=-1 AND score[i].type=staves THEN { -- sort the score
FOR j IN [oldSLength..i) DO score[j+1]← score[j]; ENDLOOP;
score[oldSLength] ← temp;
score[oldSLength].time ← 0};
IF append THEN Sync.AddTimes[temp, last, lastP];
scoreLength ← i+1;
ENDLOOP;
file in chordheap
IF Get[inputStream]#chordHeapID THEN Error;
length ← Get[inputStream];
FOR i IN [oldCHLength..oldCHLength+length) DO
[] ← GetBlock[inputStream,@chord, SIZE[ChordFormat]];
BuildChord[(chordHeap[i] ← Utility.NewChord[]),@chord];
FOR j IN [0..chord.length) DO
[] ← GetBlock[inputStream,@pointer, SIZE[RelativePTR]];
chordHeap[i].note[j] ← score[pointer.heap+oldSLength].event[pointer.index];
chordHeap[i].note[j].chord ← chordHeap[i];
ENDLOOP;
ENDLOOP;
file in beamheap
IF Get[inputStream]#beamHeapID THEN Error;
length ← Get[inputStream];
FOR i IN [oldBHLength..oldBHLength+length) DO beamHeap[i] ← Utility.NewBeam[]; ENDLOOP;
FOR i IN [oldBHLength..oldBHLength+length) DO
[] ← GetBlock[inputStream,@beam, SIZE[BeamFormat]];
FOR j IN [0..beam.length) DO
[] ← GetBlock[inputStream,@pointer, SIZE[RelativePTR]];
SELECT pointer.heap FROM
beams => {
beamHeap[i].chord[j] ← [beam[beamHeap[pointer.index+oldBHLength]]];
beamHeap[pointer.index+oldBHLength].beam ← beamHeap[i];
};
chords =>{
c ← chordHeap[pointer.index+oldCHLength];
beamHeap[i].chord[j] ← [chord[c]];
FOR k IN [0..chordLength) DO
IF c.note[k] = NIL THEN EXIT;
c.note[k].beam ← beamHeap[i];
ENDLOOP;
};
ENDCASE=>{
n ← score[pointer.heap+oldSLength].event[pointer.index];
beamHeap[i].chord[j] ← [note[n]];
n.beam ← beamHeap[i];
};
BuildBeam[beamHeap[i],@beam];
ENDLOOP;
ENDLOOP;
FOR i IN [oldBHLength..oldBHLength+length) DO
Beam.SetSyncs[beamHeap[i]];
ENDLOOP;
file in spares
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
IF Get[inputStream]#nullID THEN Error;
file in view
[] ← GetBlock[inputStream,@view, SIZE[ViewFormat]];
BuildView[@view];
clean up and return
bufferIndex ← 0;
inputStream.destroy[inputStream];
command ← TRUE;
Score.FileStats[];
Sheet.SetBegin[0];
END;
Get: PROC[s: StreamDefs.DiskHandle] RETURNS[data: UNSPECIFIED] =
INLINE { [] ← GetBlock[s,@data, 1]; };
GetBlock: PROC[s: StreamDefs.DiskHandle, p: POINTER, length: CARDINAL] RETURNS[INTEGER] = {
a hack to speed up disk transfers by batching them together
i: CARDINAL;
array: POINTER TO ARRAY[0..1000) OF INTEGERLOOPHOLE[p];
IF p=NIL THEN {
[] ← StreamDefs.ReadBlock[s,@buffer, bufferLength];
bufferIndex ← 0;
RETURN[0];
};
FOR i IN [0..length) DO
array[i] ← buffer[bufferIndex];
bufferIndex ← bufferIndex+1;
IF bufferIndex< bufferLength THEN LOOP;
[] ← StreamDefs.ReadBlock[s,@buffer, bufferLength];
bufferIndex ← 0;
ENDLOOP;
RETURN[0];
};
BuildEvent: PROC[old: SyncPTR, new: POINTER TO EventFormat] = {
IF new.identifier#eventID THEN Error;
old.time ← new.time;
SELECT version FROM
1 => old.type ← LOOPHOLE[LOOPHOLE[new.type, CARDINAL]/4];
ENDCASE => old.type ← new.type;
IF old.type=timeSignature THEN old.ts ← LOOPHOLE[new.value]
ELSE old.value← new.value;
};
BuildSheet: PROC[old: SyncPTR, staves: StavesPTR] = {
old.event ← LOOPHOLE[staves^];
staves ← LOOPHOLE[@old.event];
IF version<3 THEN ConvertSheet2[old];
IF old.type=staves AND old.value=-1 THEN FindStyle[old];
};
ConvertSheet2: PROC[old: SyncPTR] = {
staves: StavesPTR ← LOOPHOLE[@old.event];
IF old.value=-1 THEN {old.type ← staves; RETURN};
IF staves.staff[old.value].pitch=15 THEN {
old.type ← octava1;
staves.height ← -30;
RETURN};
IF staves.staff[old.value].pitch=60 THEN {
old.type ← octava1;
staves.height ← 60;
RETURN};
FOR i: CARDINAL DECREASING IN [0..scoreLength) DO
is the present clef change the latter part of an octava pair?
IF score[i].type NOT IN SheetSwitch THEN LOOP;
staves ← LOOPHOLE[@score[i].event];
SELECT staves.staff[old.value].pitch FROM
15 => old.type ← octava2;
60 => old.type ← octava2;
ENDCASE => old.type ← clef;
RETURN; ENDLOOP;
};
FindStyle: PROC[old: SyncPTR] = {
staves: StavesPTR ← LOOPHOLE[@old.event];
index: INTEGER ← 1;
FOR i: CARDINAL IN [1..staves.sl] DO
IF staves.staff[i].y=staves.staff[i-1].y THEN LOOP;
index ← index+1;
ENDLOOP;
IF index=4 AND staves.staff[0].pitch=72 THEN index ← 0;
old.value ← index;
staves^ ← style[index];
};
BuildNote: PROC[old: NotePTR, new: POINTER TO NoteFormat] = {
IF new.identifier#noteID THEN Error;
old.pitch ← new.pitch;
old.value ← new.value;
old.embellish ← new.embellish;
old.grace ← new.grace;
old.voice ← new.voice;
maxVoice ← MAX[old.voice, maxVoice];
old.spelled ← new.spelled;
old.rest ← new.rest;
old.dotted ← new.dotted;
old.doubleDotted ← new.doubleDotted;
old.stemUp ← new.stemUp;
old.staff ← new.staff;
old.toc ← new.toc;
old.duration ← new.duration;
};
BuildChord: PROC[old: ChordPTR, new: POINTER TO ChordFormat] = {
IF new.identifier#chordID THEN Error;
old.stemUp ← new.stemUp;
};
BuildBeam: PROC[old: BeamPTR, new: POINTER TO BeamFormat] = {
IF new.identifier#beamID THEN Error;
old.tilt ← new.tilt;
old.beamed ← new.beamed;
old.invisible ← new.invisible;
old.ntuple ← new.ntuple;
old.against ← new.against;
old.height ← new.height;
old.staff ← new.staff;
Beam.SetSyncs[old];
};
BuildView: PROC[view: POINTER TO ViewFormat] = {
TF ← view.scale;
IF view.display#physical AND TF>10 THEN TF ← 3; --temporary hack
SELECT view.sheet FROM -- convert from old indices to new ones
1 => Score.Look[sheet,, 0];
6, 7 => Score.Look[sheet,, 1];
2 => Score.Look[sheet,, 2];
4, 5 => Score.Look[sheet,, 3];
3 => Score.Look[sheet,, 4];
ENDCASE;
show.accidental ← view.accidental;
show.sync ← view.sync;
show.notehead ← view.notehead;
show.display ← view.display;
show.noCarry ← view.noCarry;
Score.Look[hardcopy, view.hardcopy,];
IF version=1 THEN Score.SetKey[0, EndOfScore[], view.key];
IF version=1 THEN Score.SetMetrenome[0, EndOfScore[], view.speed];
Sheet.Reset[];
};
****************************************************************************
fileout
****************************************************************************
FO: PROC RETURNS[STRING] = {
RETURN[IF FileOut["temp.music"]
THEN "filed out on temp.music" 
ELSE "fileout aborted"];
};
buffer: ARRAY [0..bufferLength) OF INTEGER;
bufferIndex: CARDINAL ← 0;
bufferLength: CARDINAL = 500;
FileOut: PUBLIC PROC[s: STRING] RETURNS[BOOLEAN] = {
OPEN StreamDefs;
i, j: CARDINAL;
outputStream: StreamDefs.DiskHandle;
event: EventFormat;
note: NoteFormat;
chord: ChordFormat;
beam: BeamFormat;
tie: TieFormat;
view: ViewFormat;
pointer: RelativePTR;
n: NotePTR;
IF Score.Test[] THEN RETURN[FALSE];
outputStream ← StreamDefs.NewWordStream[s, StreamDefs.Write+StreamDefs.Append];
outputStream.reset[outputStream];
file out score
Put[outputStream, versionID];
Put[outputStream, scoreID];
Put[outputStream, scoreLength];
FOR i IN [0..scoreLength) DO
ConvertEvent[score[i],@event];
[] ← PutBlock[outputStream,@event, SIZE[EventFormat]];
IF event.exception THEN
{
sheet: Staves ← LOOPHOLE[score[i].event];
[] ← PutBlock[outputStream,@sheet, SIZE[SheetFormat]];
};
FOR j IN [0..syncLength) DO
IF (n ← score[i].event[j])=NIL THEN EXIT;
ConvertNote[n,@note];
note.tie ← n.tie#NIL;
[] ← PutBlock[outputStream,@note, SIZE[NoteFormat]];
IF NOT note.tie THEN LOOP;
tie.heap ← Sync.GetScoreIndex[n.tie.sync];
tie.index ← Note.GetSyncIndex[n.tie.sync, n.tie];
tie.height ← score[i].event[j].tieHeight;
[] ← PutBlock[outputStream,@tie, SIZE[TieFormat]]
ENDLOOP;
ENDLOOP;
file out chordheap
Put[outputStream, chordHeapID];
Put[outputStream, chordHeapLength];
FOR i IN [0..chordHeapLength) DO
ConvertChord[chordHeap[i],@chord];
[] ← PutBlock[outputStream,@chord, SIZE[ChordFormat]];
pointer.heap ← Sync.GetScoreIndex[chordHeap[i].note[0].sync]; 
FOR j IN [0..chordLength) DO
IF chordHeap[i].note[j] = NIL THEN EXIT;
pointer.index ← Note.GetSyncIndex[score[pointer.heap], chordHeap[i].note[j]];
[] ← PutBlock[outputStream,@pointer, SIZE[RelativePTR]];
ENDLOOP;
ENDLOOP;
file out beamheap
Put[outputStream, beamHeapID];
Put[outputStream, beamHeapLength];
FOR i IN [0..beamHeapLength) DO
ConvertBeam[beamHeap[i],@beam];
[] ← PutBlock[outputStream,@beam, SIZE[BeamFormat]];
FOR j IN [0..beamLength) DO
IF beamHeap[i].chord[j] = endOfBeam THEN EXIT;
WITH ev: beamHeap[i].chord[j] SELECT FROM
note => {
pointer.heap ← Sync.GetScoreIndex[ev.n.sync];
pointer.index← Note.GetSyncIndex[score[pointer.heap], ev.n];
};
chord=> {
pointer.heap ← chords;
pointer.index← Chord.GetHeapIndex[ev.c];
};
beam => {
pointer.heap ← beams;
pointer.index← Beam.GetHeapIndex[ev.b];
};
ENDCASE;
[] ← PutBlock[outputStream,@pointer, SIZE[RelativePTR]];
ENDLOOP;
ENDLOOP;
file out nine spares
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
Put[outputStream, nullID];
file out view
ConvertView[@view];
[] ← PutBlock[outputStream,@view, SIZE[ViewFormat]];
clean up and return
[] ← PutBlock[outputStream, NIL, 0]; --clean up buffer
outputStream.destroy[outputStream];
command ← TRUE;
RETURN[TRUE];
};
Put: PROC[s: StreamDefs.DiskHandle, data: INTEGER] =
INLINE { [] ← PutBlock[s,@data, 1]; };
PutBlock: PROC[s: StreamDefs.DiskHandle, p: POINTER, length: CARDINAL] RETURNS[INTEGER] = {
a hack to speed up disk transfers by batching them together
i: CARDINAL;
array: POINTER TO ARRAY[0..1000) OF INTEGERLOOPHOLE[p];
IF length=0 THEN {
IF bufferIndex=0 THEN RETURN[0];
[] ← StreamDefs.WriteBlock[s,@buffer, bufferIndex];
bufferIndex ← 0;
RETURN[0]; };
FOR i IN [0..length) DO
buffer[bufferIndex] ← array[i];
bufferIndex ← bufferIndex+1;
IF bufferIndex< bufferLength THEN LOOP;
[] ← StreamDefs.WriteBlock[s,@buffer, bufferIndex];
bufferIndex ← 0;
ENDLOOP;
RETURN[0];
};
ConvertEvent: PROC[data: SyncPTR, file: POINTER TO EventFormat] = {
file^ ← []; --defaults to the values listed in musicFileDefs
file.time ← data.time;
file.type ← data.type;
SELECT data.type FROM
notes => file.length ← Sync.Length[data];
timeSignature => file.value ← LOOPHOLE[data.ts];
ENDCASE => file.value ← data.value;
IF data.type IN SheetSwitch THEN file.exception ← TRUE;
};
ConvertNote: PROC[old: NotePTR, new: POINTER TO NoteFormat] = {
new.pitch ← old.pitch;
new.value ← old.value;
new.embellish ← old.embellish;
new.voice ← old.voice;
new.spelled ← old.spelled;
new.rest ← old.rest;
new.dotted ← old.dotted;
new.doubleDotted ← old.doubleDotted;
new.grace ← old.grace;
new.stemUp ← old.stemUp;
new.staff ← old.staff;
new.toc ← old.toc;
new.duration ← old.duration;
};
ConvertChord: PROC[old: ChordPTR, new: POINTER TO ChordFormat] = {
new.stemUp ← old.stemUp;
new.length ← Chord.Length[old];
};
ConvertBeam: PROC[old: BeamPTR, new: POINTER TO BeamFormat] = {
new.tilt ← old.tilt;
new.beamed ← old.beamed;
new.invisible ← old.invisible;
new.ntuple ← old.ntuple;
new.against ← old.against;
new.height ← old.height;
new.staff ← old.staff;
new.length ← Beam.Length[old];
};
ConvertView: PROC[view: POINTER TO ViewFormat] = {
view.scale ← TF;
view.sheet ← 0;
view.speed ← 128;
view.accidental ← show.accidental;
view.sync ← show.sync;
view.notehead ← show.notehead;
view.display ← show.display;
view.noCarry ← show.noCarry;
view.hardcopy ← hardcopy;
};
END.
ConvertReals: PROC = {
i: CARDINAL;
FOR i IN [0..beamHeapLength) DO
IF beamHeap[i]=NIL THEN LOOP;
beamHeap[i].tilt ← RealConvert.Mesa5ToIeee[beamHeap[i].tilt];
ENDLOOP;
};
****************************************************************************
filein, fileout pianorolls
****************************************************************************
FileInOld: PUBLIC PROC[s: STRING] = {
OPEN DataDefs, StreamDefs;
i, length: CARDINAL ← 0;
pn: PhysicalNote;
note: NotePTR;
sync: SyncPTR ← NIL;
oldToc: Time;
inputStream: DiskHandle;
inputStream ← NewWordStream[s, Read];
inputStream.reset[inputStream];
length ← inputStream.get[inputStream];
[] ← inputStream.get[inputStream];
NewScore[];
WHILE NOT inputStream.endof[inputStream] DO
[] ← ReadBlock[inputStream,@pn, SIZE[PhysicalNote]];
IF pn.duration<4 THEN LOOP;
IF pn.pitch>80 OR pn.pitch<-7 THEN LOOP;
note ← NewNote[];
note^ ← []; --defaults to the values listed in musicDefs
note.toc ← pn.toc;
note.duration ← pn.duration;
note.pitch ← pn.pitch;
SELECT TRUE FROM
note.pitch IN [67..80] => { note.stemUp ← FALSE; note.staff ← 0; };
note.pitch IN [56..66] => { note.stemUp← TRUE; note.staff ← 0; };
note.pitch IN [43..55] => { note.stemUp ← FALSE; note.staff ← 1; };
note.pitch IN [32..42] => { note.stemUp← TRUE; note.staff ← 1; };
note.pitch IN [22..31] => { note.stemUp ← FALSE; note.staff ← 2; };
note.pitch IN [10..21] => { note.stemUp← TRUE; note.staff ← 2; };
note.pitch IN [ 0.. 9] => { note.stemUp ← FALSE; note.staff ← 3; };
note.pitch IN [-7..-1] => { note.stemUp← TRUE; note.staff ← 3; };
ENDCASE;
IF ABS[note.toc - oldToc] > 200
THEN {
AddSyncToPiece[sync, score];
oldToc ← note.toc;
sync ← NewSync[];
};
sync.time ← note.toc/256;
AddToSync[sync, note];
i ← i + 1;
IF i=length THEN EXIT;
ENDLOOP;
AddSyncToPiece[sync, score];
inputStream.destroy[inputStream];
ActionDefs.Look[accidental, FALSE,];
ActionDefs.Look[sheet,, 1];
ActionDefs.Look[notehead, FALSE,];
selectionLength ← 0;
SortScore[];
UtilityDefs.DrawScore[TRUE];
};
FileOutOld: PUBLIC PROC[s: STRING] = {
OPEN StreamDefs;
i, j: CARDINAL;
pNote: PhysicalNote;
n: NotePTR;
inputStream: DiskHandle;
inputStream ← NewWordStream[s, Write+Append];
inputStream.reset[inputStream];
inputStream.put[inputStream, 0];
inputStream.put[inputStream, 0];
FOR i IN [0..scoreLength) DO
FOR j IN [0..syncLength) DO
IF (n ← score[i].event[j])=NIL THEN EXIT;
IF score[i].event[j].rest THEN LOOP;
IF n.duration = 0 THEN LOOP;
pNote ← [n.pitch, n.duration, 50, n.toc];
[] ← WriteBlock[inputStream,@pNote, SIZE[PhysicalNote]];
ENDLOOP;
ENDLOOP;
inputStream.destroy[inputStream];
UtilityDefs.DrawScore[TRUE];
};
}....
************************************************************************
filein, fileout old .logical format
************************************************************************
FileInOld: PUBLIC PROC[s: STRING] = {
OPEN StreamDefs;
i, j, noChords, noBeams: CARDINAL;
rchord: RChord;
rbeam: RBeam;
convert: BOOLEANFALSE;
inputStream: DiskHandle;
inputStream ← NewWordStream[s, Read];
inputStream.reset[inputStream];
IF append THEN InitAppend[] ELSE NewScore[];
scoreLength ← inputStream.get[inputStream]+start;
maxVoice ← 0;
FOR i IN [start..scoreLength) DO score[i] ← NewSync[]; ENDLOOP;
FOR i IN [start..scoreLength) DO
[] ← ReadBlock[inputStream, score[i], SIZE[Sync]];
score[i].time ← score[i].time + offset;
FOR j IN [0..syncLength) DO
IF score[i].event[j]=NIL THEN EXIT;
[] ← ReadBlock[inputStream, score[i].event[j] ← NewNote[], SIZE[Note]];
score[i].event[j].sync ← score[i];
IF skipBeams THEN score[i].event[j].beam ← NIL;
maxVoice ← MAX[maxVoice, score[i].event[j].voice];
ENDLOOP;
ENDLOOP;
noChords ← inputStream.get[inputStream];
FOR i IN [0..noChords) DO
[] ← ReadBlock[inputStream,@rchord, SIZE[RChord]];
RestoreChord[@rchord, NewChord[]];
ENDLOOP;
noBeams ← inputStream.get[inputStream];
FOR i IN [0..noBeams) DO
[] ← ReadBlock[inputStream,@rbeam, SIZE[RBeam]];
IF skipBeams THEN LOOP;
RestoreBeam[@rbeam, NewBeam[]];
IF rbeam.beam.tilt> 3 OR rbeam.beam.tilt<-3 THEN convert ← TRUE;
ENDLOOP;
IF NOT inputStream.endof[inputStream] THEN FileInSheet[inputStream];
inputStream.destroy[inputStream];
IF convert THEN Convert[];
UtilityDefs.ResetSheet[];
UtilityDefs.DrawScore[TRUE];
};
FileInSheet: PROC[stream: StreamDefs.DiskHandle]= {
OPEN StreamDefs;
[] ← ReadBlock[stream,@keyArray, 2*keyLength];
[] ← ReadBlock[stream,@show, SIZE[DocumentProfile]];
[] ← ReadBlock[stream,@metrenome, SIZE[INTEGER]];
[] ← ReadBlock[stream,@TF, SIZE[CARDINAL]];
[] ← ReadBlock[stream,@sheet, SIZE[Staves]];
sheet.staff[4] ← [0, 0]; sheet.staff[5] ← [0, 0];
KeyIndexToSync[];
};
KeyIndexToSync: PROC = {
k: CARDINAL;
FOR k IN [0..keyLength) DO
keyArray[k].sync ← score[LOOPHOLE[keyArray[k].sync, CARDINAL]];
ENDLOOP;
};
skipBeams: BOOLEANFALSE;
bstart, cstart: CARDINAL ← 0;
offset: Time ← 0;
append: BOOLEANFALSE;
InitAppend: PROC = {
start ← scoreLength;
bstart ← beamHeapLength;
cstart ← chordHeapLength;
IF scoreLength#0 THEN offset ← score[scoreLength-1].time+10;
};
RestoreChord: PROC[r: POINTER TO RChord, chord: ChordPTR] = {
i: CARDINAL;
chord^ ← [r.stem, 0, ALL[NIL]];
FOR i IN [0..chordLength) DO
IF r.n[i]=100 THEN EXIT;
chord.note[i] ← score[r.s+start].event[r.n[i]];
ENDLOOP;
};
RestoreBeam: PROC[r: POINTER TO RBeam, beam: BeamPTR]= {
i, j: CARDINAL;
beam^ ← r.beam;
beam.sync1 ← score[LOOPHOLE[beam.sync1, CARDINAL]+start];
beam.sync2 ← score[LOOPHOLE[beam.sync2, CARDINAL]+start];
FOR i IN [0..beamLength) DO
IF r.n[i].type = null THEN EXIT;
SELECT r.n[i].type FROM
note => beam.chord[i] ←
[note[score[r.n[i].sync+start].event[r.n[i].index]]];
chord=> beam.chord[i] ← [chord[chordHeap[r.n[i].index+cstart]]];
beam => beam.chord[i] ← [beam[beamHeap[r.n[i].index+bstart]]];
null => beam.chord[i] ← endOfBeam;
ENDCASE =>NULL; --later ERROR
ENDLOOP;
FOR i IN [0..beamLength) DO
WITH ev: beam.chord[i] SELECT FROM
note => IF ev.n#NIL THEN ev.n.beam ← beam;
chord=> FOR j IN [0..chordLength) DO
IF ev.c.note[j]#NIL THEN ev.c.note[j].beam ← beam;
ENDLOOP;
beam => SetBeamPTRToBeam[ev.b, beam];
ENDCASE;
ENDLOOP;
};
RChord: TYPE = RECORD[s: CARDINAL, stem: BOOLEAN,
n: ARRAY [0..chordLength) OF CARDINAL];
RBeam: TYPE = RECORD[beam: BeamedSet, n: ARRAY [0..beamLength) OF VPointer];
VPointer: TYPE = RECORD[type: {note, chord, beam, null}, sync: CARDINAL, index: CARDINAL];
FileOutOld: PUBLIC PROC[s: STRING] = {
OPEN StreamDefs;
i, j: CARDINAL;
rchord: RChord;
rbeam: RBeam;
inputStream: DiskHandle;
IF UtilityDefs.Test[] THEN ERROR; -- PLEASE save MESA.TYPESCRIPT for me to examine!
to try to recover, SEt Root & SEt Module to utility,
Interpret Procedure: cleanUp,
SEt Root & Module to MusicData,
Interpret Procedure: fo (for "FileOut"),
save the mesa.typescript somewhere(like ivy) and then
reinvoke mockingbird and filein temp.logical.
If this doesn't work, I may still be able to recover
part of the file if you save temp.logical somewhere.
inputStream ← NewWordStream[s, Write+Append];
inputStream.reset[inputStream];
inputStream.put[inputStream, scoreLength];
FOR i IN [0..scoreLength) DO
[] ← WriteBlock[inputStream, score[i], SIZE[Sync]];
FOR j IN [0..syncLength) DO
IF score[i].event[j]=NIL THEN EXIT;
[] ← WriteBlock[inputStream, score[i].event[j], SIZE[Note]];
ENDLOOP;
ENDLOOP;
inputStream.put[inputStream, chordHeapLength];
FOR i IN [0..chordHeapLength) DO
rchord ← RelativeChord[chordHeap[i]];
[] ← WriteBlock[inputStream,@rchord, SIZE[RChord]];
ENDLOOP;
inputStream.put[inputStream, beamHeapLength];
FOR i IN [0..beamHeapLength) DO
rbeam ← RelativeBeam[beamHeap[i]];
[] ← WriteBlock[inputStream,@rbeam, SIZE[RBeam]];
ENDLOOP;
FileOutSheet[inputStream];
inputStream.destroy[inputStream];
command ← TRUE;
UtilityDefs.DrawScore[TRUE];
};
FileOutSheet: PROC[stream: StreamDefs.DiskHandle]= {
OPEN StreamDefs;
KeySyncToIndex[];
[] ← WriteBlock[stream,@keyArray, 2*keyLength];
[] ← WriteBlock[stream,@show, SIZE[DocumentProfile]];
[] ← WriteBlock[stream,@metrenome, SIZE[INTEGER]];
[] ← WriteBlock[stream,@TF, SIZE[CARDINAL]];
[] ← WriteBlock[stream,@sheet, SIZE[Staves]];
KeyIndexToSync[];
};
KeySyncToIndex: PROC = {
i, k: CARDINAL;
syncFound: BOOLEAN;
FOR k IN [0..keyLength) DO
syncFound ← FALSE;
FOR i IN [0..scoreLength] DO
IF score[i]#keyArray[k].sync THEN LOOP;
syncFound ← TRUE;
keyArray[k].sync ← LOOPHOLE[i];
EXIT;
ENDLOOP;
IF NOT syncFound THEN ERROR;
ENDLOOP;
};
RelativeChord: PROC[c: ChordPTR] RETURNS[RChord]= {
i, j: CARDINAL;
r: RChord ← [0, c.stemUp, ALL[100]];
FOR i IN [0..scoreLength) DO
IF score[i]=c.note[0].sync THEN { r.s ← i; EXIT; };
ENDLOOP;
FOR i IN [0..chordLength) DO
IF c.note[i]=NIL THEN EXIT;
FOR j IN [0..syncLength) DO
IF score[r.s].event[j] # c.note[i] THEN LOOP;
r.n[i] ← j; EXIT;
ENDLOOP;
ENDLOOP;
RETURN[r];
};
RelativeBeam: PROC[b: BeamPTR] RETURNS[RBeam]= {
i, j: CARDINAL;
r: RBeam;
r.beam ← b^;
r.n ← ALL[[null, 0, 0]];
FOR i IN [0..scoreLength) DO
IF r.beam.sync1=score[i] THEN r.beam.sync1 ← LOOPHOLE[i];
IF r.beam.sync2=score[i] THEN r.beam.sync2 ← LOOPHOLE[i];
ENDLOOP;
IF LOOPHOLE[r.beam.sync1, CARDINAL]>scoreLength THEN ERROR;
IF LOOPHOLE[r.beam.sync2, CARDINAL]>scoreLength THEN ERROR;
FOR i IN [0..beamLength) DO
IF b.chord[i]=endOfBeam THEN EXIT;
WITH ev: b.chord[i] SELECT FROM
chord => {
r.n[i].type ← chord;
FOR j IN [0..chordHeapLength) DO
IF chordHeap[j]=ev.c THEN r.n[i].index ← j;
ENDLOOP;
};
beam => {
r.n[i].type ← beam;
FOR j IN [0..beamHeapLength) DO
IF beamHeap[j]=ev.b THEN r.n[i].index ← j;
ENDLOOP;
};
note => {
r.n[i].type ← note;
FOR j IN [0..scoreLength) DO
IF score[j]=ev.n.sync THEN r.n[i].sync ← j;
ENDLOOP;
FOR j IN [0..syncLength) DO
IF score[r.n[i].sync].event[j]=ev.n
THEN r.n[i].index ← j;
ENDLOOP;
};
ENDCASE;
ENDLOOP;
RETURN[r];
};