--Author: John Maxwell --last modified: December 16, 1981 7:58 AM 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: 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 PROCEDURE[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 BEGIN sheet:Staves_[,0,0,0,,]; [] _ GetBlock[inputStream,@sheet,SIZE[SheetFormat]]; BuildSheet[score[i],@sheet]; END; 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 => BEGIN beamHeap[i].chord[j] _ [beam[beamHeap[pointer.index+oldBHLength]]]; beamHeap[pointer.index+oldBHLength].beam _ beamHeap[i]; END; chords =>BEGIN 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; END; ENDCASE=>BEGIN n _ score[pointer.heap+oldSLength].event[pointer.index]; beamHeap[i].chord[j]_[note[n]]; n.beam _ beamHeap[i]; END; 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:PROCEDURE[s:StreamDefs.DiskHandle] RETURNS[data:UNSPECIFIED] = INLINE BEGIN []_GetBlock[s,@data,1]; END; GetBlock:PROCEDURE[s:StreamDefs.DiskHandle,p:POINTER,length:CARDINAL] RETURNS[INTEGER] = --a hack to speed up disk transfers by batching them together BEGIN i:CARDINAL; array:POINTER TO ARRAY[0..1000) OF INTEGER _ LOOPHOLE[p]; IF p=NIL THEN BEGIN [] _ StreamDefs.ReadBlock[s,@buffer,bufferLength]; bufferIndex _ 0; RETURN[0]; END; 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]; END; BuildEvent:PROCEDURE[old:SyncPTR,new:POINTER TO EventFormat] = BEGIN 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; END; BuildSheet:PROCEDURE[old:SyncPTR,staves:StavesPTR] = BEGIN 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]; END; ConvertSheet2:PROCEDURE[old:SyncPTR] = BEGIN 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; END; FindStyle:PROCEDURE[old:SyncPTR] = BEGIN 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]; END; BuildNote:PROCEDURE[old:NotePTR,new:POINTER TO NoteFormat] = BEGIN 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; END; BuildChord:PROCEDURE[old:ChordPTR,new:POINTER TO ChordFormat] = BEGIN IF new.identifier#chordID THEN Error; old.stemUp _ new.stemUp; END; BuildBeam:PROCEDURE[old:BeamPTR,new:POINTER TO BeamFormat] = BEGIN 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]; END; BuildView:PROCEDURE[view:POINTER TO ViewFormat] = BEGIN 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[]; END; --**************************************************************************** --fileout --**************************************************************************** FO:PROCEDURE RETURNS[STRING] = BEGIN RETURN[IF FileOut["temp.music"] THEN "filed out on temp.music" ELSE "fileout aborted"]; END; buffer:ARRAY [0..bufferLength) OF INTEGER; bufferIndex:CARDINAL_0; bufferLength:CARDINAL = 500; FileOut:PUBLIC PROCEDURE[s:STRING] RETURNS[BOOLEAN] = BEGIN 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 BEGIN sheet:Staves _ LOOPHOLE[score[i].event]; []_PutBlock[outputStream,@sheet,SIZE[SheetFormat]]; END; 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 => BEGIN pointer.heap _ Sync.GetScoreIndex[ev.n.sync]; pointer.index_ Note.GetSyncIndex[score[pointer.heap],ev.n]; END; chord=> BEGIN pointer.heap _ chords; pointer.index_ Chord.GetHeapIndex[ev.c]; END; beam => BEGIN pointer.heap _ beams; pointer.index_ Beam.GetHeapIndex[ev.b]; END; 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]; END; Put:PROCEDURE[s:StreamDefs.DiskHandle,data:INTEGER] = INLINE BEGIN []_PutBlock[s,@data,1]; END; PutBlock:PROCEDURE[s:StreamDefs.DiskHandle,p:POINTER,length:CARDINAL] RETURNS[INTEGER] = --a hack to speed up disk transfers by batching them together BEGIN i:CARDINAL; array:POINTER TO ARRAY[0..1000) OF INTEGER _ LOOPHOLE[p]; IF length=0 THEN BEGIN IF bufferIndex=0 THEN RETURN[0]; [] _ StreamDefs.WriteBlock[s,@buffer,bufferIndex]; bufferIndex_0; RETURN[0]; END; 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]; END; ConvertEvent:PROCEDURE[data:SyncPTR,file:POINTER TO EventFormat] = BEGIN 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; END; ConvertNote:PROCEDURE[old:NotePTR,new:POINTER TO NoteFormat] = BEGIN 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; END; ConvertChord:PROCEDURE[old:ChordPTR,new:POINTER TO ChordFormat] = BEGIN new.stemUp _ old.stemUp; new.length _ Chord.Length[old]; END; ConvertBeam:PROCEDURE[old:BeamPTR,new:POINTER TO BeamFormat] = BEGIN 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]; END; ConvertView:PROCEDURE[view:POINTER TO ViewFormat] = BEGIN 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; END... ConvertReals:PROCEDURE = BEGIN i:CARDINAL; FOR i IN [0..beamHeapLength) DO IF beamHeap[i]=NIL THEN LOOP; beamHeap[i].tilt _ RealConvert.Mesa5ToIeee[beamHeap[i].tilt]; ENDLOOP; END; --**************************************************************************** --filein, fileout pianorolls --**************************************************************************** FileInOld:PUBLIC PROCEDURE[s:STRING] = BEGIN 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] => BEGIN note.stemUp_FALSE; note.staff_0; END; note.pitch IN [56..66] => BEGIN note.stemUp_ TRUE; note.staff_0; END; note.pitch IN [43..55] => BEGIN note.stemUp_FALSE; note.staff_1; END; note.pitch IN [32..42] => BEGIN note.stemUp_ TRUE; note.staff_1; END; note.pitch IN [22..31] => BEGIN note.stemUp_FALSE; note.staff_2; END; note.pitch IN [10..21] => BEGIN note.stemUp_ TRUE; note.staff_2; END; note.pitch IN [ 0.. 9] => BEGIN note.stemUp_FALSE; note.staff_3; END; note.pitch IN [-7..-1] => BEGIN note.stemUp_ TRUE; note.staff_3; END; ENDCASE; IF ABS[note.toc - oldToc] > 200 THEN BEGIN AddSyncToPiece[sync,score]; oldToc _ note.toc; sync _ NewSync[]; END; 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]; END; FileOutOld:PUBLIC PROCEDURE[s:STRING] = BEGIN 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]; END; END.... --************************************************************************ --filein, fileout old .logical format --************************************************************************ FileInOld:PUBLIC PROCEDURE[s:STRING] = BEGIN OPEN StreamDefs; i,j,noChords,noBeams:CARDINAL; rchord:RChord; rbeam:RBeam; convert:BOOLEAN _ FALSE; 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]; END; FileInSheet:PROCEDURE[stream:StreamDefs.DiskHandle]= BEGIN 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[]; END; KeyIndexToSync:PROCEDURE = BEGIN k:CARDINAL; FOR k IN [0..keyLength) DO keyArray[k].sync _ score[LOOPHOLE[keyArray[k].sync,CARDINAL]]; ENDLOOP; END; skipBeams:BOOLEAN _ FALSE; bstart,cstart:CARDINAL_0; offset:Time_0; append:BOOLEAN _ FALSE; InitAppend:PROCEDURE = BEGIN start _ scoreLength; bstart _ beamHeapLength; cstart _ chordHeapLength; IF scoreLength#0 THEN offset _ score[scoreLength-1].time+10; END; RestoreChord:PROCEDURE[r:POINTER TO RChord,chord:ChordPTR] = BEGIN 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; END; RestoreBeam:PROCEDURE[r:POINTER TO RBeam,beam:BeamPTR]= BEGIN 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; END; 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 PROCEDURE[s:STRING] = BEGIN 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]; END; FileOutSheet:PROCEDURE[stream:StreamDefs.DiskHandle]= BEGIN 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[]; END; KeySyncToIndex:PROCEDURE = BEGIN 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; END; RelativeChord:PROCEDURE[c:ChordPTR] RETURNS[RChord]= BEGIN i,j:CARDINAL; r:RChord _ [0,c.stemUp,ALL[100]]; FOR i IN [0..scoreLength) DO IF score[i]=c.note[0].sync THEN BEGIN r.s_i; EXIT; END; 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]; END; RelativeBeam:PROCEDURE[b:BeamPTR] RETURNS[RBeam]= BEGIN 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 => BEGIN r.n[i].type _ chord; FOR j IN [0..chordHeapLength) DO IF chordHeap[j]=ev.c THEN r.n[i].index_j; ENDLOOP; END; beam => BEGIN r.n[i].type _ beam; FOR j IN [0..beamHeapLength) DO IF beamHeap[j]=ev.b THEN r.n[i].index_j; ENDLOOP; END; note => BEGIN 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; END; ENDCASE; ENDLOOP; RETURN[r]; END; e6(0,3648)(1,4288)(2,6016)\792i15I99b6B450i24I28i1I2i19I262i15I40i1I26i1I1010i19I44i1I414i18I43i1I1033i16I352i14I70i21I311i59I1368i61I1602i15I631i7I314b7B404i16I29i1I26i1I30i1I698i20I31i1I34i1I462i19I30i1I700i22I235i15I73i21I38i9I267i59I547i46I1682i26I81b9B547i42I1175b10B711i35I77b9B3096i11I560b11B156i496I835b1B