From:
[email protected] (Peter da Silva)
Newsgroups: alt.binaries.multimedia
Subject: Definition of Electronic Arts IFF format
Date: 10 Dec 90 12:56:36 GMT
Reply-To:
[email protected] (Peter da Silva)
Organization: Sugar Land Unix - Houston
In a radical move, infomation instead of flames.
Definitions of the Electronic Arts IFF formats for text, sampled sounds,
musical scores, and images.
: This archive contains the following files...
: '8svx'
: 'ea.iff.85'
: 'ftxt'
: 'ilbm'
: 'smus'
: To extract them, run the following through /bin/sh
echo x - 8svx
sed 's/^X//' > 8svx << '//END'
X"8SVX" IFF 8-Bit Sampled Voice
X
XDate: February 7, 1985
XFrom: Steve Hayes and Jerry Morrison, Electronic Arts
XStatus: Adopted
X
X1. Introduction
X
XThis memo is the IFF supplement for FORM "8SVX". An 8SVX is an IFF
X"data section" or "FORM" (which can be an IFF file or a part of one)
Xcontaining a digitally sampled audio voice consisting of 8-bit samples.
XA voice can be a one-shot sound orQwith repetition and pitch scalingQa
Xmusical instrument. "EA IFF 85" is Electronic Arts' standard interchange
Xfile format. [See "EA IFF 85" Standard for Interchange Format Files.]
X
XThe 8SVX format is designed for playback hardware that uses 8-bit
Xsamples attenuated by a volume control for good overall signal-to-noise
Xratio. So a FORM 8SVX stores 8-bit samples and a volume level.
X
XA similar data format (or two) will be needed for higher resolution
Xsamples (typically 12 or 16 bits). Properly converting a high resolution
Xsample down to 8 bits requires one pass over the data to find the
Xminimum and maximum values and a second pass to scale each sample
Xinto the range -128 through 127. So it's reasonable to store higher
Xresolution data in a different FORM type and convert between them.
X
XFor instruments, FORM 8SVX can record a repeating waveform optionally
Xpreceded by a startup transient waveform. These two recorded signals
Xcan be pre-synthesized or sampled from an acoustic instrument. For
Xmany instruments, this representation is compact. FORM 8SVX is less
Xpractical for an instrument whose waveform changes from cycle to cycle
Xlike a plucked string, where a long sample is needed for accurate
Xresults.
X
XFORM 8SVX can store an "envelope" or "amplitude contour" to enrichen
Xmusical notes. A future voice FORM could also store amplitude, frequency,
Xand filter modulations.
X
XFORM 8SVX is geared for relatively simple musical voices, where one
Xwaveform per octave is sufficient, where the waveforms for the different
Xoctaves follows a factor-of-two size rule, and where one envelope
Xis adequate for all octaves. You could store a more general voice
Xas a LIST containing one or more FORMs 8SVX per octave. A future voice
XFORM could go beyond one "one-shot" waveform and one "repeat" waveform
Xper octave.
X
XSection 2 defines the required property sound header "VHDR", optional
Xproperties name "NAME", copyright "(c)J", and author "AUTH", the optional
Xannotation data chunk "ANNO", the required data chunk "BODY", and
Xoptional envelope chunks "ATAK" and "RLSE". These are the "standard"
Xchunks. Specialized chunks for private or future needs can be added
Xlater, e.g. to hold a frequency contour or Fourier series coefficients.
XThe 8SVX syntax is summarized in Appendix A as a regular expression
Xand in Appendix B as an example box diagram. Appendix C explains the
Xoptional Fibonacci-delta compression algorithm.
X
XCaution: The VHDR structure Voice8Header changed since draft proposal
X#4! The new structure is incompatible with the draft version.
X
X
X
XReference:
X
X"EA IFF 85" Standard for Interchange Format Files describes the underlying
Xconventions for all IFF files.
X
XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
X
XElectronic Arts[tm] is a trademark of Electronic Arts.
X
XMacWrite[tm] is a trademark of Apple Computer, Inc.
X
X
X
X2. Standard Data and Property Chunks
X
XFORM 8SVX stores all the waveform data in one body chunk "BODY". It
Xstores playback parameters in the required header chunk "VHDR". "VHDR"
Xand any optional property chunks "NAME", "(c)J", and "AUTH" must all
Xappear before the BODY chunk. Any of these properties may be shared
Xover a LIST of FORMs 8SVX by putting them in a PROP 8SVX. [See "EA
XIFF 85" Standard for Interchange Format Files.]
X
XBackground
X
XThere are two ways to use FORM 8SVX: as a one-shot sampled sound or
Xas a sampled musical instrument that plays "notes". Storing both kinds
Xof sounds in the same kind of FORM makes it easy to play a one-shot
Xsound as a (staccato) instrument or an instrument as a (one-note)
Xsound.
X
XA one-shot sound is a series of audio data samples with a nominal
Xplayback rate and amplitude. The recipient program can optionally
Xadjust or modulate the amplitude and playback data rate.
X
XFor musical instruments, the idea is to store a sampled (or pre-synthesized)
Xwaveform that will be parameterized by pitch, duration, and amplitude
Xto play each "note". The creator of the FORM 8SVX can supply a waveform
Xper octave over a range of octaves for this purpose. The intent is
Xto perform a pitch by selecting the closest octave's waveform and
Xscaling the playback data rate. An optional "one-shot" waveform supplies
Xan arbitrary startup transient, then a "repeat" waveform is iterated
Xas long as necessary to sustain the note.
X
XA FORM 8SVX can also store an envelope to modulate the waveform. Envelopes
Xare mostly useful for variable-duration notes but could be used for
Xone-shot sounds, too.
X
XThe FORM 8SVX standard has some restrictions. For example, each octave
Xof data must be twice as long as the next higher octave. Most sound
Xdriver software and hardware imposes additional restrictions. E.g.
Xthe Amiga sound hardware requires an even number of samples in each
Xone-shot and repeat waveform.
X
XRequired Property VHDR
X
XThe required property "VHDR" holds a Voice8Header structure as defined
Xin these C declarations and following documentation. This structure
Xholds the playback parameters for the sampled waveforms in the BODY
Xchunk. (See "Data Chunk BODY", below, for the storage layout of these
Xwaveforms.)
X
X#define ID_8SVX MakeID('8', 'S', 'V', 'X')
X#define ID_VHDR MakeID('V', 'H', 'D', 'R')
X
Xtypedef LONG Fixed;
X /* A fixed-point value, 16 bits to the left of the point and 16
X * to the right. A Fixed is a number of 216ths, i.e. 65536ths. */
X
X#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume */
X
X/* sCompression: Choice of compression algorithm applied to the samples. */
X
X#define sCmpNone 0 /* not compressed */
X#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */
X
X/* Can be more kinds in the future. */
X
Xtypedef struct {
X ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
X repeatHiSamples, /* # samples in the high octave repeat part */
X samplesPerHiCycle; /* # samples/cycle in high octave, else 0 */
X UWORD samplesPerSec; /* data sampling rate */
X UBYTE ctOctave, /* # octaves of waveforms */
X sCompression; /* data compression technique used */
X Fixed volume; /* playback volume from 0 to Unity (full
X * volume). Map this value into the output
X * hardware's dynamic range. */
X } Voice8Header;
X
X[Implementation details. Fields are filed in the order shown. The
XUBYTE fields are byte-packed (2 per 16-bit word). MakeID is a C macro
Xdefined in the main IFF document and in the source file IFF.h.]
X
XA FORM 8SVX holds waveform data for one or more octaves, each containing
Xa one-shot part and a repeat part. The fields oneShotHiSamples and
XrepeatHiSamples tell the number of audio samples in the two parts
Xof the highest frequency octave. Each successive (lower frequency)
Xoctave contains twice as many data samples in both its one-shot and
Xrepeat parts. One of these two parts can be empty across all octaves.
X
XNote: Most audio output hardware and software has limitations. The
XAmiga computer's sound hardware requires that all one-shot and repeat
Xparts have even numbers of samples. Amiga sound driver software would
Xhave to adjust an odd-sized waveform, ignore an odd-sized lowest octave,
Xor ignore odd FORMs 8SVX altogether. Some other output devices require
Xall sample sizes to be powers of two.
X
XThe field samplesPerHiCycle tells the number of samples/cycle in the
Xhighest frequency octave of data, or else 0 for "unknown". Each successive
X(lower frequency) octave contains twice as many samples/cycle. The
XsamplesPerHiCycle value is needed to compute the data rate for a desired
Xplayback pitch.
X
XActually, samplesPerHiCycle is an average number of samples/cycle.
XIf the one-shot part contains pitch bends, store the samples/cycle
Xof the repeat part in samplesPerHiCycle. The division repeatHiSamples/samplesPe
XrHiCycle should yield an integer number of cycles. (When the repeat
Xwaveform is repeated, a partial cycle would come out as a higher-frequency
Xcycle with a "click".)
X
XMore limitations: Some Amiga music drivers require samplesPerHiCycle
Xto be a power of two in order to play the FORM 8SVX as a musical instrument
Xin tune. They may even assume samplesPerHiCycle is a particular power
Xof two without checking. (If samplesPerHiCycle is different by a factor
Xof two, the instrument will just be played an octave too low or high.)
X
XThe field samplesPerSec gives the sound sampling rate. A program may
Xadjust this to achieve frequency shifts or vary it dynamically to
Xachieve pitch bends and vibrato. A program that plays a FORM 8SVX
Xas a musical instrument would ignore samplesPerSec and select a playback
Xrate for each musical pitch.
X
XThe field ctOctave tells how many octaves of data are stored in the
XBODY chunk. See "Data Chunk BODY", below, for the layout of the octaves.
X
XThe field sCompression indicates the compression scheme, if any, that
Xwas applied to the entire set of data samples stored in the BODY chunk.
XThis field should contain one of the values defined above. Of course,
Xthe matching decompression algorithm must be applied to the BODY data
Xbefore the sound can be played. (The Fibonacci-delta encoding scheme
XsCmpFibDelta is described in Appendix C.) Note that the whole series
Xof data samples is compressed as a unit.
X
XThe field volume gives an overall playback volume for the waveforms
X(all octaves). It lets the 8-bit data samples use the full range -128
Xthrough 127 for good signal-to-noise ratio and be attenuated on playback
Xto the desired level. The playback program should multiply this value
Xby a "volume control" and perhaps by a playback envelope (see ATAK
Xand RLSE, below).
X
XRecording a one-shot sound. To store a one-shot sound in a FORM 8SVX,
Xset oneShotHiSamples = number of samples, repeatHiSamples = 0 ,
XsamplesPerHiCycle = 0, samplesPerSec = sampling rate, and ctOctave = 1.
XScale the signal amplitude to the full sampling range -128 through 127. Set
Xvolume so the sound will playback at the desired volume level. If
Xyou set the samplesPerHiCycle field properly, the data can also be
Xused as a musical instrument.
X
XExperiment with data compression. If the decompressed signal sounds
Xok, store the compressed data in the BODY chunk and set sCompression
Xto the compression code number.
X
XRecording a musical instrument. To store a musical instrument in a
XFORM 8SVX, first record or synthesize as many octaves of data as you
Xwant to make available for playback. Set ctOctaves to the count of
Xoctaves. From the recorded data, excerpt an integral number of steady
Xstate cycles for the repeat part and set repeatHiSamples and samplesPerHiCycle.
XEither excerpt a startup transient waveform and set oneShotHiSamples,
Xor else set oneShotHiSamples to 0. Remember, the one-shot and repeat
Xparts of each octave must be twice as long as those of the next higher
Xoctave. Scale the signal amplitude to the full sampling range and
Xset volume to adjust the instrument playback volume. If you set the
XsamplesPerSec field properly, the data can also be used as a one-shot
Xsound.
X
XA distortion-introducing compressor like sCmpFibDelta is not recommended
Xfor musical instruments, but you might try it anway.
X
XTypically, creators of FORM 8SVX record an acoustic instrument at
Xjust one frequency. Decimate (down- sample with filtering) to compute
Xhigher octaves. Interpolate to compute lower octaves.
X
XIf you sample an acoustic instrument at different octaves, you may
Xfind it hard to make the one-shot and repeat waveforms follow the
Xfactor-of-two rule for octaves. To compensate, lengthen an octave's
Xone-shot part by appending replications of the repeating cycle or
Xprepending zeros. (This will have minimal impact on the sound's start
Xtime.) You may be able to equalize the ratio one-shot-samples : repeat-samples
Xacross all octaves.
X
XNote that a "one-shot sound" may be played as a "musical instrument"
Xand vice versa. However, an instrument player depends on samplesPerHiCycle,
Xand a one-shot player depends on samplesPerSec.
X
XPlaying a one-shot sound. To play any FORM 8SVX data as a one-shot
Xsound, first select an octave if ctOctave > 1. (The lowest-frequency
Xoctave has the greatest resolution.) Play the one-shot samples then
Xthe repeat samples, scaled by volume, at a data rate of samplesPerSec.
XOf course, you may adjust the playback rate and volume. You can play
Xout an envelope, too. (See ATAK and RLSE, below.)
X
XPlaying a musical note. To play a musical note using any FORM 8SVX,
Xfirst select the nearest octave of data from those available. Play
Xthe one-shot waveform then cycle on the repeat waveform as long as
Xneeded to sustain the note. Scale the signal by volume, perhaps also
Xby an envelope, and by a desired note volume. Select a playback data
Xrate s samples/second to achieve the desired frequency (in Hz):
Xfrequency = sJ/JsamplesPerHiCycle
Xfor the highest frequency octave.
X
XThe idea is to select an octave and one of 12 sampling rates (assuming
Xa 12-tone scale). If the FORM 8SVX doesn't have the right octave,
Xyou can decimate or interpolate from the available data.
X
XWhen it comes to musical instruments, FORM 8SVX is geared for a simple
Xsound driver. Such a driver uses a single table of 12 data rates to
Xreach all notes in all octaves. That's why 8SVX requires each octave
Xof data to have twice as many samples as the next higher octave. If
Xyou restrict samplesPerHiCycle to a power of two, you can use a predetermined
Xtable of data rates.
X
XOptional Text Chunks NAME, (c), AUTH, ANNO
X
XSeveral text chunks may be included in a FORM 8SVX to keep ancillary
Xinformation.
X
XThe optional property "NAME" names the voice, for instance "tubular
Xbells".
X
XThe optional property "(c)J" holds a copyright notice for the voice.
XThe chunk ID "(c)J" serves as the copyright characters ")J". E.g.
Xa "(c)J" chunk containing "1986 Electronic Arts" means ") 1986 Electronic
XArts".
X
XThe optional property "AUTH" holds the name of the instrument's "author"
Xor "creator".
X
XThe chunk types "NAME", "(c) ", and "AUTH" are property chunks. Putting
Xmore than one NAME (or other) property in a FORM is redundant. Just
Xthe last NAME counts. A property should be shorter than 256 characters.
XProperties can appear in a PROP 8SVX to share them over a LIST of
XFORMs 8SVX.
X
XThe optional data chunk "ANNO" holds any text annotations typed in
Xby the author.
X
XAn ANNO chunk is not a property chunk, so you can put more than one
Xin a FORM 8SVX. You can make ANNO chunks any length up to 231 - 1
Xcharacters, but 32767 is a practical limit. Since they're not properties,
XANNO chunks don't belong in a PROP 8SVX. That means they can't be
Xshared over a LIST of FORMs 8SVX.
X
XSyntactically, each of these chunks contains an array of 8-bit ASCII
Xcharacters in the range " " (SP, hex 20) through "~" (tilde, hex 7F),
Xjust like a standard "TEXT" chunk. [See "Strings, String Chunks, and
XString Properties" in "EA IFF 85" Electronic Arts Interchange File
XFormat.] The chunk's ckSize field holds the count of characters.
X
X#define ID_NAME MakeID('N', 'A', 'M', 'E')
X/* NAME chunk contains a CHAR[], the voice's name. */
X
X#define ID_Copyright MakeID('(', 'c', ')', ' ')
X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
X
X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
X/* AUTH chunk contains a CHAR[], the author's name. */
X
X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
X/* ANNO chunk contains a CHAR[], author's text annotations. */
X
XRemember to store a 0 pad byte after any odd-length chunk.
X
XOptional Data Chunks ATAK and RLSE
X
XThe optional data chunks ATAK and RLSE together give a piecewise-linear
X"envelope" or "amplitude contour". This contour may be used to modulate
Xthe sound during playback. It's especially useful for playing musical
Xnotes of variable durations. Playback programs may ignore the supplied
Xenvelope or substitute another.
X
X#define ID_ATAK MakeID('A', 'T', 'A', 'K')
X#define ID_RLSE MakeID('R', 'L', 'S', 'E')
X
Xtypedef struct {
X UWORD duration; /* segment duration in milliseconds, > 0 */
X Fixed dest; /* destination volume factor */
X } EGPoint;
X
X/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope.*/
X/* The envelope defines a function of time returning Fixed values. It's
X * used to scale the nominal volume specified in the Voice8Header. */
X
XTo explain the meaning of the ATAK and RLSE chunks, we'll overview
Xthe envelope generation algorithm. Start at 0 volume, step through
Xthe ATAK contour, then hold at the sustain level (the last ATAK EGPoint's
Xdest), and then step through the RLSE contour. Begin the release at
Xthe desired note stop time minus the total duration of the release
Xcontour (the sum of the RLSE EGPoints' durations). The attack contour
Xshould be cut short if the note is shorter than the release contour.
X
XThe envelope is a piecewise-linear function. The envelope generator
Xinterpolates between the EGPoints.
X
XRemember to multiply the envelope function by the nominal voice header
Xvolume and by any desired note volume.
X
XFigure 1 shows an example envelope. The attack period is described
Xby 4 EGPoints in an ATAK chunk. The release period is described by
X4 EGPoints in a RLSE chunk. The sustain period in the middle just
Xholds the final ATAK level until it's time for the release.
X
X
X
X
X
X
X
X
X
X
X Figure 1. Amplitude contour.
X
XNote: The number of EGPoints in an ATAK or RLSE chunk is its ckSize
X/ sizeof(EGPoint). In RAM, the playback program may terminate the
Xarray with a 0 duration EGPoint.
X
XIssue: Synthesizers also provide frequency contour (pitch bend), filtering
Xcontour (wah-wah), amplitude oscillation (tremolo), frequency oscillation
X(vibrato), and filtering oscillation (leslie). In the future, we may
Xdefine optional chunks to encode these modulations. The contours can
Xbe encoded in linear segments. The oscillations can be stored as segments
Xwith rate and depth parameters.
X
XData Chunk BODY
X
XThe BODY chunk contains the audio data samples.
X
X#define ID_BODY MakeID('B', 'O', 'D', 'Y')
X
Xtypedef character BYTE; /* 8 bit signed number, -128 through 127. */
X
X/* BODY chunk contains a BYTE[], array of audio data samples. */
X
XThe BODY contains data samples grouped by octave. Within each octave
Xare one-shot and repeat portions. Figure 2 depicts this arrangement
Xof samples for an 8SVX where oneShotHiSamples = 24, repeatHiSamples
X= 16, samplesPerHiCycle = 8, and ctOctave = 3. The major divisions
Xare octaves, the intermediate divisions separate the one-shot and
Xrepeat portions, and the minor divisions are cycles.
X
X
X
X
X
X
X
X
X
X Figure 2. BODY subdivisions.
X
XIn general, the BODY has ctOctave octaves of data. The highest frequency
Xoctave comes first, comprising the fewest samples: oneShotHiSamples
X+ repeatHiSamples. Each successive octave contains twice as many samples
Xas the next higher octave but the same number of cycles. The lowest
Xfrequency octave comes last with the most samples: 2ctOctave-1 * (oneShotHiSamp
Xles + repeatHiSamples).
X
XThe number of samples in the BODY chunk is
X
X 0 (ctOctave-1)
X(2 + ... + 2 * (oneShotHiSamples + repeatHiSamples)
X
XFigure 3, below, looks closer at an example waveform within one octave
Xof a different BODY chunk. In this example, oneShotHiSamples / samplesPerHiCycl
Xe = 2 cycles and repeatHiSamples / samplesPerHiCycle = 1 cycle.
X
X
X
X
X
X
X
X
X
X Figure 3. Example waveform.
X
XTo avoid playback "clicks", the one-shot part should begin with a
Xsmall sample value, and the one-shot part should flow smoothly into
Xthe repeat part, and the end of the repeat part should flow smoothly
Xinto the beginning of the repeat part.
X
XIf the VHDR field sCompression - sCmpNone, the BODY chunk is just
Xan array of data bytes to feed through the specified decompresser
Xfunction. All this stuff about sample sizes, octaves, and repeat parts
Xapplies to the decompressed data.
X
XBe sure to follow an odd-length BODY chunk with a 0 pad byte.
X
XOther Chunks
X
XIssue: In the future, we may define an optional chunk containing Fourier
Xseries coefficients for a repeating waveform. An editor for this kind
Xof synthesized voice could modify the coefficients and regenerate
Xthe waveform.
X
X
X
XAppendix A. Quick Reference
X
XType Definitions
X
X#define ID_8SVX MakeID('8', 'S', 'V', 'X')
X#define ID_VHDR MakeID('V', 'H', 'D', 'R')
X
Xtypedef LONG Fixed; /* A fixed-point value, 16 bits to the left
X * of the point and 16 to the right. A Fixed
X * is a number of 216ths, i.e. 65536ths. */
X
X#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume */
X
X/* sCompression: Choice of compression algorithm applied to the samples */
X
X#define sCmpNone 0 /* not compressed */
X#define sCmpFibDelta 1 /* Fibonacci-delta encoding (Appendix C) */
X /* Can be more kinds in the future. */
X
Xtypedef struct {
X ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
X repeatHiSamples, /* # samples in the high octave repeat part */
X samplesPerHiCycle; /* # samples/cycle in high octave, else 0 */
X UWORD samplesPerSec; /* data sampling rate */
X UBYTE ctOctave, /* # octaves of waveforms */
X sCompression; /* data compression technique used */
X Fixed volume; /* playback volume from 0 to Unity (full
X * volume). Map this value into the output
X * hardware's dynamic range. */
X } Voice8Header;
X
X#define ID_NAME MakeID('N', 'A', 'M', 'E')
X/* NAME chunk contains a CHAR[], the voice's name. */
X
X#define ID_Copyright MakeID('(', 'c', ')', ' ')
X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
X
X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
X/* AUTH chunk contains a CHAR[], the author's name. */
X
X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
X/* ANNO chunk contains a CHAR[], author's text annotations. */
X
X#define ID_ATAK MakeID('A', 'T', 'A', 'K')
X#define ID_RLSE MakeID('R', 'L', 'S', 'E')
X
Xtypedef struct {
X UWORD duration; /* segment duration in milliseconds, > 0 */
X Fixed dest; /* destination volume factor */
X } EGPoint;
X
X/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope. */
X/* The envelope defines a function of time returning Fixed values. It's
X * used to scale the nominal volume specified in the Voice8Header. */
X
X#define ID_BODY MakeID('B', 'O', 'D', 'Y')
X
Xtypedef character BYTE; /* 8 bit signed number, -128 through 127. */
X
X/* BODY chunk contains a BYTE[], array of audio data samples. */
X
X8SVX Regular Expression
X
XHere's a regular expression summary of the FORM 8SVX syntax. This
Xcould be an IFF file or part of one.
X
X8SVX ::= "FORM" #{ "8SVX" VHDR [NAME] [Copyright] [AUTH] ANNO*
X [ATAK] [RLSE] BODY }
X
XVHDR ::= "VHDR" #{ Voice8Header }
XNAME ::= "NAME" #{ CHAR* } [0]
XCopyright ::= "(c) " #{ CHAR* } [0]
XAUTH ::= "AUTH" #{ CHAR* } [0]
XANNO ::= "ANNO" #{ CHAR* } [0]
X
XATAK ::= "ATAK" #{ EGPoint* }
XRLSE ::= "RLSE" #{ EGPoint* }
XBODY ::= "FORM" #{ BYTE* } [0]
X
XThe token "#" represents a ckSize LONG count of the following {braced}
Xdata bytes. E.g. a VHDR's "#" should equal sizeof(Voice8Header). Literal
Xitems are shown in "quotes", [square bracket items] are optional,
Xand "*" means 0 or more replications. A sometimes-needed pad byte
Xis shown as "[0]".
X
XActually, the order of chunks in a FORM 8SVX is not as strict as this
Xregular expression indicates. The property chunks VHDR, NAME, Copyright,
Xand AUTH may actually appear in any order as long as they all precede
Xthe BODY chunk. The optional data chunks ANNO, ATAK, and RLSE don't
Xhave to precede the BODY chunk. And of course, new kinds of chunks
Xmay appear inside a FORM 8SVX in the future.
X
X
XAppendix B. 8SVX Example
X
XHere's a box diagram for a simple example containing the three octave
XBODY shown earlier in Figure 2.
X
X +-----------------------------------+
X |'FORM' 362 |
X +-----------------------------------+
X |'8SVX' |
X +-----------------------------------+
X | +-----------------------------+ |
X | |'VHDR' 20 | |
X | |24,16,8,10000,3,0,1.0 | |
X | +-----------------------------+ |
X | +-----------------------------+ |
X | |'NAME' 11 | |
X | |'bass guitar' | |
X | +-----------------------------+ |
X | 0 |
X | +-----------------------------+ |
X | |'(c)' 20 | |
X | |1985 Electronic Arts | |
X | +-----------------------------+ |
X | +-----------------------------+ |
X | |'BODY' 280 | |
X | |1, 2, 3, 4, ... | |
X | +-----------------------------+ |
X +-----------------------------------+
X
XThe "0" after the NAME chunk is a pad byte.
X
X
X
XAppendix B. Standards Committee
X
XThe following people contributed to the design of this IFF standard:
X
XBob "Kodiak" Burns, Commodore-Amiga
XR. J. Mical, Commodore-Amiga
XJerry Morrison, Electronic Arts
XGreg Riker, Electronic Arts
XSteve Shaw, Electronic Arts
XBarry Walsh, Commodore-Amiga
X
X
XThe "0" after the NAME chunk is a pad byte.
X
X
X
XAppendix C. Fibonacci Delta Compression
X
XThis is Steve Hayes' Fibonacci Delta sound compression technique.
XIt's like the traditional delta encoding but encodes each delta in
Xa mere 4 bits. The compressed data is half the size of the original
Xdata plus a 2-byte overhead for the initial value. This much compression
Xintroduces some distortion, so try it out and use it with discretion.
X
XTo achieve a reasonable slew rate, this algorithm looks up each stored
X4-bit value in a table of Fibonacci numbers. So very small deltas
Xare encoded precisely while larger deltas are approximated. When it
Xhas to make approximations, the compressor should adjust all the values
X(forwards and backwards in time) for minimum overall distortion.
X
XHere is the decompressor written in the C programming language.
X
X/* Fibonacci delta encoding for sound data. */
X
XBYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
X
X/* Unpack Fibonacci-delta encoded data from n byte source buffer into 2*n byte
X * dest buffer, given initial data value x. It returns the last data value x
X * so you can call it several times to incrementally decompress the data. */
X
Xshort D1Unpack(source, n, dest, x)
X BYTE source[], dest[];
X LONG n;
X BYTE x;
X {
X BYTE d;
X LONG i, lim;
X
X lim = n <<<< 1;
X for (i = 0; i << lim; ++i)
X {
X /* Decode a data nybble; high nybble then low nybble. */
X d = source[i >> 1]; /* get a pair of nybbles */
X if (i & 1) /* select low or high nybble? */
X d &= 0xf; /* mask to get the low nybble */
X else
X d >>= 4; /* shift to get the high nybble */
X x += codeToDelta[d]; /* add in the decoded delta */
X dest[i] = x; /* store a 1-byte sample */
X }
X return(x);
X }
X
X/* Unpack Fibonacci-delta encoded data from n byte source buffer into 2*(n-2)
X * byte dest buffer. Source buffer has a pad byte, an 8-bit initial value,
X * followed by n-2 bytes comprising 2*(n-2) 4-bit encoded samples. */
X
Xvoid DUnpack(source, n, dest)
X BYTE source[], dest[];
X LONG n;
X {
X D1Unpack(source + 2, n - 2, dest, source[1]);
X }
//END
echo x - ea.iff.85
sed 's/^X//' > ea.iff.85 << '//END'
X"EA IFF 85" Standard for Interchange Format Files
X
XDocument Date: January 14, 1985
XFrom: Jerry Morrison, Electronic Arts
XStatus of Standard: Released and in use
X
X1. Introduction
X
XStandards are Good for Software Developers
X
XAs home computer hardware evolves to better and better media machines,
Xthe demand increases for higher quality, more detailed data. Data
Xdevelopment gets more expensive, requires more expertise and better
Xtools, and has to be shared across projects. Think about several ports
Xof a product on one CD-ROM with 500M Bytes of common data!
X
XDevelopment tools need standard interchange file formats. Imagine
Xscanning in images of "player" shapes, moving them to a paint program
Xfor editing, then incorporating them into a game. Or writing a theme
Xsong with a Macintosh score editor and incorporating it into an Amiga
Xgame. The data must at times be transformed, clipped, filled out,
Xand moved across machine kinds. Media projects will depend on data
Xtransfer from graphic, music, sound effect, animation, and script
Xtools.
X
XStandards are Good for Software Users
X
XCustomers should be able to move their own data between independently
Xdeveloped software products. And they should be able to buy data libraries
Xusable across many such products. The types of data objects to exchange
Xare open-ended and include plain and formatted text, raster and structured
Xgraphics, fonts, music, sound effects, musical instrument descriptions,
Xand animation.
X
XThe problem with expedient file formats typically memory dumps is
Xthat they're too provincial. By designing data for one particular
Xuse (e.g. a screen snapshot), they preclude future expansion (would
Xyou like a full page picture? a multi-page document?). In neglecting
Xthe possibility that other programs might read their data, they fail
Xto save contextual information (how many bit planes? what resolution?).
XIgnoring that other programs might create such files, they're intolerant
Xof extra data (texture palette for a picture editor), missing data
X(no color map), or minor variations (smaller image). In practice,
Xa filed representation should rarely mirror an in-memory representation.
XThe former should be designed for longevity; the latter to optimize
Xthe manipulations of a particular program. The same filed data will
Xbe read into different memory formats by different programs.
X
XThe IFF philosophy: "A little behind-the-scenes conversion when programs
Xread and write files is far better than NxM explicit conversion utilities
Xfor highly specialized formats."
X
XSo we need some standardization for data interchange among development
Xtools and products. The more developers that adopt a standard, the
Xbetter for all of us and our customers.
X
XHere is "EA IFF 1985"
X
XHere is our offering: Electronic Arts' IFF standard for Interchange
XFile Format. The full name is "EA IFF 1985". Alternatives and justifications
Xare included for certain choices. Public domain subroutine packages
Xand utility programs are available to make it easy to write and use
XIFF-compatible programs.
X
XPart 1 introduces the standard. Part 2 presents its requirements and
Xbackground. Parts 3, 4, and 5 define the primitive data types, FORMs,
Xand LISTs, respectively, and how to define new high level types. Part
X6 specifies the top level file structure. Appendix A is included for
Xquick reference and Appendix B names the committee responsible for
Xthis standard.
X
XReferences
X
XAmerican National Standard Additional Control Codes for Use with ASCII,
XANSI standard 3.64-1979 for an 8-bit character set. See also ISO standard
X2022 and ISO/DIS standard 6429.2.
X
XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
X
XC, A Reference Manual, Samuel P. Harbison and Guy L. Steele Jr., Tartan
XLaboratories. Prentice-Hall, Englewood Cliffs, NJ, 1984.
X
XCompiler Construction, An Advanced Course, edited by F. L. Bauer and
XJ. Eickel (Springer-Verlag, 1976). This book is one of many sources
Xfor information on recursive descent parsing.
X
XDIF Technical Specification (c)1981 by Software Arts, Inc. DIF[tm] is
Xthe format for spreadsheet data interchange developed by Software
XArts, Inc.
XDIF[tm] is a trademark of Software Arts, Inc.
X
XElectronic Arts[tm] is a trademark of Electronic Arts.
X
X"FTXT" IFF Formatted Text, from Electronic Arts. IFF supplement document
Xfor a text format.
X
XInside Macintosh (c) 1982, 1983, 1984, 1985 Apple Computer, Inc., a
Xprogrammer's reference manual.
XApple(R) is a trademark of Apple Computer, Inc.
XMacintosh[tm] is a trademark licensed to Apple Computer, Inc.
X
X"ILBM" IFF Interleaved Bitmap, from Electronic Arts. IFF supplement
Xdocument for a raster image format.
X
XM68000 16/32-Bit Microprocessor Programmer's Reference Manual(c) 1984,
X1982, 1980, 1979 by Motorola, Inc.
X
XPostScript Language Manual (c) 1984 Adobe Systems Incorporated.
XPostScript[tm] is a trademark of Adobe Systems, Inc.
XTimes and Helvetica(R) are trademarks of Allied Corporation.
X
XInterScript: A Proposal for a Standard for the Interchange of Editable
XDocuments (c)1984 Xerox Corporation.
XIntroduction to InterScript (c) 1985 Xerox Corporation.
X
X
X
X2. Background for Designers
X
XPart 2 is about the background, requirements, and goals for the standard.
XIt's geared for people who want to design new types of IFF objects.
XPeople just interested in using the standard may wish to skip this
Xpart.
X
XWhat Do We Need?
X
XA standard should be long on prescription and short on overhead. It
Xshould give lots of rules for designing programs and data files for
Xsynergy. But neither the programs nor the files should cost too much
Xmore than the expedient variety. While we're looking to a future with
XCD-ROMs and perpendicular recording, the standard must work well on
Xfloppy disks.
X
XFor program portability, simplicity, and efficiency, formats should
Xbe designed with more than one implementation style in mind. (In practice,
Xpure stream I/O is adequate although random access makes it easier
Xto write files.) It ought to be possible to read one of many objects
Xin a file without scanning all the preceding data. Some programs need
Xto read and play out their data in real time, so we need good compromises
Xbetween generality and efficiency.
X
XAs much as we need standards, they can't hold up product schedules.
XSo we also need a kind of decentralized extensibility where any software
Xdeveloper can define and refine new object types without some "standards
Xauthority" in the loop. Developers must be able to extend existing
Xformats in a forward- and backward-compatible way. A central repository
Xfor design information and example programs can help us take full
Xadvantage of the standard.
X
XFor convenience, data formats should heed the restrictions of various
Xprocessors and environments. E.g. word-alignment greatly helps 68000
Xaccess at insignificant cost to 8088 programs.
X
XOther goals include the ability to share common elements over a list
Xof objects and the ability to construct composite objects containing
Xother data objects with structural information like directories.
X
XAnd finally, "Simple things should be simple and complex things should
Xbe possible." Alan Kay.
X
XThink Ahead
X
XLet's think ahead and build programs that read and write files for
Xeach other and for programs yet to be designed. Build data formats
Xto last for future computers so long as the overhead is acceptable.
XThis extends the usefulness and life of today's programs and data.
X
XTo maximize interconnectivity, the standard file structure and the
Xspecific object formats must all be general and extensible. Think
Xahead when designing an object. It should serve many purposes and
Xallow many programs to store and read back all the information they
Xneed; even squeeze in custom data. Then a programmer can store the
Xavailable data and is encouraged to include fixed contextual details.
XRecipient programs can read the needed parts, skip unrecognized stuff,
Xdefault missing data, and use the stored context to help transform
Xthe data as needed.
X
XScope
X
XIFF addresses these needs by defining a standard file structure, some
Xinitial data object types, ways to define new types, and rules for
Xaccessing these files. We can accomplish a great deal by writing programs
Xaccording to this standard, but don't expect direct compatibility
Xwith existing software. We'll need conversion programs to bridge the
Xgap from the old world.
X
XIFF is geared for computers that readily process information in 8-bit
Xbytes. It assumes a "physical layer" of data storage and transmission
Xthat reliably maintains "files" as strings of 8-bit bytes. The standard
Xtreats a "file" as a container of data bytes and is independent of
Xhow to find a file and whether it has a byte count.
X
XThis standard does not by itself implement a clipboard for cutting
Xand pasting data between programs. A clipboard needs software to mediate
Xaccess, to maintain a "contents version number" so programs can detect
Xupdates, and to manage the data in "virtual memory".
X
XData Abstraction
X
XThe basic problem is how to represent information in a way that's
Xprogram-independent, compiler- independent, machine-independent, and
Xdevice-independent.
X
XThe computer science approach is "data abstraction", also known as
X"objects", "actors", and "abstract data types". A data abstraction
Xhas a "concrete representation" (its storage format), an "abstract
Xrepresentation" (its capabilities and uses), and access procedures
Xthat isolate all the calling software from the concrete representation.
XOnly the access procedures touch the data storage. Hiding mutable
Xdetails behind an interface is called "information hiding". What data
Xabstraction does is abstract from details of implementing the object,
Xnamely the selected storage representation and algorithms for manipulating
Xit.
X
XThe power of this approach is modularity. By adjusting the access
Xprocedures we can extend and restructure the data without impacting
Xthe interface or its callers. Conversely, we can extend and restructure
Xthe interface and callers without making existing data obsolete. It's
Xgreat for interchange!
X
XBut we seem to need the opposite: fixed file formats for all programs
Xto access. Actually, we could file data abstractions ("filed objects")
Xby storing the data and access procedures together. We'd have to encode
Xthe access procedures in a standard machine-independent programming
Xlanguage la PostScript. Even still, the interface can't evolve freely
Xsince we can't update all copies of the access procedures. So we'll
Xhave to design our abstract representations for limited evolution
Xand occasional revolution (conversion).
X
XIn any case, today's microcomputers can't practically store data abstractions.
XThey can do the next best thing: store arbitrary types of data in
X"data chunks", each with a type identifier and a length count. The
Xtype identifier is a reference by name to the access procedures (any
Xlocal implementation). The length count enables storage-level object
Xoperations like "copy" and "skip to next" independent of object type.
X
XChunk writing is straightforward. Chunk reading requires a trivial
Xparser to scan each chunk and dispatch to the proper access/conversion
Xprocedure. Reading chunks nested inside other chunks requires recursion,
Xbut no lookahead or backup.
X
XThat's the main idea of IFF. There are, of course, a few other detailsI
X
XPrevious Work
X
XWhere our needs are similar, we borrow from existing standards.
X
XOur basic need to move data between independently developed programs
Xis similar to that addressed by the Apple Macintosh desk scrap or
X"clipboard" [Inside Macintosh chapter "Scrap Manager"]. The Scrap
XManager works closely with the Resource Manager, a handy filer and
Xswapper for data objects (text strings, dialog window templates, pictures,
XfontsI) including types yet to be designed [Inside Macintosh chapter
X"Resource Manager"]. The Resource Manager is a kin to Smalltalk's
Xobject swapper.
X
XWe will probably write a Macintosh desk accessory that converts IFF
Xfiles to and from the Macintosh clipboard for quick and easy interchange
Xwith programs like MacPaint and Resource Mover.
X
XMacintosh uses a simple and elegant scheme of 4-character "identifiers"
Xto identify resource types, clipboard format types, file types, and
Xfile creator programs. Alternatives are unique ID numbers assigned
Xby a central authority or by hierarchical authorities, unique ID numbers
Xgenerated by algorithm, other fixed length character strings, and
Xvariable length strings. Character string identifiers double as readable
Xsignposts in data files and programs. The choice of 4 characters is
Xa good tradeoff between storage space, fetch/compare/store time, and
Xname space size. We'll honor Apple's designers by adopting this scheme.
X
X"PICT" is a good example of a standard structured graphics format
X(including raster images) and its many uses [Inside Macintosh chapter
X"QuickDraw"]. Macintosh provides QuickDraw routines in ROM to create,
Xmanipulate, and display PICTs. Any application can create a PICT by
Xsimply asking QuickDraw to record a sequence of drawing commands.
XSince it's just as easy to ask QuickDraw to render a PICT to a screen
Xor a printer, it's very effective to pass them between programs, say
Xfrom an illustrator to a word processor. An important feature is the
Xability to store "comments" in a PICT which QuickDraw will ignore.
XActually, it passes them to your optional custom "comment handler".
X
XPostScript, Adobe's print file standard, is a more general way to
Xrepresent any print image (which is a specification for putting marks
Xon paper) [PostScript Language Manual]. In fact, PostScript is a full-fledged
Xprogramming language. To interpret a PostScript program is to render
Xa document on a raster output device. The language is defined in layers:
Xa lexical layer of identifiers, constants, and operators; a layer
Xof reverse polish semantics including scope rules and a way to define
Xnew subroutines; and a printing-specific layer of built-in identifiers
Xand operators for rendering graphic images. It is clearly a powerful
X(Turing equivalent) image definition language. PICT and a subset of
XPostScript are candidates for structured graphics standards.
X
XA PostScript document can be printed on any raster output device (including
Xa display) but cannot generally be edited. That's because the original
Xflexibility and constraints have been discarded. Besides, a PostScript
Xprogram may use arbitrary computation to supply parameters like placement
Xand size to each operator. A QuickDraw PICT, in comparison, is a more
Xrestricted format of graphic primitives parameterized by constants.
XSo a PICT can be edited at the level of the primitives, e.g. move
Xor thicken a line. It cannot be edited at the higher level of, say,
Xthe bar chart data which generated the picture.
X
XPostScript has another limitation: Not all kinds of data amount to
Xmarks on paper. A musical instrument description is one example. PostScript
Xis just not geared for such uses.
X
X"DIF" is another example of data being stored in a general format
Xusable by future programs [DIF Technical Specification]. DIF is a
Xformat for spreadsheet data interchange. DIF and PostScript are both
Xexpressed in plain ASCII text files. This is very handy for printing,
Xdebugging, experimenting, and transmitting across modems. It can have
Xsubstantial cost in compaction and read/write work, depending on use.
XWe won't store IFF files this way but we could define an ASCII alternate
Xrepresentation with a converter program.
X
XInterScript is Xerox' standard for interchange of editable documents
X[Introduction to InterScript]. It approaches a harder problem: How
Xto represent editable word processor documents that may contain formatted
Xtext, pictures, cross-references like figure numbers, and even highly
Xspecialized objects like mathematical equations? InterScript aims
Xto define one standard representation for each kind of information.
XEach InterScript-compatible editor is supposed to preserve the objects
Xit doesn't understand and even maintain nested cross-references. So
Xa simple word processor would let you edit the text of a fancy document
Xwithout discarding the equations or disrupting the equation numbers.
X
XOur task is similarly to store high level information and preserve
Xas much content as practical while moving it between programs. But
Xwe need to span a larger universe of data types and cannot expect
Xto centrally define them all. Fortunately, we don't need to make programs
Xpreserve information that they don't understand. And for better or
Xworse, we don't have to tackle general-purpose cross-references yet.
X
X
X
X3. Primitive Data Types
X
XAtomic components such as integers and characters that are interpretable
Xdirectly by the CPU are specified in one format for all processors.
XWe chose a format that's most convenient for the Motorola MC68000
Xprocessor [M68000 16/32-Bit Microprocessor Programmer's Reference
XManual].
X
XN.B.: Part 3 dictates the format for "primitive" data types where and
Xonly where used in the overall file structure and standard kinds of
Xchunks (Cf. Chunks). The number of such occurrences will be small
Xenough that the costs of conversion, storage, and management of processor-
Xspecific files would far exceed the costs of conversion during I/O by "foreign"
Xprograms. A particular data chunk may be specified with a different
Xformat for its internal primitive types or with processor- or environment-
Xspeci fic variants if necessary to optimize local usage. Since that hurts
Xdata interchange, it's not recommended. (Cf. Designing New Data Sections,
Xin Part 4.)
X
XAlignment
X
XAll data objects larger than a byte are aligned on even byte addresses
Xrelative to the start of the file. This may require padding. Pad bytes
Xare to be written as zeros, but don't count on that when reading.
X
XThis means that every odd-length "chunk" (see below) must be padded
Xso that the next one will fall on an even boundary. Also, designers
Xof structures to be stored in chunks should include pad fields where
Xneeded to align every field larger than a byte. Zeros should be stored
Xin all the pad bytes.
X
XJustification: Even-alignment causes a little extra work for files
Xthat are used only on certain processors but allows 68000 programs
Xto construct and scan the data in memory and do block I/O. You just
Xadd an occasional pad field to data structures that you're going to
Xblock read/write or else stream read/write an extra byte. And the
Xsame source code works on all processors. Unspecified alignment, on
Xthe other hand, would force 68000 programs to (dis)assemble word and
Xlong-word data one byte at a time. Pretty cumbersome in a high level
Xlanguage. And if you don't conditionally compile that out for other
Xprocessors, you won't gain anything.
X
XNumbers
X
XNumeric types supported are two's complement binary integers in the
Xformat used by the MC68000 processor high byte first, high word first the
Xreverse of 8088 and 6502 format. They could potentially include signed
Xand unsigned 8, 16, and 32 bit integers but the standard only uses
Xthe following:
X
XUBYTE 8 bits unsigned
XWORD 16 bits signed
XUWORD 16 bits unsigned
XLONG 32 bits signed
X
XThe actual type definitions depend on the CPU and the compiler. In
Xthis document, we'll express data type definitions in the C programming
Xlanguage. [See C, A Reference Manual.] In 68000 Lattice C:
X
Xtypedef unsigned char UBYTE; /* 8 bits unsigned */
Xtypedef short WORD; /* 16 bits signed */
Xtypedef unsigned short UWORD; /* 16 bits unsigned */
Xtypedef long LONG; /* 32 bits signed */
X
XCharacters
X
XThe following character set is assumed wherever characters are used,
Xe.g. in text strings, IDs, and TEXT chunks (see below).
X
XCharacters are encoded in 8-bit ASCII. Characters in the range NUL
X(hex 0) through DEL (hex 7F) are well defined by the 7-bit ASCII standard.
XIFF uses the graphic group RJS (SP, hex 20) through R~S (hex 7E).
X
XMost of the control character group hex 01 through hex 1F have no
Xstandard meaning in IFF. The control character LF (hex 0A) is defined
Xas a "newline" character. It denotes an intentional line break, that
Xis, a paragraph or line terminator. (There is no way to store an automatic
Xline break. That is strictly a function of the margins in the environment
Xthe text is placed.) The control character ESC (hex 1B) is a reserved
Xescape character under the rules of ANSI standard 3.64-1979 American
XNational Standard Additional Control Codes for Use with ASCII, ISO
Xstandard 2022, and ISO/DIS standard 6429.2.
X
XCharacters in the range hex 7F through hex FF are not globally defined
Xin IFF. They are best left reserved for future standardization. But
Xnote that the FORM type FTXT (formatted text) defines the meaning
Xof these characters within FTXT forms. In particular, character values
Xhex 7F through hex 9F are control codes while characters hex A0 through
Xhex FF are extended graphic characters like , as per the ISO and
XANSI standards cited above. [See the supplementary document "FTXT"
XIFF Formatted Text.]
X
XDates
X
XA "creation date" is defined as the date and time a stream of data
Xbytes was created. (Some systems call this a "last modified date".)
XEditing some data changes its creation date. Moving the data between
Xvolumes or machines does not.
X
XThe IFF standard date format will be one of those used in MS-DOS,
XMacintosh, or Amiga DOS (probably a 32-bit unsigned number of seconds
Xsince a reference point). Issue: Investigate these three.
X
XType IDs
X
XA "type ID", "property name", "FORM type", or any other IFF identifier
Xis a 32-bit value: the concatenation of four ASCII characters in the
Xrange R S (SP, hex 20) through R~S (hex 7E). Spaces (hex 20) should
Xnot precede printing characters; trailing spaces are ok. Control characters
Xare forbidden.
X
Xtypedef CHAR ID[4];
X
XIDs are compared using a simple 32-bit case-dependent equality test.
X
XData section type IDs (aka FORM types) are restriced IDs. (Cf. Data
XSections.) Since they may be stored in filename extensions (Cf. Single
XPurpose Files) lower case letters and punctuation marks are forbidden.
XTrailing spaces are ok.
X
XCarefully choose those four characters when you pick a new ID. Make
Xthem mnemonic so programmers can look at an interchange format file
Xand figure out what kind of data it contains. The name space makes
Xit possible for developers scattered around the globe to generate
XID values with minimal collisions so long as they choose specific
Xnames like "MUS4" instead of general ones like "TYPE" and "FILE".
XEA will "register" new FORM type IDs and format descriptions as they're
Xdevised, but collisions will be improbable so there will be no pressure
Xon this "clearinghouse" process. Appendix A has a list of currently
Xdefined IDs.
X
XSometimes it's necessary to make data format changes that aren't backward
Xcompatible. Since IDs are used to denote data formats in IFF, new
XIDs are chosen to denote revised formats. Since programs won't read
Xchunks whose IDs they don't recognize (see Chunks, below), the new
XIDs keep old programs from stumbling over new data. The conventional
Xway to chose a "revision" ID is to increment the last character if
Xit's a digit or else change the last character to a digit. E.g. first
Xand second revisions of the ID "XY" would be "XY1" and "XY2". Revisions
Xof "CMAP" would be "CMA1" and "CMA2".
X
XChunks
X
XChunks are the building blocks in the IFF structure. The form expressed
Xas a C typedef is:
X
Xtypedef struct {
X ID ckID;
X LONG ckSize; /* sizeof(ckData) */
X UBYTE ckData[/* ckSize */];
X } Chunk;
X
XWe can diagram an example chunk a "CMAP" chunk containing 12 data
Xbytes like this:
X ----------------
X ckID: | 'CMAP' |
X ckSize: | 12 |
X ckData: | 0, 0, 0, 32 | --------
X | 0, 0, 64, 0 | 12 bytes
X | 0, 0, 64, 0 | ---------
X ----------------
X
XThe fixed header part means "Here's a type ckID chunk with ckSize
Xbytes of data."
X
XThe ckID identifies the format and purpose of the chunk. As a rule,
Xa program must recognize ckID to interpret ckData. It should skip
Xover all unrecognized chunks. The ckID also serves as a format version
Xnumber as long as we pick new IDs to identify new formats of ckData
X(see above).
X
XThe following ckIDs are universally reserved to identify chunks with
Xparticular IFF meanings: "LIST", "FORM", "PROP", "CAT ", and "
X". The special ID " " (4 spaces) is a ckID for "filler" chunks,
Xthat is, chunks that fill space but have no meaningful contents. The
XIDs "LIS1" through "LIS9", "FOR1" through "FOR9", and "CAT1" through
X"CAT9" are reserved for future "version number" variations. All IFF-compatible
Xsoftware must account for these 23 chunk IDs. Appendix A has a list
Xof predefined IDs.
X
XThe ckSize is a logical block size how many data bytes are in ckData.
XIf ckData is an odd number of bytes long, a 0 pad byte follows which
Xis not included in ckSize. (Cf. Alignment.) A chunk's total physical
Xsize is ckSize rounded up to an even number plus the size of the header.
XSo the smallest chunk is 8 bytes long with ckSize = 0. For the sake
Xof following chunks, programs must respect every chunk's ckSize as
Xa virtual end-of-file for reading its ckData even if that data is
Xmalformed, e.g. if nested contents are truncated.
X
XWe can describe the syntax of a chunk as a regular expression with
X"#" representing the ckSize, i.e. the length of the following {braced}
Xbytes. The "[0]" represents a sometimes needed pad byte. (The regular
Xexpressions in this document are collected in Appendix A along with
Xan explanation of notation.)
X
XChunk ::= ID #{ UBYTE* } [0]
X
XOne chunk output technique is to stream write a chunk header, stream
Xwrite the chunk contents, then random access back to the header to
Xfill in the size. Another technique is to make a preliminary pass
Xover the data to compute the size, then write it out all at once.
X
XStrings, String Chunks, and String Properties
X
XIn a string of ASCII text, LF denotes a forced line break (paragraph
Xor line terminator). Other control characters are not used. (Cf. Characters.)
X
XThe ckID for a chunk that contains a string of plain, unformatted
Xtext is "TEXT". As a practical matter, a text string should probably
Xnot be longer than 32767 bytes. The standard allows up to 231 - 1
Xbytes.
X
XWhen used as a data property (see below), a text string chunk may
Xbe 0 to 255 characters long. Such a string is readily converted to
Xa C string or a Pascal STRING[255]. The ckID of a property must be
Xthe property name, not "TEXT".
X
XWhen used as a part of a chunk or data property, restricted C string
Xformat is normally used. That means 0 to 255 characters followed by
Xa NUL byte (ASCII value 0).
X
XData Properties
X
XData properties specify attributes for following (non-property) chunks.
XA data property essentially says "identifier = value", for example
X"XY = (10, 200)", telling something about following chunks. Properties
Xmay only appear inside data sections ("FORM" chunks, cf. Data Sections)
Xand property sections ("PROP" chunks, cf. Group PROP).
X
XThe form of a data property is a special case of Chunk. The ckID is
Xa property name as well as a property type. The ckSize should be small
Xsince data properties are intended to be accumulated in RAM when reading
Xa file. (256 bytes is a reasonable upper bound.) Syntactically:
X
XProperty ::= Chunk
X
XWhen designing a data object, use properties to describe context information
Xlike the size of an image, even if they don't vary in your program.
XOther programs will need this information.
X
XThink of property settings as assignments to variables in a programming
Xlanguage. Multiple assignments are redundant and local assignments
Xtemporarily override global assignments. The order of assignments
Xdoesn't matter as long as they precede the affected chunks. (Cf. LISTs,
XCATs, and Shared Properties.)
X
XEach object type (FORM type) is a local name space for property IDs.
XThink of a "CMAP" property in a "FORM ILBM" as the qualified ID "ILBM.CMAP".
XProperty IDs specified when an object type is designed (and therefore
Xknown to all clients) are called "standard" while specialized ones
Xadded later are "nonstandard".
X
XLinks
X
XIssue: A standard mechanism for "links" or "cross references" is very
Xdesirable for things like combining images and sounds into animations.
XPerhaps we'll define "link" chunks within FORMs that refer to other
XFORMs or to specific chunks within the same and other FORMs. This
Xneeds further work. EA IFF 1985 has no standard link mechanism.
X
XFor now, it may suffice to read a list of, say, musical instruments,
Xand then just refer to them within a musical score by index number.
X
XFile References
X
XIssue: We may need a standard form for references to other files.
XA "file ref" could name a directory and a file in the same type of
Xoperating system as the ref's originator. Following the reference
Xwould expect the file to be on some mounted volume. In a network environment,
Xa file ref could name a server, too.
X
XIssue: How can we express operating-system independent file refs?
X
XIssue: What about a means to reference a portion of another file?
XWould this be a "file ref" plus a reference to a "link" within the
Xtarget file?
X
X
X
X4. Data Sections
X
XThe first thing we need of a file is to check: Does it contain IFF
Xdata and, if so, does it contain the kind of data we're looking for?
XSo we come to the notion of a "data section".
X
XA "data section" or IFF "FORM" is one self-contained "data object"
Xthat might be stored in a file by itself. It is one high level data
Xobject such as a picture or a sound effect. The IFF structure "FORM"
Xmakes it self- identifying. It could be a composite object like a
Xmusical score with nested musical instrument descriptions.
X
XGroup FORM
X
XA data section is a chunk with ckID "FORM" and this arrangement:
X
XFORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)*
X}
XFormType ::= ID
XLocalChunk ::= Property | Chunk
X
XThe ID "FORM" is a syntactic keyword like "struct" in C. Think of
Xa "struct ILBM" containing a field "CMAP". If you see "FORM" you'll
Xknow to expect a FORM type ID (the structure name, "ILBM" in this
Xexample) and a particular contents arrangement or "syntax" (local
Xchunks, FORMs, LISTs, and CATs). (LISTs and CATs are discussed in
Xpart 5, below.) A "FORM ILBM", in particular, might contain a local
Xchunk "CMAP", an "ILBM.CMAP" (to use a qualified name).
X
XSo the chunk ID "FORM" indicates a data section. It implies that the
Xchunk contains an ID and some number of nested chunks. In reading
Xa FORM, like any other chunk, programs must respect its ckSize as
Xa virtual end-of-file for reading its contents, even if they're truncated.
X
XThe FormType (or FORM type) is a restricted ID that may not contain
Xlower case letters or punctuation characters. (Cf. Type IDs. Cf. Single
XPurpose Files.)
X
XThe type-specific information in a FORM is composed of its "local
Xchunks": data properties and other chunks. Each FORM type is a local
Xname space for local chunk IDs. So "CMAP" local chunks in other FORM
Xtypes may be unrelated to "ILBM.CMAP". More than that, each FORM type
Xdefines semantic scope. If you know what a FORM ILBM is, you'll know
Xwhat an ILBM.CMAP is.
X
XLocal chunks defined when the FORM type is designed (and therefore
Xknown to all clients of this type) are called "standard" while specialized
Xones added later are "nonstandard".
X
XAmong the local chunks, property chunks give settings for various
Xdetails like text font while the other chunks supply the essential
Xinformation. This distinction is not clear cut. A property setting
Xcancelled by a later setting of the same property has effect only
Xon data chunks in between. E.g. in the sequence:
X
Xprop1 = x (propN = value)* prop1 = y
X
Xwhere the propNs are not prop1, the setting prop1 = x has no effect.
X
XThe following universal chunk IDs are reserved inside any FORM: "LIST",
X"FORM", "PROP", "CAT ", "JJJJ", "LIS1" through "LIS9", "FOR1" through
X"FOR9", and "CAT1" through "CAT9". (Cf. Chunks. Cf. Group LIST. Cf.
XGroup PROP.) For clarity, these universal chunk names may not be FORM
Xtype IDs, either.
X
XPart 5, below, talks about grouping FORMs into LISTs and CATs. They
Xlet you group a bunch of FORMs but don't impose any particular meaning
Xor constraints on the grouping. Read on.
X
XComposite FORMs
X
XA FORM chunk inside a FORM is a full-fledged data section. This means
Xyou can build a composite object like a multi-frame animation sequence
Xfrom available picture FORMs and sound effect FORMs. You can insert
Xadditional chunks with information like frame rate and frame count.
X
XUsing composite FORMs, you leverage on existing programs that create
Xand edit the component FORMs. Those editors may even look into your
Xcomposite object to copy out its type of component, although it'll
Xbe the rare program that's fancy enough to do that. Such editors are
Xnot allowed to replace their component objects within your composite
Xobject. That's because the IFF standard lets you specify consistency
Xrequirements for the composite FORM such as maintaining a count or
Xa directory of the components. Only programs that are written to uphold
Xthe rules of your FORM type should create or modify such FORMs.
X
XTherefore, in designing a program that creates composite objects,
Xyou are strongly requested to provide a facility for your users to
Ximport and export the nested FORMs. Import and export could move the
Xdata through a clipboard or a file.
X
XHere are several existing FORM types and rules for defining new ones.
X
XFTXT
X
XAn FTXT data section contains text with character formatting information
Xlike fonts and faces. It has no paragraph or document formatting information
Xlike margins and page headers. FORM FTXT is well matched to the text
Xrepresentation in Amiga's Intuition environment. See the supplemental
Xdocument "FTXT" IFF Formatted Text.
X
XILBM
X
X"ILBM" is an InterLeaved BitMap image with color map; a machine-independent
Xformat for raster images. FORM ILBM is the standard image file format
Xfor the Commodore-Amiga computer and is useful in other environments,
Xtoo. See the supplemental document "ILBM" IFF Interleaved Bitmap.
X
XPICS
X
XThe data chunk inside a "PICS" data section has ID "PICT" and holds
Xa QuickDraw picture. Issue: Allow more than one PICT in a PICS? See
XInside Macintosh chapter "QuickDraw" for details on PICTs and how
Xto create and display them on the Macintosh computer.
X
XThe only standard property for PICS is "XY", an optional property
Xthat indicates the position of the PICT relative to "the big picture".
XThe contents of an XY is a QuickDraw Point.
X
XNote: PICT may be limited to Macintosh use, in which case there'll
Xbe another format for structured graphics in other environments.
X
XOther Macintosh Resource Types
X
XSome other Macintosh resource types could be adopted for use within
XIFF files; perhaps MWRT, ICN, ICN#, and STR#.
X
XIssue: Consider the candidates and reserve some more IDs.
X
XDesigning New Data Sections
X
XSupplemental documents will define additional object types. A supplement
Xneeds to specify the object's purpose, its FORM type ID, the IDs and
Xformats of standard local chunks, and rules for generating and interpreting
Xthe data. It's a good idea to supply typedefs and an example source
Xprogram that accesses the new object. See "ILBM" IFF Interleaved Bitmap
Xfor a good example.
X
XAnyone can pick a new FORM type ID but should reserve it with Electronic
XArts at their earliest convenience. [Issue: EA contact person? Hand
Xthis off to another organization?] While decentralized format definitions
Xand extensions are possible in IFF, our preference is to get design
Xconsensus by committee, implement a program to read and write it,
Xperhaps tune the format, and then publish the format with example
Xcode. Some organization should remain in charge of answering questions
Xand coordinating extensions to the format.
X
XIf it becomes necessary to revise the design of some data section,
Xits FORM type ID will serve as a version number (Cf. Type IDs). E.g.
Xa revised "VDEO" data section could be called "VDE1". But try to get
Xby with compatible revisions within the existing FORM type.
X
XIn a new FORM type, the rules for primitive data types and word-alignment
X(Cf. Primitive Data Types) may be overriden for the contents of its
Xlocal chunks but not for the chunk structure itself if your documentation
Xspells out the deviations. If machine-specific type variants are needed,
Xe.g. to store vast numbers of integers in reverse bit order, then
Xoutline the conversion algorithm and indicate the variant inside each
Xfile, perhaps via different FORM types. Needless to say, variations
Xshould be minimized.
X
XIn designing a FORM type, encapsulate all the data that other programs
Xwill need to interpret your files. E.g. a raster graphics image should
Xspecify the image size even if your program always uses 320 x 200
Xpixels x 3 bitplanes. Receiving programs are then empowered to append
Xor clip the image rectangle, to add or drop bitplanes, etc. This enables
Xa lot more compatibility.
X
XSeparate the central data (like musical notes) from more specialized
Xinformation (like note beams) so simpler programs can extract the
Xcentral parts during read-in. Leave room for expansion so other programs
Xcan squeeze in new kinds of information (like lyrics). And remember
Xto keep the property chunks manageably short let's say 2 256 bytes.
X
XWhen designing a data object, try to strike a good tradeoff between
Xa super-general format and a highly-specialized one. Fit the details
Xto at least one particular need, for example a raster image might
Xas well store pixels in the current machine's scan order. But add
Xthe kind of generality that makes it usable with foreseeable hardware
Xand software. E.g. use a whole byte for each red, green, and blue
Xcolor value even if this year's computer has only 4-bit video DACs.
XThink ahead and help other programs so long as the overhead is acceptable.
XE.g. run compress a raster by scan line rather than as a unit so future
Xprograms can swap images by scan line to and from secondary storage.
X
XTry to design a general purpose "least common multiple" format that
Xencompasses the needs of many programs without getting too complicated.
XLet's coalesce our uses around a few such formats widely separated
Xin the vast design space. Two factors make this flexibility and simplicity
Xpractical. First, file storage space is getting very plentiful, so
Xcompaction is not a priority. Second, nearly any locally-performed
Xdata conversion work during file reading and writing will be cheap
Xcompared to the I/O time.
X
XIt must be ok to copy a LIST or FORM or CAT intact, e.g. to incorporate
Xit into a composite FORM. So any kind of internal references within
Xa FORM must be relative references. They could be relative to the
Xstart of the containing FORM, relative from the referencing chunk,
Xor a sequence number into a collection.
X
XWith composite FORMs, you leverage on existing programs that create
Xand edit the components. If you write a program that creates composite
Xobjects, please provide a facility for your users to import and export
Xthe nested FORMs. The import and export functions may move data through
Xa separate file or a clipboard.
X
XFinally, don't forget to specify all implied rules in detail.
X
X
X
X5. LISTs, CATs, and Shared Properties
X
XData often needs to be grouped together like a list of icons. Sometimes
Xa trick like arranging little images into a big raster works, but
Xgenerally they'll need to be structured as a first class group. The
Xobjects "LIST" and "CAT" are IFF-universal mechanisms for this purpose.
X
XProperty settings sometimes need to be shared over a list of similar
Xobjects. E.g. a list of icons may share one color map. LIST provides
Xa means called "PROP" to do this. One purpose of a LIST is to define
Xthe scope of a PROP. A "CAT", on the other hand, is simply a concatenation
Xof objects.
X
XSimpler programs may skip LISTs and PROPs altogether and just handle
XFORMs and CATs. All "fully-conforming" IFF programs also know about
X"CAT ", "LIST", and "PROP". Any program that reads a FORM inside a
XLIST must process shared PROPs to correctly interpret that FORM.
X
XGroup CAT
X
XA CAT is just an untyped group of data objects.
X
XStructurally, a CAT is a chunk with chunk ID "CAT " containing a "contents
Xtype" ID followed by the nested objects. The ckSize of each contained
Xchunk is essentially a relative pointer to the next one.
X
XCAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* }
XContentsType ::= ID -- a hint or an "abstract data type" ID
X
XIn reading a CAT, like any other chunk, programs must respect it's
XckSize as a virtual end-of-file for reading the nested objects even
Xif they're malformed or truncated.
X
XThe "contents type" following the CAT's ckSize indicates what kind
Xof FORMs are inside. So a CAT of ILBMs would store "ILBM" there. It's
Xjust a hint. It may be used to store an "abstract data type". A CAT
Xcould just have blank contents ID ("JJJJ") if it contains more than
Xone kind of FORM.
X
XCAT defines only the format of the group. The group's meaning is open
Xto interpretation. This is like a list in LISP: the structure of cells
Xis predefined but the meaning of the contents as, say, an association
Xlist depends on use. If you need a group with an enforced meaning
X(an "abstract data type" or Smalltalk "subclass"), some consistency
Xconstraints, or additional data chunks, use a composite FORM instead
X(Cf. Composite FORMs).
X
XSince a CAT just means a concatenation of objects, CATs are rarely
Xnested. Programs should really merge CATs rather than nest them.
X
XGroup LIST
X
XA LIST defines a group very much like CAT but it also gives a scope
Xfor PROPs (see below). And unlike CATs, LISTs should not be merged
Xwithout understanding their contents.
X
XStructurally, a LIST is a chunk with ckID "LIST" containing a "contents
Xtype" ID, optional shared properties, and the nested contents (FORMs,
XLISTs, and CATs), in that order. The ckSize of each contained chunk
Xis a relative pointer to the next one. A LIST is not an arbitrary
Xlinked list the cells are simply concatenated.
X
XLIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* }
XContentsType ::= ID
X
XGroup PROP
X
XPROP chunks may appear in LISTs (not in FORMs or CATs). They supply
Xshared properties for the FORMs in that LIST. This ability to elevate
Xsome property settings to shared status for a list of forms is useful
Xfor both indirection and compaction. E.g. a list of images with the
Xsame size and colors can share one "size" property and one "color
Xmap" property. Individual FORMs can override the shared settings.
X
XThe contents of a PROP is like a FORM with no data chunks:
X
XPROP ::= "PROP" #{ FormType Property* }
X
XIt means, "Here are the shared properties for FORM type <<FormType>."
X
XA LIST may have at most one PROP of a FORM type, and all the PROPs
Xmust appear before any of the FORMs or nested LISTs and CATs. You
Xcan have subsequences of FORMs sharing properties by making each subsequence
Xa LIST.
X
XScoping: Think of property settings as variable bindings in nested
Xblocks of a programming language. Where in C you could write:
X
XTEXT_FONT text_font = Courier; /* program's global default */
X
XFile(); {
X TEXT_FONT text_font = TimesRoman; /* shared setting */
X
X {
X TEXT_FONT text_font = Helvetica; /* local setting */
X Print("Hello "); /* uses font Helvetica */
X }
X
X {
X Print("there."); /* uses font TimesRoman */
X }
X }
X
XAn IFF file could contain:
X
XLIST {
X PROP TEXT {
X FONT {TimesRoman} /* shared setting */
X }
X
X FORM TEXT {
X FONT {Helvetica} /* local setting */
X CHRS {Hello } /* uses font Helvetica */
X }
X
X FORM TEXT {
X CHRS {there.} /* uses font TimesRoman */
X }
X }
X
XThe shared property assignments selectively override the reader's
Xglobal defaults, but only for FORMs within the group. A FORM's own
Xproperty assignments selectively override the global and group-supplied
Xvalues. So when reading an IFF file, keep property settings on a stack.
XThey're designed to be small enough to hold in main memory.
X
XShared properties are semantically equivalent to copying those properties
Xinto each of the nested FORMs right after their FORM type IDs.
X
XProperties for LIST
X
XOptional "properties for LIST" store the origin of the list's contents
Xin a PROP chunk for the fake FORM type "LIST". They are the properties
Xoriginating program "OPGM", processor family "OCPU", computer type
X"OCMP", computer serial number or network address "OSN ", and user
Xname "UNAM". In our imperfect world, these could be called upon to
Xdistinguish between unintended variations of a data format or to work
Xaround bugs in particular originating/receiving program pairs. Issue:
XSpecify the format of these properties.
X
XA creation date could also be stored in a property but let's ask that
Xfile creating, editing, and transporting programs maintain the correct
Xdate in the local file system. Programs that move files between machine
Xtypes are expected to copy across the creation dates.
X
X
X
X6. Standard File Structure
X
XFile Structure Overview
X
XAn IFF file is just a single chunk of type FORM, LIST, or CAT. Therefore
Xan IFF file can be recognized by its first 4 bytes: "FORM", "LIST",
Xor "CAT ". Any file contents after the chunk's end are to be ignored.
X
XSince an IFF file can be a group of objects, programs that read/write
Xsingle objects can communicate to an extent with programs that read/write
Xgroups. You're encouraged to write programs that handle all the objects
Xin a LIST or CAT. A graphics editor, for example, could process a
Xlist of pictures as a multiple page document, one page at a time.
X
XPrograms should enforce IFF's syntactic rules when reading and writing
Xfiles. This ensures robust data transfer. The public domain IFF reader/writer
Xsubroutine package does this for you. A utility program "IFFCheck"
Xis available that scans an IFF file and checks it for conformance
Xto IFF's syntactic rules. IFFCheck also prints an outline of the chunks
Xin the file, showing the ckID and ckSize of each. This is quite handy
Xwhen building IFF programs. Example programs are also available to
Xshow details of reading and writing IFF files.
X
XA merge program "IFFJoin" will be available that logically appends
XIFF files into a single CAT group. It "unwraps" each input file that
Xis a CAT so that the combined file isn't nested CATs.
X
XIf we need to revise the IFF standard, the three anchoring IDs will
Xbe used as "version numbers". That's why IDs "FOR1" through "FOR9",
X"LIS1" through "LIS9", and "CAT1" through "CAT9" are reserved.
X
XIFF formats are designed for reasonable performance with floppy disks.
XWe achieve considerable simplicity in the formats and programs by
Xrelying on the host file system rather than defining universal grouping
Xstructures like directories for LIST contents. On huge storage systems,
XIFF files could be leaf nodes in a file structure like a B-tree. Let's
Xhope the host file system implements that for us!
X
XThre are two kinds of IFF files: single purpose files and scrap files.
XThey differ in the interpretation of multiple data objects and in
Xthe file's external type.
X
XSingle Purpose Files
X
XA single purpose IFF file is for normal "document" and "archive" storage.
XThis is in contrast with "scrap files" (see below) and temporary backing
Xstorage (non-interchange files).
X
XThe external file type (or filename extension, depending on the host
Xfile system) indicates the file's contents. It's generally the FORM
Xtype of the data contained, hence the restrictions on FORM type IDs.
X
XProgrammers and users may pick an "intended use" type as the filename
Xextension to make it easy to filter for the relevant files in a filename
Xrequestor. This is actually a "subclass" or "subtype" that conveniently
Xseparates files of the same FORM type that have different uses. Programs
Xcannot demand conformity to its expected subtypes without overly restricting
Xdata interchange since they cannot know about the subtypes to be used
Xby future programs that users will want to exchange data with.
X
XIssue: How to generate 3-letter MS-DOS extensions from 4-letter FORM
Xtype IDs?
X
XMost single purpose files will be a single FORM (perhaps a composite
XFORM like a musical score containing nested FORMs like musical instrument
Xdescriptions). If it's a LIST or a CAT, programs should skip over
Xunrecognized objects to read the recognized ones or the first recognized
Xone. Then a program that can read a single purpose file can read something
Xout of a "scrap file", too.
X
XScrap Files
X
XA "scrap file" is for maximum interconnectivity in getting data between
Xprograms; the core of a clipboard function. Scrap files may have type
X"IFF " or filename extension ".IFF".
X
XA scrap file is typically a CAT containing alternate representations
Xof the same basic information. Include as many alternatives as you
Xcan readily generate. This redundancy improves interconnectivity in
Xsituations where we can't make all programs read and write super-general
Xformats. [Inside Macintosh chapter "Scrap Manager".] E.g. a graphically-
Xannotated musical score might be supplemented by a stripped down 4-voice
Xmelody and by a text (the lyrics).
X
XThe originating program should write the alternate representations
Xin order of "preference": most preferred (most comprehensive) type
Xto least preferred (least comprehensive) type. A receiving program
Xshould either use the first appearing type that it understands or
Xsearch for its own "preferred" type.
X
XA scrap file should have at most one alternative of any type. (A LIST
Xof same type objects is ok as one of the alternatives.) But don't
Xcount on this when reading; ignore extra sections of a type. Then
Xa program that reads scrap files can read something out of single
Xpurpose files.
X
XRules for Reader Programs
X
XHere are some notes on building programs that read IFF files. If you
Xuse the standard IFF reader module "IFFR.C", many of these rules and
Xdetails will be automatically handled. (See "Support Software" in
XAppendix A.) We recommend that you start from the example program
X"ShowILBM.C". You should also read up on recursive descent parsers.
X[See, for example, Compiler Construction, An Advanced Course.]
X
X% The standard is very flexible so many programs can exchange
Xdata. This implies a program has to scan the file and react to what's
Xactually there in whatever order it appears. An IFF reader program
Xis a parser.
X
X% For interchange to really work, programs must be willing to
Xdo some conversion during read-in. If the data isn't exactly what
Xyou expect, say, the raster is smaller than those created by your
Xprogram, then adjust it. Similarly, your program could crop a large
Xpicture, add or drop bitplanes, and create/discard a mask plane. The
Xprogram should give up gracefully on data that it can't convert.
X
X% If it doesn't start with "FORM", "LIST", or "CAT ", it's not
Xan IFF-85 file.
X
X% For any chunk you encounter, you must recognize its type ID
Xto understand its contents.
X
X% For any FORM chunk you encounter, you must recognize its FORM
Xtype ID to understand the contained "local chunks". Even if you don't
Xrecognize the FORM type, you can still scan it for nested FORMs, LISTs,
Xand CATs of interest.
X
X% Don't forget to skip the pad byte after every odd-length chunk.
X
X% Chunk types LIST, FORM, PROP, and CAT are generic groups. They
Xalways contain a subtype ID followed by chunks.
X
X% Readers ought to handle a CAT of FORMs in a file. You may treat
Xthe FORMs like document pages to sequence through or just use the
Xfirst FORM.
X
X% Simpler IFF readers completely skip LISTs. "Fully IFF-conforming"
Xreaders are those that handle LISTs, even if just to read the first
XFORM from a file. If you do look into a LIST, you must process shared
Xproperties (in PROP chunks) properly. The idea is to get the correct
Xdata or none at all.
X
X% The nicest readers are willing to look into unrecognized FORMs
Xfor nested FORM types that they do recognize. For example, a musical
Xscore may contain nested instrument descriptions and an animation
Xfile may contain still pictures.
X
XNote to programmers: Processing PROP chunks is not simple! You'll
Xneed some background in interpreters with stack frames. If this is
Xforeign to you, build programs that read/write only one FORM per file.
XFor the more intrepid programmers, the next paragraph summarizes how
Xto process LISTs and PROPs. See the general IFF reader module "IFFR.C"
Xand the example program "ShowILBM.C" for details.
X
XAllocate a stack frame for every LIST and FORM you encounter and initialize
Xit by copying the stack frame of the parent LIST or FORM. At the top
Xlevel, you'll need a stack frame initialized to your program's global
Xdefaults. While reading each LIST or FORM, store all encountered properties
Xinto the current stack frame. In the example ShowILBM, each stack
Xframe has a place for a bitmap header property ILBM.BMHD and a color
Xmap property ILBM.CMAP. When you finally get to the ILBM's BODY chunk,
Xuse the property settings accumulated in the current stack frame.
X
XAn alternate implementation would just remember PROPs encountered,
Xforgetting each on reaching the end of its scope (the end of the containing
XLIST). When a FORM XXXX is encountered, scan the chunks in all remembered
XPROPs XXXX, in order, as if they appeared before the chunks actually
Xin the FORM XXXX. This gets trickier if you read FORMs inside of FORMs.
X
XRules for Writer Programs
X
XHere are some notes on building programs that write IFF files, which
Xis much easier than reading them. If you use the standard IFF writer
Xmodule "IFFW.C" (see "Support Software" in Appendix A), many of these
Xrules and details will automatically be enforced. See the example
Xprogram "Raw2ILBM.C".
X
X% An IFF file is a single FORM, LIST, or CAT chunk.
X
X% Any IFF-85 file must start with the 4 characters "FORM", "LIST",
Xor "CAT ", followed by a LONG ckSize. There should be no data after
Xthe chunk end.
X
X% Chunk types LIST, FORM, PROP, and CAT are generic. They always
Xcontain a subtype ID followed by chunks. These three IDs are universally
Xreserved, as are "LIS1" through "LIS9", "FOR1" through "FOR9", "CAT1"
Xthrough "CAT9", and " ".
X
X% Don't forget to write a 0 pad byte after each odd-length chunk.
X
X% Four techniques for writing an IFF group: (1) build the data
Xin a file mapped into virtual memory, (2) build the data in memory
Xblocks and use block I/O, (3) stream write the data piecemeal and
X(don't forget!) random access back to set the group length count,
Xand (4) make a preliminary pass to compute the length count then stream
Xwrite the data.
X
X% Do not try to edit a file that you don't know how to create.
XPrograms may look into a file and copy out nested FORMs of types that
Xthey recognize, but don't edit and replace the nested FORMs and don't
Xadd or remove them. That could make the containing structure inconsistent.
XYou may write a new file containing items you copied (or copied and
Xmodified) from another IFF file, but don't copy structural parts you
Xdon't understand.
X
X% You must adhere to the syntax descriptions in Appendex A. E.g.
XPROPs may only appear inside LISTs.
X
X
X
X
XAppendix A. Reference
X
XType Definitions
X
XThe following C typedefs describe standard IFF structures. Declarations
Xto use in practice will vary with the CPU and compiler. For example,
X68000 Lattice C produces efficient comparison code if we define ID
Xas a "LONG". A macro "MakeID" builds these IDs at compile time.
X
X/* Standard IFF types, expressed in 68000 Lattice C. */
X
Xtypedef unsigned char UBYTE; /* 8 bits unsigned */
Xtypedef short WORD; /* 16 bits signed */
Xtypedef unsigned short UWORD; /* 16 bits unsigned */
Xtypedef long LONG; /* 32 bits signed */
X
Xtypedef char ID[4]; /* 4 chars in ' ' through '~' */
X
Xtypedef struct {
X ID ckID;
X LONG ckSize; /* sizeof(ckData) */
X UBYTE ckData[/* ckSize */];
X } Chunk;
X
X/* ID typedef and builder for 68000 Lattice C. */
Xtypedef LONG ID; /* 4 chars in ' ' through '~' */
X#define MakeID(a,b,c,d) ( (a)<<<<24 | (b)<<<<16 | (c)<<<<8 | (d) )
X
X/* Globally reserved IDs. */
X#define ID_FORM MakeID('F','O','R','M')
X#define ID_LIST MakeID('L','I','S','T')
X#define ID_PROP MakeID('P','R','O','P')
X#define ID_CAT MakeID('C','A','T',' ')
X#define ID_FILLER MakeID(' ',' ',' ',' ')
X
XSyntax Definitions
X
XHere's a collection of the syntax definitions in this document.
X
XChunk ::= ID #{ UBYTE* } [0]
X
XProperty ::= Chunk
X
XFORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)*
X}
XFormType ::= ID
XLocalChunk ::= Property | Chunk
X
XCAT ::= "CAT " #{ ContentsType (FORM | LIST | CAT)* }
XContentsType ::= ID -- a hint or an "abstract data type" ID
X
XLIST ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* }
XPROP ::= "PROP" #{ FormType Property* }
X
XIn this extended regular expression notation, the token "#" represents
Xa ckSize LONG count of the following {braced} data bytes. Literal
Xitems are shown in "quotes", [square bracketed items] are optional,
Xand "*" means 0 or more instances. A sometimes-needed pad byte is
Xshown as "[0]".
X
XDefined Chunk IDs
X
XThis is a table of currently defined chunk IDs. We may also borrow
Xsome Macintosh IDs and data formats.
X
XGroup chunk IDs
X FORM, LIST, PROP, CAT.
XFuture revision group chunk IDs
X FOR1 I FOR9, LIS1 I LIS9, CAT1 I CAT9.
XFORM type IDs
X (The above group chunk IDs may not be used for FORM type IDs.)
X (Lower case letters and punctuation marks are forbidden in FORM
Xtype IDs.)
X 8SVX 8-bit sampled sound voice, ANBM animated bitmap, FNTR raster
Xfont, FNTV vector font, FTXT formatted text, GSCR general-use musical
Xscore, ILBM interleaved raster bitmap image, PDEF Deluxe Print page
Xdefinition, PICS Macintosh picture, PLBM (obsolete), USCR Uhuru Sound
XSoftware musical score, UVOX Uhuru Sound Software Macintosh voice,
XSMUS simple musical score, VDEO Deluxe Video Construction Set video.
XData chunk IDs
X "JJJJ", TEXT, PICT.
XPROP LIST property IDs
X OPGM, OCPU, OCMP, OSN, UNAM.
X
X
X
XSupport Software
X
XThese public domain C source programs are available for use in building
XIFF-compatible programs:
X
XIFF.H, IFFR.C, IFFW.C
X
X IFF reader and writer package.
X These modules handle many of the details of reliably
X reading and writing IFF files.
X
XIFFCheck.C This handy utility program scans an IFF file, checks
X that the contents are well formed, and prints an outline
X of the chunks.
X
XPACKER.H, Packer.C, UnPacker.C
X
X Run encoder and decoder used for ILBM files.
X
XILBM.H, ILBMR.C, ILBMW.C
X
X Reader and writer support routines for raster image
X FORM ILBM. ILBMR calls IFFR and UnPacker. ILBMW calls
X IFFW and Packer.
X
XShowILBM.C
X Example caller of IFFR and ILBMR modules. This
X Commodore-Amiga program reads and displays a FORM ILBM.
XRaw2ILBM.C
X Example ILBM writer program. As a demonstration, it
X reads a raw raster image file and writes the image
X as a FORM ILBM file.
XILBM2Raw.C
X Example ILBM reader program. Reads a FORM ILBM file
X and writes it into a raw raster image.
X
XREMALLOC.H, Remalloc.c
X
X Memory allocation routines used in these examples.
X
XINTUALL.H generic "include almost everything" include-file
X with the sequence of includes correctly specified.
X
XREADPICT.H, ReadPict.c
X
X given an ILBM file, read it into a bitmap and
X a color map
X
XPUTPICT.H, PutPict.c
X
X given a bitmap and a color map, save it as
X an ILBM file.
X
XGIO.H, Gio.c generic I/O speedup package. Attempts to speed
X disk I/O by buffering writes and reads.
X
Xgiocall.c sample call to gio.
X
Xilbmdump.c reads in ILBM file, prints out ascii representation
X for including in C files.
X
Xbmprintc.c prints out a C-language representation of data for
X a bitmap.
X
X
X
XExample Diagrams
X
XHere's a box diagram for an example IFF file, a raster image FORM
XILBM. This FORM contains a bitmap header property chunk BMHD, a color
Xmap property chunk CMAP, and a raster data chunk BODY. This particular
Xraster is 320 x 200 pixels x 3 bit planes uncompressed. The "0" after
Xthe CMAP chunk represents a zero pad byte; included since the CMAP
Xchunk has an odd length. The text to the right of the diagram shows
Xthe outline that would be printed by the IFFCheck utility program
Xfor this particular file.
X
X +-----------------------------------+
X |'FORM' 24070 | FORM 24070 IBLM
X +-----------------------------------+
X |'ILBM' |
X +-----------------------------------+
X | +-------------------------------+ |
X | | 'BMHD' 20 | | .BMHD 20
X | | 320, 200, 0, 0, 3, 0, 0, ... | |
X | + ------------------------------+ |
X | | 'CMAP' 21 | | .CMAP 21
X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
X | +-------------------------------+ |
X | 0 |
X +-----------------------------------+
X |'BODY' 24000 | .BODY 24000
X |0, 0, 0, ... |
X +-----------------------------------+
X
XThis second diagram shows a LIST of two FORMs ILBM sharing a common
XBMHD property and a common CMAP property. Again, the text on the right
Xis an outline a la IFFCheck.
X
X
X +-----------------------------------------+
X |'LIST' 48114 | LIST 48114 AAAA
X +-----------------------------------------+
X |'AAAA' | .PROP 62 ILBM
X | +-----------------------------------+ |
X | |'PROP' 62 | |
X | +-----------------------------------+ |
X | |'ILBM' | |
X | +-----------------------------------+ |
X | | +-------------------------------+ | |
X | | | 'BMHD' 20 | | | ..BMHD 20
X | | | 320, 200, 0, 0, 3, 0, 0, ... | | |
X | | | ------------------------------+ | |
X | | | 'CMAP' 21 | | | ..CMAP 21
X | | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | | |
X | | +-------------------------------+ | |
X | | 0 | |
X | +-----------------------------------+ |
X | +-----------------------------------+ |
X | |'FORM' 24012 | | .FORM 24012 ILBM
X | +-----------------------------------+ |
X | |'ILBM' | |
X | +-----------------------------------+ |
X | | +-----------------------------+ | |
X | | |'BODY' 24000 | | | ..BODY 24000
X | | |0, 0, 0, ... | | |
X | | +-----------------------------+ | |
X | +-----------------------------------+ |
X | +-----------------------------------+ |
X | |'FORM' 24012 | | .FORM 24012 ILBM
X | +-----------------------------------+ |
X | |'ILBM' | |
X | +-----------------------------------+ |
X | | +-----------------------------+ | |
X | | |'BODY' 24000 | | | ..BODY 24000
X | | |0, 0, 0, ... | | |
X | | +-----------------------------+ | |
X | +-----------------------------------+ |
X +-----------------------------------------+
X
X
X
XAppendix B. Standards Committee
X
XThe following people contributed to the design of this IFF standard:
X
XBob "Kodiak" Burns, Commodore-Amiga
XR. J. Mical, Commodore-Amiga
XJerry Morrison, Electronic Arts
XGreg Riker, Electronic Arts
XSteve Shaw, Electronic Arts
XBarry Walsh, Commodore-Amiga
//END
echo x - ftxt
sed 's/^X//' > ftxt << '//END'
X"FTXT" IFF Formatted Text
X
XDate: November 15, 1985
XFrom: Steve Shaw and Jerry Morrison, Electronic Arts and
X Bob "Kodiak" Burns, Commodore-Amiga
XStatus: Draft 2.6
X
XDRAFT DRAFT DRAFT
XDRAFT DRAFT DRAFT
X
X1. Introduction
X
XThis memo is the IFF supplement for FORM FTXT. An FTXT is an IFF "data
Xsection" or "FORM type" which can be an IFF file or a part of one containing
Xa stream of text plus optional formatting information."EA IFF 85"
Xis Electronic Arts' standard for interchange format files. (See the
XIFF reference.)
X
XAn FTXT is an archival and interchange representation designed for
Xthree uses. The simplest use is for a "console device" or "glass teletype"
X(the minimal 2-D text layout means): a stream of "graphic" ("printable")
Xcharacters plus positioning characters "space" ("SP") and line terminator
X("LF"). This is not intended for cursor movements on a screen although
Xit does not conflict with standard cursor-moving characters. The second
Xuse is text that has explicit formatting information (or "looks")
Xsuch as font family and size, typeface, etc. The third use is as the
Xlowest layer of a structured document that also has "inherited" styles
Xto implicitly control character looks. For that use, FORMs FTXT would
Xbe embedded within a future document FORM type. The beauty of FTXT
Xis that these three uses are interchangeable, that is, a program written
Xfor one purpose can read and write the others' files. So a word processor
Xdoes not have to write a separate plain text file to communicate with
Xother programs.
X
XText is stored in one or more "CHRS" chunks inside an FTXT. Each CHRS
Xcontains a stream of 8-bit text compatible with ISO and ANSI data
Xinterchange standards. FTXT uses just the central character set from
Xthe ISO/ANSI standards. (These two standards are henceforth called
X"ISO/ANSI" as in "see the ISO/ANSI reference".)
X
XSince it's possible to extract just the text portions from future
Xdocument FORM types, programs can exchange data without having to
Xsave both plain text and formatted text representations.
X
XCharacter looks are stored as embedded control sequences within CHRS
Xchunks. This document specifies which class of control sequences to
Xuse: the CSI group. This document does not yet specify their meanings,
Xe.g. which one means "turn on italic face". Consult ISO/ANSI.
X
XSection 2 defines the chunk types character stream "CHRS" and font
Xspecifier "FONS". These are the "standard" chunks. Specialized chunks
Xfor private or future needs can be added later. Section 3 outlines
Xan FTXT reader program that strips a document down to plain unformatted
Xtext. Appendix A is a code table for the 8-bit ISO/ANSI character
Xset used here. Appendix B is an example FTXT shown as a box diagram.
XAppendix C is a racetrack diagram of the syntax of ISO/ANSI control
Xsequences.
X
X
XReference:
X
XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
X
XElectronic Arts[tm] is a trademark of Electronic Arts.
X
XIFF: "EA IFF 85" Standard for Interchange Format Files describes the
Xunderlying conventions for all IFF files.
X
XISO/ANSI: ISO/DIS 6429.2 and ANSI X3.64-1979. International Organization
Xfor Standardization (ISO) and American National Standards Institute
X(ANSI) data-interchange standards. The relevant parts of these two
Xstandards documents are identical. ISO standard 2022 is also relevant.
X
X
X2. Standard Data and Property Chunks
X
XThe main contents of a FORM FTXT is in its character stream "CHRS"
Xchunks. Formatting property chunks may also appear. The only formatting
Xproperty yet defined is "FONS", a font specifier. A FORM FTXT with
Xno CHRS represents an empty text stream. A FORM FTXT may contain nested
XIFF FORMs, LISTs, or CATs, although a "stripping" reader (see section
X3) will ignore them.
X
XCharacter Set
X
XFORM FTXT uses the core of the 8-bit character set defined by the
XISO/ANSI standards cited at the start of this document. (See Appendix
XA for a character code table.) This character set is divided into
Xtwo "graphic" groups plus two "control" groups. Eight of the control
Xcharacters begin ISO/ANSI standard control sequences. (See "Control
XSequences", below.) Most control sequences and control characters
Xare reserved for future use and for compatibility with ISO/ANSI. Current
Xreader programs should skip them.
X
X% C0 is the group of control characters in the range NUL (hex
X0) through hex 1F. Of these, only LF (hex 0A) and ESC (hex 1B) are
Xsignificant. ESC begins a control sequence. LF is the line terminator,
Xmeaning "go to the first horizontal position of the next line". All
Xother C0 characters are not used. In particular, CR (hex 0D) is not
Xrecognized as a line terminator.
X
X% G0 is the group of graphic characters in the range hex 20 through
Xhex 7F. SP (hex 20) is the space character. DEL (hex 7F) is the delete
Xcharacter which is not used. The rest are the standard ASCII printable
Xcharacters "!" (hex 21) through "~" (hex 7E).
X
X% C1 is the group of extended control characters in the range
Xhex 80 through hex 9F. Some of these begin control sequences. The
Xcontrol sequence starting with CSI (hex 9B) is used for FTXT formatting.
XAll other control sequences and C1 control characters are unused.
X
X% G1 is the group of extended graphic characters in the range
XNBSP (hex A0) through "X" (hex FF). It is one of the alternate graphic
Xgroups proposed for ISO/ANSI standardization.
X
XControl Sequences
X
XEight of the control characters begin ISO/ANSI standard "control sequences"
X(or "escape sequences"). These sequences are described below and diagrammed
Xin Appendix C.
X
XG0 ::= (SP through DEL)
XG1 ::= (NBSP through "X")
X
XESC-Seq ::= ESC (SP through "/")* ("0" through "~")
XShiftToG2 ::= SS2 G0
XShiftToG3 ::= SS3 G0
XCSI-Seq ::= CSI (SP through "?")* ("@" through "~")
XDCS-Seq ::= (DCS | OSC | PM | APC) (SP through "~" | G1)* ST
X
X"ESC-Seq" is the control sequence ESC (hex 1B), followed by zero or
Xmore characters in the range SP through "/S (hex 20 through hex 2F),
Xfollowed by a character in the range "0" through "~" (hex 30 through
Xhex 7E). These sequences are reserved for future use and should be
Xskipped by current FTXT reader programs.
X
XSS2 (hex 8E) and SS3 (hex 8F) shift the single following G0 character
Xinto yet-to-be-defined graphic sets G2 and G3, respectively. These
Xsequences should not be used until the character sets G2 and G3 are
Xstandardized. A reader may simply skip the SS2 or SS3 (taking the
Xfollowing character as a corresponding G0 character) or replace the
Xtwo-character sequence with a character like "?" to mean "absent".
X
XFTXT uses "CSI-Seq" control sequences to store character formatting
X(font selection by number, type face, and text size) and perhaps layout
Xinformation (position and rotation). "CSI-Seq" control sequences start
Xwith CSI (the "control sequence introducer", hex 9B). Syntactically,
Xthe sequence includes zero or more characters in the range SP through
X"?" (hex 20 through hex 3F) and a concluding character in the range
X"@" through "~" (hex 40 through hex 7E). These sequences may be skipped
Xby a minimal FTXT reader, i.e. one that ignores formatting information.
X
XNote: A future FTXT standardization document will explain the uses
Xof CSI-Seq sequences for setting character face (light weight vs.
Xmedium vs. bold, italic vs. upright, height, pitch, position, and
Xrotation). For now, consult the ISO/ANSI references.
X
X"DCS-Seq" is the control sequences starting with DCS (hex 90), OSC
X(hex 9D), PM (hex 9E), or APC (hex 9F), followed by zero or more characters
Xeach of which is in the range SP through "~" (hex 20 through hex 7E)
Xor else a G1 character, and terminated by an ST (hex 9C). These sequences
Xare reserved for future use and should be skipped by current FTXT
Xreader programs.
X
XData Chunk CHRS
X
XA CHRS chunk contains a sequence of 8-bit characters abiding by the
XISO/ANSI standards cited at the start of this document. This includes
Xthe character set and control sequences as described above and summarized
Xin Appendicies A and C.
X
XA FORM FTXT may contain any number of CHRS chunks. Taken together,
Xthey represent a single stream of textual information. That is, the
Xcontents of CHRS chunks are effectively concatenated except that (1)
Xeach control sequence must be completely within a single CHRS chunk,
Xand (2) any formatting property chunks appearing between two CHRS
Xchunks affects the formatting of the latter chunk's text. Any formatting
Xsettings set by control sequences inside a CHRS carry over to the
Xnext CHRS in the same FORM FTXT. All formatting properties stop at
Xthe end of the FORM since IFF specifies that adjacent FORMs are independent
Xof each other (although not independent of any properties inherited
Xfrom an enclosing LIST or FORM).
X
XProperty Chunk FONS
X
XThe optional property "FONS" holds a FontSpecifier as defined in the
XC declaration below. It assignes a font to a numbered "font register"
Xso it can be referenced by number within subsequent CHRS chunks. (This
Xfunction is not provided within the ISO and ANSI standards.) The font
Xspecifier gives both a name and a description for the font so the
Xrecipient program can do font substitution.
X
XBy default, CHRS text uses font 1 until it selects another font. A
Xminimal text reader always uses font 1. If font 1 hasn't been specified,
Xthe reader may use the local system font as font 1.
X
X typedef struct {
X UBYTE id;
X /* 0 through 9 is a font id number referenced by an
X * SGR control sequence selective parameter of 10
X * through 19. Other values are reserved for future
X * standardization.
X */
X UBYTE pad1; /* reserved for future use; store 0 here */
X UBYTE proportional;
X /* proportional font? 0 = unknown, 1 = no, 2 = yes */
X UBYTE serif;
X /* serif font? 0 = unknown, 1 = no, 2 = yes */
X char name[];
X /* A NULL-terminated string naming preferred font. */
X } FontSpecifier;
X
XFields are filed in the order shown. The UBYTE fields are byte-packed
X(2 per 16-bit word). The field pad1 is reserved for future standardization.
XPrograms should store 0 there for now.
X
XThe field proportional indicates if the desired font is proportional
Xwidth as opposed to fixed width. The field serif indicates if the
Xdesired font is serif as opposed to sans serif. [Issue: Discuss font
Xsubstitution!]
X
XFuture Properties
X
XNew optional property chunks may be defined in the future to store
Xadditional formatting information. They will be used to represent
Xformatting not encoded in standard ISO/ANSI control sequences and
Xfor "inherited" formatting in structured documents. Text orientation
Xmight be one example.
X
XPositioning Units
X
XUnless otherwise specified, position and size units used in FTXT formatting
Xproperties and control sequences are in decipoints (720 decipoints/inch).
XThis is ANSI/ISO Positioning Unit Mode (PUM) 2. While a metric standard
Xmight be nice, decipoints allow the existing U.S.A. typographic units
Xto be encoded easily, e.g. "12 points" is "120 decipoints".
X
X
X3. FTXT Stripper
X
XAn FTXT reader program can read the text and ignore all formatting
Xand structural information in a document FORM that uses FORMs FTXT
Xfor the leaf nodes. This amounts to stripping a document down to a
Xstream of plain text. It would do this by skipping over all chunks
Xexcept FTXT.CHRS (CHRS chunks found inside a FORM FTXT) and within
Xthe FTXT.CHRS chunks skipping all control characters and control sequences.
X(Appendix C diagrams this text scanner.) It may also read FTXT.FONS
Xchunks to find a description for font 1.
X
XHere's a Pascal-ish program for an FTXT stripper. Given a FORM (a
Xdocument of some kind), it scans for all FTXT.CHRS chunks. This would
Xlikely be applied to the first FORM in an IFF file.
X
XPROCEDURE ReadFORM4CHRS(); {Read an IFF FORM for FTXT.CHRS chunks.}
XBEGIN
XIF the FORM's subtype = "FTXT"
X THEN ReadFTXT4CHRS()
X ELSE WHILE something left to read in the FORM DO BEGIN
X read the next chunk header;
X CASE the chunk's ID OF
X "LIST", "CAT ": ReadCAT4CHRS();
X "FORM": ReadFORM4CHRS();
X OTHERWISE skip the chunk's body;
X END
X END
XEND;
X
X{Read a LIST or CAT for all FTXT.CHRS chunks.}
XPROCEDURE ReadCAT4CHRS();
X BEGIN
XWHILE something left to read in the LIST or CAT DO BEGIN
X read the next chunk header;
X CASE the chunk's ID OF
X "LIST", "CAT ": ReadCAT4CHRS();
X "FORM": ReadFORM4CHRS();
X "PROP": IF we're reading a LIST AND the PROP's subtype =
X"FTXT"
X THEN read the PROP for "FONS" chunks;
X OTHERWISE error--malformed IFF file;
X END
X END
XEND;
X
XPROCEDURE ReadFTXT4CHRS(); {Read a FORM FTXT for CHRS chunks.}
XBEGIN
XWHILE something left to read in the FORM FTXT DO BEGIN
X read the next chunk header;
X CASE the chunk's ID OF
X "CHRS": ReadCHRS();
X "FONS": BEGIN
X read the chunk's contents into a FontSpecifier variable;
X IF the font specifier's id = 1 THEN use this font;
X END;
X OTHERWISE skip the chunk's body;
X END
X END
XEND;
X
X{Read an FTXT.CHRS. Skip all control sequences and unused control
Xchars.}
XPROCEDURE ReadCHRS();
XBEGIN
XWHILE something left to read in the CHRS chunk DO
X CASE read the next character OF
X LF: start a new output line;
X ESC: SkipControl([' '..'/'], ['0'..'~']);
X IN [' '..'~'], IN [NBSP..'X']: output the character;
X SS2, SS3: ; {Just handle the following G0 character
X directly, ignoring the shift to G2 or G3.}
X CSI: SkipControl([' '..'?'], ['@'..'~']);
X DCS, OSC, PM, APC: SkipControl([' '..'~'] + [NBSP..'X'], [ST]);
X END
XEND;
X
X{Skip a control sequence of the format (rSet)* (tSet), i.e. any number
Xof characters in the set rSet followed by a character in the set tSet.}
XPROCEDURE SkipControl(rSet, tSet);
XVAR c: CHAR;
XBEGIN
XREPEAT c := read the next character
X UNTIL c NOT IN rSet;
XIF c NOT IN tSet
X THEN put character c back into the input stream;
XEND
X
XThe following program is an optimized version of the above routines
XReadFORM4CHRS and ReadCAT4CHRS for the case where you're ignoring
Xfonts as well as formatting. It takes advantage of certain facts of
Xthe IFF format to read a document FORM and its nested FORMs, LISTs,
Xand CATs without a stack. In other words, it's a hack that ignores
Xall fonts and faces to cheaply get to the plain text of the document.
X
X{Cheap scan of an IFF FORM for FTXT.CHRS chunks.}
XPROCEDURE ScanFORM4CHRS();
XBEGIN
XIF the document FORM's subtype = "FTXT"
X THEN ReadFTXT4CHRS()
X ELSE WHILE something left to read in the FORM DO BEGIN
X read the next chunk header;
X IF it's a group chunk (LIST, FORM, PROP, or CAT)
X THEN read its subtype ID;
X CASE the chunk's ID OF
X "LIST", "CAT ":; {NOTE: See explanation below.*}
X "FORM": IF this FORM's subtype = "FTXT" THEN
X ReadFTXT4CHRS()
X ELSE; {NOTE: See explanation below.*}
X OTHERWISE skip the chunk's body;
X END
X END
XEND;
X
X*Note: This implementation is subtle. After reading a group header
Xother than FORM FTXT it just continues reading. This amounts to reading
Xall the chunks inside that group as if they weren't nested in a group.
X
X
XAppendix A: Character Code Table
X
XThis table corresponds to the ISO/DIS 6429.2 and ANSI X3.64-1979 8-bit
Xcharacter set standards. Only the core character set of those standards
Xis used in FTXT.
X
XTwo G1 characters aren't defined in the standards and are shown as
Xdark gray entries in this table. Light gray shading denotes control
Xcharacters. (DEL is a control character although it belongs to the
Xgraphic group G0.) The following five rare G1 characters are left
Xblank in the table below due to limitations of available fonts: hex
XA8, D0, DE, F0, and FE.
X
X
X
X ISO/DIS 6429.2 and ANSI X3.64-1979 Character Code Table
X
X
X (figure named "TextTable", viewable by ShowILBM or SeeILBM)
X
X
X[_____] [_______________________] [_____] [____________________________]
XControl Grapic Group Control Graphic Group
X Group G0 Group G1
X C0 C1
X
X"NBSP" is a "non-breaking space"
X"SHY" is a "soft-hyphen"
X
X
X
XAppendix B. FTXT Example
X
XHere's a box diagram for a simple example: "The quick brown fox jumped.Four
Xscore and seven", written in a proportional serif font named "Roman".
X
X
X +-----------------------------------+
X |'FORM' 24070 | FORM 24070 ILBM
X +-----------------------------------+
X |'ILBM' |
X +-----------------------------------+
X | +-------------------------------+ |
X | | 'BMHD' 20 | | .BMHD 20
X | | 320, 200, 0, 0, 3, 0, 0, ... | |
X | | ------------------------------+ |
X | | 'CMAP' 21 | | .CMAP 21
X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
X | +-------------------------------+ |
X | +-------------------------------+ |
X | |'BODY' 24000 | | .BODY 24000
X | |0, 0, 0, ... | |
X | +-------------------------------+ |
X +-----------------------------------+
X
XThe "0" after the CMAP chunk is a pad byte.
X
X
X
X
XAppendix B. Standards Committee
X
XThe following people contributed to the design of this IFF standard:
X
XBob "Kodiak" Burns, Commodore-Amiga
XR. J. Mical, Commodore-Amiga
XJerry Morrison, Electronic Arts
XGreg Riker, Electronic Arts
XSteve Shaw, Electronic Arts
XBarry Walsh, Commodore-Amiga
X
X
X
XAppendix C. ISO/ANSI Control Sequences
X
XThis is a racetrack diagram of the ISO/ANSI characters and control
Xsequences as used in FTXT CHRS chunks.
X
X line terminator
X-----+-------------------> LF --------------------------------------->
X | ESC-Seq
X +-------------------> ESC ---+>----------------+--> 0 thru ~ --->
X | | |
X | +-- SP thru / <---+
X | printable
X +---------------+---> SP thru ~ --+->--------------------------->
X | | |
X | +---> G1 -------->+
X | shift to G2
X +-------------------> SS2 ----> G0 ---> (produces a G2 character)
X | shift to G3
X +-------------------> SS3 ----> G0 ---> (produces a G3 character)
X | CSI-Seq
X +-------------------> CSI ---+>----------------+--> @ thru ~ --->
X | | |
X | +-- SP thru ? <---+
X | DCS-Seq
X +----------> DCS,OSC,PM,or APC --+>-------------+--+-> ST -+---->
X | | | | |
X | +- SP thru ~ <-+ +-> G1 -+
X | discard
X +----------> any other character ------------------------------->
X
X
X
XOf the various control sequences, only CSI-Seq is used for FTXT character
Xformatting information. The others are reserved for future use and
Xfor compatibility with ISO/ANSI standards. Certain character sequences
Xare syntactically malformed, e.g. CSI followed by a C0, C1, or G1
Xcharacter. Writer programs should not generate reserved or malformed
Xsequences and reader programs should skip them.
X
XConsult the ISO/ANSI standards for the meaning of the CSI-Seq control
Xsequences.
X
XThe two character set shifts SS2 and SS3 may be used when the graphic
Xcharacter groups G2 and G3 become standardized.
X
//END
echo x - ilbm
sed 's/^X//' > ilbm << '//END'
X"ILBM" IFF Interleaved Bitmap
X
XDate: January 17, 1986
XFrom: Jerry Morrison, Electronic Arts
XStatus: Released and in use
X
X1. Introduction
X
X"EA IFF 85" is Electronic Arts' standard for interchange format files.
X"ILBM" is a format for a 2 dimensional raster graphics image, specifically
Xan InterLeaved bitplane BitMap image with color map. An ILBM is an
XIFF "data section" or "FORM type", which can be an IFF file or a part
Xof one. (See the IFF reference.)
X
XAn ILBM is an archival representation designed for three uses. First,
Xa standalone image that specifies exactly how to display itself (resolution,
Xsize, color map, etc.). Second, an image intended to be merged into
Xa bigger picture which has its own depth, color map, and so on. And
Xthird, an empty image with a color map selection or "palette" for
Xa paint program. ILBM is also intended as a building block for composite
XIFF FORMs like "animation sequence" and "structured graphics". Some
Xuses of ILBM will be to preserve as much information as possible across
Xdisparate environments. Other uses will be to store data for a single
Xprogram or highly cooperative programs while maintaining subtle details.
XSo we're trying to accomplish a lot with this one format.
X
XThis memo is the IFF supplement for FORM ILBM. Section 2 defines the
Xpurpose and format of property chunks bitmap header "BMHD", color
Xmap "CMAP", hotspot "GRAB", destination merge data "DEST", sprite
Xinformation "SPRT", and Commodore Amiga viewport mode "CAMG". Section
X3 defines the standard data chunk "BODY". These are the "standard"
Xchunks. Section 4 defines the nonstandard color range data chunk "CRNG".
XAdditional specialized chunks like texture pattern can be added later.
XThe ILBM syntax is summarized in Appendix A as a regular expression
Xand in Appendix B as a box diagram. Appendix C explains the optional
Xrun encoding scheme. Appendix D names the committee responsible for
Xthis FORM ILBM standard.
X
XDetails of the raster layout are given in part 3, "Standard Data Chunk".
XSome elements are based on the Commodore Amiga hardware but generalized
Xfor use on other computers. An alternative to ILBM would be appropriate
Xfor computers with true color data in each pixel.
X
XReference:
X
X"EA IFF 85" Standard for Interchange Format Files describes the underlying
Xconventions for all IFF files.
X
XAmiga[tm] is a trademark of Commodore-Amiga, Inc.
XElectronic Arts[tm] is a trademark of Electronic Arts.
XMacintosh[tm] is a trademark licensed to Apple Computer, Inc.
XMacPaint[tm] is a trademark of Apple Computer, Inc.
X
X
X2. Standard Properties
X
XThe required property "BMHD" and any optional properties must appear
Xbefore any "BODY" chunk. (Since an ILBM has only one BODY chunk, any
Xfollowing properties are superfluous.) Any of these properties may
Xbe shared over a LIST of FORMs IBLM by putting them in a PROP ILBM.
X(See the "EA IFF 85" memo.)
X
XBMHD
X
XThe required property "BMHD" holds a BitMapHeader as defined in these
XC declarations and following documentation. It describes the dimensions
Xand encoding of the image, including data necessary to understand
Xthe BODY chunk to follow.
X
Xtypedef UBYTE Masking; /* Choice of masking technique. */
X
X#define mskNone 0
X#define mskHasMask 1
X#define mskHasTransparentColor 2
X#define mskLasso 3
X
Xtypedef UBYTE Compression;
X /* Choice of compression algorithm applied to the rows of all
X * source and mask planes. "cmpByteRun1" is the byte run encoding
X * described in Appendix C. Do not compress across rows! */
X#define cmpNone 0
X#define cmpByteRun1 1
X
Xtypedef struct {
X UWORD w, h; /* raster width & height in pixels */
X WORD x, y; /* pixel position for this image */
X UBYTE nPlanes; /* # source bitplanes */
X Masking masking;
X Compression compression;
X UBYTE pad1; /* unused; for consistency, put 0 here */
X UWORD transparentColor; /* transparent "color number" (sort of) */
X UBYTE xAspect, yAspect; /* pixel aspect, a ratio width : height */
X WORD pageWidth, pageHeight; /* source "page" size in pixels */
X } BitMapHeader;
X
XFields are filed in the order shown. The UBYTE fields are byte-packed.
X
XThe fields w and h indicate the size of the image rectangle in pixels.
XEach row of the image is stored in an integral number of 16 bit words.
XThe number of words per row is Ceiling(w/16). The fields x and y indicate
Xthe desired position of this image within the destination picture.
XSome reader programs may ignore x and y. A safe default for writing
Xan ILBM is (x, y) = (0, 0).
X
XThe number of source bitplanes in the BODY chunk (see below) is stored
Xin nPlanes. An ILBM with a CMAP but no BODY and nPlanes = 0 is the
Xrecommended way to store a color map.
X
XNote: Color numbers are color map index values formed by pixels in
Xthe destination bitmap, which may be deeper than nPlanes if a DEST
Xchunk calls for merging the image into a deeper image.
X
XThe field masking indicates what kind of masking is to be used for
Xthis image. The value mskNone designates an opaque rectangular image.
XThe value mskHasMask means that a mask plane is interleaved with the
Xbitplanes in the BODY chunk (see below). The value mskHasTransparentColor
Xindicates that pixels in the source planes matching transparentColor
Xare to be considered "transparent". (Actually, transparentColor isn't
Xa "color number" since it's matched with numbers formed by the source
Xbitmap rather than the possibly deeper destination bitmap. Note that
Xhaving a transparent color implies ignoring one of the color registers.
XSee CMAP, below.) The value mskLasso indicates the reader may construct
Xa mask by lassoing the image as in MacPaint*. To do this, put a 1
Xpixel border of transparentColor around the image rectangle. Then
Xdo a seed fill from this border. Filled pixels are to be transparent.
X
XIssue: Include in an appendix an algorithm for converting a transparent
Xcolor to a mask plane, and maybe a lasso algorithm.
X
XA code indicating the kind of data compression used is stored in compression.
XBeware that using data compression makes your data unreadable by programs
Xthat don't implement the matching decompression algorithm. So we'll
Xemploy as few compression encodings as possible. The run encoding
XbyteRun1 is documented in Appendix C, below.
X
XThe field pad1 is a pad byte and must be set to 0 for consistency.
XThis field could get used in the future.
X
XThe transparentColor specifies which bit pattern means "transparent".
XThis only applies if masking is mskHasTransparentColor or mskLasso
X(see above). Otherwise, transparentColor should be 0.
X
XThe pixel aspect ratio is stored as a ratio in the two fields xAspect
Xand yAspect. This may be used by programs to compensate for different
Xaspects or to help interpret the fields w, h, x, y, pageWidth, and
XpageHeight, which are in units of pixels. The fraction xAspect/yAspect
Xrepresents a pixel's width/height. It's recommended that your programs
Xstore proper fractions in BitMapHeaders, but aspect ratios can always
Xbe correctly compared with the the test
X
XxAspect%yDesiredAspect = yAspect%xDesiredAspect
X
XTypical values for aspect ratio are width : height = 10 : 11 (Amiga
X320 x 200 display) and 1 : 1 (Macintosh*).
X
XThe size in pixels of the source "page" (any raster device) is stored
Xin pageWidth and pageHeight, e.g. (320, 200) for a low resolution
XAmiga display. This information might be used to scale an image or
Xto automatically set the display format to suit the image. (The image
Xcan be larger than the page.)
X
XCMAP
X
XThe optional (but encouraged) property "CMAP" stores color map data
Xas triplets of red, green, and blue intensity values. The n color
Xmap entries ("color registers") are stored in the order 0 through
Xn-1, totaling 3n bytes. Thus n is the ckSize/3. Normally, n would
Xequal 2nPlanes.
X
XA CMAP chunk contains a ColorMap array as defined below. (These typedefs
Xassume a C compiler that implements packed arrays of 3-byte elements.)
X
Xtypedef struct {
X UBYTE red, green, blue; /* color intensities 0..255 */
X } ColorRegister; /* size = 3 bytes */
X
Xtypedef ColorRegister ColorMap[n]; /* size = 3n bytes */
X
XThe color components red, green, and blue represent fractional intensity
Xvalues in the range 0 through 255 256ths. White is (255, 255, 255)
Xand black is (0, 0, 0). If your machine has less color resolution,
Xuse the high order bits. Shift each field right on reading (or left
Xon writing) and assign it to (from) a field in a local packed format
Xlike Color4, below. This achieves automatic conversion of images across
Xenvironments with different color resolutions. On reading an ILBM,
Xuse defaults if the color map is absent or has fewer color registers
Xthan you need. Ignore any extra color registers.
X
XThe example type Color4 represents the format of a color register
Xin working memory of an Amiga computer, which has 4 bit video DACs.
X(The ":4" tells the C compiler to pack the field into 4 bits.)
X
Xtypedef struct {
X unsigned pad1 :4, red :4, green :4, blue :4;
X } Color4; /* Amiga RAM format. Not filed. */
X
XRemember that every chunk must be padded to an even length, so a color
Xmap with an odd number of entries would be followed by a 0 byte, not
Xincluded in the ckSize.
X
XGRAB
X
XThe optional property "GRAB" locates a "handle" or "hotspot" of the
Ximage relative to its upper left corner, e.g. when used as a mouse
Xcursor or a "paint brush". A GRAB chunk contains a Point2D.
X
Xtypedef struct {
X WORD x, y; /* relative coordinates (pixels) */
X } Point2D;
X
XDEST
X
XThe optional property "DEST" is a way to say how to scatter zero or
Xmore source bitplanes into a deeper destination image. Some readers
Xmay ignore DEST.
X
XThe contents of a DEST chunk is DestMerge structure:
X
Xtypedef struct {
X UBYTE depth; /* # bitplanes in the original source */
X UBYTE pad1; /* unused; for consistency put 0 here */
X UWORD planePick; /* how to scatter source bitplanes into destination */
X UWORD planeOnOff; /* default bitplane data for planePick */
X UWORD planeMask; /* selects which bitplanes to store into */
X } DestMerge;
X
XThe low order depth number of bits in planePick, planeOnOff, and planeMask
Xcorrespond one-to-one with destination bitplanes. Bit 0 with bitplane
X0, etc. (Any higher order bits should be ignored.) "1" bits in planePick
Xmean "put the next source bitplane into this bitplane", so the number
Xof "1" bits should equal nPlanes. "0" bits mean "put the corresponding
Xbit from planeOnOff into this bitplane". Bits in planeMask gate writing
Xto the destination bitplane: "1" bits mean "write to this bitplane"
Xwhile "0" bits mean "leave this bitplane alone". The normal case (with
Xno DEST property) is equivalent to planePick = planeMask = 2nPlanesJ-
X1.
X
XRemember that color numbers are formed by pixels in the destination
Xbitmap (depth planes deep) not in the source bitmap (nPlanes planes
Xdeep).
X
XSPRT
X
XThe presence of an "SPRT" chunk indicates that this image is intended
Xas a sprite. It's up to the reader program to actually make it a sprite,
Xif even possible, and to use or overrule the sprite precedence data
Xinside the SPRT chunk:
X
Xtypedef UWORD SpritePrecedence; /* relative precedence, 0 is the highest */
X
XPrecedence 0 is the highest, denoting a sprite that is foremost.
X
XCreating a sprite may imply other setup. E.g. a 2 plane Amiga sprite
Xwould have transparentColor = 0. Color registers 1, 2, and 3 in the
XCMAP would be stored into the correct hardware color registers for
Xthe hardware sprite number used, while CMAP color register 0 would
Xbe ignored.
X
XCAMG
X
XA "CAMG" chunk is specifically for the Commodore Amiga computer. It
Xstores a LONG "viewport mode". This lets you specify Amiga display
Xmodes like "dual playfield" and "hold and modify".
X3. Standard Data Chunk
X
XRaster Layout
X
XRaster scan proceeds left-to-right (increasing X) across scan lines,
Xthen top-to-bottom (increasing Y) down columns of scan lines. The
Xcoordinate system is in units of pixels, where (0,0) is the upper
Xleft corner.
X
XThe raster is typically organized as bitplanes in memory. The corresponding
Xbits from each plane, taken together, make up an index into the color
Xmap which gives a color value for that pixel. The first bitplane,
Xplane 0, is the low order bit of these color indexes.
X
XA scan line is made of one "row" from each bitplane. A row is one
XplanesU bits for one scan line, but padded out to a word (2 byte)
Xboundary (not necessarily the first word boundary). Within each row,
Xsuccessive bytes are displayed in order and the most significant bit
Xof each byte is displayed first.
X
XA "mask" is an optional "plane" of data the same size (w, h) as a
Xbitplane. It tells how to "cut out" part of the image when painting
Xit onto another image."One" bits in the mask mean "copy the corresponding
Xpixel to the destination" while "zero" mask bits mean "leave this
Xdestination pixel alone". In other words, "zero" bits designate transparent
Xpixels.
X
XThe rows of the different bitplanes and mask are interleaved in the
Xfile (see below). This localizes all the information pertinent to
Xeach scan line. It makes it much easier to transform the data while
Xreading it to adjust the image size or depth. It also makes it possible
Xto scroll a big image by swapping rows directly from the file without
Xrandom-accessing to all the bitplanes.
X
XBODY
X
XThe source raster is stored in a "BODY" chunk. This one chunk holds
Xall bitplanes and the optional mask, interleaved by row.
X
XThe BitMapHeader, in a BMHD property chunk, specifies the raster's
Xdimensions w, h, and nPlanes. It also holds the masking field which
Xindicates if there is a mask plane and the compression field which
Xindicates the compression algorithm used. This information is needed
Xto interpret the BODY chunk, so the BMHD chunk must appear first.
XWhile reading an ILBM's BODY, a program may convert the image to another
Xsize by filling (with transparentColor) or clipping.
X
XThe BODY's content is a concatenation of scan lines. Each scan line
Xis a concatenation of one row of data from each plane in order 0 through
XnPlanes-1 followed by one row from the mask (if masking = hasMask
X). If the BitMapHeader field compression is cmpNone, all h rows are
Xexactly Ceiling(w/16) words wide. Otherwise, every row is compressed
Xaccording to the specified algorithm and their stored widths depend
Xon the data compression.
X
XReader programs that require fewer bitplanes than appear in a particular
XILBM file can combine planes or drop the high-order (later) planes.
XSimilarly, they may add bitplanes and/or discard the mask plane.
X
XDo not compress across rows and don't forget to compress the mask
Xjust like the bitplanes. Remember to pad any BODY chunk that contains
Xan odd number of bytes.
X4. Nonstandard Data Chunk
X
XThe following data chunk was defined after various programs began
Xusing FORM ILBM so it's a "nonstandard" chunk. That means there's
Xsome slight chance of name collisions.
X
XCRNG
X
XA "CRNG" chunk contains "color register range" information. It's used
Xby Electronic Arts' Deluxe Paint program to identify a contiguous
Xrange of color registers for a "shade range" and color cycling. There
Xcan be zero or more CRNG chunks in an ILBM, but all should appear
Xbefore the BODY chunk. Deluxe Paint normally writes 4 CRNG chunks
Xin an ILBM when the user asks it to "Save Picture".
X
Xtypedef struct {
X WORD pad1; /* reserved for future use; store 0 here */
X WORD rate; /* color cycle rate */
X WORD active; /* nonzero means cycle the colors */
X UBYTE low, high; /* lower and upper color registers selected */
X } CRange;
X
XThe fields low and high indicate the range of color registers (color
Xnumbers) selected by this CRange.
X
XThe field active indicates whether color cycling is on or off. Zero
Xmeans off.
X
XThe field rate determines the speed at which the colors will step
Xwhen color cycling is on. The units are such that a rate of 60 steps
Xper second is represented as 214 = 16384. Slower rates can be obtained
Xby linear scaling: for 30 steps/second, rate = 8192; for 1 step/second,
Xrate = 16384/60 E 273.
X
XCCRT
X
XCommodore's Graphicraft program uses a similar chunk "CCRT" (for Color
XCyling Range and Timing). This chunk contains a CycleInfo structure.
X
Xtypedef struct {
X WORD direction; /* 0 = don't cycle. 1 = cycle forwards (1, 2, 3).
X * -1 = cycle backwards (3, 2, 1) */
X UBYTE start, end; /* lower and upper color registers selected */
X LONG seconds; /* # seconds between changing colors */
X LONG microseconds; /* # microseconds between changing colors */
X WORD pad; /* reserved for future use; store 0 here */
X } CycleInfo;
X
XThis is pretty similar to a CRNG chunk. A program would probably only
Xuse one of these two methods of expressing color cycle data. You could
Xwrite out both if you want to communicate this information to both
XDeluxe Paint and Graphicraft.
X
XA CCRT chunk expresses the color cycling rate as a number of seconds
Xplus a number of microseconds.
X
X
X
XAppendix A. ILBM Regular Expression
X
XHere's a regular expression summary of the FORM ILBM syntax. This
Xcould be an IFF file or a part of one.
X
XILBM ::= "FORM" #{ "ILBM" BMHD [CMAP] [GRAB] [DEST] [SPRT] [CAMG]
X CRNG* CCRT* [BODY] }
X
XBMHD ::= "BMHD" #{ BitMapHeader }
XCMAP ::= "CMAP" #{ (red green blue)* } [0]
XGRAB ::= "GRAB" #{ Point2D }
XDEST ::= "DEST" #{ DestMerge }
XSPRT ::= "SPRT" #{ SpritePrecendence }
XCAMG ::= "CAMG" #{ LONG }
X
XCRNG ::= "CRNG" #{ CRange }
XCCRT ::= "CCRT" #{ CycleInfo }
XBODY ::= "BODY" #{ UBYTE* } [0]
X
XThe token "#" represents a ckSize LONG count of the following {braced}
Xdata bytes. E.g. a BMHD's "#" should equal sizeof(BitMapHeader). Literal
Xstrings are shown in "quotes", [square bracket items] are optional,
Xand "*" means 0 or more repetitions. A sometimes-needed pad byte is
Xshown as "[0]".
X
XThe property chunks (BMHD, CMAP, GRAB, DEST, SPRT, and CAMG) and any
XCRNG and CCRT data chunks may actually be in any order but all must
Xappear before the BODY chunk since ILBM readers usually stop as soon
Xas they read the BODY. If any of the 6 property chunks are missing,
Xdefault values are "inherited" from any shared properties (if the
XILBM appears inside an IFF LIST with PROPs) or from the reader program's
Xdefaults. If any property appears more than once, the last occurrence
Xbefore the BODY is the one that counts since that's the one that modifies
Xthe BODY.
X
X
X
XAppendix B. ILBM Box Diagram
X
XHere's a box diagram for a simple example: an uncompressed image 320
Xx 200 pixels x 3 bitplanes. The text to the right of the diagram shows
Xthe outline that would be printed by the IFFCheck utility program
Xfor this particular file.
X
X
X +-----------------------------------+
X |'FORM' 24070 | FORM 24070 IBLM
X +-----------------------------------+
X |'ILBM' |
X +-----------------------------------+
X | +-------------------------------+ |
X | | 'BMHD' 20 | | .BMHD 20
X | | 320, 200, 0, 0, 3, 0, 0, ... | |
X | + ------------------------------+ |
X | | 'CMAP' 21 | | .CMAP 21
X | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
X | +-------------------------------+ |
X | 0 |
X +-----------------------------------+
X |'BODY' 24000 | .BODY 24000
X |0, 0, 0, ... |
X +-----------------------------------+
X
X
X
XThe "0" after the CMAP chunk is a pad byte.
X
X
X
XAppendix C. ByteRun1 Run Encoding
X
XThe run encoding scheme byteRun1 is best described by psuedo code
Xfor the decoder Unpacker (called UnPackBits in the Macintosh* toolbox):
X
XUnPacker:
X LOOP until produced the desired number of bytes
X Read the next source byte into n
X SELECT n FROM
X [0..127] => copy the next n+1 bytes literally
X [-1..-127] => replicate the next byte -n+1 times
X -128 => noop
X ENDCASE;
X ENDLOOP;
X
XIn the inverse routine Packer, it's best to encode a 2 byte repeat
Xrun as a replicate run except when preceded and followed by a literal
Xrun, in which case it's best to merge the three into one literal run.
XAlways encode 3 byte repeats as replicate runs.
X
XRemember that each row of each scan line of a raster is separately
Xpacked.
X
X
X
XAppendix D. Standards Committee
X
XThe following people contributed to the design of this FORM ILBM standard:
X
XBob "Kodiak" Burns, Commodore-Amiga
XR. J. Mical, Commodore-Amiga
XJerry Morrison, Electronic Arts
XGreg Riker, Electronic Arts
XSteve Shaw, Electronic Arts
XDan Silva, Electronic Arts
XBarry Walsh, Commodore-Amiga
//END
echo x - smus
sed 's/^X//' > smus << '//END'
X"SMUS" IFF Simple Musical Score
X
XDate: February 5, 1986
XFrom: Jerry Morrison, Electronic Arts
XStatus: Adopted
X
X1. Introduction
X
XThis is a reference manual for the data interchange format "SMUS",
Xwhich stands for Simple MUsical Score. "EA IFF 85" is Electronic Arts'
Xstandard for interchange format files. A FORM (or "data section")
Xsuch as FORM SMUS can be an IFF file or a part of one. [See "EA IFF
X85" Electronic Arts Interchange File Format.]
X
XSMUS is a practical data format for uses like moving limited scores
Xbetween programs and storing theme songs for game programs. The format
Xshould be geared for easy read-in and playback. So FORM SMUS uses
Xthe compact time encoding of Common Music Notation (half notes, dotted
Xquarter rests, etc.). The SMUS format should also be structurally
Xsimple. So it has no provisions for fancy notational information needed
Xby graphical score editors or the more general timing (overlapping
Xnotes, etc.) and continuous data (pitch bends, etc.) needed by
Xperformance-oriented MIDI recorders and sequencers.
X
XA SMUS score can say which "instruments" are supposed play which notes.
XBut the score is independent of whatever output device and driver
Xsoftware is used to perform the notes. The score can contain device-
Xand driver-dependent instrument data, but this is just a cache. As
Xlong as a SMUS file stays in one environment, the embedded instrument
Xdata is very convenient. When you move a SMUS file between programs
Xor hardware configurations, the contents of this cache usually become
Xuseless.
X
XLike all IFF formats, SMUS is a filed or "archive" format. It is completely
Xindependent of score representations in working memory, editing operations,
Xuser interface, display graphics, computation hardware, and sound
Xhardware. Like all IFF formats, SMUS is extensible.
X
XSMUS is not an end-all musical score format. Other formats may be
Xmore appropriate for certain uses. (We'd like to design an general-use
XIFF score format "GSCR". FORM GSCR would encode fancy notational data
Xand performance data. There would be a SMUS to/from GSCR converter.)
X
XSection 2 gives important background information. Section 3 details
Xthe SMUS components by defining the required property score header
X"SHDR", the optional text properties name "NAME", copyright "(c) ",
Xand author "AUTH", optional text annotation "ANNO", the optional instrument
Xspecifier "INS1", and the track data chunk "TRAK". Section 4 defines
Xsome chunks for particular programs to store private information.
XThese are "standard" chunks; specialized chunks for future needs can
Xbe added later. Appendix A is a quick-reference summary. Appendix
XB is an example box diagram. Appendix C names the committee responsible
Xfor this standard.
X
XUpdate: This standard has been revised since the draft versions. The
X"INST" chunk type was revised to form the "INS1" chunk type. Also,
Xseveral SEvent types and a few text chunk types have been added.
X
XNote: This is a MacWrite[tm] 4.5 document. If you strip it down to a
Xtext file, you'll lose pictures, significant formatting information
Xlike superscripts, and characters like ")". Don't do it.
X
X
X ----------------------------------------------------------------
X |(Sorry, EA. We had to strip it down for ease of distribution, |
X | but we did convert pictures to text-form and where we could |
X | not do that, we provided ILBM illustrations that people |
X | could actually show using the standard "showilbm" program) |
X ----------------------------------------------------------------
X
X
XReferences:
X
X"EA IFF 85" Standard for Interchange Format Files describes the underlying
Xconventions for all IFF files.
X
X"8SVX" IFF 8-Bit Sampled Voice documents a data format for sampled
Xinstruments.
X
XElectronic Arts[tm] is a trademark of Electronic Arts.
X
XMIDI: Musical Instrument Digital Interface Specification 1.0, International
XMIDI Association, 1983.
X
XMacWrite[tm] is a trademark of Apple Computer, Inc.
X
XSSSP: See various articles on Structured Sound Synthesis Project in
XFoundations of Computer Music.
X
X
X
X
X2. Background
X
XHere's some background information on score representation in general
Xand design choices for SMUS.
X
XFirst, we'll borrow some terminology from the Structured Sound Synthesis
XProject. [See the SSSP reference.] A "musical note" is one kind of
Xscheduled event. It's properties include an event duration, an event
Xdelay, and a timbre object. Theevent duration tells the scheduler
Xhow long the note should last. The event delay tells how long after
Xstarting this note to wait before starting the next event. The timbre
Xobject selects sound driver data for the note; an "instrument" or
X"timbre". A "rest" is a sort of a null event. Its only property is
Xan event delay.
X
XClassical Event Durations
X
XSMUS is geared for "classical" scores, not free-form performances.
XSo its event durations are classical (whole note, dotted quarter rest,
Xetc.). It can tie notes together to build a "note event" with an unusual
Xevent duration.
X
XThe set of useful classical durations is very small. So SMUS needs
Xonly a handful of bits to encode an event duration. This is very compact.
XIt's also very easy to display in Common Music Notation (CMN).
X
XTracks
X
XThe events in a SMUS score are grouped into parallel "tracks". Each
Xtrack is a linear stream of events.
X
XWhy use tracks? Tracks serve 4 functions:
X
X1. Tracks make it possible to encode event delays very compactly.
XA "classical" score has chorded notes and sequential notes; no overlapping
Xnotes. That is, each event begins either simultaneous with or immediately
Xfollowing the previous event in that track. So each event delay is
Xeither 0 or the same as the event's duration. This binary distinction
Xrequires only one bit of storage.
X
X2. Tracks represent the "voice tracks" in Common Music Notation.
XCMN organizes a score in parallel staves, with one or two "voice tracks"
Xper staff. So one or two SMUS tracks represents a CMN staff.
X
X3. Tracks are a good match to available sound hardware. We can
Xuse "instrument settings" in a track to store the timbre assignments
Xfor that track's notes. The instrument setting may change over the
Xtrack.
X
X Furthermore, tracks can help to allocate notes among available
Xoutput channels or performance devices or tape recorder "tracks".
XTracks can also help to adapt polyphonic data to monophonic output
Xchannels.
X
X4. Tracks are a good match to simple sound software. Each track
Xis a place to hold state settings like "dynamic mark pp ", "time signature
X3/4", "mute this track", etc., just as it's a context for instrument
Xsettings. This is a lot like a text stream with running "font" and
X"face" properties (attributes). Running state is usually more compact
Xthan, say, storing an instrument setting in every note event. It's
Xalso a useful way to organize "attributes" of notes. With "running
Xtrack state" we can define new note attributes in an upward- and
Xbackward-compatible way.
X
X Running track state can be expanded (run decoded) while loading
Xa track into memory or while playing the track. The runtime track
Xstate must be reinitialized every time the score is played.
X
XSeparated vs. interleaved tracks. Multi-track data could be stored
Xeither as separate event streams or interleaved into one stream. To
Xinterleave the streams, each event has to carry a "track number" attribute.
X
XIf we were designing an editable score format, we might interleave
Xthe streams so that nearby events are stored nearby. This helps when
Xsearching the data, especially if you can't fit the entire score into
Xmemory at once. But it takes extra storage for the track numbers and
Xmay take extra work to manipulate the interleaved tracks.
X
XThe musical score format FORM SMUS is intended for simple loading
Xand playback of small scores that fit entirely in main memory. So
Xwe chose to store its tracks separately.
X
XThere can be up to 255 tracks in a FORM SMUS. Each track is stored
Xas a TRAK chunk. The count of tracks (the number of TRAK chunks) is
Xrecorded in the SHDR chunk at the beginning of the FORM SMUS. The
XTRAK chunks appear in numerical order 1, 2, 3, .... This is also priority
Xorder, most important track first. A player program that can handle
Xup to N parallel tracks should read the first N tracks and ignore
Xany others.
X
XThe different tracks in a score may have different lengths. This is
Xtrue both of storage length and of playback duration.
X
XInstrument Registers
X
XInstrument reference. In SSSP, each note event points to a "timbre
Xobject" which supplies the "instrument" (the sound driver data) for
Xthat note. FORM SMUS stores these pointers as a "current instrument
Xsetting" for each track. It's just a run encoded version of the same
Xinformation. SSSP uses a symbol table to hold all the pointers to
X"timbre object". SMUS uses INS1 chunks for the same purpose. They
Xname the score's instruments.
X
XThe actual instrument data to use depends on the playback environment,
Xbut we want the score to be independent of environment. Different
Xplayback environments have different audio output hardware and different
Xsound driver software. And there are channel allocation issues like
Xhow many output channels there are, which ones are polyphonic, and
Xwhich I/O ports they're connected to. If you use MIDI to control the
Xinstruments, you get into issues of what kind of device is listening
Xto each MIDI channel and what each of its preset sounds like. If you
Xuse computer-based instruments, you need driver-specific data like
Xwaveform tables and oscillator parameters.
X
XWe just want to put some orchestration in the score. If the score
Xwants a "piano", we let the playback program to find a "piano".
X
XInstrument reference by name. A reference from a SMUS score to actual
Xinstrument data is normally by name. The score simply names the instrument,
Xfor instance "tubular bells". It's up to the player program to find
Xsuitable instrument data for its output devices. (More on locating
Xinstruments below.)
X
XInstrument reference by MIDI channel and preset. A SMUS score can
Xalso ask for a specific MIDI channel number and preset number. MIDI
Xprograms may honor these specific requests. But these channel allocations
Xcan become obsolete or the score may be played without MIDI hardware.
XIn such cases, the player program should fall back to instrument reference
Xby name.
X
XInstrument reference via instrument register. Each reference from
Xa SMUS track to an instrument is via an "instrument register". Each
Xtrack selects an instrument register which in turn points to the specific
Xinstrument data.
X
XEach score has an array of instrument registers. Each track has a
X"current instrument setting", which is simply an index number into
Xthis array. This is like setting a raster image's pixel to a specific
Xcolor number (a reference to a color value through a "color register")
Xor setting a text character to a specific font number (a reference
Xto a font through a "font register"). This is diagrammed below.
X
X
X Track 1 |Set Inst 2| Note | Note | Set Inst 1 | Note | Note | Note |...
X | |
X +-------------+ |
X | +------------------------------------+
X | | +--------------------------------------------------------+
X | +-------->|"piano" ---------------> (internal piano data) |
X +----------->|"guitar" ---------------> (internal guitar data) |
X |"Spanish guitar" -------> (internal Spanish guitar data)|
X +-------->|"bass drum" ------------> (internal bass drum data) |
X | +--------------------------------------------------------+
X |
X +---------+
X |
X Track 2 |Set Inst 4| Note | Note | Note | Note | Note | Note | Note |...
X
X
X
XLocating instrument data by name. "INS1" chunks in a SMUS score name
Xthe instruments to use for that score. The player program uses these
Xnames to locate instrument data.
X
XTo locate instrument data, the player performs these steps:
X
XFor each instrument register, check for a suitable instrument with
Xthe right name. "Suitable" means usable with an available output
Xdevice and driver. {Use case independent name comparisons.}
X
X1. Initialize the instrument register to point to a built-in default
X instrument. {Every player program must have default instruments.
X Simple programs stop here. For fancier programs, the default
X instruments are a backstop in case the search fails.}
X
X2. Check any instrument FORMs embedded in the FORM SMUS. (This
X is an "instrument cache".)
X
X3. Else check the default instruments.
X
X4. Else search the local "instrument library". (The library might
X simply be a disk directory.)
X
X5. If all else fails, display the desired instrument name and
X ask the user to pick an available one.
X
XThis algorithm can be implemented to varying degrees of fanciness.
XIt's ok to stop searching after step 1, 2, 3, or 4. If exact instrument
Xname matches fail, it's ok to try approximate matches. E.g. search
Xfor any kind of "guitar" if you can't find a "Spanish guitar". In
Xany case, a player only has to search for instruments while loading
Xa score.
X
XWhen the embedded instruments are suitable, they save the program
Xfrom asking the user to insert the "right" disk in a drive and searching
Xthat disk for the "right" instrument. But it's just a cache. In practice,
Xwe rarely move scores between environments so the cache often works.
XWhen the score is moved, embedded instruments must be discarded (a
Xcache miss) and other instrument data used.
X
XBe careful to distinguish an instrument's name from its filenameQthe
Xcontents name vs. container name. A musical instrument FORM should
Xcontain a NAME chunk that says what instrument it really is. Its filename,
Xon the other hand, is a handle used to locate the FORM. Filenames
Xare affected by external factors like drives, directories, and filename
Xcharacter and length limits. Instrument names are not.
X
XIssue: Consider instrument naming conventions for consistency. Consider
Xa naming convention that aids approximate matches. E.g. we could accept
X"guitar, bass1" if we didn't find "guitar, bass". Failing that, we
Xcould accept "guitar" or any name starting with "guitar".
X
XSet instrument events. If the player implements the set-instrument
Xscore event, each track can change instrument numbers while playing.
XThat is, it can switch between the loaded instruments.
X
XInitial instrument settings. Each time a score is played, every tracks'
Xrunning state information must be initialized. Specifically, each
Xtrack's instrument number should be initialized to its track number.
XTrack 1 to instrument 1, etc. It's as if each track began with a
Xset-instrument event.
X
XIn this way, programs that don't implement the set-instrument event
Xstill assign an instrument to each track. The INS1 chunks imply these
Xinitial instrument settings.
X
XMIDI Instruments
X
XAs mentioned above, A SMUS score can also ask for MIDI instruments.
XThis is done by putting the MIDI channel and preset numbers in an
XINS1 chunk with the instrument name. Some programs will honor these
Xrequests while others will just find instruments by name.
X
XMIDI Recorder and sequencer programs may simply transcribe the MIDI
Xchannel and preset commands in a recording session. For this purpose,
Xset-MIDI-channel and set-MIDI-preset events can be embedded in a SMUS
Xscore's tracks. Most programs should ignore these events. An editor
Xprogram that wants to exchange scores with such programs should recognize
Xthese events. It should let the user change them to the more general
Xset-instrument events.
X
X
X
X3. Standard Data and Property Chunks
X
XA FORM SMUS contains a required property "SHDR" followed by any number
Xof parallel "track" data chunks "TRAK". Optional property chunks such
Xas "NAME", copyright "(c) ", and instrument reference "INS1" may also
Xappear. Any of the properties may be shared over a LIST of FORMs SMUS
Xby putting them in a PROP SMUS. [See the IFF reference.]
X
XRequired Property SHDR
X
XThe required property "SHDR" holds an SScoreHeader as defined in these
XC declarations and following documentation. An SHDR specifies global
Xinformation for the score. It must appear before the TRAKs in a FORM
XSMUS.
X
X#define ID_SMUS MakeID('S', 'M', 'U', 'S')
X#define ID_SHDR MakeID('S', 'H', 'D', 'R')
X
Xtypedef struct {
X UWORD tempo; /* tempo, 128ths quarter note/minute */
X UBYTE volume; /* overall playback volume 0 through 127 */
X UBYTE ctTrack; /* count of tracks in the score */
X } SScoreHeader;
X
X[Implementation details. In the C struct definitions in this memo,
Xfields are filed in the order shown. A UBYTE field is packed into
Xan 8-bit byte. Programs should set all "pad" fields to 0. MakeID is
Xa C macro defined in the main IFF document and in the source file
XIFF.h.]
X
XThe field tempo gives the nominal tempo for all tracks in the score.
XIt is expressed in 128ths of a quarter note per minute, i.e. 1 represents
X1 quarter note per 128 minutes while 12800 represents 100 quarter
Xnotes per minute. You may think of this as a fixed point fraction
Xwith a 9-bit integer part and a 7-bit fractional part (to the right
Xof the point). A course-tempoed program may simply shift tempo right
Xby 7 bits to get a whole number of quarter notes per minute. The tempo
Xfield can store tempi in the range 0 up to 512. The playback program
Xmay adjust this tempo, perhaps under user control.
X
XActually, this global tempo could actually be just an initial tempo
Xif there are any "set tempo" SEvents inside the score (see TRAK, below).
XOr the global tempo could be scaled by "scale tempo" SEvents inside
Xthe score. These are potential extensions that can safely be ignored
Xby current programs. [See More SEvents To Be Defined, below.]
X
XThe field volume gives an overall nominal playback volume for all
Xtracks in the score. The range of volume values 0 through 127 is like
Xa MIDI key velocity value. The playback program may adjust this volume,
Xperhaps under direction of a user "volume control".
X
XActually, this global volume level could be scaled by dynamic-mark
XSEvents inside the score (see TRAK, below).
X
XThe field ctTrack holds the count of tracks, i.e. the number of TRAK
Xchunks in the FORM SMUS (see below). This information helps the reader
Xprepare for the following data.
X
XA playback program will typically load the score and call a driver
Xroutine PlayScore(tracks, tempo, volume), supplying the tempo and
Xvolume from the SHDR chunk.
X
XOptional Text Chunks NAME, (c), AUTH, ANNO
X
XSeveral text chunks may be included in a FORM SMUS to keep ancillary
Xinformation.
X
XThe optional property "NAME" names the musical score, for instance
X"Fugue in C".
X
XThe optional property "(c)J" holds a copyright notice for the score.
XThe chunk ID "(c)J" serves the function of the copyright characters
X")J". E.g. a "(c)J" chunk containing "1986 Electronic Arts" means
X") 1986 Electronic Arts".
X
XThe optional property "AUTH" holds the name of the score's author.
X
XThe chunk types "NAME", "(c) ", and "AUTH" are property chunks. Putting
Xmore than one NAME (or other) property in a FORM is redundant. Just
Xthe last NAME counts. A property should be shorter than 256 characters.
XProperties can appear in a PROP SMUS to share them over a LIST of
XFORMs SMUS.
X
XThe optional data chunk "ANNO" holds any text annotations typed in
Xby the author.
X
XAn ANNO chunk is not a property chunk, so you can put more than one
Xin a FORM SMUS. You can make ANNO chunks any length up to 231 - 1
Xcharacters, but 32767 is a practical limit. Since they're not properties,
XANNO chunks don't belong in a PROP SMUS. That means they can't be
Xshared over a LIST of FORMs SMUS.
X
XSyntactically, each of these chunks contains an array of 8-bit ASCII
Xcharacters in the range R S (SP, hex 20) through R~S (tilde, hex 7F),
Xjust like a standard "TEXT" chunk. [See "Strings, String Chunks, and
XString Properties" in "EA IFF 85" Electronic Arts Interchange File
XFormat.] The chunk's ckSize field holds the count of characters.
X
X#define ID_NAME MakeID('N', 'A', 'M', 'E')
X/* NAME chunk contains a CHAR[], the musical score's name. */
X
X#define ID_Copyright MakeID('(', 'c', ')', ' ')
X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
X
X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
X/* AUTH chunk contains a CHAR[], the name of the score's author. */
X
X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
X/* ANNO chunk contains a CHAR[], author's text annotations. */
X
XRemember to store a 0 pad byte after any odd-length chunk.
X
XOptional Property INS1
X
XThe "INS1" chunks in a FORM SMUS identify the instruments to use for
Xthis score. A program can ignore INS1 chunks and stick with its built-in
Xdefault instrument assignments. Or it can use them to locate instrument
Xdata. [See "Instrument Registers" in section 2, above.]
X
X#define ID_INS1 MakeID('I', 'N', 'S', '1')
X
X/* Values for the RefInstrument field "type". */
X#define INS1_Name 0 /* just use the name; ignore data1, data2 */
X#define INS1_MIDI 1 /* <<data1, data2> = MIDI <<channel, preset> */
X
Xtypedef struct {
X UBYTE register; /* set this instrument register number */
X UBYTE type; /* instrument reference type */
X UBYTE data1, data2; /* depends on the "type" field */
X CHAR name[]; /* instrument name */
X } RefInstrument;
X
XAn INS1 chunk names the instrument for instrument register number
Xregister. The register field can range from 0 through 255. In practice,
Xmost scores will need only a few instrument registers.
X
XThe name field gives a text name for the instrument. The string length
Xcan be determined from the ckSize of the INS1 chunk. The string is
Xsimply an array of 8-bit ASCII characters in the range R S (SP, hex
X20) through R~S (tilde, hex 7F).
X
XBesides the instrument name, an INS1 chunk has two data numbers to
Xhelp locate an instrument. The use of these data numbers is controlled
Xby the type field. A value type = INS1_Name means just find an instrument
Xby name. In this case, data1 and data2 should just be set to 0. A
Xvalue type = INS1_MIDI means look for an instrument on MIDI channel
X# data1, preset # data2. Programs and computers without MIDI outputs
Xwill just ignore the MIDI data. They'll always look for the named
Xinstrument. Other values of the type field are reserved for future
Xstandardization.
X
XSee section 2, above, for the algorithm for locating instrument data
Xby name.
X
XObsolete Property INST
X
XThe chunk type "INST" is obsolete in SMUS. It was revised to form
Xthe "INS1" chunk.
X
XData Chunk TRAK
X
XThe main contents of a score is stored in one or more TRAK chunks
Xrepresenting parallel "tracks". One TRAK chunk per track.
X
XThe contents of a TRAK chunk is an array of 16-bit "events" such as
X"note", "rest", and "set instrument". Events are really commands to
Xa simple scheduler, stored in time order. The tracks can be polyphonic,
Xthat is, they can contain chorded "note" events.
X
XEach event is stored as an "SEvent" record. ("SEvent" means "simple
Xmusical event".) Each SEvent has an 8-bit type field called an "sID"
Xand 8 bits of type-dependent data. This is like a machine language
Xinstruction with an 8-bit opcode and an 8-bit operand.
X
XThis format is extensible since new event types can be defined in
Xthe future. The "note" and "rest" events are the only ones that every
Xprogram must understand. We will carefully design any new event types
Xso that programs can safely skip over unrecognized events in a score.
X
XCaution: SID codes must be allocated by a central clearinghouse to
Xavoid conflicts.
X
XHere are the C type definitions for TRAK and SEvent and the currently
Xdefined sID values. Afterward are details on each SEvent.
X
X#define ID_TRAK MakeID('T', 'R', 'A', 'K')
X
X/* TRAK chunk contains an SEvent[]. */
X
X/* SEvent: Simple musical event. */
Xtypedef struct {
X UBYTE sID; /* SEvent type code */
X UBYTE data; /* sID-dependent data */
X } SEvent;
X
X/* SEvent type codes "sID". */
X#define SID_FirstNote 0
X#define SID_LastNote 127 /* sIDs in the range SID_FirstNote through
X * SID_LastNote (sign bit = 0) are notes. The
X * sID is the MIDI tone number (pitch). */
X#define SID_Rest 128 /* a rest (same data format as a note). */
X
X#define SID_Instrument 129 /* set instrument number for this
Xtrack. */
X#define SID_TimeSig 130 /* set time signature for this track. */
X#define SID_KeySig 131 /* set key signature for this track. */
X#define SID_Dynamic 132 /* set volume for this track. */
X#define SID_MIDI_Chnl 133 /* set MIDI channel number (sequencers) */
X#define SID_MIDI_Preset 134 /* set MIDI preset number (sequencers) */
X
X/* SID values 144 through 159: reserved for Instant Music SEvents. */
X
X/* Remaining sID values up through 254: reserved for future
X * standardization. */
X
X#define SID_Mark 255 /* sID reserved for an end-mark in RAM. */
X
XNote and Rest SEvents
X
XThe note and rest SEvents SID_FirstNote through SID_Rest have the
Xfollowing structure overlaid onto the SEvent structure:
X
Xtypedef struct {
X UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */
X unsigned chord :1, /* 1 = a chorded note */
X tieOut :1, /* 1 = tied to the next note or chord */
X nTuplet :2, /* 0 = none, 1 = triplet, 2 = quintuplet,
X * 3 = septuplet */
X dot :1, /* dotted note; multiply duration by 3/2 */
X division :3; /* basic note duration is 2-division: 0 = whole
X * note, 1 = half note, 2 = quarter note, I
X * 7 = 128th note */
X } SNote;
X
X[Implementation details. Unsigned ":n" fields are packed into n bits
Xin the order shown, most significant bit to least significant bit.
XAn SNote fits into 16 bits like any other SEvent. Warning: Some compilers
Xdon't implement bit-packed fields properly. E.g. Lattice 68000 C pads
Xa group of bit fields out to a LONG, which would make SNote take 5-bytes!
XIn that situation, use the bit-field constants defined below.]
X
XThe SNote structure describes one "note" or "rest" in a track. The
Xfield SNote.tone, which is overlaid with the SEvent.sID field, indicates
Xthe MIDI tone number (pitch) in the range 0 through 127. A value of
X128 indicates a rest.
X
XThe fields nTuplet, dot, and division together give the duration of
Xthe note or rest. The division gives the basic duration: whole note,
Xhalf note, etc. The dot indicates if the note or rest is dotted. A
Xdotted note is 3/2 as long as an undotted note. The value nTuplet
X(0 through 3) tells if this note or rest is part of an N-tuplet of
Xorder 1 (normal), 3, 5, or 7; an N-tuplet of order (2J*JnTupletJ+J1).
XA triplet note is 2/3 as long as a normal note, while a quintuplet
Xis 4/5 as long and a septuplet is 6/7 as long.
X
XPutting these three fields together, the duration of the note or rest
Xis 2-division * {1, 3/2} * {1, 2/3, 4/5, 6/7}
X
XThese three fields are contiguous so you can easily convert to your
Xlocal duration encoding by using the combined 6 bits as an index into
Xa mapping table.
X
XThe field chord indicates if the note is chorded with the following
Xnote (which is supposed to have the same duration). A group of notes
Xmay be chorded together by setting the chord bit of all but the last
Xone. (In the terminology of SSSP and GSCR, setting the chord bit to
X1 makes the "entry delay" 0.) A monophonic-track player can simply
Xignore any SNote event whose chord bit is set, either by discarding
Xit when reading the track or by skipping it when playing the track.
X
XPrograms that create polyphonic tracks are expected to store the most
Ximportant note of each chord last, which is the note with the 0 chord
Xbit. This way, monophonic programs will play the most important note
Xof the chord. The most important note might be the chord's root note
Xor its melody note.
X
XIf the field tieOut is set, the note is tied to the following note
Xin the track if the following note has the same pitch. A group of
Xtied notes is played as a single note whose duration is the sum of
Xthe component durations. Actually, the tie mechanism ties a group
Xof one or more chorded notes to another group of one or more chorded
Xnotes. Every note in a tied chord should have its tieOut bit set.
X
XOf course, the chord and tieOut fields don't apply to SID_Rest SEvents.
X
XPrograms should be robust enough to ignore an unresolved tie, i.e.
Xa note whose tieOut bit is set but isn't followed by a note of the
Xsame pitch. If that's true, monophonic-track programs can simply ignore
Xchorded notes even in the presense of ties. That is, tied chords pose
Xno extra problems.
X
XThe following diagram shows some combinations of notes and chords
Xtied to notes and chords. The text below the staff has a column for
Xeach SNote SEvent to show the pitch, chord bit, and tieOut bit.
X
X
X
X (figure)
X
X
X
X
XIf you read the above track into a monophonic-track program, it'll
Xstrip out the chorded notes and ignore unresolved ties. You'll end
Xup with:
X
X
X
X (figure)
X
X
X
X
XA rest event (sID = SID_Rest) has the same SEvent.data field as a
Xnote. It tells the duration of the rest. The chord and tieOut fields
Xof rest events are ignored.
X
XWithin a TRAK chunk, note and rest events appear in time order.
X
XInstead of the bit-packed structure SNote, it might be easier to assemble
Xdata values by or-ing constants and to disassemble them by masking
Xand shifting. In that case, use the following definitions.
X
X#define noteChord (1<<<<7) /* note is chorded to next note */
X
X#define noteTieOut (1<<<<6) /* tied to next note/chord */
X
X#define noteNShift 4 /* shift count for nTuplet field */
X#define noteN3 (1<<<<noteNShift) /* note is a triplet */
X#define noteN5 (2<<<<noteNShift) /* note is a quintuplet */
X#define noteN7 (3<<<<noteNShift) /* note is a septuplet */
X#define noteNMask noteN7 /* bit mask for the nTuplet field */
X
X#define noteDot (1<<<<3) /* note is dotted */
X
X#define noteD1 0 /* whole note division */
X#define noteD2 1 /* half note division */
X#define noteD4 2 /* quarter note division */
X#define noteD8 3 /* eighth note division */
X#define noteD16 4 /* sixteenth note division */
X#define noteD32 5 /* thirty-secondth note division */
X#define noteD64 6 /* sixty-fourth note division */
X#define noteD128 7 /* 1/128 note division */
X#define noteDMask noteD128 /* bit mask for the division field */
X
X#define noteDurMask 0x3F /* mask for combined duration fields */
X
XNote: The remaining SEvent types are optional. A writer program doesn't
Xhave to generate them. A reader program can safely ignore them.
X
XSet Instrument SEvent
X
XOne of the running state variables of every track is an instrument
Xnumber. An instrument number is the array index of an "instrument
Xregister", which in turn points to an instrument. (See "Instrument
XRegisters", in section 2.) This is like a color number in a bitmap;
Xa reference to a color through a "color register".
X
XThe initial setting for each track's instrument number is the track
Xnumber. Track 1 is set to instrument 1, etc. Each time the score is
Xplayed, every track's instrument number should be reset to the track
Xnumber.
X
XThe SEvent SID_Instrument changes the instrument number for a track,
Xthat is, which instrument plays the following notes. Its SEvent.data
Xfield is an instrument register number in the range 0 through 255.
XIf a program doesn't implement the SID_Instrument event, each track
Xis fixed to one instrument.
X
XSet Time Signature SEvent
X
XThe SEvent SID_TimeSig sets the time signature for the track. A "time
Xsignature" SEvent has the following structure overlaid on the SEvent
Xstructure:
X
Xtypedef struct {
X UBYTE type; /* = SID_TimeSig */
X unsigned timeNSig :5, /* time sig. "numerator" is timeNSig + 1 */
X timeDSig :3; /* time sig. "denominator" is 2timeDSig:
X * 0 = whole note, 1 = half note, 2 = quarter
X * note, I 7 = 128th note */
X } STimeSig;
X
X[Implementation details. Unsigned ":n" fields are packed into n bits
Xin the order shown, most significant bit to least significant bit.
XAn STimeSig fits into 16 bits like any other SEvent. Warning: Some
Xcompilers don't implement bit-packed fields properly. E.g. Lattice
XC pads a group of bit fields out to a LONG, which would make an STimeSig
Xtake 5-bytes! In that situation, use the bit-field constants defined
Xbelow.]
X
XThe field type contains the value SID_TimeSig, indicating that this
XSEvent is a "time signature" event. The field timeNSig indicates the
Xtime signature "numerator" is timeNSig + 1, that is, 1 through 32
Xbeats per measure. The field timeDSig indicates the time signature
X"denominator" is 2timeDSig, that is each "beat" is a 2-timeDSig note
X(see SNote division, above). So 4/4 time is expressed as timeNSig
X= 3, timeDSig = 2.
X
XThe default time signature is 4/4 time.
X
XBeware that the time signature has no effect on the score's playback.
XTempo is uniformly expressed in quarter notes per minute, independent
Xof time signature. (Quarter notes per minute equals beats per minute
Xonly if timeDSig = 2, n/4 time). Nonetheless, any program that has
Xtime signatures should put them at the beginning of each TRAK when
Xcreating a FORM SMUS because music editors need them.
X
XInstead of the bit-packed structure STimeSig, it might be easier to
Xassemble data values by or-ing constants and to disassemble them by
Xmasking and shifting. In that case, use the following definitions.
X
X#define timeNMask 0xF8 /* bit mask for the timeNSig field */
X#define timeNShift 3 /* shift count for timeNSig field */
X
X#define timeDMask 0x07 /* bit mask for the timeDSig field */
X
XKey Signature SEvent
X
XAn SEvent SID_KeySig sets the key signature for the track. Its data
Xfield is a UBYTE number encoding a major key:
X
Xdata key music notation data key music notation
XJ0 C maj
XJ1 G # J8 F b
XJ2 D ## J9 Bb bb
XJ3 A ### 10 Eb bbb
XJ4 E #### 11 Ab bbbb
XJ5 B ##### 12 Db bbbbb
XJ6 F# ###### 13 Gb bbbbbb
XJ7 C# ####### 14 Cb bbbbbbb
X
XA SID_KeySig SEvent changes the key for the following notes in that
Xtrack. C major is the default key in every track before the first
XSID_KeySig SEvent.
X
XDynamic Mark SEvent
X
XAn SEvent SID_Dynamic represents a dynamic mark like ppp and fff in
XCommon Music Notation. Its data field is a MIDI key velocity number
X0 through 127. This sets a "volume control" for following notes in
Xthe track. This "track volume control" is scaled by the overall score
Xvolume in the SHDR chunk.
X
XThe default dynamic level is 127 (full volume).
X
XSet MIDI Channel SEvent
X
XThe SEvent SID_MIDI_Chnl is for recorder programs to record the set-MIDI-channe
Xl low level event. The data byte contains a MIDI channel number. Other
Xprograms should use instrument registers instead.
X
XSet MIDI Preset SEvent
X
XThe SEvent SID_MIDI_Preset is for recorder programs to record the
Xset-MIDI-preset low level event. The data byte contains a MIDI preset
Xnumber. Other programs should use instrument registers instead.
X
XInstant Music Private SEvents
X
XSixteen SEvents are used for private data for the Instant Music program.
XSID values 144 through 159 are reserved for this purpose. Other programs
Xshould skip over these SEvents.
X
XEnd-Mark SEvent
X
XThe SEvent type SID_Mark is reserved for an end marker in working
Xmemory. This event is never stored in a file. It may be useful if
Xyou decide to use the filed TRAK format intact in working memory.
X
XMore SEvents To Be Defined
X
XMore SEvents can be defined in the future. The sID codes 133 through
X143 and 160 through 254 are reserved for future needs. Caution: sID
Xcodes must be allocated by a central "clearinghouse" to avoid conflicts.
XWhen this SMUS standard passes the "draft" state, Commodore-Amiga
Xwill be in charge of this activity.
X
XThe following SEvent types are under consideration and should not
Xyet be used.
X
XIssue: A "change tempo" SEvent changes tempo during a score. Changing
Xthe tempo affects all tracks, not just the track containing the change
Xtempo event.
X
XOne possibility is a "scale tempo" SEvent SID_ScaleTempo that rescales
Xthe global tempo:
XcurrentTempo := globalTempo * (data + 1) / 128
X
XThis can scale the global tempo (in the SHDR) anywhere from x1/128
Xto x2 in roughly 1% increments.
X
XAn alternative is two events SID_SetHTempo and SID_SetLTempo. SID_SetHTempo
Xgives the high byte and SID_SetLTempo gives the low byte of a new
Xtempo setting, in 128ths quarter note/minute. SetHTempo automatically
Xsets the low byte to 0, so the SetLTempo event isn't needed for course
Xsettings. In this scheme, the SHDR's tempo is simply a starting tempo.
X
XAn advantage of SID_ScaleTempo is that the playback program can just
Xalter the global tempo to adjust the overall performance time and
Xstill easily implement tempo variations during the score. But the
X"set tempo" SEvent may be simpler to generate.
X
XIssue: The events SID_BeginRepeat and SID_EndRepeat define a repeat
Xspan for one track. The span of events between a BeginRepeat and an
XEndRepeat is played twice. The SEvent.data field in the BeginRepeat
Xevent could give an iteration count,1 through 255 times or 0 for "repeat
Xforever".
X
XRepeat spans can be nested. All repeat spans automatically end at
Xthe end of the track.
X
XAn event SID_Ending begins a section like "first ending" or "second
Xending". The SEvent.data field gives the ending number. This SID_Ending
Xevent only applies to the innermost repeat group. (Consider generalizing
Xit.)
X
XA more general alternative is a "subtrack" or "subscore" event. A
X"subtrack" event is essentially a "subroutine call" to another series
Xof SEvents. This is a nice way to encode all the possible variations
Xof repeats, first endings, codas, and such.
X
XTo define a subtrack, we must demark its start and end. One possibility
Xis to define a relative brach-to-subtrack event SID_BSR and a return-from-subtr
Xack event SID_RTS. The 8-bit data field in the SID_BSR event can reach
Xas far as 512 SEvents. A second possibility is to call a subtrack
Xby index number, with an IFF chunk outside the TRAK defining the start
Xand end of all subtracks. This is very general since a portion of
Xone subtrack can be used as another subtrack. It also models the tape
Xrecording practice of first "laying down a track" and then selecting
Xportions of it to play and repeat. To embody the music theory idea
Xof playing a sequence like "ABBA", just compose the "main" track entirely
Xof subtrack events. A third possibility is to use a numbered subtrack
Xchunk "STRK" for each subroutine.
X
X
X
X
X4. Private Chunks
X
XAs in any IFF FORM, there can be private chunks in a FORM SMUS that
Xare designed for one particular program to store its private information.
XAll IFF reader programs skip over unrecognized chunks, so the presense
Xof private chunks can't hurt.
X
XInstant Music stores some global score information in a chunk of ID
X"IRev".
X
X
X
XAppendix A. Quick Reference
X
XType Definitions
X
XHere's a collection of the C type definitions in this memo. In the
X"struct" type definitions, fields are filed in the order shown. A
XUBYTE field is packed into an 8-bit byte. Programs should set all
X"pad" fields to 0.
X
X#define ID_SMUS MakeID('S', 'M', 'U', 'S')
X#define ID_SHDR MakeID('S', 'H', 'D', 'R')
X
Xtypedef struct {
X UWORD tempo; /* tempo, 128ths quarter note/minute */
X UBYTE volume; /* overall playback volume 0 through 127 */
X UBYTE ctTrack; /* count of tracks in the score */
X } SScoreHeader;
X
X#define ID_NAME MakeID('N', 'A', 'M', 'E')
X/* NAME chunk contains a CHAR[], the musical score's name. */
X
X#define ID_Copyright MakeID('(', 'c', ')', ' ')
X/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
X
X#define ID_AUTH MakeID('A', 'U', 'T', 'H')
X/* AUTH chunk contains a CHAR[], the name of the score's author. */
X
X#define ID_ANNO MakeID('A', 'N', 'N', 'O')
X/* ANNO chunk contains a CHAR[], author's text annotations. */
X
X#define ID_INS1 MakeID('I', 'N', 'S', '1')
X
X/* Values for the RefInstrument field "type". */
X#define INS1_Name 0 /* just use the name; ignore data1, data2 */
X#define INS1_MIDI 1 /* <<data1, data2> = MIDI <<channel, preset> */
X
Xtypedef struct {
X UBYTE register; /* set this instrument register number */
X UBYTE type; /* instrument reference type */
X UBYTE data1, data2; /* depends on the "type" field */
X CHAR name[]; /* instrument name */
X } RefInstrument;
X
X#define ID_TRAK MakeID('T', 'R', 'A', 'K')
X/* TRAK chunk contains an SEvent[]. */
X
X/* SEvent: Simple musical event. */
Xtypedef struct {
X UBYTE sID; /* SEvent type code */
X UBYTE data; /* sID-dependent data */
X } SEvent;
X
X/* SEvent type codes "sID". */
X#define SID_FirstNote 0
X#define SID_LastNote 127 /* sIDs in the range SID_FirstNote through
X * SID_LastNote (sign bit = 0) are notes. The
X * sID is the MIDI tone number (pitch). */
X#define SID_Rest 128 /* a rest (same data format as a note). */
X
X#define SID_Instrument 129 /* set instrument number for this
Xtrack. */
X#define SID_TimeSig 130 /* set time signature for this track. */
X#define SID_KeySig 131 /* set key signature for this track. */
X#define SID_Dynamic 132 /* set volume for this track. */
X#define SID_MIDI_Chnl 133 /* set MIDI channel number (sequencers) */
X#define SID_MIDI_Preset 134 /* set MIDI preset number (sequencers) */
X
X/* SID values 144 through 159: reserved for Instant Music SEvents. */
X
X/* Remaining sID values up through 254: reserved for future
X * standardization. */
X
X#define SID_Mark 255 /* sID reserved for an end-mark in RAM. */
X
X/* SID_FirstNote..SID_LastNote, SID_Rest SEvents */
Xtypedef struct {
X UBYTE tone; /* MIDI tone number 0 to 127; 128 = rest */
X unsigned chord :1, /* 1 = a chorded note */
X tieOut :1, /* 1 = tied to the next note or chord */
X nTuplet :2, /* 0 = none, 1 = triplet, 2 = quintuplet,
X * 3 = septuplet */
X dot :1, /* dotted note; multiply duration by 3/2 */
X division :3; /* basic note duration is 2-division: 0 = whole
X * note, 1 = half note, 2 = quarter note, I
X * 7 = 128th note */
X } SNote;
X
X#define noteChord (1<<<<7) /* note is chorded to next note */
X
X#define noteTieOut (1<<<<6) /* tied to next note/chord */
X
X#define noteNShift 4 /* shift count for nTuplet field */
X#define noteN3 (1<<<<noteNShift) /* note is a triplet */
X#define noteN5 (2<<<<noteNShift) /* note is a quintuplet */
X#define noteN7 (3<<<<noteNShift) /* note is a septuplet */
X#define noteNMask noteN7 /* bit mask for the nTuplet field */
X
X#define noteDot (1<<<<3) /* note is dotted */
X
X#define noteD1 0 /* whole note division */
X#define noteD2 1 /* half note division */
X#define noteD4 2 /* quarter note division */
X#define noteD8 3 /* eighth note division */
X#define noteD16 4 /* sixteenth note division */
X#define noteD32 5 /* thirty-secondth note division */
X#define noteD64 6 /* sixty-fourth note division */
X#define noteD128 7 /* 1/128 note division */
X#define noteDMask noteD128 /* bit mask for the division field */
X
X#define noteDurMask 0x3F /* mask for combined duration fields */
X
X/* SID_Instrument SEvent */
X/* "data" value is an instrument register number 0 through 255. */
X
X/* SID_TimeSig SEvent */
Xtypedef struct {
X UBYTE type; /* = SID_TimeSig */
X unsigned timeNSig :5, /* time sig. "numerator" is timeNSig + 1 */
X timeDSig :3; /* time sig. "denominator" is 2timeDSig:
X * 0 = whole note, 1 = half note, 2 = quarter
X * note, I 7 = 128th note */
X } STimeSig;
X
X#define timeNMask 0xF8 /* bit mask for the timeNSig field */
X#define timeNShift 3 /* shift count for timeNSig field */
X
X#define timeDMask 0x07 /* bit mask for the timeDSig field */
X
X/* SID_KeySig SEvent */
X/* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#;
X * 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb. */
X
X/* SID_Dynamic SEvent */
X/* "data" value is a MIDI key velocity 0..127. */
X
XSMUS Regular Expression
X
XHere's a regular expression summary of the FORM SMUS syntax. This
Xcould be an IFF file or part of one.
X
XSMUS ::= "FORM" #{ "SMUS" SHDR [NAME] [Copyright] [AUTH] [IRev]
X ANNO* INS1* TRAK* InstrForm* }
X
XSHDR ::= "SHDR" #{ SScoreHeader }
XNAME ::= "NAME" #{ CHAR* } [0]
XCopyright ::= "(c) " #{ CHAR* } [0]
XAUTH ::= "AUTH" #{ CHAR* } [0]
XIRev ::= "IRev" #{ ... }
X
XANNO ::= "ANNO" #{ CHAR* } [0]
XINS1 ::= "INS1" #{ RefInstrument } [0]
X
XTRAK ::= "TRAK" #{ SEvent* }
X
XInstrForm ::= "FORM" #{ ... }
X
XThe token "#" represents a ckSize LONG count of the following {braced}
Xdata bytes. Literal items are shown in "quotes", [square bracket items]
Xare optional, and "*" means 0 or more replications. A sometimes-needed
Xpad byte is shown as "[0]".
X
XActually, the order of chunks in a FORM SMUS is not as strict as this
Xregular expression indicates. The SHDR, NAME, Copyright, AUTH, IRev,
XANNO, and INS1 chunks may appear in any order, as long as they precede
Xthe TRAK chunks.
X
XThe chunk RInstrFormS represents any kind of instrument data FORM
Xembedded in the FORM SMUS. For example, see the document "8SVX" IFF
X8-Bit Sampled Voice. Of course, a recipient program will ignore an
Xinstrument FORM if it doesn't recognize that FORM type.
X
X
X
XAppendix B. SMUS Example
X
XHere's a box diagram for a simple example, a SMUS with two instruments
Xand two tracks. Each track contains 1 note event and 1 rest event.
X
X
X
X +-----------------------------------------+ ------
X |'FORM' 94 | ^
X | +-----------------------------------+ | |
X | |'SMUS' | | |
X | +-----------------------------------+ | |
X | | +-------------------------------+ | | |
X | | | 'SHDR' 4 | | | |
X | | | 12800, 127, 2 | | | |
X | | +-------------------------------+ | | |
X | | +-------------------------------+ | | |
X | | | 'NAME' 10 | | | |
X | | | 'Fugue in C' | | | |
X | | +-------------------------------+ | | |
X | | +-------------------------------+ | |
X | | | 'INS1' 9 | | | (94 bytes)
X | | | 1,0,0,0,'piano' | | |
X | | +-------------------------------+ | | |
X | | 0 | | |
X | | +-------------------------------+ | | |
X | | | 'INS1' 10 | | | |
X | | | 2,0,0,0,'guitar' | | | |
X | | +-------------------------------+ | | |
X | | +-------------------------------+ | | |
X | | | 'TRAK' 4 | | | |
X | | | 60, 16, 128, 16 | | | |
X | | +-------------------------------+ | | |
X | | +-------------------------------+ | | |
X | | | 'TRAK' 4 | | | |
X | | | 128, 16, 60, 16 | | | |
X | | +-------------------------------+ | | |
X | +-----------------------------------+ | V
X +-----------------------------------------+ -----
X
X
X
XAppendix B. Standards Committee
X
XThe following people contributed to the design of this IFF standard:
X
XBob "Kodiak" Burns, Commodore-Amiga
XR. J. Mical, Commodore-Amiga
XJerry Morrison, Electronic Arts
XGreg Riker, Electronic Arts
XSteve Shaw, Electronic Arts
XBarry Walsh, Commodore-Amiga
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
XThe "0" after the first INS1 chunk is a pad byte.
X
X
X
XAppendix C. Standards Committee
X
XThe following people contributed to the design of this SMUS standard:
X
XRalph Bellafatto, Cherry Lane Technologies
XGeoff Brown, Uhuru Sound Software
XSteve Hayes, Electronic Arts
XJerry Morrison, Electronic Arts
//END
: end of archive.
exit 0
--
Peter da Silva. `-_-'
<
[email protected]>.