MusicDefs.mesa
Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved.
Author: John Maxwell
Last Edited by: Maxwell, November 22, 1983 12:46 pm
Last Edited by: Doug Wyatt, June 18, 1984 12:37:59 pm PDT
This module gives the types used internally by the editor.
MusicFileDefs gives the types used externally in the file format.
DIRECTORY
Imager USING [Context],
MusicFileDefs USING [AccidentalFormat, DisplayModeFormat, EmbellishmentFormat, NoteValueFormat],
MusicDefs: CEDAR DEFINITIONS
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
Error: SIGNAL[s: ROPE];
Notify: SIGNAL[s: ROPE];
****************************************************************************
the basic music types
****************************************************************************
ScorePTR: TYPE ~ REF ScoreRec;
ScoreRec:
TYPE ~
RECORD [
name: ROPE ← 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: NAT ← 0, -- index of the highest numbered voice
command: BOOL ← FALSE, -- we have a new command
flash: BOOL ← FALSE, -- flash the screen for an error
length: NAT ← 0, -- length of score
event: SEQUENCE max: NAT OF EventPTR -- collection of events
];
ScorePortionPTR: TYPE ~ REF 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: ScoreStateRec ← [] -- state of score at beginning and end
];
ScoreStatePTR: TYPE ~ REF ScoreStateRec;
ScoreStateRec:
TYPE ~
RECORD[
key: INTEGER ← 0,
style: NAT ← 1,
staff: ARRAY [0..4) OF Staff ← ALL[[]]
];
EventPTR: TYPE ~ REF EventRec;
EventRec:
TYPE ~
RECORD[
time: Time ← 0, -- measured in pixels from beginning of piece
variant:
SELECT type: EventType
FROM
sync => [
length: NAT ← 0, -- actual length of the sequence
note: SEQUENCE max: NAT OF NotePTR -- collection of notes
],
measure => [
measure: MeasureType ← measure,
eol: BOOL ← FALSE -- eol => force to end of line
],
timeSignature => [ts: TimeSignature ← [4,4]],
keySignature => [key: INTEGER ← 0],
metronome => [metronome: INTEGER ← 128],
staves => [
-- marks a change in staffing
staves: StavesType ← style,
value: NAT ← 0, -- index of the staff OR style number
height: INTEGER ← 0,
offset: INTEGER ← 0,
length: [0..4] ← 4, -- number of staffs in following array
staff: ARRAY [0..4) OF Staff ← ALL[[0, 0]]
],
ENDCASE
];
SyncPTR: TYPE ~ REF EventRec[sync]; -- 'sync' comes from 'synchronize'
MeasurePTR: TYPE ~ REF EventRec[measure];
TimeSignaturePTR: TYPE ~ REF EventRec[timeSignature];
KeySignaturePTR: TYPE ~ REF EventRec[keySignature];
MetronomePTR: TYPE ~ REF EventRec[metronome];
StavesPTR: TYPE ~ REF EventRec[staves];
Time: TYPE ~ LONG INTEGER;
EventType: TYPE ~ {sync, measure, timeSignature, keySignature, metronome, staves};
MeasureType: TYPE ~ {measure, repeat1, repeat2, endMeasure, doubleMeasure, m5};
TimeSignature: TYPE ~ RECORD [top, bottom: [0..32)];
StavesType: TYPE ~ {style, clef, octava1, octava2};
NotePTR: TYPE ~ REF NoteRec;
NoteRec:
TYPE ~
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: NAT ← 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: BOOL ← FALSE, -- is this a rest note?
dotted: BOOL ← FALSE, -- is this note dotted?
doubleDotted: BOOL ← FALSE, -- is this note double dotted?
grace: BOOL ← FALSE, -- is this a grace note?
stemUp: BOOL ← TRUE, -- is the stem up or down?
spare1: BOOL ← FALSE,
embellish: Embellishment ← none, -- does this note have an embellishment on it?
tied: BOOL ← 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: BOOL ← 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 occurrence (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 occurrence
];
ChordPTR: TYPE ~ REF ChordRec;
ChordRec:
TYPE ~
RECORD[
stemUp: BOOL ← TRUE,
delta: INTEGER ← 0, -- offset from center line of sync (cached)
length: NAT ← 0, -- length of note sequence
note: SEQUENCE max: NAT OF NotePTR
];
BeamPTR: TYPE ~ REF BeamRec;
BeamRec:
TYPE ~
RECORD[
tilt: REAL ← 0, -- tilt of beam
beamed: BOOL ← 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: BOOL ← FALSE,
length: NAT ← 0, -- length of chord sequence
staff: NAT ← 0, -- graphical information
chord: SEQUENCE max: NAT OF VariousPTR -- chord sequence
];
VariousPTR: TYPE ~ REF; -- NotePTR, ChordPTR, or BeamPTR
endOfBeam: VariousPTR ~
NIL;
******************************************************************************
other types
******************************************************************************
BeamHeapPTR: TYPE ~ REF BeamHeapRec;
BeamHeapRec:
TYPE ~
RECORD[
length: NAT ← 0,
beam: SEQUENCE max: NAT OF BeamPTR
];
ChordHeapPTR: TYPE ~ REF ChordHeapRec;
ChordHeapRec:
TYPE ~
RECORD[
length: NAT ← 0,
chord: SEQUENCE max: NAT OF ChordPTR
];
CachePTR: TYPE ~ REF CacheRec;
CacheRec:
TYPE ~
RECORD[
-- all of the structural (non-sync) events
beamIndex: NAT ← 0,
beamQueue: ARRAY [0..3) OF BeamPTR ← ALL[NIL], -- drawn beams
key1, key2: KeySignaturePTR ← NIL, -- bracketing keys
ts1, ts2: TimeSignaturePTR ← NIL, -- bracketing time signatures
met1, met2: MetronomePTR ← NIL -- bracketing metronomes
];
SheetPTR: TYPE ~ REF SheetRec;
SheetRec:
TYPE ~
RECORD[
context: Imager.Context ← NIL,
voice: NAT ← 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: BOOL ← TRUE,
notehead: BOOL ← TRUE,
sync: BOOL ← FALSE,
display: DisplayMode ← graphical,
noCarry: BOOL ← FALSE,
hardcopy: BOOL ← FALSE, -- display in hardcopy mode
printing: BOOL ← FALSE, -- we are printing instead of displaying
width: INTEGER ← 550, -- width of staff
current: NAT ← 0, -- current section index
length: NAT ← 0, -- length of sheet sequence
section: SEQUENCE max: NAT 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: NAT ~ 1000;
Staff:
TYPE ~
RECORD[
pitch: INTEGER ← 0, -- pitch of note on bottom line
y: INTEGER ← 0 -- height relative to bottom line
];
StylePTR: TYPE ~ REF StyleRec;
StyleRec:
TYPE ~
RECORD[
length: NAT ← 0,
style: SEQUENCE max: NAT OF StavesPTR
];
SelectionPTR: TYPE ~ REF SelectionRec;
SelectionRec:
TYPE ~
RECORD[
lineSelect: BOOL ← 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: NAT ← 0, -- length of note selection
note: SEQUENCE max: NAT 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;
ColorType: TYPE ~ {black, grey, light, white};
FontType: TYPE ~ {text, music};
PaintMode: TYPE ~ {opaque, transparent, invert};
****************************************************************************
INLINE Procedures
****************************************************************************
Measure:
PROC[event: EventPTR]
RETURNS[
BOOL] ~
INLINE {
WITH event
SELECT
FROM
ev: MeasurePTR => RETURN[TRUE];
ev: StavesPTR => RETURN[ev.staves=style];
ENDCASE => RETURN[FALSE];
};
EndOfScore:
PROC[score: ScorePTR]
RETURNS[Time] ~
INLINE {
IF score.length#0 THEN RETURN[score.event[score.length-1].time+40] ELSE RETURN[10]
};
LMod:
PROC[m, n: Time]
RETURNS[k: Time] ~
INLINE {
k ← m - n*(m/n); IF k>n THEN k ← k+n;
};
Mod:
PROC[m, n:
INTEGER]
RETURNS[k:
INTEGER] ~
INLINE {
k ← m MOD n; IF k<0 THEN k ← k+n;
};
SetDirty:
PROC[score: ScorePTR, begin, end: Time] ~
INLINE {
score.sheet.dirty1 ← MIN[score.sheet.dirty1, begin];
score.sheet.dirty2 ← MAX[score.sheet.dirty2, end];
END.