-- MusicDefs.mesa
-- Author: John Maxwell
-- Last Edited by: Maxwell, November 22, 1983 12:46 pm
-- This module gives the types used internally by the editor.
-- MusicFileDefs gives the types used externally in the file format.
DIRECTORY
Graphics USING [Context, FontRef, PaintMode, SetPaintMode, SetStipple],
KeyboardFace USING [keyboard],
MouseFace USING [buttons],
MusicFileDefs;
MusicDefs: DEFINITIONS IMPORTS Graphics, KeyboardFace, MouseFace =
BEGIN
Error: SIGNAL[s: STRING];
Notify: SIGNAL[s: STRING];
-- ****************************************************************************
-- the basic music types
-- ****************************************************************************
ScorePTR: TYPE = LONG POINTER TO ScoreRec;
ScoreRec: TYPE = RECORD [
name: LONG STRING ← NIL, -- name of the score
beamHeap: BeamHeapPTR ← NIL, -- collection of beams
chordHeap: ChordHeapPTR ← NIL, -- collection of chords
cache: CachePTR ← NIL, -- current key, time signature, etc.
sheet: SheetPTR ← NIL, -- cached information about the sheet (derived from the piece)
style: StylePTR ← NIL, --
maxVoice: CARDINAL ← 0, -- index of the highest numbered voice
command: BOOLEAN ← FALSE, -- we have a new command
flash: BOOLEAN ← FALSE, -- flash the screen for an error
length: CARDINAL ← 0, -- length of score
event: SEQUENCE max: CARDINAL OF EventPTR]; -- collection of events
-- endOfScore: CARDINAL = LAST[CARDINAL];
ScorePortionPTR: TYPE = LONG POINTER TO ScorePortionRec;
ScorePortionRec: TYPE = RECORD[ -- a portion of a score.
score: ScorePTR ← NIL,
toc: Time ← 0, -- length of portion in seconds of playing time.
duration: Time ← 0, -- length in portion in pixels on the screen.
-- duration = 0 means score is from synthesizer (ignore ss1 and ss2).
ss1, ss2: ScoreState ← []]; -- state of score at beginning and end
ScoreStatePTR: TYPE = LONG POINTER TO ScoreState;
ScoreState: TYPE = RECORD[
key: INTEGER ← 0,
style: CARDINAL ← 1,
staff: ARRAY [0..4) OF Staff ← ALL[[]]];
EventPTR: TYPE = LONG POINTER TO EventRec;
EventRec: TYPE = RECORD[
time: Time ← 0, -- measured in pixels from beginning of piece
variant: SELECT type: EventType FROM
sync => [length: CARDINAL ← 0, -- actual length of the sequence
note: SEQUENCE max: CARDINAL OF NotePTR], -- collection of notes
measure => [measure: MeasureType ← measure, eol: BOOLEAN ← FALSE], -- eol = force to end of line
timeSignature => [ts: TimeSignature ← [4,4]],
keySignature => [key: INTEGER ← 0],
metrenome => [metrenome: INTEGER ← 128],
staves => [ -- marks a change in staffing
staves: StavesType ← style,
height: INTEGER ← 0,
offset: INTEGER ← 0,
value: CARDINAL ← 0, -- index of the staff OR style number
length: [0..4] ← 4, -- number of staffs in following array
staff: ARRAY [0..4) OF Staff ← ALL[[]]],
ENDCASE];
Time: TYPE = LONG INTEGER;
SyncPTR: TYPE = LONG POINTER TO sync EventRec; -- 'sync' comes from 'synchronize'
StavesPTR: TYPE = LONG POINTER TO staves EventRec;
StavesType: TYPE = {style, clef, octava1, octava2};
EventType: TYPE = MACHINE DEPENDENT {sync (0), measure (1),
timeSignature (7), keySignature (8), metrenome (9), staves (10), spare14 (31)};
MeasureType: TYPE = {measure, repeat1, repeat2, endMeasure, doubleMeasure, m5};
TimeSignature: TYPE = RECORD [top, bottom: [0..32)];
NotePTR: TYPE = LONG POINTER TO NoteRec;
NoteRec: TYPE = MACHINE DEPENDENT RECORD[
sync: SyncPTR ← NIL, -- pointer back to sync
beam: BeamPTR ← NIL, -- pointer back to beam
chord: ChordPTR ← NIL, -- pointer back to chord
pitch: INTEGER ← 44, -- pitch of the note
voice: CARDINAL ← 0, -- the voice that this note belongs to
value: NoteValue ← unknown, -- what is the logical value of this note?
spelled: Accidental ← inKey, -- does this note have an explicit spelling on it?
rest: BOOLEAN ← FALSE, -- is this a rest note?
dotted: BOOLEAN ← FALSE, -- is this note dotted?
doubleDotted: BOOLEAN ← FALSE, -- is this note double dotted?
grace: BOOLEAN ← FALSE, -- is this a grace note?
stemUp: BOOLEAN ← TRUE, -- is the stem up or down?
spare1: BOOLEAN ← FALSE,
embellish: Embellishment ← none, -- does this note have an embellishment on it?
tied: BOOLEAN ← FALSE, -- is this the second note of a tied note?
tie: NotePTR ← NIL, -- pointer to the second note of a tie
tieHeight: INTEGER ← 0, -- the height of said tie
show: BOOLEAN ← FALSE,
shown: Accidental ← inKey, -- the accidental displayed on the screen (cached)
spare: [0..256) ← 0,
staff: [0..16) ← 1, -- the index of the staff that this note is on
delta: [-128..128) ← 0, -- how far to move the note relative to the sync
accDelta: [-128..128) ← 0, -- how far to move the accidental relative to the sync
toc: LONG CARDINAL ← 0, -- physical-note time of occurance (in clock pulses)
duration: CARDINAL ← 0]; -- physical-note duration (in clock pulses)
NoteValue: TYPE = MusicFileDefs.NoteValueFormat;
Accidental: TYPE = MusicFileDefs.AccidentalFormat;
Embellishment: TYPE = MusicFileDefs.EmbellishmentFormat;
PhysicalNote: TYPE = RECORD[
pitch: INTEGER ← 0,
duration: CARDINAL ← 0,
loudness: CARDINAL ← 0,
toc: LONG CARDINAL ← 0]; --toc is the physical time of occurrance
ChordPTR: TYPE = LONG POINTER TO ChordRec;
ChordRec: TYPE = RECORD[
stemUp: BOOLEAN ← TRUE,
delta: INTEGER ← 0, -- offset from center line of sync (cached)
length: CARDINAL ← 0, -- length of note sequence
note: SEQUENCE max: CARDINAL OF NotePTR];
BeamPTR: TYPE = LONG POINTER TO BeamRec;
BeamRec: TYPE = RECORD[
tilt: REAL, -- tilt of beam
beamed: BOOLEAN ← TRUE, -- does the beam show, or do you use brackets instead?
ntuple, against: [0..128) ← 1, -- for ntupled beams; the ratio is what is important
sync1, sync2: SyncPTR ← NIL, -- first and last sync in beam (cached)
beam: BeamPTR ← NIL, -- beam that this beam belongs to
height: INTEGER ← 0, -- height of beam from top of left-most note
invisible: BOOLEAN ← FALSE,
length: [0..1024) ← 0, -- length of chord sequence
staff: [0..32) ← 0, -- graphical information
chord: SEQUENCE max: CARDINAL OF VariousPTR];
VariousPTR: TYPE = RECORD[SELECT type: {note,chord,beam} FROM
note => [n: NotePTR], chord=> [c: ChordPTR], beam=>[b: BeamPTR], ENDCASE];
endOfBeam: VariousPTR; -- saves a call to CodeBlockEqualLong
-- ******************************************************************************
-- other types
-- ******************************************************************************
BeamHeapPTR: TYPE = LONG POINTER TO BeamHeapRec;
BeamHeapRec: TYPE = RECORD[
length: CARDINAL ← 0,
beam: SEQUENCE max: CARDINAL OF BeamPTR];
ChordHeapPTR: TYPE = LONG POINTER TO ChordHeapRec;
ChordHeapRec: TYPE = RECORD[
length: CARDINAL ← 0,
chord: SEQUENCE max: CARDINAL OF ChordPTR];
CachePTR: TYPE = LONG POINTER TO CacheRec;
CacheRec: TYPE = RECORD[ -- all of the structural (non-sync) events
beamQueueLength: CARDINAL ← 0,
beamQueue: ARRAY [0..3) OF BeamPTR ← ALL[NIL], -- drawn beams
key1, key2: LONG POINTER TO EventRec.keySignature ← NIL, -- bracketing keys
ts1, ts2: LONG POINTER TO EventRec.timeSignature ← NIL, -- bracketing time signatures
met1, met2: LONG POINTER TO EventRec.metrenome ← NIL];-- bracketing metrenomes
SheetPTR: TYPE = LONG POINTER TO SheetRec;
SheetRec: TYPE = RECORD[
context: Graphics.Context ← NIL,
voice: CARDINAL ← noVoice, -- currently selected voice
top: INTEGER ← 0, -- the y position of the top of the score (for scrolling)
begin, endTime: Time ← 0, -- start and end of the part of the score that is currently visible
dirty1, dirty2: Time ← 0, -- the portion of the score that needs to be repainted
scale: INTEGER ← 1, -- normal, hardcopy and overview
density: INTEGER ← 256, -- scale factor in physical mode.
justification: INTEGER ← 1, -- density of justification. used in graphical mode.
accidental: BOOLEAN ← TRUE,
notehead: BOOLEAN ← TRUE,
sync: BOOLEAN ← FALSE,
display: DisplayMode ← graphical,
noCarry: BOOLEAN ← FALSE,
hardcopy: BOOLEAN ← FALSE, -- display in hardcopy mode
printing: BOOLEAN ← FALSE, -- we are printing instead of displaying
width: INTEGER ← 550, -- width of staff
current: CARDINAL ← 0, -- current section index
length: CARDINAL ← 0, -- length of sheet sequence
section: SEQUENCE max: CARDINAL OF Section]; -- sequence of sections
Section: TYPE = RECORD[
time: Time ← 0, -- actual time of beginning of section. (may be different from staves.time)
x, y: INTEGER ← 0, -- position of the lower left corner of the section
page: INTEGER ← 0, -- the page that this section is on
key: INTEGER ← 0, -- the key for this section
staves: StavesPTR ← NIL];
noVoice: CARDINAL = 1000;
StylePTR: TYPE = LONG POINTER TO StyleRec;
StyleRec: TYPE = RECORD[
length: CARDINAL ← 0,
style: SEQUENCE max: CARDINAL OF StavesPTR];
Staff: TYPE = MusicFileDefs.Staff;
SelectionPTR: TYPE = LONG POINTER TO SelectionRec;
SelectionRec: TYPE = RECORD[
lineSelect: BOOLEAN ← FALSE, -- line selection or note selection?
score: ScorePTR ← NIL, -- score of primary selection or note selection
select1, select2: Time ← 0, -- line selected
score2: ScorePTR ← NIL, -- score of secondary selection
greySelect1, greySelect2: Time ← 0, -- secondary line selection
length: CARDINAL ← 0, -- length of note selection
note: SEQUENCE max: CARDINAL OF NotePTR]; -- notes selected
DisplayMode: TYPE = MusicFileDefs.DisplayModeFormat;
ObjectType: TYPE = {measure, note, leftBeam, rightBeam, tie};
LookCommand: TYPE = {accidental, graphical, hardcopy, justified, logical, noCarry, notehead, overview, physical, style, sync, voice};
-- chordLength: CARDINAL = 10;
-- syncLength: CARDINAL = 13;
-- beamLength: CARDINAL = 16;
sheetLength: CARDINAL= 350;
maxScoreLength: CARDINAL = MAX[maxPieceLength,3000]; --6000
maxPieceLength: CARDINAL = 1000;
maxBeamHeapLength: CARDINAL = 1000; --2000
maxChordHeapLength: CARDINAL = 1000; --2000
maxSelectionLength: CARDINAL = 100;
--******************************************************************************
--global variables
--******************************************************************************
-- style: ARRAY [0..20] OF Staves;
--view on score
-- TF: CARDINAL; ++ "Time Factor" = horizontal scale of score on sheet.
-- scale,staffLength,top: INTEGER;
--return info for commands
-- min,max: Time; ++ extent of change
-- command,flash: BOOLEAN; ++ flash = "error"
--graphics
-- context: Graphics.Context;
text,music: Graphics.FontRef;
-- print: BOOLEAN;
--communicating with the synthesizer
dataStructureInFlux: BOOLEAN;
playing,listening: READONLY BOOLEAN;
--data storage
zone: UNCOUNTED ZONE;
-- ****************************************************************************
-- INLINE Procedures
-- ****************************************************************************
white: CARDINAL = 000000B;
light: CARDINAL;
grey: CARDINAL = 122645B;
black: CARDINAL = 177777B;
Measure: PROC[event: EventPTR] RETURNS[BOOLEAN] = INLINE
{IF event.type = measure THEN RETURN[TRUE];
IF event.type = staves THEN WITH ev: event SELECT FROM
staves => RETURN[ev.staves = style];
ENDCASE;
RETURN[FALSE]};
EndOfScore: PROCEDURE[score: ScorePTR] RETURNS[Time] =INLINE
{IF score.length#0 THEN RETURN[score.event[score.length-1].time+40] ELSE RETURN[10]};
LMod: PROCEDURE[m,n: Time] RETURNS[k: Time] = INLINE
{k ← m - n*(m/n); IF k>n THEN k ← k+n};
Mod: PROCEDURE[m,n: INTEGER] RETURNS[k: INTEGER] = INLINE
{k ← m MOD n; IF k<0 THEN k ← k+n};
SetBrush: PROCEDURE[score: ScorePTR, tex: CARDINAL, pnt: Graphics.PaintMode] = INLINE
{Graphics.SetStipple[score.sheet.context,tex];
[] ← Graphics.SetPaintMode[score.sheet.context,pnt]};
SetDirty: PROCEDURE[score: ScorePTR, begin,end: Time] = INLINE
{score.sheet.dirty1 ← MIN[score.sheet.dirty1, begin];
score.sheet.dirty2 ← MAX[score.sheet.dirty2, end]};
-- *************************************************************************
-- mouse and keyboard
-- *************************************************************************
AnyBug: PROCEDURE RETURNS[BOOLEAN] =
INLINE {RETURN[RedBug[] OR BlueBug[] OR YellowBug[]]};
RedBug: PROCEDURE RETURNS[BOOLEAN] =
INLINE {RETURN[MouseFace.buttons[Mouse1] = down]};
YellowBug: PROCEDURE RETURNS[BOOLEAN] =
INLINE {RETURN[MouseFace.buttons[Mouse2] = down]};
BlueBug: PROCEDURE RETURNS[BOOLEAN] =
INLINE {RETURN[MouseFace.buttons[Mouse3] = down]};
Shift: PROCEDURE RETURNS[BOOLEAN] = INLINE {RETURN[
KeyboardFace.keyboard[57] = down OR -- A5
KeyboardFace.keyboard[76] = down]}; -- A6
Control: PROCEDURE RETURNS[BOOLEAN] =
INLINE {RETURN[KeyboardFace.keyboard[52] = down]}; -- L11
END.