add directory study
This commit is contained in:
BIN
study/sabre/os/files/Sound/AC97ComponentSpecificationv2.1.pdf
Normal file
BIN
study/sabre/os/files/Sound/AC97ComponentSpecificationv2.1.pdf
Normal file
Binary file not shown.
120
study/sabre/os/files/Sound/ANSIMusicTechDetails.txt
Normal file
120
study/sabre/os/files/Sound/ANSIMusicTechDetails.txt
Normal file
@@ -0,0 +1,120 @@
|
||||
ANSI Music - The Technical Details
|
||||
|
||||
ANSI is an acronym for "American National Standards Institute" and
|
||||
actually has little to do with this "ANSI music" stuff. However, the
|
||||
American National Standards Institute defined a set of codes for
|
||||
terminals to provide a standard for cursor control. This was expanded to
|
||||
include graphics modes and color with the release of the ANSI.SYS device
|
||||
driver. It wasn't actually ANSI who expanded the set of codes to include
|
||||
the graphics, which are specific to IBM compatible computers with
|
||||
certain video adapters, but the name ANSI stuck. The original purpose of
|
||||
ANSI cursor control was to give mainframes a way to control the cursor
|
||||
on various terminals connected to them. The purpose of the ANSI.SYS
|
||||
driver was to give programs a simple and compatible way of controlling
|
||||
the video screen. However, it seems that the only real use for ANSI has
|
||||
been to give BBS's the ability to control the screen colors and cursor
|
||||
positioning. This even led to a new artform, but let's not even think
|
||||
about that. It's too much like Art Deco. In CGA color, no less.
|
||||
The ANSI.SYS driver also includes provisions for redefining keys
|
||||
on the keyboard. This can be used for character translation or to create
|
||||
simple macros. It has even been used to create trojan text files that
|
||||
redefined your keys to destroy data (i.e. your enter key becomes "DEL
|
||||
*.* <return> Y <return>"). Watch out for this kind of thing. It's not
|
||||
hard to do.
|
||||
|
||||
Now I said that the actual "ANSI" organization had little to do
|
||||
with "ANSI music." The reason that the music codes were given the name
|
||||
"ANSI" is because they start with the same escape sequences. All ANSI
|
||||
codes start with <esc>[ as do the music codes. What I mean by <esc>[ is
|
||||
the escape character (27 decimal, 1E hex) and the open-bracket
|
||||
character. Now, on to the REAL details of ANSI music.
|
||||
|
||||
As I just got through saying, ANSI music starts with the
|
||||
characters <esc><open-bracket>. An ANSI music sequence ends with the
|
||||
character <control-N> (14 decimal, 0E hex). In between, the commands are
|
||||
exactly the same as those used for the "PLAY" command in BASIC. Now you
|
||||
can just look up the PLAY command and you know most everything you need
|
||||
to know about ANSI music. But for those of you still confused, I'll
|
||||
summarize the PLAY commands and give a few examples and pointers. Here
|
||||
we go:
|
||||
|
||||
The PLAY commands are pretty simple. This info was taken from the Tandy
|
||||
BASIC reference manual, but the Tandy-specific commands are not
|
||||
recognized by ANSI music and will be left out. Here we go again:
|
||||
|
||||
A - G Plays the notes corresponding to the notes A-G on the musical
|
||||
scale. A # or + after the note makes it sharp, and a - makes
|
||||
it flat.
|
||||
|
||||
Ln Sets the duration of the notes that follow. n is a number from
|
||||
1 to 64. 1 is a whole note, 2 is a half note, 4 is a quarter
|
||||
note, 8 is an eighth note, etc.
|
||||
|
||||
On Sets the current octave. There are 7 octaves, 0 through 6. The
|
||||
default octave is 4. Each octave starts with C and ends with B.
|
||||
Octave 3 starts with middle C.
|
||||
|
||||
Nn Plays a note. n is in the range 0 to 84. Instead of specifying
|
||||
the note's letter and octave, you may specify the note's number.
|
||||
Note zero is a rest.
|
||||
|
||||
Pn Plays a rest (if that's the right terminology). n is the same as
|
||||
for the L command, but specifies the length of the rest.
|
||||
|
||||
. Plays the note as a dotted note. You music buffs know that means
|
||||
that the note is one half it's length longer when dotted. Place
|
||||
the dot after the note, not before it. More than one dot may be
|
||||
used after a note, and dots may be specified for rests.
|
||||
|
||||
MF, MB I'm not sure these options work. Music Foreground and Music
|
||||
Background. Supposedly these options will let you specify
|
||||
MF and have the computer stop whatever it's doing and play
|
||||
the note, while MB lets the computer do whatever it was doing
|
||||
and play the note at the same time, kind of lo-tech multitasking.
|
||||
The default (for BASIC anyway, and it seems for ANSI-music) is
|
||||
Music Background.
|
||||
|
||||
MN "Music Normal." Each note plays 7/8 of the duration set by the
|
||||
L command.
|
||||
|
||||
ML "Music Legato." Each note plays the full duration as set by the
|
||||
L command.
|
||||
|
||||
MS "Music Staccato." Each note plays 3/4 of the duration set by the
|
||||
L command.
|
||||
|
||||
That's it for the basic set of commands. There are other options
|
||||
in BASIC that are unusuable in the ANSI music, such as the X command
|
||||
which lets you include a variable name in the play command, where a
|
||||
string variable name is given and the string contains a series of play
|
||||
commands. Another command which is usable only on a Tandy or other
|
||||
computer with the TI sound chip (the PCjr, for instance) is the V
|
||||
command, for setting the volume of the sound. Now for some examples.
|
||||
|
||||
<esc>[cdefgab<control-n> plays the notes "cdefgab" (the entire octave) on
|
||||
the default octave 4.
|
||||
|
||||
<esc>[l4al2cl8e<control-n> plays a quarter-note A, a half note C, and an
|
||||
eighth-note E. Not too musical, but an
|
||||
example nonetheless.
|
||||
|
||||
I'm not one for giving too many examples, I think that's plenty
|
||||
for you to get the basic idea. Try it in BASIC before you try it as an
|
||||
ANSI code in a message/picture. Just type PLAY "ABCDE" <return> and put
|
||||
whatever you like in the quotes. That's the easiest way to work out the
|
||||
notes and get the timing right before you blast it up to your favorite
|
||||
BBS.
|
||||
*********** Closing Comments ***********
|
||||
|
||||
I only know of two major comm programs that support ANSI music:
|
||||
TeliMate and Qmodem. I personally prefer TeliMate. If we (the collective
|
||||
we, that is) spread the use of ANSI music, hopefully the makers of other
|
||||
comm programs will incorporate this feature. If the makers of Telix and
|
||||
Procomm included this, that would cover 95% of IBM compatible BBS'ers. A
|
||||
new version of Telix is due out in a few months and I'm hoping this new
|
||||
version will add ANSI music. I gave up Procomm years ago, so I don't
|
||||
really know when a new version of that's due out, but it still seems to
|
||||
be the most common terminal program around. Still, TeliMate is gaining
|
||||
popularity for its mouse support and multitasking ablility (I wrote most
|
||||
of this document while downloading a 371k file at 1200 baud), and Qmodem
|
||||
is pretty popular already.
|
||||
252
study/sabre/os/files/Sound/MIDI/MIDIInstrumentPatchMap.txt
Normal file
252
study/sabre/os/files/Sound/MIDI/MIDIInstrumentPatchMap.txt
Normal file
@@ -0,0 +1,252 @@
|
||||
|
||||
**** Brief Overview of Proposed General MIDI Level 1 Spec ****
|
||||
|
||||
The heart of General MIDI (GM) is the _Instrument Patch Map_, shown in
|
||||
Table 1 (see below). This is a list of 128 sounds, with corresponding
|
||||
MIDI program numbers. Most of these are imitative sounds, though the
|
||||
list includes synth sounds, ethnic instruments and a handful of sound
|
||||
effects.
|
||||
The sounds fall roughtly into sixteen families of eight variations
|
||||
each. Grouping sounds makes it easy to re-orchestrate a piece using
|
||||
similar sounds. The Instrument Map isn't the final word on musical
|
||||
instruments of the world, but it's pretty complete
|
||||
General MIDI also includes a _Percusssion Key Map_, show in Table 2
|
||||
(see below). This mapping derives from the Roland/Sequential mapping
|
||||
used on early drum machines. As with the Instrument Map, it doesn't
|
||||
cover every percussive instrument in the world, but it's more than
|
||||
adequate as a basic set.
|
||||
To avoid concerns with channels, GM restricts percussion to MIDI
|
||||
Channel 10. Theoretically, the lower nine channels are for the
|
||||
instruments, but the GM spec states that a sound module must respond
|
||||
to all sixteen MIDI channels, with dynamic voice allocation and a
|
||||
minimum of 24 voices.
|
||||
General MIDI doesn't mention sound quality of synthesis methods.
|
||||
Discussions are under way on standardizing sound parameters such as
|
||||
playable range and envelope times. This will ensure that an arrangement
|
||||
that relies on phrsing and balance can play back on a variety of
|
||||
modules.
|
||||
Other requirements for a GM sound module include response to velocity,
|
||||
mod wheel, aftertouch, sustain and expression pedal, main volume and
|
||||
pan, and the All Notes Off and Reset All Controllers messages. The
|
||||
module also must respond to both Pitch Bend and Pitch Bend Sensitivity
|
||||
(a MIDI registered parameter). The default pitch bend range is +-2
|
||||
semitones.
|
||||
Middle C (C3) corresponds to MIDI key 60, and master tuning must be
|
||||
adjustable. Finally, the MIDI Manufacturers Association (MMA) created a
|
||||
new Universal System Exclusive message to turn General MIDI on and off
|
||||
(for devices that might have "consumer" and "programmable" settings).
|
||||
Table 3 (see below) summarizes these requirements.
|
||||
General MIDI has room for future expansion, including additional drum
|
||||
and instrument assignments and more required controllers. Also under
|
||||
discussion is an "authorizing document" that would standardize things
|
||||
such as channel assignments (e.g., lead on 1, bass on 2, etc.) and setup
|
||||
information in a MIDI file.
|
||||
|
||||
Copies of the Level 1 Specification documents for General MIDI ($5 each
|
||||
at last notice) are available from the Internation MIDI Association,
|
||||
5316 West 57th Street Los Angeles, CA 90056, (213) 649-6434. The first
|
||||
issue of the Journal of the MMA (back issues, $15 each) contains an
|
||||
article by PassPort Designs and Stanley Junglieb about General MIDI.
|
||||
|
||||
|
||||
Roland's GS Standard
|
||||
|
||||
When Warner New Media first proposed a General MIDI standard, most MMA
|
||||
members gave it little thought. As discussions proceeded, Roland
|
||||
listened and developed a sound module to meet the proposed
|
||||
specification. At the same NAMM show where the MMA ratified General MIDI
|
||||
Level 1, Roland showed their Sound Brush and Sound Canvas, a Standard
|
||||
MIDI File player and GM-compatible sound module.
|
||||
Some companies feel that General MIDI doesn't go far enough, so Roland
|
||||
created a superset of General MIDI Level 1, which they call GS Standard.
|
||||
It obeys all the protocols and sound maps of General MIDI and adds many
|
||||
extra controllers and sounds. Some of the controllers use Unregistered
|
||||
Parameter Numbers to give macro control over synth parameters such as
|
||||
envelope attack and decay rates.
|
||||
The new MIDI Bank Select message provides access to extra sounds
|
||||
(including variations on the stock sounds and a re-creation of the MT-32
|
||||
factory patches). The programs in each bank align with the original 128
|
||||
in General MIDI's Instrument Patch Map, with eight banks housing related
|
||||
families. The GS Standard includes a "fall back" system. If the Sound
|
||||
Canvas receives a request for a bank/program number combination that
|
||||
does not exist, it will reassign it to the master instrument in that
|
||||
family. A set of Roland System Exclusive messages allows reconfiguration
|
||||
and customization of the sound module.
|
||||
This means that a Roland GS Standard sound module will correctly play
|
||||
back any song designed for General MIDI. In addition, if the song's
|
||||
creator wants to create some extra nuance, they can include the GS
|
||||
Standard extensions in their sequence. None of these extensions are so
|
||||
radical as to make the song unplayable on a normal GM sound module.
|
||||
After all, compatibility is what MIDI - and especially General MIDI - is
|
||||
all about.
|
||||
Music authors interested in the GS Standard should contact Tom White
|
||||
at RolandCorp USA, 7200 Dominion Circle, Los Angeles, CA 90040, (213)
|
||||
685-5141.
|
||||
|
||||
**** TABLE 1 - General MIDI Instrument Patch Map ****
|
||||
(groups sounds into sixteen families, w/8 instruments in each family)
|
||||
|
||||
Prog# Instrument Prog# Instrument
|
||||
|
||||
(1-8 PIANO) (9-16 CHROM PERCUSSION)
|
||||
1 Acoustic Grand 9 Celesta
|
||||
2 Bright Acoustic 10 Glockenspiel
|
||||
3 Electric Grand 11 Music Box
|
||||
4 Honky-Tonk 12 Vibraphone
|
||||
5 Electric Piano 1 13 Marimba
|
||||
6 Electric Piano 2 14 Xylophone
|
||||
7 Harpsichord 15 Tubular Bells
|
||||
8 Clav 16 Dulcimer
|
||||
|
||||
(17-24 ORGAN) (25-32 GUITAR)
|
||||
17 Drawbar Organ 25 Acoustic Guitar(nylon)
|
||||
18 Percussive Organ 26 Acoustic Guitar(steel)
|
||||
19 Rock Organ 27 Electric Guitar(jazz)
|
||||
20 Church Organ 28 Electric Guitar(clean)
|
||||
21 Reed Organ 29 Electric Guitar(muted)
|
||||
22 Accoridan 30 Overdriven Guitar
|
||||
23 Harmonica 31 Distortion Guitar
|
||||
24 Tango Accordian 32 Guitar Harmonics
|
||||
|
||||
(33-40 BASS) (41-48 STRINGS)
|
||||
33 Acoustic Bass 41 Violin
|
||||
34 Electric Bass(finger) 42 Viola
|
||||
35 Electric Bass(pick) 43 Cello
|
||||
36 Fretless Bass 44 Contrabass
|
||||
37 Slap Bass 1 45 Tremolo Strings
|
||||
38 Slap Bass 2 46 Pizzicato Strings
|
||||
39 Synth Bass 1 47 Orchestral Strings
|
||||
40 Synth Bass 2 48 Timpani
|
||||
|
||||
(49-56 ENSEMBLE) (57-64 BRASS)
|
||||
49 String Ensemble 1 57 Trumpet
|
||||
50 String Ensemble 2 58 Trombone
|
||||
51 SynthStrings 1 59 Tuba
|
||||
52 SynthStrings 2 60 Muted Trumpet
|
||||
53 Choir Aahs 61 French Horn
|
||||
54 Voice Oohs 62 Brass Section
|
||||
55 Synth Voice 63 SynthBrass 1
|
||||
56 Orchestra Hit 64 SynthBrass 2
|
||||
|
||||
(65-72 REED) (73-80 PIPE)
|
||||
65 Soprano Sax 73 Piccolo
|
||||
66 Alto Sax 74 Flute
|
||||
67 Tenor Sax 75 Recorder
|
||||
68 Baritone Sax 76 Pan Flute
|
||||
69 Oboe 77 Blown Bottle
|
||||
70 English Horn 78 Skakuhachi
|
||||
71 Bassoon 79 Whistle
|
||||
72 Clarinet 80 Ocarina
|
||||
|
||||
(81-88 SYNTH LEAD) (89-96 SYNTH PAD)
|
||||
81 Lead 1 (square) 89 Pad 1 (new age)
|
||||
82 Lead 2 (sawtooth) 90 Pad 2 (warm)
|
||||
83 Lead 3 (calliope) 91 Pad 3 (polysynth)
|
||||
84 Lead 4 (chiff) 92 Pad 4 (choir)
|
||||
85 Lead 5 (charang) 93 Pad 5 (bowed)
|
||||
86 Lead 6 (voice) 94 Pad 6 (metallic)
|
||||
87 Lead 7 (fifths) 95 Pad 7 (halo)
|
||||
88 Lead 8 (bass+lead) 96 Pad 8 (sweep)
|
||||
|
||||
(97-104 SYNTH EFFECTS) (105-112 ETHNIC)
|
||||
97 FX 1 (rain) 105 Sitar
|
||||
98 FX 2 (soundtrack) 106 Banjo
|
||||
99 FX 3 (crystal) 107 Shamisen
|
||||
100 FX 4 (atmosphere) 108 Koto
|
||||
101 FX 5 (brightness) 109 Kalimba
|
||||
102 FX 6 (goblins) 110 Bagpipe
|
||||
103 FX 7 (echoes) 111 Fiddle
|
||||
104 FX 8 (sci-fi) 112 Shanai
|
||||
|
||||
(113-120 PERCUSSIVE) (121-128 SOUND EFFECTS)
|
||||
113 Tinkle Bell 121 Guitar Fret Noise
|
||||
114 Agogo 122 Breath Noise
|
||||
115 Steel Drums 123 Seashore
|
||||
116 Woodblock 124 Bird Tweet
|
||||
117 Taiko Drum 125 Telephone Ring
|
||||
118 Melodic Tom 126 Helicopter
|
||||
119 Synth Drum 127 Applause
|
||||
120 Reverse Cymbal 128 Gunshot
|
||||
|
||||
|
||||
**** TABLE 2 - General MIDI Percussion Key Map ****
|
||||
(assigns drum sounds to note numbers. MIDI Channel 10 is for percussion)
|
||||
|
||||
MIDI Drum Sound MIDI Drum Sound
|
||||
Key Key
|
||||
|
||||
35 Acoustic Bass Drum 59 Ride Cymbal 2
|
||||
36 Bass Drum 1 60 Hi Bongo
|
||||
37 Side Stick 61 Low Bongo
|
||||
38 Acoustic Snare 62 Mute Hi Conga
|
||||
39 Hand Clap 63 Open Hi Conga
|
||||
40 Electric Snare 64 Low Conga
|
||||
41 Low Floor Tom 65 High Timbale
|
||||
42 Closed Hi-Hat 66 Low Timbale
|
||||
43 High Floor Tom 67 High Agogo
|
||||
44 Pedal Hi-Hat 68 Low Agogo
|
||||
45 Low Tom 69 Cabasa
|
||||
46 Open Hi-Hat 70 Maracas
|
||||
47 Low-Mid Tom 71 Short Whistle
|
||||
48 Hi-Mid Tom 72 Long Whistle
|
||||
49 Crash Cymbal 1 73 Short Guiro
|
||||
50 High Tom 74 Long Guiro
|
||||
51 Ride Cymbal 1 75 Claves
|
||||
52 Chinese Cymbal 76 Hi Wood Block
|
||||
53 Ride Bell 77 Low Wood Block
|
||||
54 Tambourine 78 Mute Cuica
|
||||
55 Splash Cymbal 79 Open Cuica
|
||||
56 Cowbell 80 Mute Triangle
|
||||
57 Crash Cymbal 2 81 Open Triangle
|
||||
58 Vibraslap
|
||||
|
||||
|
||||
**** TABLE 3 - General MIDI minimum sound module specs ****
|
||||
|
||||
Voices:
|
||||
A minimum of either 24 fully dynamically allocated voices
|
||||
available simultaneously for both melodic and percussive sounds or 16
|
||||
dynamically allocated voices for melody plus eight for percussion.
|
||||
|
||||
Channels:
|
||||
General MIDI mode supports all sixteen MIDI channels. Each channel can
|
||||
play a variable number of voices (polyphony). Each channel can play a
|
||||
different instrument (timbre). Keybased Percussion is always on
|
||||
Channel 10.
|
||||
|
||||
Instruments:
|
||||
A minimum of sixteen different timbres playing various instrument
|
||||
sounds. A minimum of 128 preset for Intruments (MIDI program numbers).
|
||||
|
||||
Note on/Note off:
|
||||
Octabe Registration: Middle C(C3) = MIDI key 60. All Voices including
|
||||
percussion respond to velocity.
|
||||
|
||||
Controllers:
|
||||
Controller # Description
|
||||
1 Modulation
|
||||
7 Main Volume
|
||||
10 Pan
|
||||
11 Expression
|
||||
64 Sustain
|
||||
121 Reset All Controllers
|
||||
123 All Notes Off
|
||||
|
||||
Registered Description
|
||||
Parameter #
|
||||
0 Pitch Bend Sensitivity
|
||||
1 Fine Tuning
|
||||
2 Coarse Tuning
|
||||
|
||||
Additional Channel Messages:
|
||||
Channel Pressure (Aftertouch)
|
||||
Pitch Bend
|
||||
|
||||
Power-Up Defaults:
|
||||
Pitch Bend Amount = 0
|
||||
Pitch Bend Sensitivity = +-2 semitones
|
||||
Volume = 90
|
||||
All Other Controllers = reset
|
||||
|
||||
|
||||
|
||||
214
study/sabre/os/files/Sound/MIDI/MIDISampleDumpStandard.txt
Normal file
214
study/sabre/os/files/Sound/MIDI/MIDISampleDumpStandard.txt
Normal file
@@ -0,0 +1,214 @@
|
||||
MIDI SAMPLE DUMP STANDARD
|
||||
|
||||
1) INTRODUCTION
|
||||
|
||||
The MIDI SDS was adopted in January 1986 by the MIDI
|
||||
Manufacturers Association and the Japanese MIDI Standards Committee.
|
||||
The SDS defines the standard method for transfer of sound sample data
|
||||
between MIDI-equipped devices. Sample dumps may be accomplished with
|
||||
either an 'open loop' or 'closed loop' system. The open loop method
|
||||
simply involves the straight dump of all sample data from its source
|
||||
to the destination, with no timeouts, packet acknowledgements, or any
|
||||
other form of handshaking, much as in the manner of a sysex bulk dump,
|
||||
usually intiated at the source. The closed loop method allows the use
|
||||
of handshaking messages between the dump source and destination, and
|
||||
usually places the dump process under the control of the slave, to
|
||||
allow it time to process the incoming data as necessary. As with any
|
||||
standard, it can not be assumed that a device adheres to it unless the
|
||||
accompanying documentation specifically indicates it. Even then, it is
|
||||
best to check its conformity with non-critical data.
|
||||
|
||||
2) SPEC: SAMPLE DUMP FORMATS
|
||||
|
||||
DUMP HEADER:
|
||||
|
||||
F0 7E cc 01 ss ss ee ff ff ff gg gg gg hh hh hh ii ii ii jj F7
|
||||
|
||||
where
|
||||
|
||||
cc = channel number
|
||||
ss ss = sample number (LSB first)
|
||||
ee = sample format (number of significant bits; 8->28)
|
||||
ff ff ff = sample period (1/sample rate) in nanoseconds (LSB first)
|
||||
gg gg gg = sample length, in words
|
||||
hh hh hh = sustain loop start point (word number) (LSB first)
|
||||
ii ii ii = sustain loop end point (word number) (LSB first)
|
||||
jj = loop type (00:forwards only; 01:alternating)
|
||||
|
||||
DATA PACKET:
|
||||
|
||||
F0 7E cc 02 kk <120 bytes> mm F7
|
||||
|
||||
where
|
||||
|
||||
cc = channel number
|
||||
kk = running packet count (00->7F)
|
||||
mm = checksum (XOR of 7E, cc, 02, kk <120 bytes>)
|
||||
|
||||
The total size of a data packet is 127 bytes. This is to avoid
|
||||
overflow of the MIDI input buffer of a device that may want to receive
|
||||
an entire packet before processing it.
|
||||
A data packet consists of its own header, a packet number, 120
|
||||
bytes of data, a checksum, and an EOX. The packet number begins at 00
|
||||
and increments with each new packet. It resets to 00 after it reaches
|
||||
7F, and continues counting. The packet number is used by the receiver
|
||||
to distinguish between a new data packet, or a resend of a previous
|
||||
packet. The packet number is followed by 120 bytes of data, which form
|
||||
60, 40, or 30 words (MSB first for multiword samples), depending on
|
||||
the length of a single data sample.
|
||||
Each data byte hold seven bits, with the msb in each byte set to
|
||||
0, in order to conform to the requirements of MIDI data transmission.
|
||||
Information is left justified within the 7-bit bytes, and unused bits
|
||||
are filled with 0.
|
||||
Example: Assume a data point in the memory of a 16-bit sampler,
|
||||
with the value 87E5. In binary, that would be
|
||||
|
||||
1000 0111 1110 0101
|
||||
|
||||
and would be encoded as the following MIDI data stream:
|
||||
|
||||
01000011 01111001 00100000
|
||||
|
||||
The checksum is the running XOR of all the data after the SYSEX
|
||||
byte, up to but not including the checksum itself.
|
||||
|
||||
3) SPEC: SAMPLE DUMP MESSAGES
|
||||
|
||||
DUMP REQUEST:
|
||||
|
||||
F0 7E cc 03 ss ss F7
|
||||
|
||||
where
|
||||
|
||||
cc = channel number
|
||||
ss ss = sample number requested (LSB first)
|
||||
|
||||
Upon receiving the request, the sampler checks the sample number
|
||||
to see if it is within legal range. If it is not, the request is
|
||||
ignored. If it is, the sample dump is started. One packet at a time is
|
||||
sent, under control of the handshaking messages outlined below.
|
||||
|
||||
HANDSHAKING MESSAGES:
|
||||
|
||||
For all below:
|
||||
|
||||
cc = channel number
|
||||
pp = packet number
|
||||
|
||||
Packet numbers are included in the handshaking messages to
|
||||
accomodate machines that have the intelligence to re-transmit specific
|
||||
packets after an entire dump is finished, or if synchronization is
|
||||
lost.
|
||||
|
||||
ACK : F0 7E cc 7F pp F7
|
||||
|
||||
Means last packet was recieved correctly (checksum OK, etc),
|
||||
please send next one. Packet number is packet being acknowledged as
|
||||
correct.
|
||||
|
||||
NAK : F0 7E cc 7E pp F7
|
||||
|
||||
Means last packet not received correctly, please send again.
|
||||
Packet number is packet being rejected.
|
||||
|
||||
CANCEL : F0 7E cc 7D pp F7
|
||||
|
||||
Means abort dump immediately. Packet number is packet on which
|
||||
abort occurs.
|
||||
|
||||
WAIT : F0 7E cc 7C pp F7
|
||||
|
||||
Means pause dump indefinitely, until next message is sent. Allows
|
||||
the unit recieving the dump to perform other functions (disk access,
|
||||
etc), before receiving the remainder of the dump. The next message it
|
||||
sends (eg ACK, ABORT) will determine if the dump continues or aborts.
|
||||
|
||||
4) DUMP PROCEDURE: MASTER (DUMP SOURCE)
|
||||
|
||||
Once a dump has been requested, either via MIDI or through the
|
||||
front panel, the DUMP HEADER is sent. After sending the header, the
|
||||
master must time out for at least two seconds, to allow the receiver
|
||||
to decide if it will accept this sample (has enough memory, etc).
|
||||
If it receives a CANCEL, within this time, it should abort
|
||||
immediately. If it receives an CAK, it will start sending packets
|
||||
immediately. If it receives a WAIT, it pauses until another message is
|
||||
received, and then processes that mesage normally. If nothing is
|
||||
recieved within the timeout, an open loop is assumed, and the dump
|
||||
starts with the first packet.
|
||||
After sending each packet, the master should time out for at
|
||||
least 20 milliseconds and watch its MIDI In. If an ACK is received, it
|
||||
sends the next packet immediately. If it receives an NAK, and the
|
||||
packet number matches the number of the last packet sent, it resend
|
||||
that packet If the packet numbers don't match, and the device is
|
||||
incapable of sending packets out of order, the NAK will be ignored.
|
||||
If a WAIT is received, the master should watch its MIDI In port
|
||||
indefinitely for another ACK, NAK, or CANCEL message, which it should
|
||||
then process normally.
|
||||
If no messages are received within 20 milliseconds of the
|
||||
transmission of a packet, the master may assume an open loop
|
||||
configuration, and send the next packet.
|
||||
This process continues until there are less than 121 data bytes
|
||||
to send. The final packet will still consist of 120n bytes, regardless
|
||||
of how many significant bytes actually remain, and the unused bytes
|
||||
will be filled with zeroes. The receiver should handshake after
|
||||
receiving the last packet.
|
||||
|
||||
5) DUMP PROCEDURE: SLAVE (DUMP DESTINATION)
|
||||
|
||||
When receiving a sample dump, a device should keep a running
|
||||
checksum during reception. If its checksum matches the checksum in the
|
||||
data packet, it will send an ACK and wait for the next packet. If it
|
||||
does not match, it will send an NAK containing the number of the
|
||||
packet that caused the error, and wait for the next packet. If, after
|
||||
sending an NAK, the packet number of the next packet doesn't match the
|
||||
previous packet number (the one that was NAK'd), and the unit is not
|
||||
capable of accepting packets out of order, the error is ignored and
|
||||
the dump continues as if the checksums had matched.
|
||||
If a receiver runs out of memory before the dumpo is completed,
|
||||
it should send a CANCEL to stop the dump.
|
||||
|
||||
6) SDS OVERVIEW
|
||||
|
||||
SAMPLE DUMP DATA FORMAT: DUMP HEADER:
|
||||
|
||||
Sysex
|
||||
ID: Universal Non-Real Time
|
||||
Channel Number
|
||||
Sub ID: Header
|
||||
Sample Number (2 bytes, LSB first)
|
||||
Sample Format
|
||||
Sample Period (3 bytes, LSB first)
|
||||
Sample Length (3 bytes, LSB first)
|
||||
Sustain Loop Start Point (3 bytes, LSB first)
|
||||
Sustain Loop End Point (3 bytes, LSB first)
|
||||
Loop Type
|
||||
Eox
|
||||
|
||||
SAMPLE DUMP DATA FORMAT: DATA PACKET:
|
||||
|
||||
Sysex
|
||||
ID: Universal Non-Real Time
|
||||
Channel Number
|
||||
Sub ID: Data Packet
|
||||
Packet Number
|
||||
Sample Data (120 bytes)
|
||||
Checksum
|
||||
Eox
|
||||
|
||||
SAMPLE DUMP MESSAGES: DUMP REQUEST:
|
||||
|
||||
Sysex
|
||||
ID: Universal Non-Real Time
|
||||
Channel Number
|
||||
Sub ID: Dump Request
|
||||
Sample Number (2 bytes, LSB first)
|
||||
Eox
|
||||
|
||||
SAMPLE DUMP MESSAGES: HANDSHAKING FLAGS:
|
||||
|
||||
Sysex
|
||||
ID: Universal Non-Real Time
|
||||
Channel Number
|
||||
Sub ID: ACK or NAK or CANCEL or WAIT
|
||||
Packet Number
|
||||
Eox
|
||||
171
study/sabre/os/files/Sound/MIDI/MIDIStreamSpec1.00.txt
Normal file
171
study/sabre/os/files/Sound/MIDI/MIDIStreamSpec1.00.txt
Normal file
@@ -0,0 +1,171 @@
|
||||
MIDI 1.0 Specification:
|
||||
|
||||
Status Data Byte(s) Description
|
||||
D7----D0 D7----D0
|
||||
-------------------------------------------------------------------------
|
||||
Channel Voice Messages
|
||||
-------------------------------------------------------------------------
|
||||
1000cccc 0nnnnnnn Note Off event.
|
||||
0vvvvvvv This message is sent when a
|
||||
note is released (ended).
|
||||
(nnnnnnn) is the note number.
|
||||
(vvvvvvv) is the velocity.
|
||||
|
||||
1001cccc 0nnnnnnn Note On event.
|
||||
0vvvvvvv This message is sent when a
|
||||
note is depressed (start).
|
||||
(nnnnnnn) is the note number.
|
||||
(vvvvvvv) is the velocity.
|
||||
|
||||
1010cccc 0nnnnnnn Polyphonic Key Pressure (After-touch).
|
||||
0vvvvvvv This message is sent when the pressure
|
||||
(velocity) of a previously
|
||||
triggered note changes.
|
||||
(nnnnnnn) is the note number.
|
||||
(vvvvvvv) is the new velocity.
|
||||
|
||||
1011cccc 0ccccccc Control Change.
|
||||
0vvvvvvv This message is sent when a controller
|
||||
value changes. Controllers include devices
|
||||
such as pedals and levers.
|
||||
Certain controller numbers are reserved
|
||||
for specific purposes. See Channel Mode Messages.
|
||||
(ccccccc) is the controller number.
|
||||
(vvvvvvv) is the new value.
|
||||
|
||||
1100cccc 0ppppppp Program Change.
|
||||
This message sent when the patch number changes.
|
||||
(ppppppp) is the new program number.
|
||||
|
||||
1101nnnn 0ccccccc Channel Pressure (After-touch).
|
||||
This message is sent when the channel pressure
|
||||
changes. Some velocity-sensing keyboards do not
|
||||
support polyphonic after-touch. Use this
|
||||
message to send the single greatest velocity
|
||||
(of all te current depressed keys).
|
||||
(ccccccc) is the channel number.
|
||||
|
||||
1110nnnn 0lllllll Pitch Wheel Change.
|
||||
0mmmmmmm This message is sent to indicate a change in the
|
||||
pitch wheel. The pitch wheel is measured by a
|
||||
fourteen bit value. Center (no pitch change) is
|
||||
2000H. Sensitivity is a function of the
|
||||
transmitter.
|
||||
(llllll) are the least significant 7 bits.
|
||||
(mmmmmm) are the most significant 7 bits.
|
||||
-------------------------------------------------------------------------
|
||||
Channel Mode Messages (See also Control Change, above)
|
||||
-------------------------------------------------------------------------
|
||||
1011nnnn 0ccccccc Channel Mode Messages.
|
||||
0vvvvvvv This the same code as the Control
|
||||
Change (above), but implements Mode
|
||||
control by using reserved controller
|
||||
numbers. The numbers are:
|
||||
|
||||
Local Control.
|
||||
When Local Control is Off, all devices
|
||||
on a given channel will respond only to
|
||||
data received over MIDI. Played data, etc.
|
||||
will be ignored. Local Control On
|
||||
restores the functions of the normal
|
||||
controllers.
|
||||
c = 122, v = 0: Local Control Off
|
||||
c = 122, v = 127: Local Control On
|
||||
|
||||
All Notes Off.
|
||||
When an All Notes Off is received,
|
||||
all oscillators will turn off.
|
||||
c = 123, v = 0: All Notes Off
|
||||
|
||||
(See text for description of actual
|
||||
mode commands.)
|
||||
c = 124, v = 0: Omni Mode Off
|
||||
c = 125, v = 0: Omni Mode On
|
||||
c = 126, v = M: Mono Mode On (Poly Off)
|
||||
where M is the number of channels
|
||||
(Omni Off) or 0 (Omni On)
|
||||
c = 127, v = 0: Poly Mode On (Mono Off)
|
||||
(Note: These four messages also cause
|
||||
All Notes Off)
|
||||
.pa
|
||||
-------------------------------------------------------------------------
|
||||
System Common Messages
|
||||
-------------------------------------------------------------------------
|
||||
11110000 0iiiiiii System Exclusive.
|
||||
0ddddddd This message makes up for all that MIDI
|
||||
.. doesn't support. (iiiiiii) is a seven
|
||||
.. bit Manufacturer's I.D. code. If the
|
||||
0ddddddd synthesizer recognizes the I.D. code as
|
||||
11110111 its own, it will listen to the rest of
|
||||
the message (ddddddd). Otherwise, the
|
||||
message will be ignored. System Exclusive
|
||||
is used to send bulk dumps such as patch
|
||||
parameters and other non-spec data.
|
||||
(Note: Real-Time messages ONLY may be
|
||||
interleaved with a System Exclusive.)
|
||||
|
||||
11110001 Undefined.
|
||||
|
||||
11110010 0lllllll Song Position Pointer.
|
||||
0mmmmmmm This is an internal 14 bit register that
|
||||
holds the number of MIDI beats (1 beat=
|
||||
six MIDI clocks) since the start of
|
||||
the song. l is the LSB, m the MSB.
|
||||
|
||||
11110011 0sssssss Song Select.
|
||||
The Song Select specifies which sequence
|
||||
or song is to be played.
|
||||
|
||||
11110100 Undefined.
|
||||
|
||||
11110101 Undefined.
|
||||
|
||||
11110110 Tune Request.
|
||||
Upon receiving a Tune Request, all analog
|
||||
sythesizers should tune their oscillators.
|
||||
|
||||
11110111 End of Exclusive.
|
||||
Used to terminate a System Exclusive
|
||||
dump (see above).
|
||||
.pa
|
||||
-------------------------------------------------------------------------
|
||||
System Real-Time Messages
|
||||
-------------------------------------------------------------------------
|
||||
11111000 Timing Clock.
|
||||
Sent 24 times per quarter note when
|
||||
synchronization is required (see text).
|
||||
|
||||
11111001 Undefined.
|
||||
|
||||
11111010 Start.
|
||||
Start the current sequence playing.
|
||||
(This message will be followed with
|
||||
Timing Clocks).
|
||||
|
||||
11111011 Continue.
|
||||
Continue at the point the sequence was
|
||||
Stopped.
|
||||
|
||||
11111100 Stop.
|
||||
Stop the current sequence.
|
||||
|
||||
11111101 Undefined.
|
||||
|
||||
11111110 Active Sensing.
|
||||
Use of this message is optional. When
|
||||
initially sent, the receiver will expect
|
||||
to receive another Active Sensing message
|
||||
each 300ms (max), or it will be assume
|
||||
that the connection has been terminated.
|
||||
At termination, the receiver will turn off
|
||||
all voices and return to normal (non-
|
||||
active sensing) operation.
|
||||
|
||||
11111111 Reset.
|
||||
Reset all receivers in the system to
|
||||
power-up status. This should be used
|
||||
sparingly, preferably under manual
|
||||
control. In particular, it should not
|
||||
be sent on power-up.
|
||||
|
||||
-- Greg, lee@uhccux.uhcc.hawaii.edu
|
||||
@@ -0,0 +1,689 @@
|
||||
Standard MIDI-File Format Spec. 1.1
|
||||
|
||||
1 - Sequences, Tracks, Chunks: File Block Structure
|
||||
|
||||
CONVENTIONS
|
||||
|
||||
Some numbers in MIDI Files are represented is a form called VARIABLE-LENGTH
|
||||
QUANTITY. These numbers are represented 7 bits per byte, most significant
|
||||
bits first. All bytes except the last have bit 7 set, and the last byte has
|
||||
bit 7 clear. If the number is between 0 and 127, it is thus represented
|
||||
exactly as one byte.
|
||||
|
||||
|
||||
Here are some examples of numbers represented as variable-length
|
||||
quantities:
|
||||
|
||||
00000000 00
|
||||
00000040 40
|
||||
0000007F 7F
|
||||
00000080 81 00
|
||||
00002000 C0 00
|
||||
00003FFF FF 7F
|
||||
00004000 81 80 00
|
||||
00100000 C0 80 00
|
||||
001FFFFF FF FF 7F
|
||||
00200000 81 80 80 00
|
||||
08000000 C0 80 80 00
|
||||
0FFFFFFF FF FF FF 7F
|
||||
|
||||
The largest number which is allowed is 0FFFFFFF so that the variable-length
|
||||
representations must fit in 32 bits in a routine to write variable-length
|
||||
numbers. Theoretically, larger numbers are possible, but 2 x 10^8 96ths of
|
||||
a beat at a fast tempo of 500 beats per minute is four days, long enough
|
||||
for any delta-time!
|
||||
|
||||
FILES
|
||||
To any file system, a MIDI File is simply a series of 8-bit bytes. On the
|
||||
Macintosh, this byte stream is stored in the data fork of a file (with file
|
||||
type 'MIDI'), or on the Clipboard (with data type 'MIDI'). Most other
|
||||
computers store 8-bit byte streams in files -- naming or storage
|
||||
conventions for those computers will be defined as required.
|
||||
|
||||
|
||||
CHUNKS
|
||||
MIDI Files are made up of -chunks-. Each chunk has a 4-character type and a
|
||||
32-bit length, which is the number of bytes in the chunk. This structure
|
||||
allows future chunk types to be designed which may be easily be ignored if
|
||||
encountered by a program written before teh chunk type is introduced. Your
|
||||
programs should EXPECT alien chunks and treat them as if they weren't
|
||||
there.
|
||||
|
||||
Each chunk begins with a 4-character ASCII type. It is followed by a 32-bit
|
||||
length, most significant byte first (a length of 6 is stored as 00 00 00
|
||||
06). This length refers to the number of bytes of data which follow: the
|
||||
eight bytes of type and length are not included. Therefore, a chunk with a
|
||||
length of 6 would actually occupy 14 bytes in the disk file.
|
||||
|
||||
This chunk architecture is similar to that used by Electronic Arts' IFF
|
||||
format, and the chunks described herin could easily be placed in an IFF
|
||||
file. The MIDI File itself is not an IFF file: it contains no nested
|
||||
chunks, and chunks are not constrained to be an even number of bytes long.
|
||||
Converting it to an IFF file is as easy as padding odd length chunks, and
|
||||
sticking the whole thing inside a FORM chunk.
|
||||
|
||||
MIDI Files contain two types of chunks: header chunks and track chunks. A
|
||||
-header- chunk provides a minimal amount of information pertaining to the
|
||||
entire MIDI file. A -track- chunk contains a sequential stream of MIDI data
|
||||
which may contain information for up to 16 MIDI channels. The concepts of
|
||||
multiple tracks, multiple MIDI outputs, patterns, sequences, and songs may
|
||||
all be implemented using several track chunks.
|
||||
|
||||
A MIDI File always starts with a header chunk, and is followed by one or
|
||||
more track chunks.
|
||||
|
||||
MThd <length of header data>
|
||||
<header data>
|
||||
MTrk <length of track data>
|
||||
<track data>
|
||||
MTrk <length of track data>
|
||||
<track data>
|
||||
. . .
|
||||
|
||||
|
||||
2 - Chunk Descriptions
|
||||
|
||||
HEADER CHUNKS
|
||||
The header chunk at the beginning of the file specifies some basic
|
||||
information about the data in the file. Here's the syntax of the complete
|
||||
chunk:
|
||||
|
||||
<Header Chunk> = <chunk type><length><format><ntrks><division>
|
||||
|
||||
As described above, <chunk type> is the four ASCII characters 'MThd';
|
||||
<length> is a 32-bit representation of the number 6 (high byte first).
|
||||
|
||||
The data section contains three 16-bit words, stored most-significant byte
|
||||
first.
|
||||
|
||||
The first word, <format>, specifies the overall organization of the file.
|
||||
Only three values of <format> are specified:
|
||||
|
||||
0-the file contains a single multi-channel track
|
||||
1-the file contains one or more simultanious tracks (or MIDI outputs) of a
|
||||
sequence
|
||||
2-the file contains one or more sequentially independant single-track
|
||||
patterns
|
||||
|
||||
More information about these formats is provided below.
|
||||
|
||||
The next word, <ntrks>, is the number of track chunks in the file. It will
|
||||
always be 1 for a format 0 file.
|
||||
|
||||
The third word, <division>, specifies the meaning of the delta-times. It
|
||||
has two formats, one for metrical time, and one for time-code-based time:
|
||||
|
||||
+---+-----------------------------------------+
|
||||
| 0 | ticks per quarter-note |
|
||||
==============================================|
|
||||
| 1 | negative SMPTE format | ticks per frame |
|
||||
+---+-----------------------+-----------------+
|
||||
|15 |14 8 |7 0 |
|
||||
|
||||
If bit 15 of <division> is zero, the bits 14 thru 0 represent the number of
|
||||
delta time "ticks" which make up a quarter-note. For instance, if division
|
||||
is 96, then a time interval of an eighth-note between two events in the
|
||||
file would be 48.
|
||||
|
||||
|
||||
If bit 15 of <division> is a one, delta times in a file correspond to
|
||||
subdivisions of a second, in a way consistent with SMPTE and MIDI Time
|
||||
Code. Bits 14 thru 8 contain one of the four values -24, -25, -29, or -30,
|
||||
corresponding to the four standard SMPTE and MIDI Time Code formats (-29
|
||||
corresponds to 30 drop frome), and represents the number of frames per
|
||||
second. These negative numbers are stored in two's compliment form. The
|
||||
second byte (stored positive) is the resolution within a frame: typical
|
||||
values may be 4 (MIDI Time Code resolution), 8, 10, 80 (bit resolution), or
|
||||
100. This stream allows exact specifications of time-code-based tracks, but
|
||||
also allows milisecond-based tracks by specifying 25|frames/sec and a
|
||||
resolution of 40 units per frame. If the events in a file are stored with a
|
||||
bit resolution of thirty-framel time code, the division word would be E250
|
||||
hex.
|
||||
|
||||
FORMATS 0, 1, AND 2
|
||||
A Format 0 file has a header chunk followed by one track chunk. It is the
|
||||
most interchangable representation of data. It is very useful for a simple
|
||||
single-track player in a program which needs to make synthesizers make
|
||||
sounds, but which is primarily concerened with something else such as
|
||||
mixers or sound effect boxes. It is very desirable to be able to produce
|
||||
such a format, even if your program is track-based, in order to work with
|
||||
these simple programs. On the other hand, perhaps someone will write a
|
||||
format conversion from format 1 to format 0 which might be so easy to use
|
||||
in some setting that it would save you the trouble of putting it into your
|
||||
program.
|
||||
|
||||
A Format 1 or 2 file has a header chunk followed by one or more track
|
||||
chunks. programs which support several simultanious tracks should be able
|
||||
to save and read data in format 1, a vertically one-dementional form, that
|
||||
is, as a collection of tracks. Programs which support several independant
|
||||
patterns should be able to save and read data in format 2, a horizontally
|
||||
one-dementional form. Providing these minimum capabilities will ensure
|
||||
maximum interchangability.
|
||||
|
||||
In a MIDI system with a computer and a SMPTE synchronizer which uses Song
|
||||
Pointer and Timing Clock, tempo maps (which describe the tempo throughout
|
||||
the track, and may also include time signature information, so that the bar
|
||||
number may be derived) are generally created on the computer. To use them
|
||||
with the synchronizer, it is necessary to transfer them from the computer.
|
||||
To make it easy for the synchronizer to extract this data from a MIDI File,
|
||||
tempo information should always be stored in the first MTrk chunk. For a
|
||||
format 0 file, the tempo will be scattered through the track and the tempo
|
||||
map reader should ignore the intervening events; for a format 1 file, the
|
||||
tempo map must be stored as the first track. It is polite to a tempo map
|
||||
reader to offerr your user the ability to make a format 0 file with just
|
||||
the tempo, unless you can use format 1.
|
||||
|
||||
All MIDI Files should specify tempo and time signature. If they donn't, the
|
||||
time signature is assumed to be 4/4, and the tempo 120 beats per minute. In
|
||||
format 0, these meta-events should occur at least at the beginning of the
|
||||
single multi-channel track. In format 1, these meta-events should be
|
||||
contained i| the first track. In format 2, each of the temporally
|
||||
independant patterns should contain at least initial time signature and
|
||||
tempo information.
|
||||
|
||||
We may decide to define other format IDs to support other structures. A
|
||||
program encountering an unknown format ID may still read other MTrk chunks
|
||||
it finds from the file, as format 1 or 2, if its user can make sense of
|
||||
them and arrange them into some other structure if appropriate. Also, more
|
||||
parameters may be added to the MThd chunk in the future: it is important to
|
||||
read and honor the length, even if it is longer than 6.
|
||||
|
||||
TRACK CHUNKS
|
||||
The track chunks (type MTrk) are where actual song data is stored. Each
|
||||
track chunk is simply a stream of MIDI events (and non-MIDI events),
|
||||
preceded by delta-time values. The format for Track Chunks (described
|
||||
below) is exactly the same for all three formats (0, 1, and 2: see "Header
|
||||
Chunk" above) of MIDI Files.
|
||||
|
||||
Here is the syntax of an MTrk chunk (the + means "one or more": at least
|
||||
one MTrk event must be present):
|
||||
|
||||
<Track Chunk> = <chunk type><length><MTrk event>+
|
||||
|
||||
The syntax of an MTrk event is very simple:
|
||||
|
||||
<MTrk event> = <delta-time><event>
|
||||
|
||||
<delta-time> is stored as a variable-length quantity. It represents the
|
||||
amount of time before the following event. If the first event in a track
|
||||
occurs at the very beginning of a track, or if two events occur
|
||||
simultaineously, a delta-time of zero is used. Delta-times are always
|
||||
present. (Not storing delta-times of 0 requires at least two bytes for any
|
||||
other value, and most delta-times aren't zero.) Delta-time is in some
|
||||
fraction of a beat (or a second, for recording a track with SMPTE times),
|
||||
as specified in the header chunk.
|
||||
|
||||
<event> = <MIDI event> | <sysex event> | <meta-event>
|
||||
|
||||
<MIDI event> is any MIDI channel message. Running status is used: status
|
||||
bytes of MIDI channel messages may be omitted if the preceding event is a
|
||||
MIDI channel message with the same status. The first event in each MTrk
|
||||
chunk must specifyy status. Delta-time is not considered an event itself:
|
||||
it is an integral part of the syntax for an MTrk event. Notice that running
|
||||
status occurs across delta-times.
|
||||
|
||||
<sysex event> is used to specify a MIDI system exclusive message, either as
|
||||
one unit or in packets, or as an "escape" to specify any arbitrary bytes to
|
||||
be transmitted. A normal complete system exclusive message is stored in a
|
||||
MIDI File in this way:
|
||||
|
||||
F0 <length> <bytes to be transmitted after F0>
|
||||
|
||||
The length is stored as a variable-length quantity. It specifies the number
|
||||
of bytes which follow it, not including the F0 or the length itself. For
|
||||
instance, the transmitted message F0 43 12 00 07 F7 would be stored in a
|
||||
MIDI File as F0 05 43 12 00 07 F7. It is required to include the F7 at the
|
||||
end so that the reader of the MIDI File knows that it has read the entire
|
||||
message.
|
||||
|
||||
Another form of sysex event is provided which does not imply that an F0
|
||||
should be transmitted. This may be used as an "escape" to provide for the
|
||||
transmission of things which would not otherwise be legal, including system
|
||||
realtime messages, song pointer or select, MIDI Time Code, etc. This uses
|
||||
the F7 code:
|
||||
|
||||
F7 <length> <all bytes to be transmitted>
|
||||
|
||||
Unfortunately, some synthesizer manufacturers specify that their system
|
||||
exclusive messages are to be transmitted as little packets. Each packet is
|
||||
only part of an entire syntactical system exclusive message, but the times
|
||||
they are transmitted are important. Examples of this are the bytes sent in
|
||||
a CZ patch dump, or the FB-01's "system exclusive mode" in which microtonal
|
||||
data can be transmitted. The F0 and F7 sysex events may be used together to
|
||||
break up syntactically complete system exclusive messages into timed
|
||||
packets.
|
||||
|
||||
An F0 sysex event is used for the first packet in a series -- it is a
|
||||
message in which the F0 should be transmitted. An F7 sysex event is used
|
||||
for the remainder of the packets, which do not begin with F0. (Of course,
|
||||
the F7 is not considered part of the system exclusive message).
|
||||
|
||||
A syntactic system exclusive message must always end with an F7, even if
|
||||
the real-life device didn't send one, so that you know when you've reached
|
||||
the end of an entire sysex message without looking ahead to the next event
|
||||
in the MIDI File. If it's stored in one compllete F0 sysex event, the last
|
||||
byte must be an F7. There also must not be any transmittable MIDI events in
|
||||
between the packets of a multi-packet system exclusive message. This
|
||||
principle is illustrated in the paragraph below.
|
||||
|
||||
Here is a MIDI File of a multi-packet system exclusive message: suppose the
|
||||
bytes F0 43 12 00 were to be sent, followed by a 200-tick delay, followed
|
||||
by the bytes 43 12 00 43 12 00, followed by a 100-tick delay, followed by
|
||||
the bytes 43 12 00 F7, this would be in the MIDI File:
|
||||
|
||||
F0 03 43 12 00
|
||||
81 48 200-tick delta time
|
||||
F7 06 43 12 00 43 12 00
|
||||
64 100-tick delta time
|
||||
F7 04 43 12 00 F7
|
||||
|
||||
|
||||
When reading a MIDI File, and an F7 sysex event is encountered without a
|
||||
preceding F0 sysex event to start a multi-packet system exclusive message
|
||||
sequence, it should be presumed that the F7 event is being used as an
|
||||
"escape". In this case, it is not necessary that it end with an F7, unless
|
||||
it is desired that the F7 be transmitted.
|
||||
|
||||
|
||||
<meta-event> specifies non-MIDI information useful to this format or to
|
||||
sequencers, with this syntax:
|
||||
|
||||
FF <type> <length> <bytes>
|
||||
|
||||
All meta-events begin with FF, then have an event type byte (which is
|
||||
always less than 128), and then have the length of the data stored as a
|
||||
variable-length quantity, and then the data itself. If there is no data,
|
||||
the length is 0. As with chunks, future meta-events may be designed which
|
||||
may not be known to existing programs, so programs must properly ignore
|
||||
meta-events which they do not recognize, and indeed should expect to see
|
||||
them. Programs must never ignore the length of a meta-event which they do
|
||||
not recognize, and they shouldn't be surprized if it's bigger than
|
||||
expected. If so, they must ignore everything past what they know about.
|
||||
However, they must not add anything of their own to the end of the meta-
|
||||
event.
|
||||
Sysex events and meta events cancel any running status which was in effect.
|
||||
Running status does not apply to and may not be used for these messages.
|
||||
|
||||
|
||||
3 - Meta-Events
|
||||
|
||||
A few meta-events are defined herin. It is not required for every program
|
||||
to support every meta-event.
|
||||
|
||||
In the syntax descriptions for each of the meta-events a set of conventions
|
||||
is used to describe parameters of the events. The FF which begins each
|
||||
event, the type of each event, and the lengths of events which do not have
|
||||
a variable amount of data are given directly in hexadecimal. A notation
|
||||
such as dd or se, which consists of two lower-case letters, mnemonically
|
||||
represents an 8-bit value. Four identical lower-case letters such as wwww
|
||||
mnemonically refer to a 16-bit value, stored most-significant-byte first.
|
||||
Six identical lower-case letters such as tttttt refer to a 24-bit value,
|
||||
stored most-significan-byte first. The notation len refers to teh length
|
||||
portion of the meta-event syntax, that is, a number, stored as a variable-
|
||||
length quantity, which specifies how many bytes (possibly text) data were
|
||||
just specified by the length.
|
||||
|
||||
In general, meta-events in a track which occur at the same time may occur
|
||||
in any order. If a copyright event is used, it should be placed as early as
|
||||
possible in the file, so it will be noticed easily. Sequence Number and
|
||||
Sequence/Track Name events, if present, must appear at time 0. An end-of-
|
||||
track event must occur as the last event in the track.
|
||||
|
||||
Meta-events initially defined include:
|
||||
|
||||
FF 00 02 Sequence Number
|
||||
This optional event, which must occur at the beginning of a track,
|
||||
before any nonzero delta-times, and before any transmittable MIDI
|
||||
events, specifies the number of a sequence. In a format 2 MIDI File, it
|
||||
is used to identify each "pattern" so that a "song" sequence using the
|
||||
Cue message to refer to the patterns. If the ID numbers are omitted,
|
||||
the sequences' lacations in order in the file are used as defaults. In
|
||||
a format 0 or 1 MIDI File, which only contain one sequence, this number
|
||||
should be contained in the first (or only) track. If transfer of
|
||||
several multitrack sequences is required, this must be done as a group
|
||||
of format 1 files, each with a different sequence number.
|
||||
|
||||
FF 01 len text Text Event
|
||||
Any amount of text describing anything. It is a good idea to put a text
|
||||
event right at the beginning of a track, with the name of the track, a
|
||||
description of its intended orchestration, and any other information
|
||||
which the user wants to put there. Text events may also occur at other
|
||||
times in a track, to be used as lyrics, or descriptions of cue points.
|
||||
The text in this event should be printable ASCII characters for maximum
|
||||
interchange. However, other characters codes using the high-order bit
|
||||
may be used for interchange of files between different programs on the
|
||||
same computer which supports an extended character set. Programs on a
|
||||
computer which does not support non-ASCII characters should ignore
|
||||
those characters.
|
||||
|
||||
Meta-event types 01 through 0F are reserved for various types of text
|
||||
events, each of which meets the specification of text events (above)
|
||||
but is used for a different purpose:
|
||||
|
||||
FF 02 len text Copyright Notice
|
||||
Contains a copyright notice as printable ASCII text. The notice should
|
||||
contain the characters (C), the year of the copyright, and the owner of
|
||||
the copyright. If several pieces of music are in the same MIDI File,
|
||||
all of the copyright notices should be placed together in this event so
|
||||
that it will be at the beginning of the file. This event should be the
|
||||
first event in the track chunk, at time 0.
|
||||
|
||||
FF 03 len text Sequence/Track Name
|
||||
If in a format 0 track, or the first track in a format 1 file, the name
|
||||
of the sequence. Otherwise, the name of the track.
|
||||
|
||||
FF 04 len text Instrument Name
|
||||
A description of the type of instrumentation to be used in that track.
|
||||
May be used with the MIDI Prefix meta-event to specify which MIDI
|
||||
channel the description applies to, or the channel may be specified as
|
||||
text in the event itself.
|
||||
|
||||
FF 05 len text Lyric
|
||||
A lyric to be sung. Generally, each syllable will be a seperate lyric
|
||||
event which begins at the event's time.
|
||||
|
||||
FF 06 len text Marker
|
||||
Normally in a format 0 track, or the first track in a format 1 file.
|
||||
The name of that point in the sequence, such as a rehersal letter or
|
||||
section name ("First Verse", etc.)
|
||||
|
||||
FF 07 len text Cue Point
|
||||
A description of something happening on a film or video screen or stage
|
||||
at that point in the musical score ("Car crashes into house",
|
||||
"curtain opens", "she slaps his face", etc.)
|
||||
|
||||
FF 20 01 cc MIDI Channeel Prefix
|
||||
The MIDI channel (0-15) containted in this event may be used to
|
||||
associate a MIDI channel with all events which follow, including System
|
||||
exclusive and meta-events. This channel is "effective" until the next
|
||||
normal MIDI event (which contains a channel) or the next MIDI Channel
|
||||
Prefix meta-event. If MIDI channels refer to "tracks", this message may
|
||||
into a format 0 file, keeping their non-MIDI data associated with a
|
||||
track. This capability is also present in Yamaha's ESEQ file format.
|
||||
|
||||
FF 2F 00 End of Track
|
||||
This event is not optional. It is included so that an exact ending
|
||||
point may be specified for the track, so that an exect length, which is
|
||||
necessary for tracks which are looped or concatenated.
|
||||
|
||||
|
||||
FF 51 03 tttttt Set Tempo
|
||||
(in microseconds per MIDI quarter-note)
|
||||
This event indicates a tempo change. Another way of putting
|
||||
"microseconds per quarter-note" is "24ths of a microsecond per MIDI
|
||||
clock". Repersenting tempos as time per beat instead of beat per time
|
||||
allows absolutly exact long-term synchronization with a time-based sync
|
||||
protocol such as SMPTE time code or MIDI time code. This amount of
|
||||
accuracy provided by this tempo resolution allows a four-minute piece
|
||||
at 120 beats per minute to be accurate within 500 usec at the end of
|
||||
the piece. Ideally, these events should only occur where MIDI clocks
|
||||
would be located -- this convention is intended to guarntee, or at
|
||||
least increase the liklihood, of compatibility with other
|
||||
synchronization devices so that a time signature/tempo map stored in
|
||||
this format may easily be transfered to another device.
|
||||
|
||||
FF 54 05 hr mn se fr ff SMPTE Offset
|
||||
This event, if present, designates the SMPTE time at which the track
|
||||
chunk is supposed to start. It should be present at the beginning of
|
||||
the track, that is, before any nonzero delta-times, and before any
|
||||
transmittable MIDI events. the hour must be encoded with the SMPTE
|
||||
format, just as it is in MIDI Time Code. In a format 1 file, the SMPTE
|
||||
Offset must be stored with the tempo map, and has no meaning in any of
|
||||
the other tracks. The ff field contains fractional frames, in 100ths of
|
||||
a frame, even in SMPTE-based tracks which specify a different frame
|
||||
subdivision for delta-times.
|
||||
|
||||
FF 58 04 nn dd cc bb Time Signature
|
||||
The time signature is expressed as four numbers. nn and dd represent
|
||||
the numerator and denominator of the time signature as it would be
|
||||
notated. The denominator is a neqative power of two: 2 represents a
|
||||
quarter-note, 3 represents an eighth-note, etc. The cc parameter
|
||||
expresses the number of MIDI clocks in a metronome click. The bb
|
||||
parameter expresses the number of notated 32nd-notes in a MIDI
|
||||
quarter-note (24 MIDI clocks). This was added because there are already
|
||||
multiple programs which allow a user to specify that what MIDI thinks
|
||||
of as a quarter-note (24 clocks) is to be notated as, or related to in
|
||||
terms of, something else.
|
||||
|
||||
Therefore, the complete event for 6/8 time, where the metronome clicks
|
||||
every three eighth-notes, but there are 24 clocks per quarter-note, 72
|
||||
to the bar, would be (in hex):
|
||||
|
||||
FF 58 04 06 03 24 08
|
||||
|
||||
That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 36 MIDI
|
||||
clocks per dotted-quarter (24 hex!), and eight notated 32nd-notes per
|
||||
quarter-note.
|
||||
|
||||
|
||||
FF 59 02 sf mi Key Signature
|
||||
sf = -7: 7 flats
|
||||
sf = -1: 1 flat
|
||||
sf = 0: key of C
|
||||
sf = 1: 1 sharp
|
||||
sf = 7: 7 sharps
|
||||
|
||||
mi = 0: major key
|
||||
mi = 1: minor key
|
||||
|
||||
FF 7F len data Sequencer Specific Meta-Event
|
||||
Special requirements for particular sequencers may use this event type:
|
||||
the first byte or bytes of data is a manufacturer ID (these are one
|
||||
byte, or if the first byte is 00, three bytes). As with MIDI System
|
||||
Exclusive, manufacturers who define something using this meta-event
|
||||
should publish it so that others may be used by a sequencer which
|
||||
elects to use this as its only file format; sequencers with their
|
||||
established feature-specific formats should probably stick to the
|
||||
standard features when using this format.
|
||||
|
||||
4 - Program Fragments and Example MIDI Files
|
||||
|
||||
Here are some of the routines to read and write variable-length numbers in
|
||||
MIDI Files. These routines are in C, and use getc and putc, which read and
|
||||
write single 8-bit characters from/to the files infile and outfile.
|
||||
|
||||
WriteVarLen (value)
|
||||
register long value;
|
||||
(
|
||||
register long buffer;
|
||||
|
||||
buffer = value & 0x7f;
|
||||
while ((value >>= 7) > 0)
|
||||
(
|
||||
buffer <<= 8;
|
||||
buffer |= 0x80;
|
||||
buffer += (value & 0x7f);
|
||||
)
|
||||
|
||||
while (TRUE)
|
||||
(
|
||||
putc(buffer,outfile);
|
||||
if (buffer & 0x80)
|
||||
buffer >>= 8;
|
||||
else
|
||||
break;
|
||||
)
|
||||
)
|
||||
|
||||
doubleword ReadVarLen ()
|
||||
(
|
||||
register doubleword value;
|
||||
register byte c;
|
||||
|
||||
if ((value = getc(infile)) & 0x80)
|
||||
(
|
||||
value &= 0x7f;
|
||||
do
|
||||
(
|
||||
value = (value << 7) + ((c = getc(infile))) & 0x7f);
|
||||
) while (c & 0x80);
|
||||
)
|
||||
return (value);
|
||||
)
|
||||
|
||||
|
||||
As an example, MIDI Files for the following excerpt are shown below. First,
|
||||
a format 0 file is shown, with all information intermingled; then, a format
|
||||
1 file is shown with all data seperated into four tracks: one for tempo and
|
||||
time signature, and three for the notes. A resolution of 96 "ticks" per
|
||||
quarter note is used. A time signature of 4/4 and a tempo of 120, though
|
||||
implied, are explicitly stated.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|\
|
||||
---- | > ---------------------------------------
|
||||
|/ ____ O
|
||||
Channel 1 ---- X --------------------------------|--------
|
||||
/ |
|
||||
Preset 5 -- / | --------------------------------|--------
|
||||
/ ____ |
|
||||
-| | \ --------------------------------------
|
||||
\ | |
|
||||
-- \_|__/ --------------------------------------
|
||||
_|
|
||||
|
||||
|
||||
|\
|
||||
---- | > ---------------------------------------
|
||||
|/ \
|
||||
Channel 2 ---- X ------------>----------|-----------------
|
||||
/ / |
|
||||
Preset 46 -- / | ----------<------------|-----------------
|
||||
/ ____ \ | .
|
||||
-| | \ --------->---------O------------------
|
||||
\ | | (
|
||||
-- \_|__/ --------\-----------------------------
|
||||
_| \
|
||||
|
||||
|
||||
--O--
|
||||
|
||||
----__ -----------------------------------------
|
||||
/ \ .
|
||||
Channel 3 - / | ---------------------------------------
|
||||
| .
|
||||
Preset 70 ------ | ---------------------------------------
|
||||
/ O
|
||||
---- / -----------------------------------------
|
||||
/
|
||||
-- / -------------------------------------------
|
||||
|
||||
|
||||
The contents of the MIDI stream represented by this example are broken down
|
||||
here:
|
||||
|
||||
Delta-Time Event-Code Other Bytes Comment
|
||||
(decimal) (hex) (decimal)
|
||||
---------- ---------- ----------- -----------------------------
|
||||
0 FF 58 04 04 02 24 08 4 bytes; 4/4 time; 24 MIDI
|
||||
clocks/click, 8 32nd notes/
|
||||
24 MIDI clocks
|
||||
0 FF 51 03 500000 3 bytes: 500,000 usec/
|
||||
quarter note
|
||||
0 C0 5 Ch.1 Program Change 5
|
||||
0 C1 46 Ch.2 Program Change 46
|
||||
0 C2 70 Ch.3 Program Change 70
|
||||
0 92 48 96 Ch.3 Note On C2, forte
|
||||
0 92 60 96 Ch.3 Note On C3, forte
|
||||
96 91 67 64 Ch.2 Note On G3, mezzo-forte
|
||||
96 90 76 32 Ch.1 Note On E4, piano
|
||||
192 82 48 64 Ch.3 Note Off C2, standard
|
||||
0 82 60 64 Ch.3 Note Off C3, standard
|
||||
0 81 67 64 Ch.2 Note Off G3, standard
|
||||
0 80 76 64 Ch.1 Note Off E4, standard
|
||||
0 FF 2F 00 Track End
|
||||
|
||||
The entire format 0 MIDI file contents in hex follow. First, the header
|
||||
chunk:
|
||||
40 54 68 64 MThd
|
||||
00 00 00 06 chunk length
|
||||
00 00 format 0
|
||||
00 01 one track
|
||||
00 60 96 per quarter-note
|
||||
|
||||
Then the track chunk. Its header followed by the events (notice the running
|
||||
status is used in places):
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 3B chunk length (59)
|
||||
|
||||
Delta-Time Event Comments
|
||||
---------- ----------------------- -------------------------------
|
||||
00 FF 58 04 04 02 18 08 time signature
|
||||
00 FF 51 03 07 A1 20 tempo
|
||||
00 C0 05
|
||||
00 C1 2E
|
||||
00 C2 46
|
||||
00 92 30 60
|
||||
00 3C 60 running status
|
||||
60 91 43 40
|
||||
60 90 4C 20
|
||||
81 40 82 30 40 two-byte delta-time
|
||||
00 3C 40 running status
|
||||
00 81 43 40
|
||||
00 80 4C 40
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
A format 1 representation of the file is slightly different. Its header
|
||||
chunk:
|
||||
|
||||
4D 54 68 64 MThd
|
||||
00 00 00 06 chunk length
|
||||
00 01 format 1
|
||||
00 04 four tracks
|
||||
00 60 96 per quarter note
|
||||
|
||||
First, the track chunk for the time signature/tempo track. Its header,
|
||||
followed by the events:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 14 chunk length (20)
|
||||
|
||||
Delta-Time Event Comments
|
||||
---------- ----------------------- -------------------------------
|
||||
00 FF 58 04 04 02 18 08 time signature
|
||||
00 FF 51 03 07 A1 20 tempo
|
||||
83 00 FF 2F 00 end of track
|
||||
|
||||
Then, the track chunk for the first music track. The MIDI convention for
|
||||
note on/off running status is used in this example:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 10 chunk length (16)
|
||||
|
||||
Delta-Time Event Comments
|
||||
---------- ----------------------- -------------------------------
|
||||
00 C0 05
|
||||
81 40 90 4C 20
|
||||
81 40 4C 00 Running status: note on, vel=0
|
||||
00 FF 2F 00
|
||||
|
||||
Then, the track chunk for the second music track:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 0F chunk length (15)
|
||||
|
||||
Delta-Time Event Comments
|
||||
---------- ----------------------- -------------------------------
|
||||
00 C1 2E
|
||||
60 91 43 40
|
||||
82 20 43 00 running status
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
|
||||
Then, the track chunk for the third music track:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 15 chunk length (21)
|
||||
|
||||
Delta-Time Event Comments
|
||||
---------- ----------------------- -------------------------------
|
||||
00 C2 46
|
||||
00 92 30 60
|
||||
00 3C 60 running status
|
||||
83 00 30 00 two-byte delta-time, running status
|
||||
00 3C 00 running status
|
||||
00 FF 2F 00 end of track
|
||||
405
study/sabre/os/files/Sound/MIDI/StandardMIDIFileFormat.txt
Normal file
405
study/sabre/os/files/Sound/MIDI/StandardMIDIFileFormat.txt
Normal file
@@ -0,0 +1,405 @@
|
||||
Standard MIDI File Format
|
||||
Dustin Caldwell
|
||||
|
||||
The standard MIDI file format is a very strange beast. When viewed as a
|
||||
whole, it can be quite overwhelming. Of course, no matter how you look at it,
|
||||
describing a piece of music in enough detail to be able to reproduce it
|
||||
accurately is no small task. So, while complicated, the structure of the midi
|
||||
file format is fairly intuitive when understood.
|
||||
I must insert a disclaimer here that I am by no means an expert with
|
||||
midi nor midi files. I recently obtained a Gravis UltraSound board for my PC,
|
||||
and upon hearing a few midi files (.MID) thought, "Gee, I'd like to be able to
|
||||
make my own .MID files." Well, many aggravating hours later, I discovered that
|
||||
this was no trivial task. But, I couldn't let a stupid file format stop me.
|
||||
(besides, I once told my wife that computers aren't really that hard to use,
|
||||
and I'd hate to be a hypocrite) So if any errors are found in this
|
||||
information, please let me know and I will fix it. Also, this document's scope
|
||||
does not extend to EVERY type of midi command and EVERY possible file
|
||||
configuration. It is a basic guide that should enable the reader (with a
|
||||
moderate investment in time) to generate a quality midi file.
|
||||
|
||||
1. Overview
|
||||
|
||||
A midi (.MID) file contains basically 2 things, Header chunks and Track
|
||||
chunks. Section 2 explains the header chunks, and Section 3 explains the track
|
||||
chunks. A midi file contains ONE header chunk describing the file format,
|
||||
etc., and any number of track chunks. A track may be thought of in the same
|
||||
way as a track on a multi-track tape deck. You may assign one track to each
|
||||
voice, each staff, each instrument or whatever you want.
|
||||
|
||||
2. Header Chunk
|
||||
|
||||
The header chunk appears at the beginning of the file, and describes the
|
||||
file in three ways. The header chunk always looks like:
|
||||
|
||||
4D 54 68 64 00 00 00 06 ff ff nn nn dd dd
|
||||
|
||||
The ascii equivalent of the first 4 bytes is MThd. After MThd comes the 4-byte
|
||||
size of the header. This will always be 00 00 00 06, because the actual header
|
||||
information will always be 6 bytes.
|
||||
|
||||
ff ff is the file format. There are 3 formats:
|
||||
|
||||
0 - single-track
|
||||
1 - multiple tracks, synchronous
|
||||
2 - multiple tracks, asynchronous
|
||||
|
||||
Single track is fairly self-explanatory - one track only. Synchronous multiple
|
||||
tracks means that the tracks will all be vertically synchronous, or in other
|
||||
words, they all start at the same time, and so can represent different parts
|
||||
in one song. Asynchronous multiple tracks do not necessarily start at the same
|
||||
time, and can be completely asynchronous.
|
||||
|
||||
nn nn is the number of tracks in the midi file.
|
||||
|
||||
dd dd is the number of delta-time ticks per quarter note. (More about this
|
||||
later)
|
||||
|
||||
|
||||
3. Track Chunks
|
||||
|
||||
The remainder of the file after the header chunk consists of track chunks.
|
||||
Each track has one header and may contain as many midi commands as you like.
|
||||
The header for a track is very similar to the one for the file:
|
||||
|
||||
4D 54 72 6B xx xx xx xx
|
||||
|
||||
As with the header, the first 4 bytes has an ascii equivalent. This one is
|
||||
MTrk. The 4 bytes after MTrk give the length of the track (not including the
|
||||
track header) in bytes.
|
||||
Following the header are midi events. These events are identical to the
|
||||
actual data sent and received by MIDI ports on a synth with one addition. A
|
||||
midi event is preceded by a delta-time. A delta time is the number of ticks
|
||||
after which the midi event is to be executed. The number of ticks per quarter
|
||||
note was defined previously in the file header chunk. This delta-time is a
|
||||
variable-length encoded value. This format, while confusing, allows large
|
||||
numbers to use as many bytes as they need, without requiring small numbers to
|
||||
waste bytes by filling with zeros. The number is converted into 7-bit bytes,
|
||||
and the most-significant bit of each byte is 1 except for the last byte of the
|
||||
number, which has a msb of 0. This allows the number to be read one byte at a
|
||||
time, and when you see a msb of 0, you know that it was the last (least
|
||||
significant) byte of the number. According to the MIDI spec, the entire delta-
|
||||
time should be at most 4 bytes long.
|
||||
Following the delta-time is a midi event. Each midi event (except a
|
||||
running midi event) has a command byte which will always have a msb of 1 (the
|
||||
value will be >= 128). A list of most of these commands is in appendix A. Each
|
||||
command has different parameters and lengths, but the data that follows the
|
||||
command will have a msb of 0 (less than 128). The exception to this is a meta-
|
||||
event, which may contain data with a msb of 1. However, meta-events require a
|
||||
length parameter which alleviates confusion.
|
||||
One subtlety which can cause confusion is running mode. This is where
|
||||
the actual midi command is omitted, and the last midi command issued is
|
||||
assumed. This means that the midi event will consist of a delta-time and the
|
||||
parameters that would go to the command if it were included.
|
||||
|
||||
4. Conclusion
|
||||
|
||||
If this explanation has only served to confuse the issue more, the
|
||||
appendices contain examples which may help clarify the issue. Also, 2
|
||||
utilities and a graphic file should have been included with this document:
|
||||
|
||||
DEC.EXE - This utility converts a binary file (like .MID) to a tab-delimited
|
||||
text file containing the decimal equivalents of each byte.
|
||||
|
||||
REC.EXE - This utility converts a tab-delimited text file of decimal values
|
||||
into a binary file in which each byte corresponds to one of the decimal
|
||||
values.
|
||||
|
||||
MIDINOTE.PS - This is the postscript form of a page showing note numbers with
|
||||
a keyboard and with the standard grand staff.
|
||||
|
||||
Appendix A
|
||||
|
||||
1. MIDI Event Commands
|
||||
|
||||
Each command byte has 2 parts. The left nybble (4 bits) contains the actual
|
||||
command, and the right nybble contains the midi channel number on which the
|
||||
command will be executed. There are 16 midi channels, and 8 midi commands (the
|
||||
command nybble must have a msb of 1).
|
||||
In the following table, x indicates the midi channel number. Note that all
|
||||
data bytes will be <128 (msb set to 0).
|
||||
|
||||
Hex Binary Data Description
|
||||
8x 1000xxxx nn vv Note off (key is released)
|
||||
nn=note number
|
||||
vv=velocity
|
||||
|
||||
9x 1001xxxx nn vv Note on (key is pressed)
|
||||
nn=note number
|
||||
vv=velocity
|
||||
|
||||
Ax 1010xxxx nn vv Key after-touch
|
||||
nn=note number
|
||||
vv=velocity
|
||||
|
||||
Bx 1011xxxx cc vv Control Change
|
||||
cc=controller number
|
||||
vv=new value
|
||||
|
||||
Cx 1100xxxx pp Program (patch) change
|
||||
pp=new program number
|
||||
|
||||
Dx 1101xxxx cc Channel after-touch
|
||||
cc=channel number
|
||||
|
||||
Ex 1110xxxx bb tt Pitch wheel change (2000H is normal or no
|
||||
change)
|
||||
bb=bottom (least sig) 7 bits of value
|
||||
tt=top (most sig) 7 bits of value
|
||||
The following table lists meta-events which have no midi channel number. They
|
||||
are of the format:
|
||||
|
||||
FF xx nn dd
|
||||
|
||||
All meta-events start with FF followed by the command (xx), the length, or
|
||||
number of bytes that will contain data (nn), and the actual data (dd).
|
||||
|
||||
Hex Binary Data Description
|
||||
00 00000000 nn ssss Sets the track's sequence number.
|
||||
nn=02 (length of 2-byte sequence number)
|
||||
ssss=sequence number
|
||||
|
||||
01 00000001 nn tt .. Text event- any text you want.
|
||||
nn=length in bytes of text
|
||||
tt=text characters
|
||||
|
||||
02 00000010 nn tt .. Same as text event, but used for
|
||||
copyright info.
|
||||
nn tt=same as text event
|
||||
|
||||
03 00000011 nn tt .. Sequence or Track name
|
||||
nn tt=same as text event
|
||||
|
||||
04 00000100 nn tt .. Track instrument name
|
||||
nn tt=same as text event
|
||||
|
||||
05 00000101 nn tt .. Lyric
|
||||
nn tt=same as text event
|
||||
|
||||
06 00000110 nn tt .. Marker
|
||||
nn tt=same as text event
|
||||
|
||||
07 00000111 nn tt .. Cue point
|
||||
nn tt=same as text event
|
||||
|
||||
2F 00101111 00 This event must come at the end of each
|
||||
track
|
||||
|
||||
51 01010001 03 tttttt Set tempo
|
||||
tttttt=microseconds/quarter note
|
||||
|
||||
58 01011000 04 nn dd ccbb Time Signature
|
||||
nn=numerator of time sig.
|
||||
dd=denominator of time sig. 2=quarter
|
||||
3=eighth, etc.
|
||||
cc=number of ticks in metronome click
|
||||
bb=number of 32nd notes to the quarter
|
||||
note
|
||||
|
||||
59 01011001 02 sf mi Key signature
|
||||
sf=sharps/flats (-7=7 flats, 0=key of C,
|
||||
7=7 sharps)
|
||||
mi=major/minor (0=major, 1=minor)
|
||||
|
||||
7F 01111111 xx dd .. Sequencer specific information
|
||||
xx=number of bytes to be sent
|
||||
dd=data
|
||||
The following table lists system messages which control the entire system.
|
||||
These have no midi channel number. (these will generally only apply to
|
||||
controlling a midi keyboard, etc.)
|
||||
|
||||
Hex Binary Data Description
|
||||
F8 11111000 Timing clock used when synchronization is
|
||||
required.
|
||||
|
||||
FA 11111010 Start current sequence
|
||||
|
||||
FB 11111011 Continue a stopped sequence where left
|
||||
off
|
||||
|
||||
FC 11111100 Stop a sequence
|
||||
|
||||
|
||||
The following table lists the numbers corresponding to notes for use in note
|
||||
on and note off commands.
|
||||
|
||||
|
||||
Octave|| Note Numbers
|
||||
# ||
|
||||
|| C | C# | D | D# | E | F | F# | G | G# | A | A# | B
|
||||
-----------------------------------------------------------------------------
|
||||
0 || 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11
|
||||
1 || 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23
|
||||
2 || 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35
|
||||
3 || 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47
|
||||
4 || 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59
|
||||
5 || 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71
|
||||
6 || 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83
|
||||
7 || 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95
|
||||
8 || 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107
|
||||
9 || 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119
|
||||
10 || 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 |
|
||||
|
||||
|
||||
BIBLIOGRAPHY
|
||||
|
||||
"MIDI Systems and Control" Francis Rumsey 1990 Focal Press
|
||||
|
||||
"MIDI and Sound Book for the Atari ST" Bernd Enders and Wolfgang Klemme
|
||||
1989 M&T Publishing, Inc.
|
||||
|
||||
MIDI file specs and general MIDI specs were also obtained by sending e-mail
|
||||
to LISTSERV@AUVM.AMERICAN.EDU with the phrase GET MIDISPEC PACKAGE
|
||||
in the message.
|
||||
|
||||
|
||||
------------------------------- DEC.CPP ------------------------------------
|
||||
|
||||
/* file dec.cpp
|
||||
|
||||
by Dustin Caldwell (dustin@gse.utah.edu)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void helpdoc();
|
||||
|
||||
main()
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
unsigned char ch, c;
|
||||
|
||||
if((fp=fopen(_argv[1], "rb"))==NULL) /* open file to read */
|
||||
{
|
||||
printf("cannot open file %s\n",_argv[1]);
|
||||
helpdoc();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
c=0;
|
||||
ch=fgetc(fp);
|
||||
|
||||
while(!feof(fp)) /* loop for whole file */
|
||||
{
|
||||
printf("%u\t", ch); /* print every byte's decimal equiv. */
|
||||
c++;
|
||||
if(c>8) /* print 8 numbers to a line */
|
||||
{
|
||||
c=0;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
ch=fgetc(fp);
|
||||
}
|
||||
|
||||
fclose(fp); /* close up */
|
||||
}
|
||||
|
||||
void helpdoc() /* print help message */
|
||||
{
|
||||
printf("\n Binary File Decoder\n\n");
|
||||
|
||||
printf("\n Syntax: dec binary_file_name\n\n");
|
||||
|
||||
printf("by Dustin Caldwell (dustin@gse.utah.edu)\n\n");
|
||||
printf("This is a filter program that reads a binary file\n");
|
||||
printf("and prints the decimal equivalent of each byte\n");
|
||||
printf("tab-separated. This is mostly useful when piped \n");
|
||||
printf("into another file to be edited manually. eg:\n\n");
|
||||
printf("c:\>dec sonata3.mid > son3.txt\n\n");
|
||||
printf("This will create a file called son3.txt which can\n");
|
||||
printf("be edited with any ascii editor. \n\n");
|
||||
printf("(rec.exe may also be useful, as it reencodes the \n");
|
||||
printf("ascii text file).\n\n");
|
||||
printf("Have Fun!!\n");
|
||||
}
|
||||
|
||||
---------------------------- REC.CPP ----------------------------------
|
||||
|
||||
/* File rec.cpp
|
||||
by Dustin Caldwell (dustin@gse.utah.edu)
|
||||
*/
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void helpdoc();
|
||||
|
||||
main()
|
||||
{
|
||||
FILE *rfp, *wfp;
|
||||
|
||||
unsigned char ch, c;
|
||||
char s[20];
|
||||
|
||||
if((rfp=fopen(_argv[1], "r"))==NULL) /* open the read file */
|
||||
{
|
||||
printf("cannot open file %s \n",_argv[1]);
|
||||
helpdoc();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if((wfp=fopen(_argv[2], "wb"))==NULL) /* open the write file */
|
||||
{
|
||||
printf("cannot open file %s \n",_argv[1]);
|
||||
helpdoc();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
c=0;
|
||||
|
||||
ch=fgetc(rfp);
|
||||
|
||||
while(!feof(rfp)) /* loop for whole file */
|
||||
{
|
||||
|
||||
if(isalnum(ch)) /* only 'see' valid ascii chars */
|
||||
{
|
||||
c=0;
|
||||
while(isdigit(ch)) /* only use decimal digits (0-9) */
|
||||
{
|
||||
s[c]=ch; /* build a string containing the number */
|
||||
c++;
|
||||
ch=fgetc(rfp);
|
||||
}
|
||||
s[c]=NULL; /* must have NULL terminator */
|
||||
|
||||
fputc(atoi(s), wfp);/* write the binary equivalent to file */
|
||||
|
||||
}
|
||||
|
||||
ch=fgetc(rfp); /* loop until next number starts */
|
||||
|
||||
|
||||
}
|
||||
|
||||
fclose(rfp); /* close up */
|
||||
fclose(wfp);
|
||||
}
|
||||
|
||||
|
||||
void helpdoc() /* print help message */
|
||||
{
|
||||
printf("\n Text File Encoder\n\n");
|
||||
|
||||
printf("\n Syntax: rec text_file_name binary_file_name\n\n");
|
||||
|
||||
printf("by Dustin Caldwell (dustin@gse.utah.edu)\n\n");
|
||||
printf("This is a program that reads an ascii tab-\n");
|
||||
printf("delimited file and builds a binary file where\n");
|
||||
printf("each byte of the binary file is one of the decimal\n");
|
||||
printf("digits in the text file.\n");
|
||||
printf(" eg:\n\n");
|
||||
printf("c:\>rec son3.txt son3.mid\n\n");
|
||||
printf("(This will create a file called son3.mid which is\n");
|
||||
printf("a valid binary file)\n\n");
|
||||
printf("(dec.exe may also be useful, as it decodes binary files)\n\n");
|
||||
printf("Have Fun!!\n");
|
||||
}
|
||||
641
study/sabre/os/files/Sound/MIDI/StandardMIDIFileFormat0.06.txt
Normal file
641
study/sabre/os/files/Sound/MIDI/StandardMIDIFileFormat0.06.txt
Normal file
@@ -0,0 +1,641 @@
|
||||
To get your copy of the 1.0 spec, send a $2 check to:
|
||||
|
||||
International Midi Association
|
||||
5316 West 57th Street
|
||||
Los Angeles, CA 90056
|
||||
(415) 321-MIDI
|
||||
|
||||
Make your checks payable to the IMA. BYW, the 1.0 spec is technically
|
||||
identical to the .06 spec, but the description has been re-written.
|
||||
Since the spec has been offically approved, there shouldn't be any
|
||||
problem with posting this summary of the .06 spec:
|
||||
|
||||
|
||||
[This document is Dave Oppenheim's current version of the MIDI file
|
||||
specification, as sent to those who have participated in its
|
||||
development. The consensus seems to be to submit this to the MIDI
|
||||
Manufacturers' Association as version 1.0. I apologize for any loss of
|
||||
clarity that might have occurred in the conversion from a Microsoft Word
|
||||
document to this pure text file. I have removed some of the discussion
|
||||
about recent changes to the specification in order to keep the file size
|
||||
reasonable.--Doug Wyatt]
|
||||
|
||||
Standard MIDI Files 0.06 March 1, 1988
|
||||
|
||||
|
||||
0 Introduction
|
||||
|
||||
This describes a proposed standard MIDI file format. MIDI files contain
|
||||
one or more MIDI streams, with time information for each event. Song,
|
||||
sequence, and track structures, tempo and time signature information,
|
||||
are all supported. Track names and other descriptive information may be
|
||||
stored with the MIDI data. This format supports multiple tracks and
|
||||
multiple sequences so that if the user of a program which supports
|
||||
multiple tracks intends to move a file to another one, this format can
|
||||
allow that to happen.
|
||||
|
||||
This spec defines the 8-bit binary data stream used in the file. The
|
||||
data can be stored in a binary file, nibbleized, 7-bit-ized for
|
||||
efficient MIDI transmission, converted to Hex ASCII, or translated
|
||||
symbolically to a printable text file. This spec addresses what's in
|
||||
the 8-bit stream.
|
||||
|
||||
|
||||
1 Sequences, Tracks, Chunks: File Block Structure
|
||||
|
||||
Sequence files are made up of chunks. Each chunk has a 4-character type
|
||||
and a 32-bit length, which is the number of bytes in the chunk. On the
|
||||
Macintosh, data is passed either in the data fork of a file, or on the
|
||||
Clipboard. (The file type on the Macintosh for a file in this format
|
||||
will be "Midi".) On any other computer, the data is simply the contents
|
||||
of the file. This structure allows future chunk types to be designed
|
||||
which may easily be ignored if encountered by a program written before
|
||||
the chunk type is introduced. Your programs should expect alien chunks
|
||||
and treat them as if they weren't there.
|
||||
|
||||
This proposal defines two types of chunks: a header chunk and a track
|
||||
chunk. A header chunk provides a minimal amount of information
|
||||
pertaining to the entire MIDI file. A track chunk contains a sequential
|
||||
stream of MIDI data which may contain information for up to 16 MIDI
|
||||
channels. The concepts of multiple tracks, multiple MIDI outputs,
|
||||
patterns, sequences, and songs may all be implemented using several
|
||||
track chunks.
|
||||
|
||||
A MIDI file always starts with a header chunk, and is followed by one or
|
||||
more track chunks.
|
||||
|
||||
MThd <length of header data>
|
||||
<header data>
|
||||
MTrk <length of track data>
|
||||
<track data>
|
||||
MTrk <length of track data>
|
||||
<track data>
|
||||
...
|
||||
|
||||
Track Data Format (MTrk chunk type)
|
||||
|
||||
The MTrk chunk type is where actual song data is stored. It is simply a
|
||||
stream of MIDI events (and non-MIDI events), preceded by delta-time
|
||||
values.
|
||||
|
||||
Some numbers in MTrk chunks are represented in a form called a variable-
|
||||
length quantity. These numbers are represented 7 bits per byte, most
|
||||
significant bits first. All bytes except the last have bit 7 set, and
|
||||
the last byte has bit 7 clear. If the number is between 0 and 127, it
|
||||
is thus represented exactly as one byte.
|
||||
|
||||
Here are some examples of numbers represented as variable-length
|
||||
quantities:
|
||||
|
||||
Number (hex) Representation (hex)
|
||||
00000000 00
|
||||
00000040 40
|
||||
0000007F 7F
|
||||
00000080 81 00
|
||||
00002000 C0 00
|
||||
00003FFF FF 7F
|
||||
00004000 81 80 00
|
||||
00100000 C0 80 00
|
||||
001FFFFF FF FF 7F
|
||||
00200000 81 80 80 00
|
||||
08000000 C0 80 80 00
|
||||
0FFFFFFF FF FF FF 7F
|
||||
|
||||
|
||||
The largest number which is allowed is 0FFFFFFF so that the variable-
|
||||
length representation must fit in 32 bits in a routine to write
|
||||
variable-length numbers. Theoretically, larger numbers are possible,
|
||||
but 2 x 108 96ths of a beat at a fast tempo of 500 beats per minute is
|
||||
four days, long enough for any delta-time!
|
||||
|
||||
Here is the syntax of an MTrk chunk:
|
||||
|
||||
<track data> = <MTrk event>+
|
||||
|
||||
<MTrk event> = <delta-time> <event>
|
||||
|
||||
<delta-time> is stored as a variable-length quantity. It represents the
|
||||
amount of time before the following event. If the first event in a
|
||||
track occurs at the very beginning of a track, or if two events occur
|
||||
simultaneously, a delta-time of zero is used. Delta-times are always
|
||||
present. (Not storing delta-times of 0 requires at least two bytes for
|
||||
any other value, and most delta-times aren't zero.) Delta-time is in
|
||||
some fraction of a beat (or a second, for recording a track with SMPTE
|
||||
times), as specified in the header chunk.
|
||||
|
||||
<event> = <MIDI event> | <sysex event> | <meta-event>
|
||||
|
||||
<MIDI event> is any MIDI channel message. Running status is used:
|
||||
status bytes may be omitted after the first byte. The first event in a
|
||||
file must specify status. Delta-time is not considered an event
|
||||
itself: it is an integral part of the specification. Notice that
|
||||
running status occurs across delta-times.
|
||||
|
||||
<meta-event> specifies non-MIDI information useful to this format or to
|
||||
sequencers, with this syntax:
|
||||
|
||||
FF <type> <length> <bytes>
|
||||
|
||||
All meta-events begin with FF, then have an event type byte (which is
|
||||
always less than 128), and then have the length of the data stored as a
|
||||
variable-length quantity, and then the data itself. If there is no
|
||||
data, the length is 0. As with sysex events, running status is not
|
||||
allowed. As with chunks, future meta-events may be designed which may
|
||||
not be known to existing programs, so programs must properly ignore
|
||||
meta-events which they do not recognize, and indeed, should expect to
|
||||
see them. New for 0.06: programs must never ignore the length of a
|
||||
meta-event which they do recognize, and they shouldn't be surprised if
|
||||
it's bigger than they expected. If so, they must ignore everything past
|
||||
what they know about. However, they must not add anything of their own
|
||||
to the end of a meta-event.
|
||||
|
||||
<sysex event> is used to specify a MIDI system exclusive message, or as
|
||||
an "escape" to specify any arbitrary bytes to be transmitted.
|
||||
Unfortunately, some synthesizer manufacturers specify that their system
|
||||
exclusive messages are to be transmitted as little packets. Each packet
|
||||
is only part of an entire syntactical system exclusive message, but the
|
||||
times they are transmitted at are important. Examples of this are the
|
||||
bytes sent in a CZ patch dump, or the FB-01's "system exclusive mode" in
|
||||
which microtonal data can be transmitted. To be able to handle
|
||||
situations like these, two forms of <sysex event> are provided:
|
||||
|
||||
F0 <length> <bytes to be transmitted after F0>
|
||||
F7 <length> <all bytes to be transmitted>
|
||||
|
||||
In both cases, <length> is stored as a variable-length quantity. It is
|
||||
equal to the number of bytes following it, not including itself or the
|
||||
message type (F0 or F7), but all the bytes which follow, including any
|
||||
F7 at the end which is intended to be transmitted. The first form, with
|
||||
the F0 code, is used for syntactically complete system exclusive
|
||||
messages, or the first packet an a series Q that is, messages in which
|
||||
the F0 should be transmitted. The second form is used for the remainder
|
||||
of the packets within a syntactic sysex message, which do not begin with
|
||||
F0. Of course, the F7 is not considered part of the system exclusive
|
||||
message. Of course, just as in MIDI, running status is not allowed, in
|
||||
this case because the length is stored as a variable-length quantity
|
||||
which may or may not start with bit 7 set.
|
||||
|
||||
(New to 0.06) A syntactic system exclusive message must always end with
|
||||
an F7, even if the real-life device didn't send one, so that you know
|
||||
when you've reached the end of an entire sysex message without looking
|
||||
ahead to the next event in the MIDI file. This principle is repeated
|
||||
and illustrated in the paragraphs below.
|
||||
|
||||
The vast majority of system exclusive messages will just use the F0
|
||||
format. For instance, the transmitted message F0 43 12 00 07 F7 would
|
||||
be stored in a MIDI file as F0 05 43 12 00 07 F7. As mentioned above,
|
||||
it is required to include the F7 at the end so that the reader of the
|
||||
MIDI file knows that it has read the entire message.
|
||||
|
||||
For special situations when a single system exclusive message is split
|
||||
up, with parts of it being transmitted at different times, such as in a
|
||||
Casio CZ patch transfer, or the FB-01's "system exclusive mode", the F7
|
||||
form of sysex event is used for each packet except the first. None of
|
||||
the packets would end with an F7 except the last one, which must end
|
||||
with an F7. There also must not be any transmittable MIDI events in-
|
||||
between the packets of a multi-packet system exclusive message. Here is
|
||||
an example: suppose the bytes F0 43 12 00 were to be sent, followed by
|
||||
a 200-tick delay, followed by the bytes 43 12 00 43 12 00, followed by
|
||||
a 100-tick delay, followed by the bytes 43 12 00 F7, this would be in
|
||||
the MIDI File:
|
||||
|
||||
F0 03 43 12 00
|
||||
81 48 200-tick delta-time
|
||||
F7 06 43 12 00 43 12 00
|
||||
64 100-tick delta-time
|
||||
F7 04 43 12 00 F7
|
||||
|
||||
The F7 event may also be used as an "escape" to transmit any bytes
|
||||
whatsoever, including real-time bytes, song pointer, or MIDI Time Code,
|
||||
which are not permitted normally in this specification. No effort
|
||||
should be made to interpret the bytes used in this way. Since a system
|
||||
exclusive message is not being transmitted, it is not necessary or
|
||||
appropriate to end the F7 event with an F7 in this case.
|
||||
|
||||
|
||||
2 Header Chunk
|
||||
|
||||
The header chunk at the beginning of the file specifies some basic
|
||||
information about the data in the file. The data section contains three
|
||||
16-bit words, stored high byte first (of course). Here's the syntax of
|
||||
the complete chunk:
|
||||
|
||||
<chunk type> <length> <format> <ntrks> <division>
|
||||
|
||||
As described above, <chunk type> is the four ASCII characters 'MThd';
|
||||
<length> is a 32-bit representation of the number 6 (high byte first).
|
||||
The first word, format, specifies the overall organization of the file.
|
||||
Only three values of format are specified:
|
||||
|
||||
0 the file contains a single multi-channel track
|
||||
1 the file contains one or more simultaneous tracks (or MIDI
|
||||
outputs) of a sequence
|
||||
2 the file contains one or more sequentially independent
|
||||
single-track patterns
|
||||
|
||||
The next word, ntrks, is the number of track chunks in the file. The
|
||||
third word, division, is the division of a quarter-note represented by
|
||||
the delta-times in the file. (If division is negative, it represents
|
||||
the division of a second represented by the delta-times in the file, so
|
||||
that the track can represent events occurring in actual time instead of
|
||||
metrical time. It is represented in the following way: the upper byte
|
||||
is one of the four values -24, -25, -29, or -30, corresponding to the
|
||||
four standard SMPTE and MIDI time code formats, and represents the
|
||||
number of frames per second. The second byte (stored positive) is the
|
||||
resolution within a frame: typical values may be 4 (MIDI time code
|
||||
resolution), 8, 10, 80 (bit resolution), or 100. This system allows
|
||||
exact specification of time-code-based tracks, but also allows
|
||||
millisecond-based tracks by specifying 25 frames/sec and a resolution of
|
||||
40 units per frame.)
|
||||
|
||||
Format 0, that is, one multi-channel track, is the most interchangeable
|
||||
representation of data. One application of MIDI files is a simple
|
||||
single-track player in a program which needs to make synthesizers make
|
||||
sounds, but which is primarily concerned with something else such as
|
||||
mixers or sound effect boxes. It is very desirable to be able to
|
||||
produce such a format, even if your program is track-based, in order to
|
||||
work with these simple programs. On the other hand, perhaps someone
|
||||
will write a format conversion from format 1 to format 0 which might be
|
||||
so easy to use in some setting that it would save you the trouble of
|
||||
putting it into your program.
|
||||
|
||||
Programs which support several simultaneous tracks should be able to
|
||||
save and read data in format 1, a vertically one-dimensional form, that
|
||||
is, as a collection of tracks. Programs which support several
|
||||
independent patterns should be able to save and read data in format 2, a
|
||||
horizontally one-dimensional form. Providing these minimum capabilities
|
||||
will ensure maximum interchangeability.
|
||||
|
||||
MIDI files can express tempo and time signature, and they have been
|
||||
chosen to do so for transferring tempo maps from one device to another.
|
||||
For a format 0 file, the tempo will be scattered through the track and
|
||||
the tempo map reader should ignore the intervening events; for a format
|
||||
1 file, the tempo map must (starting in 0.04) be stored as the first
|
||||
track. It is polite to a tempo map reader to offer your user the
|
||||
ability to make a format 0 file with just the tempo, unless you can use
|
||||
format 1.
|
||||
|
||||
All MIDI files should specify tempo and time signature. If they don't,
|
||||
the time signature is assumed to be 4/4, and the tempo 120 beats per
|
||||
minute. In format 0, these meta-events should occur at least at the
|
||||
beginning of the single multi-channel track. In format 1, these meta-
|
||||
events should be contained in the first track. In format 2, each of the
|
||||
temporally independent patterns should contain at least initial time
|
||||
signature and tempo information.
|
||||
|
||||
We may decide to define other format IDs to support other structures. A
|
||||
program reading an unfamiliar format ID should return an error to the
|
||||
user rather than trying to read further.
|
||||
|
||||
3 Meta-Events
|
||||
|
||||
A few meta-events are defined herein. It is not required for every
|
||||
program to support every meta-event. Meta-events initially defined
|
||||
include:
|
||||
|
||||
FF 00 02 ssss Sequence Number
|
||||
This optional event, which must occur at the beginning of a track,
|
||||
before any nonzero delta-times, and before any transmittable MIDI
|
||||
events, specifies the number of a sequence. The number in this track
|
||||
corresponds to the sequence number in the new Cue message discussed at
|
||||
the summer 1987 MMA meeting. In a format 2 MIDI file, it is used to
|
||||
identify each "pattern" so that a "song" sequence using the Cue message
|
||||
to refer to the patterns. If the ID numbers are omitted, the sequences'
|
||||
locations in order in the file are used as defaults. In a format 0 or 1
|
||||
MIDI file, which only contain one sequence, this number should be
|
||||
contained in the first (or only) track. If transfer of several
|
||||
multitrack sequences is required, this must be done as a group of format
|
||||
1 files, each with a different sequence number.
|
||||
|
||||
FF 01 len text Text Event
|
||||
Any amount of text describing anything. It is a good idea to put a text
|
||||
event right at the beginning of a track, with the name of the track, a
|
||||
description of its intended orchestration, and any other information
|
||||
which the user wants to put there. Text events may also occur at other
|
||||
times in a track, to be used as lyrics, or descriptions of cue points.
|
||||
The text in this event should be printable ASCII characters for maximum
|
||||
interchange. However, other character codes using the high-order bit
|
||||
may be used for interchange of files between different programs on the
|
||||
same computer which supports an extended character set. Programs on a
|
||||
computer which does not support non-ASCII characters should ignore those
|
||||
characters.
|
||||
|
||||
(New for 0.06 ). Meta event types 01 through 0F are reserved for
|
||||
various types of text events, each of which meets the specification of
|
||||
text events(above) but is used for a different purpose:
|
||||
|
||||
FF 02 len text Copyright Notice
|
||||
Contains a copyright notice as printable ASCII text. The notice should
|
||||
contain the characters (C), the year of the copyright, and the owner of
|
||||
the copyright. If several pieces of music are in the same MIDI file,
|
||||
all of the copyright notices should be placed together in this event so
|
||||
that it will be at the beginning of the file. This event should be the
|
||||
first event in the first track chunk, at time 0.
|
||||
|
||||
|
||||
FF 03 len text Sequence/Track Name
|
||||
If in a format 0 track, or the first track in a format 1 file, the name
|
||||
of the sequence. Otherwise, the name of the track.
|
||||
|
||||
FF 04 len text Instrument Name
|
||||
A description of the type of instrumentation to be used in that track.
|
||||
May be used with the MIDI Prefix meta-event to specify which MIDI
|
||||
channel the description applies to, or the channel may be specified as
|
||||
text in the event itself.
|
||||
|
||||
FF 05 len text Lyric
|
||||
A lyric to be sung. Generally, each syllable will be a separate lyric
|
||||
event which begins at the event's time.
|
||||
|
||||
FF 06 len text Marker
|
||||
Normally in a format 0 track, or the first track in a format 1 file.
|
||||
The name of that point in the sequence, such as a rehearsal letter or
|
||||
section name ("First Verse", etc.).
|
||||
|
||||
|
||||
FF 07 len text Cue Point
|
||||
A description of something happening on a film or video screen or stage
|
||||
at that point in the musical score ("Car crashes into house", "curtain
|
||||
opens", "she slaps his face", etc.)
|
||||
|
||||
FF 2F 00 End of Track
|
||||
This event is not optional. It is included so that an exact ending
|
||||
point may be specified for the track, so that it has an exact length,
|
||||
which is necessary for tracks which are looped or concatenated.
|
||||
|
||||
FF 51 03 tttttt Set Tempo, in microseconds per MIDI quarter-note
|
||||
This event indicates a tempo change. Another way of putting
|
||||
"microseconds per quarter-note" is "24ths of a microsecond per MIDI
|
||||
clock". Representing tempos as time per beat instead of beat per time
|
||||
allows absolutely exact long-term synchronization with a time-based sync
|
||||
protocol such as SMPTE time code or MIDI time code. This amount of
|
||||
accuracy provided by this tempo resolution allows a four-minute piece at
|
||||
120 beats per minute to be accurate within 500 usec at the end of the
|
||||
piece. Ideally, these events should only occur where MIDI clocks would
|
||||
be located Q this convention is intended to guarantee, or at least
|
||||
increase the likelihood, of compatibility with other synchronization
|
||||
devices so that a time signature/tempo map stored in this format may
|
||||
easily be transferred to another device.
|
||||
|
||||
FF 54 05 hr mn se fr ff SMPTE Offset (New in 0.06 - SMPTE Format
|
||||
specification)
|
||||
This event, if present, designates the SMPTE time at which the track
|
||||
chunk is supposed to start. It should be present at the beginning of
|
||||
the track, that is, before any nonzero delta-times, and before any
|
||||
transmittable MIDI events. The hour must be encoded with the SMPTE
|
||||
format, just as it is in MIDI Time Code. In a format 1 file, the SMPTE
|
||||
Offset must be stored with the tempo map, and has no meaning in any of
|
||||
the other tracks. The ff field contains fractional frames, in 100ths of
|
||||
a frame, even in SMPTE-based tracks which specify a different frame
|
||||
subdivision for delta-times.
|
||||
|
||||
FF 58 04 nn dd cc bb Time Signature
|
||||
The time signature is expressed as four numbers. nn and dd represent
|
||||
the numerator and denominator of the time signature as it would be
|
||||
notated. The denominator is a negative power of two: 2 represents a
|
||||
quarter-note, 3 represents an eighth-note, etc. The cc parameter
|
||||
expresses the number of MIDI clocks in a metronome click. The bb
|
||||
parameter expresses the number of notated 32nd-notes in a MIDI quarter-
|
||||
note (24 MIDI Clocks). This was added because there are already
|
||||
multiple programs which allow the user to specify that what MIDI thinks
|
||||
of as a quarter-note (24 clocks) is to be notated as, or related to in
|
||||
terms of, something else.
|
||||
|
||||
Therefore, the complete event for 6/8 time, where the metronome clicks
|
||||
every three eighth-notes, but there are 24 clocks per quarter-note, 72
|
||||
to the bar, would be (in hex):
|
||||
|
||||
FF 58 04 06 03 24 08
|
||||
|
||||
That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 32 MIDI
|
||||
clocks per dotted-quarter (24 hex!), and eight notated 32nd-notes per
|
||||
MIDI quarter note.
|
||||
|
||||
FF 59 02 sf mi Key Signature
|
||||
sf = -7: 7 flats
|
||||
sf = -1: 1 flat
|
||||
sf = 0: key of C
|
||||
sf = 1: 1 sharp
|
||||
sf = 7: 7 sharps
|
||||
|
||||
mi = 0: major key
|
||||
mi = 1: minor key
|
||||
|
||||
FF 7F len data Sequencer-Specific Meta-Event
|
||||
|
||||
Special requirements for particular sequencers may use this
|
||||
event type: the first byte or bytes of data is a manufacturer ID.
|
||||
However, as this is an interchange format, growth of the spec proper is
|
||||
preferred to use of this event type. This type of event may be used by
|
||||
a sequencer which elects to use this as its only file format;
|
||||
sequencers with their established feature-specific formats should
|
||||
probably stick to the standard features when using this format.
|
||||
|
||||
4 Program Fragments and Example MIDI Files
|
||||
|
||||
Here are some of the routines to read and write variable-length numbers
|
||||
in MIDI Files. These routines are in C, and use getc and putc, which
|
||||
read and write single 8-bit characters from/to the files infile and
|
||||
outfile.
|
||||
|
||||
WriteVarLen (value)
|
||||
register long value;
|
||||
{
|
||||
register long buffer;
|
||||
|
||||
buffer = value & 0x7f;
|
||||
while ((value >>= 7) > 0)
|
||||
{
|
||||
buffer <<= 8;
|
||||
buffer |= 0x80;
|
||||
buffer += (value & 0x7f);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
putc(buffer,outfile);
|
||||
if (buffer & 0x80)
|
||||
buffer >>= 8;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
doubleword ReadVarLen ()
|
||||
{
|
||||
register doubleword value;
|
||||
register byte c;
|
||||
|
||||
if ((value = getc(infile)) & 0x80)
|
||||
{
|
||||
value &= 0x7f;
|
||||
do
|
||||
{
|
||||
value = (value << 7) + ((c = getc(infile)) & 0x7f);
|
||||
} while (c & 0x80);
|
||||
}
|
||||
return (value);
|
||||
}
|
||||
|
||||
As an example, MIDI Files for the following excerpt are shown below.
|
||||
First, a format 0 file is shown, with all information intermingled;
|
||||
then, a format 1 file is shown with all data separated into four tracks:
|
||||
one for tempo and time signature, and three for the notes. A resolution
|
||||
of 96 "ticks" per quarter note is used. A time signature of 4/4 and a
|
||||
tempo of 120, though implied, are explicitly stated.
|
||||
|
||||
|
||||
|
||||
|
||||
The contents of the MIDI stream represented by this example are broken
|
||||
down here:
|
||||
|
||||
Delta Time(decimal) Event Code (hex) Other Bytes (decimal)
|
||||
Comment
|
||||
0 FF 58 04 04 02 24 08 4 bytes: 4/4 time, 24 MIDI
|
||||
clocks/click,
|
||||
8 32nd notes/24 MIDI clocks
|
||||
0 FF 51 03 500000 3 bytes: 500,000 5sec per quarter-note
|
||||
0 C0 5 Ch. 1, Program Change 5
|
||||
0 C0 5 Ch. 1, Program Change 5
|
||||
0 C1 46 Ch. 2, Program Change 46
|
||||
0 C2 70 Ch. 3, Program Change 70
|
||||
0 92 48 96 Ch. 3 Note On C2, forte
|
||||
0 92 60 96 Ch. 3 Note On C3, forte
|
||||
96 91 67 64 Ch. 2 Note On G3, mezzo-forte
|
||||
96 90 76 32 Ch. 1 Note On E4, piano
|
||||
192 82 48 64 Ch. 3 Note Off C2, standard
|
||||
0 82 60 64 Ch. 3 Note Off C3, standard
|
||||
0 81 67 64 Ch. 2 Note Off G3, standard
|
||||
0 80 76 64 Ch. 1 Note Off E4, standard
|
||||
0 FF 2F 00 Track End
|
||||
|
||||
The entire format 0 MIDI file contents in hex follow. First, the header
|
||||
chunk:
|
||||
|
||||
4D 54 68 64 MThd
|
||||
00 00 00 06 chunk length
|
||||
00 00 format 0
|
||||
00 01 one track
|
||||
00 60 96 per quarter-note
|
||||
|
||||
Then, the track chunk. Its header, followed by the events (notice that
|
||||
running status is used in places):
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 3B chunk length (59)
|
||||
|
||||
Delta-time Event Comments
|
||||
00 FF 58 04 04 02 18 08 time signature
|
||||
00 FF 51 03 07 A1 20 tempo
|
||||
00 C0 05
|
||||
00 C1 2E
|
||||
00 C2 46
|
||||
00 92 30 60
|
||||
00 3C 60 running status
|
||||
60 91 43 40
|
||||
60 90 4C 20
|
||||
81 40 82 30 40 two-byte delta-time
|
||||
00 3C 40 running status
|
||||
00 81 43 40
|
||||
00 80 4C 40
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
A format 1 representation of the file is slightly different. Its header
|
||||
chunk:
|
||||
|
||||
4D 54 68 64 MThd
|
||||
00 00 00 06 chunk length
|
||||
00 01 format 1
|
||||
00 04 four tracks
|
||||
00 60 96 per quarter-note
|
||||
|
||||
First, the track chunk for the time signature/tempo track. Its header,
|
||||
followed by the events:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 14 chunk length (20)
|
||||
|
||||
Delta-time Event Comments
|
||||
00 FF 58 04 04 02 18 08 time signature
|
||||
00 FF 51 03 07 A1 20 tempo
|
||||
83 00 FF 2F 00 end of track
|
||||
|
||||
Then, the track chunk for the first music track. The MIDI convention
|
||||
for note on/off running status is used in this example:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 10 chunk length (16)
|
||||
|
||||
Delta-time Event Comments
|
||||
00 C0 05
|
||||
81 40 90 4C 20
|
||||
81 40 4C 00 Running status: note on, vel = 0
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
Then, the track chunk for the second music track:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 0F chunk length (15)
|
||||
|
||||
Delta-time Event Comments
|
||||
00 C1 2E
|
||||
60 91 43 40
|
||||
82 20 43 00 running status
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
Then, the track chunk for the third music track:
|
||||
|
||||
4D 54 72 6B MTrk
|
||||
00 00 00 15 chunk length (21)
|
||||
|
||||
Delta-time Event Comments
|
||||
00 C2 46
|
||||
00 92 30 60
|
||||
00 3C 60 running status
|
||||
83 00 30 00 two-byte delta-time, running status
|
||||
00 3C 00 running status
|
||||
00 FF 2F 00 end of track
|
||||
|
||||
5 MIDI Transmission of MIDI Files
|
||||
|
||||
Since it is inconvenient to exchange disks between different computers,
|
||||
and since many computers which will use this format will have a MIDI
|
||||
interface anyway, MIDI seems like a perfect way to send these files from
|
||||
one computer to another. And, while we're going through all the trouble
|
||||
to make a way of sending MIDI Files, it would be nice if they could send
|
||||
any files (like sampled sound files, text files, etc.)
|
||||
|
||||
Goals
|
||||
The transmission protocol for MIDI files should be reasonably efficient,
|
||||
should support fast transmission for computers which are capable of it,
|
||||
and slower transmission for less powerful ones. It should not be
|
||||
impossible to convert a MIDI File to or from an arbitrary internal
|
||||
representation on the fly as it is transmitted, but, as long as it is
|
||||
not too difficult, it is very desirable to use a generic method so that
|
||||
any file type could be accommodated.
|
||||
|
||||
To make the protocol efficient, the MIDI transmission of these files
|
||||
will take groups of seven 8-bit bytes and transmit them as eight 7-bit
|
||||
MIDI data bytes. This is certainly in the spirit of the rest of this
|
||||
format (keep it small, because it's not that hard to do). To
|
||||
accommodate a wide range of transmission speeds, files will be
|
||||
transmitted in packets with acknowledge -- this allows data to be stored
|
||||
to disk as it is received. If the sender does not receive a response
|
||||
from a reader in a certain amount of time, it can assume an open-loop
|
||||
situation, and then just continue.
|
||||
|
||||
The last edition of MIDI Files contained a specialized protocol for
|
||||
sending just MIDI Files. To meet a deadline, unfortunately I don't have
|
||||
time right now to propose a new generalized protocol. This will be done
|
||||
within the next couple of months. I would welcome any proposals anyone
|
||||
else has, and would direct your attention to the proposal from Ralph
|
||||
Muha of Kurzweil, available in a recent MMA bulletin, and also directly
|
||||
from him.
|
||||
|
||||
|
||||
--
|
||||
Michael S. Czeiszperger | "The only good composer is a dead composer"
|
||||
Systems Analyst | Snail: 2015 Neil Avenue (614)
|
||||
The Ohio State University | Columbus, OH 43210 292-
|
||||
ARPA:czei@accelerator.eng.ohio-state.edu PAN:CZEI 0161
|
||||
601
study/sabre/os/files/Sound/MIDI/TheUSENETMIDIPrimer.txt
Normal file
601
study/sabre/os/files/Sound/MIDI/TheUSENETMIDIPrimer.txt
Normal file
@@ -0,0 +1,601 @@
|
||||
The USENET MIDI Primer
|
||||
|
||||
Bob McQueer
|
||||
|
||||
PURPOSE
|
||||
|
||||
It seems as though many people in the USENET community have an interest
|
||||
in the Musical Instrument Digital Interface (MIDI), but for one reason
|
||||
or another have only obtained word of mouth or fragmentary descriptions
|
||||
of the specification. Basic questions such as "what's the baud rate?",
|
||||
"is it EIA?" and the like seem to keep surfacing in about half a dozen
|
||||
newsgroups. This article is an attempt to provide the basic data to
|
||||
the readers of the net.
|
||||
|
||||
REFERENCE
|
||||
|
||||
The major written reference for this article is version 1.0 of the MIDI
|
||||
specification, published by the International MIDI Association, copyright
|
||||
1983. There exists an expanded document. This document, which I have not
|
||||
seen, is simply an expansion of the 1.0 spec. to contain more explanatory
|
||||
material, and fill in some areas of hazy explanation. There are no
|
||||
radical departures from 1.0 in it. I have also heard of a "2.0" spec.,
|
||||
but the IMA claims no such animal exists. In any event, backwards
|
||||
compatibility with the information I am presenting here should be
|
||||
maintained.
|
||||
|
||||
CONVENTIONS
|
||||
|
||||
I will give constants in C syntax, ie. 0x for hexadecimal. If I
|
||||
refer to bits by number, I number them starting with 0 for the low
|
||||
order (1's place) bit. The following notation:
|
||||
|
||||
>>
|
||||
|
||||
text
|
||||
|
||||
<<
|
||||
|
||||
will be used to delimit commentary which is not part of the "bare-
|
||||
bones" specification. A sentence or paragraph marked with a question
|
||||
mark in column 1 is a point I would kind of like to hear something
|
||||
about myself.
|
||||
|
||||
OK, let's give it a shot.
|
||||
|
||||
PHYSICAL CONNECTOR SPECIFICATION
|
||||
|
||||
The standard connectors used for MIDI are 5 pin DIN. Separate sockets
|
||||
are used for input and output, clearly marked on a given device. The
|
||||
spec. gives 50 feet as the maximum cable length. Cables are to be
|
||||
shielded twisted pair, with the shield connecting pin 2 at both ends.
|
||||
The pair is pins 4 and 5, pins 1 and 3 being unconnected:
|
||||
|
||||
2
|
||||
5 4
|
||||
3 1
|
||||
|
||||
A device may also be equipped with a "MIDI-THRU" socket which is used
|
||||
to pass the input of one device directly to output.
|
||||
|
||||
>>
|
||||
I think this arrangement shows some of the original conception
|
||||
of MIDI more as a way of allowing keyboardists to control
|
||||
multiple boxes than an instrument to computer interface. The
|
||||
"daisy-chain" arrangement probably has advantages for a performing
|
||||
musician who wants to play "stacked" synthesizers for a desired
|
||||
sound, and has to be able to set things up on the road.
|
||||
<<
|
||||
|
||||
ELECTRICAL SPECIFICATION
|
||||
|
||||
Asynchronous serial interface. The baud rate is 31.25 Kbaud (+/- 1%).
|
||||
There are 8 data bits, with 1 start bit and 1 stop bit, for 320 microseconds
|
||||
per serial byte.
|
||||
|
||||
MIDI is current loop, 5 mA. Logic 0 is current ON. The specification
|
||||
states that input is to be opto-isolated, and points out that Sharp
|
||||
PC-900 and HP 6N138 optoisolators are satisfactory devices. Rise and
|
||||
fall time for the optoisolator should be less than 2 microseconds.
|
||||
|
||||
The specification shows a little circuit diagram for the connections
|
||||
to a UART. I am not going to reproduce it here. There's not much
|
||||
to it - I think the important thing it shows is +5 volt connection
|
||||
to pin 4 of the MIDI out with pin 5 going to the UART, through 220
|
||||
ohm load resistors. It also shows that you're supposed to connect
|
||||
to the "in" side of the UART through an optoisolator, and to the
|
||||
MIDI-THRU on the UART side of the isolator.
|
||||
|
||||
>>
|
||||
I'm not much of a hardware person, and don't really know what
|
||||
I'm talking about in paragraphs like the three above. I DO
|
||||
recognize that this is a "non-standard" specification, which
|
||||
won't work over serial ports intended for anything else. People
|
||||
who do know about such things seem to either have giggling
|
||||
or gagging fits when they see it, depending on their dispos-
|
||||
itions, saying things like "I haven't seen current loop since
|
||||
the days of the old teletypes". I also know the fast 31.25
|
||||
Kbaud pushes the edge for clocking commonly available UART's.
|
||||
<<
|
||||
|
||||
DATA FORMAT
|
||||
|
||||
For standard MIDI messages, there is a clear concept that one device
|
||||
is a "transmitter" or "master", and the other a "receiver" or "slave".
|
||||
Messages take the form of opcode bytes, followed by data bytes.
|
||||
Opcode bytes are commonly called "status" bytes, so we shall use
|
||||
this term.
|
||||
|
||||
>>
|
||||
very similar to handling a terminal via escape sequences. There
|
||||
aren't ACK's or other handshaking mechanisms in the protocol.
|
||||
<<
|
||||
|
||||
Status bytes are marked by bit 7 being 1. All data bytes must
|
||||
contain a 0 in bit 7, and thus lie in the range 0 - 127.
|
||||
|
||||
MIDI has a logical channel concept. There are 16 logical channels,
|
||||
encoded into bits 0 - 3 of the status bytes of messages for
|
||||
which a channel number is significant. Since bit 7 is taken over
|
||||
for marking the status byte, this leaves 3 opcode bits for message
|
||||
types with a logical channel. 7 of the possible 8 opcodes are
|
||||
used in this fashion, reserving the status bytes containing all
|
||||
1's in the high nibble for "system" messages which don't have a
|
||||
channel number. The low order nibble in these remaining messages
|
||||
is really further opcode.
|
||||
|
||||
>>
|
||||
If you are interested in receiving MIDI input, look over the
|
||||
SYSTEM messages even if you wish to ignore them. Especially the
|
||||
"system exclusive" and "real time" messages. The real time
|
||||
messages may be legally inserted in the middle of other data,
|
||||
and you should be aware of them, even though many devices won't
|
||||
use them.
|
||||
<<
|
||||
|
||||
VOICE MESSAGES
|
||||
|
||||
I will cover the message with channel numbers first. The opcode determines
|
||||
the number of data bytes for a single message (see "running status byte",
|
||||
below). The specification divides these into "voice" and "mode" messages.
|
||||
The "mode" messages are for control of the logical channels, and the control
|
||||
opcodes are piggybacked onto the data bytes for the "parameter" message. I
|
||||
will go into this after describing the "voice messages". These messages are:
|
||||
|
||||
status byte meaning data bytes
|
||||
|
||||
0x80-0x8f note off 2 - 1 byte pitch, followed by 1 byte velocity
|
||||
0x90-0x9f note on 2 - 1 byte pitch, followed by 1 byte velocity
|
||||
0xa0-0xaf key pressure 2 - 1 byte pitch, 1 byte pressure (after-touch)
|
||||
0xb0-0xbf parameter 2 - 1 byte parameter number, 1 byte setting
|
||||
0xc0-0xcf program 1 byte program selected
|
||||
0xd0-0xdf chan. pressure 1 byte channel pressure (after-touch)
|
||||
0xe0-0xef pitch wheel 2 bytes giving a 14 bit value, least
|
||||
significant 7 bits first
|
||||
|
||||
Many explanations are necessary here:
|
||||
|
||||
For all of these messages, a convention called the "running status
|
||||
byte" may be used. If the transmitter wishes to send another message
|
||||
of the same type on the same channel, thus the same status byte, the
|
||||
status byte need not be resent.
|
||||
|
||||
Also, a "note on" message with a velocity of zero is to be synonymous
|
||||
with a "note off". Combined with the previous feature, this is intended
|
||||
to allow long strings of notes to be sent without repeating status bytes.
|
||||
|
||||
>>
|
||||
From what I've seen, the "zero velocity note on" feature is very
|
||||
heavily used. My six-trak sends these, even though it sends
|
||||
status bytes on every note anyway. Roland stuff uses it.
|
||||
<<
|
||||
|
||||
The pitch bytes of notes are simply number of half-steps, with
|
||||
middle C = 60.
|
||||
|
||||
>>
|
||||
On keyboard synthesizers, this usually simply means which
|
||||
physical key corresponds, since the patch selection will
|
||||
change the actual pitch range of the keyboard. Most keyboards
|
||||
have one C key which is unmistakably in the middle of the
|
||||
keyboard. This is probably note 60.
|
||||
<<
|
||||
|
||||
The velocity bytes for velocity sensing keyboards are supposed
|
||||
to represent a logarithmic scale. "advisable" in the words
|
||||
of the spec. Non-velocity sensing devices are supposed to
|
||||
send velocity 64.
|
||||
|
||||
The pitch wheel value is an absolute setting, 0 - 0x3FFF. The
|
||||
1.0 spec. says that the increment is determined by the receiver.
|
||||
0x2000 is to correspond to a centered pitch wheel (unmodified
|
||||
notes)
|
||||
|
||||
>>
|
||||
I believe standard scale steps are one of the things discussed
|
||||
in expansions. The six-trak pitch wheel is up/down about a third.
|
||||
I believe several makers have used this value, but I may be
|
||||
wrong.
|
||||
|
||||
The "pressure" messages are for keyboards which sense the amount
|
||||
of pressure placed on an already depressed key, as opposed to
|
||||
velocity, which is how fast it is depressed or released.
|
||||
|
||||
? I'm not really certain of how "channel" pressure works. Yamaha
|
||||
is one maker that uses these messages, I know.
|
||||
<<
|
||||
|
||||
Now, about those parameter messages.
|
||||
|
||||
Instruments are so fundamentally different in the various controls
|
||||
they have that no attempt was made to define a standard set, like
|
||||
say 9 for "Filter Resonance". Instead, it was simply assumed that
|
||||
these messages allow you to set "controller" dials, whose purposes
|
||||
are left to the given device, except as noted below. The first data
|
||||
bytes correspond to these "controllers" as follows:
|
||||
|
||||
data byte
|
||||
|
||||
0 - 31 continuous controllers 0 - 31, most significant byte
|
||||
32 - 63 continuous controllers 0 - 31, least significant byte
|
||||
64 - 95 on / off switches
|
||||
96 - 121 unspecified, reserved for future.
|
||||
122 - 127 the "channel mode" messages I alluded to above. See
|
||||
below.
|
||||
|
||||
The second data byte contains the seven bit setting for the controller.
|
||||
The switches have data byte 0 = OFF, 127 = ON with 1 - 126 undefined.
|
||||
If a controller only needs seven bits of resolution, it is supposed to
|
||||
use the most significant byte. If both are needed, the order is
|
||||
specified as most significant followed by least significant. With a
|
||||
14 bit controller, it is to be legal to send only the least significant
|
||||
byte if the most significant doesn't need to be changed.
|
||||
|
||||
>>
|
||||
This may of, course, wind up stretched a bit by a given manufacturer.
|
||||
The Six-Trak, for instance, uses only single byte values (LEFT
|
||||
justified within the 7 bits at that), and recognizes >32 parameters
|
||||
<<
|
||||
|
||||
Controller number 1 IS standardized to be the modulation wheel.
|
||||
|
||||
? Are there any other standardizations which are being followed by most
|
||||
manufacturers?
|
||||
|
||||
MODE MESSAGES
|
||||
|
||||
These are messages with status bytes 0xb0 through 0xbf, and leading data
|
||||
bytes 122 - 127. In reality, these data bytes function as further
|
||||
opcode data for a group of messages which control the combination of
|
||||
voices and channels to be accepted by a receiver.
|
||||
|
||||
An important point is that there is an implicit "basic" channel over which
|
||||
a given device is to receive these messages. The receiver is to ignore
|
||||
mode messages over any other channels, no matter what mode it might be in.
|
||||
The basic channel for a given device may be fixed or set in some manner
|
||||
outside the scope of the MIDI standard.
|
||||
|
||||
The meaning of the values 122 through 127 is as follows:
|
||||
|
||||
data byte second data byte
|
||||
122 local control 0 = local control off, 127 = on
|
||||
123 all notes off 0
|
||||
124 omni mode off 0
|
||||
125 omni mode on 0
|
||||
126 monophonic mode number of monophonic channels, or 0
|
||||
for a number equal to receivers voices
|
||||
127 polyphonic mode 0
|
||||
|
||||
124 - 127 also turn all notes off.
|
||||
|
||||
Local control refers to whether or not notes played on an instruments
|
||||
keyboard play on the instrument or not. With local control off, the
|
||||
host is still supposed to be able to read input data if desired, as
|
||||
well as sending notes to the instrument. Very much like "local echo"
|
||||
on a terminal, or "half duplex" vs. "full duplex".
|
||||
|
||||
The mode setting messages control what channels / how many voices the
|
||||
receiver recognizes. The "basic channel" must be kept in mind. "Omni"
|
||||
refers to the ability to receive voice messages on all channels. "Mono"
|
||||
and "Poly" refer to whether multiple voices are allowed. The rub is
|
||||
that the omni on/off state and the mono/poly state interact with each
|
||||
other. We will go over each of the four possible settings, called "modes"
|
||||
and given numbers in the specification:
|
||||
|
||||
mode 1 - Omni on / Poly - voice messages received on all channels and
|
||||
assigned polyphonically. Basically, any notes it gets, it
|
||||
plays, up to the number of voices it's capable of.
|
||||
|
||||
mode 2 - Omni on / Mono - monophonic instrument which will receive
|
||||
notes to play in one voice on all channels.
|
||||
|
||||
mode 3 - Omni off / Poly - polyphonic instrument which will receive
|
||||
voice messages on only the basic channel.
|
||||
|
||||
mode 4 - Omni off / Mono - A useful mode, but "mono" is a misnomer.
|
||||
To operate in this mode a receiver is supposed to receive
|
||||
one voice per channel. The number channels recognized will be
|
||||
given by the second data byte, or the maximum number of possible
|
||||
voices if this byte is zero. The set of channels thus defined
|
||||
is a sequential set, starting with the basic channel.
|
||||
|
||||
The spec. states that a receiver may ignore any mode that it cannot
|
||||
honor, or switch to an alternate - "usually" mode 1. Receivers are
|
||||
supposed to default to mode 1 on power up. It is also stated that
|
||||
power up conditions are supposed to place a receiver in a state where
|
||||
it will only respond to note on / note off messages, requiring a
|
||||
setting of some sort to enable the other message types.
|
||||
|
||||
>>
|
||||
I think this shows the desire to "daisy-chain" devices for
|
||||
performance from a single master again. We can set a series
|
||||
of instruments to different basic channels, tie 'em together,
|
||||
and let them pass through the stuff they're not supposed to
|
||||
play to someone down the line.
|
||||
|
||||
This suffers greatly from lack of acknowledgement concerning
|
||||
modes and usable channels by a receiver. You basically have
|
||||
to know your device, what it can do, and what channels it can
|
||||
do it on.
|
||||
|
||||
I think most makers have used the "system exclusive" message
|
||||
(see below) to handle channels in a more sophisticated manner,
|
||||
as well as changing "basic channel" and enabling receipt of
|
||||
different message types under host control rather than by
|
||||
adjustment on the device alone.
|
||||
|
||||
The "parameters" may also be usurped by a manufacturer for
|
||||
mode control, since their purposes are undefined.
|
||||
|
||||
Another HUGE problem with the "daisy-chain" mental set of MIDI
|
||||
is that most devices ALWAYS shovel whatever they play to their
|
||||
MIDI outs, whether they got it from the keyboard or MIDI in.
|
||||
This means that you have to cope with the instrument echoing
|
||||
input back at you if you're trying to do an interactive session
|
||||
with the synthesizer. There is DRASTIC need for some MIDI flag
|
||||
which specifically means that only locally generated data is to
|
||||
go to MIDI out. From device to device there are ways of coping
|
||||
with this, none of them good.
|
||||
<<
|
||||
|
||||
SYSTEM MESSAGES
|
||||
|
||||
The status bytes 0x80 - 0x8f do not have channel numbers in the
|
||||
lower nibble. These bytes are used as follows:
|
||||
|
||||
byte purpose data bytes
|
||||
|
||||
0xf0 system exclusive variable length
|
||||
0xf1 undefined
|
||||
0xf2 song position 2 - 14 bit value, least significant byte
|
||||
first
|
||||
0xf3 song select 1 - song number
|
||||
0xf4 undefined
|
||||
0xf5 undefined
|
||||
0xf6 tune request 0
|
||||
0xf7 EOX (terminator) 0
|
||||
|
||||
The status bytes 0xf8 - 0xff are the so-called "real-time" messages.
|
||||
I will discuss these after the accumulated notes concerning the
|
||||
first bunch.
|
||||
|
||||
Song position / song select are for control of sequencers. The
|
||||
song position is in beats, which are to be interpreted as every
|
||||
6 MIDI clock pulses. These messages determine what is to be played
|
||||
upon receipt of a "start" real-time message (see below).
|
||||
|
||||
The "tune request" is a command to analog synthesizers to tune their
|
||||
oscillators.
|
||||
|
||||
The system exclusive message is intended for manufacturers to use
|
||||
to insert any specific messages they want to which apply to their
|
||||
own product. The following data bytes are all to be "data" bytes,
|
||||
that is they are all to be in the range 0 - 127. The system exclusive
|
||||
is to be terminated by the 0xf7 terminator byte. The first data byte
|
||||
is also supposed to be a "manufacturer's id", assigned by a MIDI
|
||||
standards committee. THE TERMINATOR BYTE IS OPTIONAL - a system
|
||||
exclusive may also be "terminated" by the status byte of the next
|
||||
message.
|
||||
|
||||
>>
|
||||
Yamaha, in particular, caused problems by not sending terminator
|
||||
bytes. As I understand it, the DX-7 sends a system exclusive
|
||||
at something like 80 msec. intervals when it has nothing better
|
||||
to do, just so you know it's still there, I guess. The messages
|
||||
aren't explicitly terminated, so if you want to handle the
|
||||
protocol (esp. in hardware), you should be aware that a DX-7
|
||||
will leave you in "waiting for EOX" state a lot, and be sending
|
||||
data even when it isn't doing anything. This is all word of
|
||||
mouth, since I've never personally played with a DX-7.
|
||||
<<
|
||||
|
||||
some MIDI ID's:
|
||||
|
||||
Sequential Circuits 1 Bon Tempi 0x20 Kawai 0x40
|
||||
Big Briar 2 S.I.E.L. 0x21 Roland 0x41
|
||||
Octave / Plateau 3 Korg 0x42
|
||||
Moog 4 SyntheAxe 0x23 Yamaha 0x43
|
||||
Passport Designs 5
|
||||
Lexicon 6
|
||||
|
||||
PAIA 0x11
|
||||
Simmons 0x12
|
||||
Gentle Electric 0x13
|
||||
Fairlight 0x14
|
||||
|
||||
>>
|
||||
Note the USA / Europe / Japan grouping of codes. Also note
|
||||
that Sequential Circuits snarfed id number 1 - Sequential
|
||||
Circuits was one of the earliest participators in MIDI, some
|
||||
people claim its originator.
|
||||
|
||||
Two large makers missing from the original lineup were Casio
|
||||
and Oberheim. I know Oberheim is on the bandwagon now, and
|
||||
Casio also, I believe. Oberheim had their own protocol previous
|
||||
to MIDI, and when MIDI first came out they were reluctant to
|
||||
? go along with it. I wonder what we'd be looking at if Oberheim
|
||||
had pushed their ideas and made them the standard. From what I
|
||||
understand they thought THEIRS was better, and kind of sulked
|
||||
for a while until the market forced them to go MIDI.
|
||||
|
||||
? Nobody seems to care much about these ID numbers. I can only
|
||||
imagine them becoming useful if additions to the standard message
|
||||
set are placed into system exclusives, with the ID byte to let
|
||||
you know what added protocol is being used. Are any groups of
|
||||
manufacturers considering consolidating their efforts in a
|
||||
standard extension set via system exclusives?
|
||||
<<
|
||||
|
||||
REAL TIME MESSAGES.
|
||||
|
||||
This is the final group of status bytes, 0xf8 - 0xff. These bytes
|
||||
are reserved for messages which are called "real-time" messages
|
||||
because they are allowed to be sent ANYPLACE. This includes in
|
||||
between data bytes of other messages. A receiver is supposed to
|
||||
be able to receive and process (or ignore) these messages and
|
||||
resume collection of the remaining data bytes for the message
|
||||
which was in progress. Realtime messages do not affect the
|
||||
"running status byte" which might be in effect.
|
||||
|
||||
? Do any devices REALLY insert these things in the middle of
|
||||
other messages?
|
||||
|
||||
All of these messages have no data bytes following (or they could
|
||||
get interrupted themselves, obviously). The messages:
|
||||
|
||||
0xf8 timing clock
|
||||
0xf9 undefined
|
||||
0xfa start
|
||||
0xfb continue
|
||||
0xfc stop
|
||||
0xfd undefined
|
||||
0xfe active sensing
|
||||
0xff system reset
|
||||
|
||||
The timing clock message is to be sent at the rate of 24 clocks
|
||||
per quarter note, and is used to sync. devices, especially drum
|
||||
machines.
|
||||
|
||||
Start / continue / stop are for control of sequencers and drum
|
||||
machines. The continue message causes a device to pick up at the
|
||||
next clock mark.
|
||||
|
||||
>>
|
||||
These things are also designed for performance, allowing control
|
||||
of sequencers and drum machines from a "master" unit which
|
||||
sends the messages down the line when its buttons are pushed.
|
||||
|
||||
I can't tell you much about the trials and tribulations of drum
|
||||
machines. Other folks can, I am sure.
|
||||
<<
|
||||
|
||||
The active sensing byte is to be sent every 300 ms. or more often,
|
||||
if it is used. Its purpose is to implement a timeout mechanism
|
||||
for a receiver to revert to a default state. A receiver is to
|
||||
operate normally if it never gets one of these, activating the
|
||||
timeout mechanism from the receipt of the first one.
|
||||
|
||||
>>
|
||||
My impression is that active sensing is largely unused.
|
||||
<<
|
||||
|
||||
The system reset initializes to power up conditions. The spec. says
|
||||
that it should be used "sparingly" and in particular not sent
|
||||
automatically on power up.
|
||||
|
||||
AND NOW, CLIMBING TO THE PULPIT ....
|
||||
|
||||
>> - from here on out.
|
||||
|
||||
There are many deficiencies with MIDI, but it IS a standard. As such,
|
||||
it will have to be grappled with.
|
||||
|
||||
The electrical specification leaves me with only one question - WHY?
|
||||
What was wanted was a serial interface, and a perfectly good RS232
|
||||
specification was to be had. WHY wasn't it used? The baud rate is
|
||||
too fast to simply convert into something you can feed directly to
|
||||
your serial port via fairly dumb hardware, also. The "standard"
|
||||
baud rate step you would have to use would be 38.4 Kbaud which very
|
||||
few hardware interfaces accept. The other alternative is to buffer
|
||||
messages and send them out a slower baud rate - in fact buffering
|
||||
of characters by some kind of I/O processor is very helpful. Hence
|
||||
units like the MPU-401, which does a lot of other stuff, too of
|
||||
course.
|
||||
|
||||
The fast baud rate with MIDI was set for two reasons I believe:
|
||||
|
||||
1) to allow daisy-chaining of a few devices with no noticeable
|
||||
end to end lag.
|
||||
|
||||
2) to allow chords to be played by just sending all the notes down
|
||||
the pipe, the baud rate being fast enough that they will
|
||||
sound simultaneous.
|
||||
|
||||
It doesn't exactly work - I've heard gripes concerning end to end lag
|
||||
on three instrument chains. And consider chords - at two bytes (running
|
||||
status byte being used) per note, there will be a ten character lag
|
||||
between the trailing edges of the first and last notes of a six note
|
||||
chord. That's 3.2 ms., assuming no "dead air" between characters. It's
|
||||
still pretty fast, but on large chords with voices possessing distinctive
|
||||
attack characteristics, you may hear separate note beginnings.
|
||||
|
||||
I think MIDI could have used some means of packetizing chords, or having
|
||||
transaction markers. If a "chord" message were specified, you could easily
|
||||
break even on byte count with a few notes, given that we assume all notes
|
||||
of a chord at the same velocity. Transaction markers might be useful in
|
||||
any case, although I don't know if it would be worth taking over the
|
||||
remaining system message space for them. I would say yes. I would
|
||||
see having "start" and "end" transaction bytes. On receipt of a "start"
|
||||
a receiver buffers up but does not act on messages until receipt of the
|
||||
"end" byte. You could then do chords by sending the notes ahead of time,
|
||||
and precisely timing the "end" marker. Of course, the job of the hardware
|
||||
in the receiver has been complicated considerably.
|
||||
|
||||
The protocol is VERY keyboard oriented - take a look at the use of TWO
|
||||
of the opcodes in the limited opcode space for "pressure" messages,
|
||||
and the inability to specify semitones or glissando effects except
|
||||
through the pitch wheel (which took up yet ANOTHER of the opcodes).
|
||||
All keyboards I know of modify ALL playing notes when they receive
|
||||
pitch wheel data. Also, you have to use a continuous stream of
|
||||
pitch wheel messages to effect a slide, the pitch wheel step isn't
|
||||
standardized, and on a slide of a large number of tones you will
|
||||
overrun the range of the wheel.
|
||||
|
||||
? Some of these problems would be addressed by a device which allowed
|
||||
its pitch wheel to have selective control - say modifying only
|
||||
the notes playing on the channel the pitch wheel message is
|
||||
received in, for instance. The thing for a guitar synthesizer
|
||||
to do, then, would be to use mode 4, one channel per string, and
|
||||
bends would only affect the one note. You could play a chord
|
||||
on a voice with a lot of release, then bend a note and not have
|
||||
the entire still sounding chord bend. Any such devices?
|
||||
|
||||
I think some of the deficiencies in MIDI might be addressed by
|
||||
different communities of interest developing a standard set of
|
||||
system exclusives which answer the problem. One perfect area
|
||||
for this, I think, is a standard set for representation of "non-
|
||||
keyboard / drum machine" instruments which have continuous pitch
|
||||
capabilities. Like a pedal steel, for instance. Or non-western
|
||||
intervals. Like a sitar.
|
||||
|
||||
There is a crying need to do SOMETHING about the "loopback" problem.
|
||||
I would even vote for usurping a few more bytes in the mode messages
|
||||
to allow you to TURN OFF input echo by the receiver. With the
|
||||
local control message, you could then at least deal with something
|
||||
that would act precisely like a half or full duplex terminal.
|
||||
Several patchwork solutions exist to this problem, but there OUGHT
|
||||
to be a standard way of doing it within the protocol. Another
|
||||
thought is to allow data bytes of other than 0 or 127 to control
|
||||
echo on the existing local control message.
|
||||
|
||||
The lack of acknowledgement is a problem. Another candidate for a
|
||||
standard system exclusive set would be a series of messages for
|
||||
mode setting with acknowledgement. This set could then also
|
||||
take care of the loopback problem.
|
||||
|
||||
The complete lack of ability to specify standardized waveforms is
|
||||
probably another source of intense disappointment to many readers.
|
||||
Trouble is, the standard lingo used by the synthesizer industry and
|
||||
most working musicians is something which hails back to the first
|
||||
days of synthesizer design, deals with envelope generators and
|
||||
filters and VCO / LFO hardware parameters, and is very damn difficult
|
||||
to relate to Fourier series expressing the harmonic content or any other
|
||||
abstractions some people interested in doing computer composition
|
||||
would like. The parameter set used by the average synthesizer manufacturer
|
||||
isn't anyplace close to orthogonal in any sense, and is bound to vary
|
||||
wildly in comparison to anybody elses. There are essentially no
|
||||
abstractions made by most of the industry from underlying hardware
|
||||
parameters. What standardization exists reflects only the similarity
|
||||
in hardware. This is one quagmire that we have a long way to go to
|
||||
get out of, I think. It might be possible, eventually, to come up
|
||||
with translation tables describing the best way to approximate a
|
||||
desired sound on a given device in terms of its parameter set, but
|
||||
the difficulties are enormous. MIDI has chosen to punt on this one,
|
||||
folks.
|
||||
|
||||
Well, that's about it. Good luck with talking to your synthesizer.
|
||||
|
||||
Bob McQueer
|
||||
22 Bcy, 3151
|
||||
|
||||
All rites reversed. Reprint what you like.
|
||||
BIN
study/sabre/os/files/Sound/PAS_SDK_v3.0.zip
Normal file
BIN
study/sabre/os/files/Sound/PAS_SDK_v3.0.zip
Normal file
Binary file not shown.
1368
study/sabre/os/files/Sound/SoundBlaster/AWE32PRG-v1.0.TXT
Normal file
1368
study/sabre/os/files/Sound/SoundBlaster/AWE32PRG-v1.0.TXT
Normal file
File diff suppressed because it is too large
Load Diff
BIN
study/sabre/os/files/Sound/SoundBlaster/AWE32PRG.zip
Normal file
BIN
study/sabre/os/files/Sound/SoundBlaster/AWE32PRG.zip
Normal file
Binary file not shown.
205
study/sabre/os/files/Sound/SoundBlaster/DET-SB.PAS
Normal file
205
study/sabre/os/files/Sound/SoundBlaster/DET-SB.PAS
Normal file
@@ -0,0 +1,205 @@
|
||||
From : Ryan Nathan Thompson
|
||||
Subj : SB autodetect
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
Procedure SndWrite(Register, Data : Byte); assembler;
|
||||
Asm
|
||||
mov al, register
|
||||
mov dx, SndPort { read register }
|
||||
out dx, al
|
||||
in al, dx; in al, dx; { add a few more for the needed delay time }
|
||||
mov al, data
|
||||
inc dx { write register }
|
||||
out dx, al
|
||||
dec dx
|
||||
in al, dx; in al, dx; { add more for a proper delay }
|
||||
End;
|
||||
|
||||
Function SndRead : Byte; assembler;
|
||||
Asm
|
||||
mov dx, SndPort
|
||||
in al, dx
|
||||
End;
|
||||
|
||||
Procedure WriteDSP(Command : Byte); assembler;
|
||||
Asm
|
||||
mov cx, $ff
|
||||
mov dx, DSPWrite
|
||||
@Wait1:
|
||||
in al, dx
|
||||
or al, al
|
||||
jns @Wait2
|
||||
loop @Wait1
|
||||
@Wait2:
|
||||
mov al, Command
|
||||
out dx, al
|
||||
End;
|
||||
|
||||
Procedure CheckIRQ; assembler;
|
||||
Var
|
||||
Old2, Old3, Old5, Old7, Old9, Old10, Old11, Old12 : Pointer;
|
||||
Asm
|
||||
@ScanIRQ:
|
||||
cli
|
||||
in al, $21 { save the IMR. PIC1 }
|
||||
mov bl, al
|
||||
in al, $a1 { save the IMR. PIC2 }
|
||||
mov bh, al
|
||||
mov al, $ff { disable all the IRQs. }
|
||||
out $21, al { PIC1 }
|
||||
out $a1, al { PIC2 }
|
||||
xor ax, ax { trap the IRQs 2,3,5,7,10,11,12. }
|
||||
mov es, ax
|
||||
@SaveIrqs:
|
||||
mov ax, [es:$28] { irq2 } mov dx, [es:$2A]
|
||||
push ax push dx
|
||||
mov ax, [es:$2C] { irq3 } mov dx, [es:$2E]
|
||||
push ax push dx
|
||||
mov ax, [es:$34] { irq5 } mov dx, [es:$36]
|
||||
push ax push dx
|
||||
mov ax, [es:$3C] { irq7 } mov dx, [es:$3E]
|
||||
push ax push dx
|
||||
mov ax, [es:$134] { irq9 } mov dx, [es:$136]
|
||||
push ax push dx
|
||||
mov ax, [es:$138] { irq10 } mov dx, [es:$13a]
|
||||
push ax push dx
|
||||
mov ax, [es:$13c] { irq11 } mov dx, [es:$13e]
|
||||
push ax push dx
|
||||
mov ax, [es:$140] { irq12 } mov dx, [es:$142]
|
||||
push ax push dx
|
||||
@SetIrqs:
|
||||
mov ax, offset @TrapIrq2 { irq2 }
|
||||
mov [es:$28], ax mov [es:$2A], cs
|
||||
mov ax, offset @TrapIrq3 { irq3 }
|
||||
mov [es:$2C], ax mov [es:$2E], cs
|
||||
mov ax, offset @TrapIrq5 { irq5 }
|
||||
mov [es:$34], ax mov [es:$36], cs
|
||||
mov ax, offset @TrapIrq7 { irq7 }
|
||||
mov [es:$3C], ax mov [es:$3E], cs
|
||||
mov ax, offset @TrapIrq9 { irq9 }
|
||||
mov [es:$1c4], ax mov [es:$1c6], cs
|
||||
mov ax, offset @TrapIrq10 { irq10 }
|
||||
mov [es:$1c8], ax mov [es:$1ca], cs
|
||||
mov ax, offset @TrapIrq11 { irq11 }
|
||||
mov [es:$1cc], ax mov [es:$1ce], cs
|
||||
mov ax, offset @TrapIrq12 { irq12 }
|
||||
mov [es:$140], ax mov [es:$142], cs
|
||||
@EnableIrqs:
|
||||
mov al, bl
|
||||
and al, $53 { enable IRQs 2/Cascade,3,5,7. }
|
||||
out $21, al { PIC1 }
|
||||
mov al, bh
|
||||
and al, $e1 { enable IRQs 9,10,11,12. }
|
||||
out $a1, al { PIC2 }
|
||||
sti
|
||||
mov [SndIrq], 0 { clear the IRQ level. }
|
||||
mov dx, [DSPWrite] { Tell the SB to generate a IRQ! }
|
||||
@WaitSb:
|
||||
in al, dx
|
||||
or al, al
|
||||
js @WaitSb
|
||||
mov al, $F2
|
||||
out dx, al
|
||||
xor cx, cx { wait until IRQ level }
|
||||
@WaitIRQ:
|
||||
cmp [SndIrq], 0 { is changed or timeout. }
|
||||
jne @IrqOk
|
||||
loop @WaitIRQ
|
||||
@IrqOk:
|
||||
mov al, bl { restore IMR. }
|
||||
out $21, al { PIC1 }
|
||||
mov al, bh
|
||||
out $a1, al { PIC2 }
|
||||
cli { restore IRQ vectors. }
|
||||
xor ax, ax
|
||||
mov es, ax { point to vector table }
|
||||
pop dx { irq12 } pop ax
|
||||
mov [es:$140], ax mov [es:$142], dx
|
||||
pop dx { irq11 } pop ax
|
||||
mov [es:$1cc], ax mov [es:$1ce], dx
|
||||
pop dx { irq10 } pop ax
|
||||
mov [es:$1c8], ax mov [es:$1ca], dx
|
||||
pop dx { irq9 } pop ax
|
||||
mov [es:$1c6], ax mov [es:$1c4], dx
|
||||
pop dx { irq7 } pop ax
|
||||
mov [es:$3C], ax mov [es:$3E], dx
|
||||
pop dx { irq5 } pop ax
|
||||
mov [es:$34], ax mov [es:$36], dx
|
||||
pop dx { irq3 } pop ax
|
||||
mov [es:$2C], ax mov [es:$2E], dx
|
||||
pop dx { irq2 } pop ax
|
||||
mov [es:$28], ax mov [es:$2A], dx
|
||||
cli
|
||||
jmp @Done { Exit test }
|
||||
@TrapIrq2:
|
||||
push ax mov al, 2 jmp @TrapIrq
|
||||
@TrapIrq3:
|
||||
push ax mov al, 3 jmp @TrapIrq
|
||||
@TrapIrq5:
|
||||
push ax mov al, 5 jmp @TrapIrq
|
||||
@TrapIrq7:
|
||||
push ax mov al, 7 jmp @TrapIrq
|
||||
@TrapIrq9:
|
||||
push ax mov al, 9 jmp @TrapIrq
|
||||
@TrapIrq10:
|
||||
push ax mov al, 10 jmp @TrapIrq
|
||||
@TrapIrq11:
|
||||
push ax mov al, 11 jmp @TrapIrq
|
||||
@TrapIrq12:
|
||||
push ax mov al, 12
|
||||
@TrapIrq:
|
||||
push dx { General IRQ trapper }
|
||||
push ds { used for IRQ autodetect. }
|
||||
mov dx, seg SndIRQ
|
||||
mov ds, dx
|
||||
mov [SndIRQ], al { save IRQ level. }
|
||||
mov dx, [DSPStatus]
|
||||
in al, dx { SB acknowledge. }
|
||||
mov al, $20
|
||||
out $20, al { Hardware acknowledge PIC1 }
|
||||
out $a0, al { Hardware acknowledge PIC2 }
|
||||
pop ds pop dx pop ax
|
||||
iret { bye! }
|
||||
@Done:
|
||||
End;
|
||||
|
||||
Function CheckSound : Boolean;
|
||||
Var
|
||||
Ver : Byte;
|
||||
Function CheckPort(TestPort : Word) : Boolean;
|
||||
Begin
|
||||
SndPort:= TestPort;
|
||||
if Port[SndPort] < $ff then begin
|
||||
SndWrite(4, $60); SndWrite(4, $80); SndWrite(2, $ff);
|
||||
If SndRead and $e0 = 0 then begin
|
||||
SndWrite(4, $21);
|
||||
if SndRead and $e0 = $c0 then CheckPort:= true
|
||||
else CheckPort:= false;
|
||||
SndWrite(4, $60); SndWrite(4, 0); DSPStatus:= SndPort + $e;
|
||||
DSPRead:= SndPort + $a; DSPWrite:= SndPort + $c;
|
||||
end
|
||||
else CheckPort:= false;
|
||||
end;
|
||||
End;
|
||||
|
||||
Begin
|
||||
SndCard:= 'None detected'; If CheckPort($388) then begin
|
||||
SndCard:= 'AdLib'; If CheckPort($220) or CheckPort($240) or
|
||||
CheckPort($260) or CheckPort($280) then begin
|
||||
Port[DSPWrite]:= $e1; Delay(10); Ver:= Port[DSPRead];
|
||||
Case Ver of
|
||||
1, 2: SndCard:= 'SoundBlaster v';
|
||||
3: SndCard:= 'SB Pro v';
|
||||
4: SndCard:= 'SB16 v';
|
||||
5: SndCard:= 'AWE32 v';
|
||||
else SndCard:= 'SB-compatible v';
|
||||
End; Delay(10);
|
||||
SndCard:= SndCard + Stringof(Ver) + '.' + Stringof(Port[DSPRead]);
|
||||
CheckIRQ;
|
||||
end;
|
||||
end
|
||||
else SndPort:= 0;
|
||||
End;
|
||||
|
||||
--- Renegade v10-05 Exp
|
||||
* Origin: The BBS at Pooh Corner 707-445-0500/0599 14.4/28.8 (1:125/47)
|
||||
1253
study/sabre/os/files/Sound/SoundBlaster/SB-v1.31B.PAS
Normal file
1253
study/sabre/os/files/Sound/SoundBlaster/SB-v1.31B.PAS
Normal file
File diff suppressed because it is too large
Load Diff
388
study/sabre/os/files/Sound/SoundBlaster/SB16DOC.TXT
Normal file
388
study/sabre/os/files/Sound/SoundBlaster/SB16DOC.TXT
Normal file
@@ -0,0 +1,388 @@
|
||||
/-------------------------------------\
|
||||
| Programming the SoundBlaster 16 DSP |
|
||||
| Written by Ethan Brodsky |
|
||||
| Version 2.3 |
|
||||
\-------------------------------------/
|
||||
/----------------------------------------------------------------------------
|
||||
| Introduction |
|
||||
\--------------/
|
||||
|
||||
The Sound Blaster 16 is capable of both FM and digitized sounds. Digitized
|
||||
sound capibilities range from 8-bit mono 5000 HZ sound all the way up to
|
||||
16-bit stereo sound at 44khz. This FAQ documents programming the SB16 DSP
|
||||
CT1341 chip for recording and playback of digitized audio. Prior knowledge
|
||||
on programming earlier Sound Blaster sound cards is necessary.
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| The Sound Blaster 16 DSP I/O Ports |
|
||||
\------------------------------------/
|
||||
|
||||
The SB16's DSP chip is programming using several I/O ports at a base I/O
|
||||
address determined by jumper settings. On the SB16, there are 16 I/O ports
|
||||
which are used for FM synthesized music, mixer settings, DSP programming and
|
||||
CD-ROM access. Five of these ports are used in programming the DSP. They
|
||||
are listed below.
|
||||
|
||||
2x6h - DSP Reset
|
||||
2xAh - DSP Read
|
||||
2xCh - DSP Write (Command/Data), DSP write-buffer status (Bit 7)
|
||||
2xEh - DSP Read-buffer status (Bit 7), DSP interrupt acknowledge
|
||||
2xFh - DSP 16-bit interrupt acknowledge
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Resetting the DSP |
|
||||
\-------------------/
|
||||
|
||||
You have to reset the DSP before you can program it. The DSP can be reset
|
||||
using the following procedure:
|
||||
1) Write a 1 to the reset port (2x6)
|
||||
2) Wait for 3 microseconds
|
||||
3) Write a 0 to the reset port (2x6)
|
||||
4) Poll the read-buffer status port (2xE) until bit 7 is set
|
||||
5) Poll the read data port (2xA) until you receive an AA
|
||||
|
||||
The DSP usually takes about 100 microseconds to initialized itself. After
|
||||
this period of time, if the return value is not AA or there is no data at
|
||||
all, then the SB card may not be installed or an incorrect I/O address is
|
||||
being used.
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Writing to the DSP |
|
||||
\--------------------/
|
||||
|
||||
To write a byte to the SB16, the following procedure should be used:
|
||||
1) Read the write-buffer status port (2xC) until bit 7 is cleared
|
||||
2) Write the value to the write port (2xC)
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Reading the DSP |
|
||||
\-----------------/
|
||||
|
||||
To read a byte from the SB16, the following procedure should be used:
|
||||
1) Read the read-buffer status port (2xE) until bit 7 is set
|
||||
2) Read the value from the read port (2xA)
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Programming the DMA Controller |
|
||||
\--------------------------------/
|
||||
|
||||
The DMA (Direct Memory Access) controller controls data transfers between
|
||||
I/O devices and memory without using the CPU. An Intel 8237 DMAC integrated
|
||||
circut is used to control this. An IBM compatible computer has two DMA
|
||||
controllers, one for 8-bit transfers and one for 16-bit transfers. The DMA
|
||||
controller, coupled with an external page register, is capable of transfering
|
||||
blocks of up 64k to the SB16. Here is information on I/O ports and register
|
||||
settings necessary for sound card I/O:
|
||||
|
||||
I/O port addresses for the DMA Address and Count Registers
|
||||
/----------------------------------------------\
|
||||
| Controller | I/O address | Function |
|
||||
|------------+-------------+-------------------|
|
||||
| DMA 1 | 00 | Channel 0 address |
|
||||
| 8-bit | 01 | Channel 0 count |
|
||||
| Slave | 02 | Channel 1 address |
|
||||
| | 03 | Channel 1 count |
|
||||
| | 04 | Channel 2 address |
|
||||
| | 05 | Channel 2 count |
|
||||
| | 06 | Channel 3 address |
|
||||
| | 07 | Channel 3 count |
|
||||
|------------+-------------+-------------------|
|
||||
| DMA 2 | C0 | Channel 4 address |
|
||||
| 16-bit | C2 | Channel 4 count |
|
||||
| Master | C4 | Channel 5 address |
|
||||
| | C6 | Channel 5 count |
|
||||
| | C8 | Channel 6 address |
|
||||
| | CA | Channel 6 count |
|
||||
| | CC | Channel 7 address |
|
||||
| | CE | Channel 7 count |
|
||||
\----------------------------------------------/
|
||||
|
||||
I/O port addresses for the control registers
|
||||
/--------------------------------------------------------\
|
||||
| Address | Operation | Function |
|
||||
| DMAC1 DMAC2 | | |
|
||||
|-------------+-----------+------------------------------|
|
||||
| 0A D4 | Write | Write single mask register |
|
||||
| 0B D6 | Write | Write mode register |
|
||||
| 0C D8 | Write | Clear byte pointer flip-flop |
|
||||
\--------------------------------------------------------/
|
||||
|
||||
I/O port addresses for lower page registers
|
||||
/--------------------------------------\
|
||||
| Address | Function |
|
||||
|---------+----------------------------|
|
||||
| 81 | 8-bit DMA channel 2 page |
|
||||
| 82 | 8-bit DMA channel 3 page |
|
||||
| 83 | 8-bit DMA channel 1 page |
|
||||
| 87 | 8-bit DMA channel 0 page |
|
||||
| 89 | 16-bit DMA channel 6 page |
|
||||
| 8A | 16-bit DMA channel 7 page |
|
||||
| 8B | 16-bit DMA channel 5 page |
|
||||
\--------------------------------------/
|
||||
|
||||
Mode register bit assignments
|
||||
-----------------------------------------------
|
||||
| Bit/Value | Function |
|
||||
|-----------+---------------------------------|
|
||||
| Bits 7:6 | Mode selection bits |
|
||||
| 00 | Demand mode selected |
|
||||
| 01 | Single mode selected |
|
||||
| 10 | Block mode selected |
|
||||
| 11 | Cascade mode selected |
|
||||
|-----------+---------------------------------|
|
||||
| Bit 5 | Address increment/decrement bit |
|
||||
| 1 | Address decrement selected |
|
||||
| 0 | Address increment selected |
|
||||
|-----------+---------------------------------|
|
||||
| Bit 4 | Auto-initialization enable bit |
|
||||
| 1 | Auto-initialized DMA selected |
|
||||
| 0 | Single-cycle DMA selected |
|
||||
|-----------+---------------------------------|
|
||||
| Bits 3:2 | Transfer bits |
|
||||
| 00 | Verify transfer |
|
||||
| 01 | Write transfer (To memory) |
|
||||
| 10 | Read transfer (From memory) |
|
||||
| 11 | Illegal |
|
||||
| ** | Ignored if bits 7:6 = 11 |
|
||||
|-----------+---------------------------------|
|
||||
| Bits 1:0 | Channel selection bits |
|
||||
| 00 | Select channel 0 (4) |
|
||||
| 01 | Select channel 1 (5) |
|
||||
| 10 | Select channel 2 (6) |
|
||||
| 11 | Select channel 3 (7) |
|
||||
\---------------------------------------------/
|
||||
|
||||
Write single mask bit assignments
|
||||
/----------------------------------------------\
|
||||
| Bit/Value | Function |
|
||||
|-----------+----------------------------------|
|
||||
| Bits 7:3 | Unused (Set to 0) |
|
||||
|-----------+----------------------------------|
|
||||
| Bit 2 | Set/clear mask bit |
|
||||
| 1 | Set mask bit (Disable channel) |
|
||||
| 0 | Clear mask bit (Enable channel) |
|
||||
|-----------+----------------------------------|
|
||||
| Bits 1:0 | Channel selection bits |
|
||||
| 00 | Select channel 0 (4) |
|
||||
| 01 | Select channel 1 (5) |
|
||||
| 10 | Select channel 2 (6) |
|
||||
| 11 | Select channel 3 (7) |
|
||||
\----------------------------------------------/
|
||||
|
||||
DMAC2 is used for 16-bit I/O and DMAC1 is used for 8-bit I/O. The procedure
|
||||
for starting a transfer is complicated, so I'll list the steps for starting
|
||||
the type of DMA transfers used for sound I/O:
|
||||
|
||||
1) Calculate the absolute linear address of your buffer
|
||||
LinearAddr := Seg(Ptr^)*16 - Ofs(Ptr^));
|
||||
|
||||
2) Disable the sound card DMA channel by setting the appropriate mask bit
|
||||
Port[MaskPort] := 1 - (Channel mod 4);
|
||||
|
||||
3) Clear the byte pointer flip-flop
|
||||
Port[ClrBytePtr] := AnyValue;
|
||||
|
||||
4) Write the DMA mode for the transfer
|
||||
The mode selection bits should be set to 00 for demand mode. The
|
||||
address inc/dec bit should be set to 0 for address increment. The
|
||||
auto-initialization bit should be set appropriately. I will discuss
|
||||
auto-initialized DMA later. The transfer bits should be set to 10
|
||||
for playback and 01 for recording. The channel select should be
|
||||
set to the sound card DMA channel. Be aware that "read" means a read
|
||||
from memory (Write to sound card) and that "write" means a write to
|
||||
system memory (Read from sound card)
|
||||
Port[ModePort] := Mode - (Channel mod 4);
|
||||
Some often used modes are:
|
||||
48h-Channel - Single-cycle playback
|
||||
58h-Channel - Auto-initialized playback
|
||||
44h-Channel - Single-cycle recording
|
||||
54h-Channel - Auto-initialized recording
|
||||
|
||||
5) Write the offset of the buffer, low byte followed by high byte. For
|
||||
sixteen bit data, the offset should be in words from the start of a
|
||||
128kbyte page. The easiest method for computing 16-bit parameters is
|
||||
to divide the linear address by two before calculating offset.
|
||||
if SixteenBit
|
||||
then
|
||||
begin
|
||||
BufOffset := (LinearAddr div 2) mod 65536;
|
||||
Port[BaseAddrPort] := Lo(BufOffset);
|
||||
Port[BaseAddrPort] := Hi(BufOffset);
|
||||
end
|
||||
else
|
||||
begin
|
||||
BufOffset := LinearAddr mod 65536;
|
||||
Port[BaseAddrPort] := Lo(BufOffset);
|
||||
Port[BaseAddrPort] := Hi(BufOffset);
|
||||
end;
|
||||
|
||||
6) Write the transfer length, low byte followed by high byte. For an
|
||||
8-bit transfer, write the number of bytes-1. For a 16-bit transfer,
|
||||
write the number of words-1.
|
||||
Port[CountPort] := Lo(TransferLength-1);
|
||||
Port[CountPort] := Hi(TransferLength-1);
|
||||
|
||||
7) Write the buffer page to the DMA page register.
|
||||
Port[PagePort] := LinearAddr div 65536;
|
||||
|
||||
8) Enable the sound card DMA channel by clearing the appropriate mask bit
|
||||
Port[MaskPort] := DMAChannel mod 4;
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Setting the sampling rate |
|
||||
\---------------------------/
|
||||
|
||||
Unlike earlier Sound Blasters, the SB16 is programmed with actual sampling
|
||||
rates instead of time constants. On the SB16, the sampling rate is set
|
||||
using DSP commands 41h and 42h. Command 41h is used for output and 42h is
|
||||
used for input. I have heard that on the SB16, both these command currently
|
||||
do the same thing, but I would recommend using the individual commands to
|
||||
guarantee compatibility with future sound cards. The procedure for setting
|
||||
the sampling rate is:
|
||||
1) Write the command (41h for output rate, 42h for input rate)
|
||||
2) Write the high byte of the sampling rate (56h for 22050 hz)
|
||||
3) Write the low byte of the sampling rate (22h for 22050 hz)
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Digitized sound I/O |
|
||||
\---------------------/
|
||||
|
||||
To record or play back sound, you should use the following sequence:
|
||||
|
||||
1) Allocate a buffer that does not cross a 64k physical page boundary
|
||||
2) Install an interrupt service routine
|
||||
3) Program the DMA controller for background transfer
|
||||
4) Set the sampling rate
|
||||
5) Write the I/O command to the DSP
|
||||
6) Write the I/O transfer mode to the DSP
|
||||
7) Write the block size to the DSP (Low byte/High byte)
|
||||
|
||||
Upon interrupt when using single-cycle DMA:
|
||||
1) Program DMA controller for next block
|
||||
2) Program DSP for next block
|
||||
3) Copy next block if double-buffering
|
||||
4) Acknowledge the interrupt with the SB by reading from port 2xE for
|
||||
8-bit sound or port 2xF for 16-bit sound.
|
||||
5) Acknowledge the end of interrupt with the PIC by writing 20h to port
|
||||
20h. If the sound card is on IRQ8-15, you must also write 20h to A0h.
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| DSP commands |
|
||||
\--------------/
|
||||
|
||||
D0 - Pause 8-bit DMA mode digitized sound I/O initiated by command Cxh.
|
||||
Applicable to both single-cycle and auto-initialized DMA I/O.
|
||||
D4 - Continue 8-bit DMA mode digitized sound I/O paused using command D0.
|
||||
Applicable to both single-cycle and auto-initialzied DMA I/O.
|
||||
|
||||
D5 - Pause 16-bit DMA mode digitized sound I/O initiated by command Bxh.
|
||||
Applicable to both single-cycle and auto-initialized DMA I/O.
|
||||
D6 - Continue 16-bit DMA mode digitized sound I/O paused using command D5
|
||||
Applicable to both single-cycle and auto-initialized DMA I/O.
|
||||
|
||||
D9 - Exit 16-bit auto-initialized DMA mode digitized sound I/O after the
|
||||
end of the current block.
|
||||
DA - Exit 8-bit auto-initialized DMA mode digitized sound I/O after the
|
||||
end of the current block.
|
||||
|
||||
E1 - Get DSP version number. After sending this command, read back two
|
||||
bytes form the DSP. The first byte is the major version number and
|
||||
the second byte is the minor version number. A SB16 should have a
|
||||
DSP version of 4.00 or greater. Check this before using an SB16
|
||||
specific commands.
|
||||
|
||||
Bx - Program 16-bit DMA mode digitized sound I/O
|
||||
Command sequence: Command, Mode, Lo(Length-1), Hi(Length-1)
|
||||
Command:
|
||||
/-----------------------------------------------\
|
||||
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
|----+----+----+----+-------+------+-------+----|
|
||||
| 1 | 0 | 1 | 1 | A/D | A/I | FIFO | 0 |
|
||||
\-------------------+-------+------+-------+----/
|
||||
| 0=D/A | 0=SC | 0=off |
|
||||
| 1=A/D | 1=AI | 1=on |
|
||||
\----------------------/
|
||||
Mode:
|
||||
/-----------------------------------------------------\
|
||||
| D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
|----+----+----------+------------+----+----+----+----|
|
||||
| 0 | 0 | Stereo | Signed | 0 | 0 | 0 | 0 |
|
||||
\--------------------+--------------------------------/
|
||||
| 0=Mono | 0=unsigned |
|
||||
| 1=Stereo | 1=signed |
|
||||
\-----------------------/
|
||||
|
||||
Cx - Program 8-bit DMA mode digitized sound I/O
|
||||
Same procedure as 16-bit sound I/O using command Bx
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| Auto-initialized DMA |
|
||||
\----------------------/
|
||||
|
||||
When single-cycle DMA is used, sound output stops at the end of each block.
|
||||
The interrupt handler can start another transfer, but there will be a break
|
||||
in output. This causes a click between each block, reducing sound quality.
|
||||
When auto-initialized DMA is used, sound output loops around at the end of
|
||||
the buffer. The DMA controller keeps transfering the same block of memory
|
||||
that the DMA transfer was initiated with. When the end of the buffer is
|
||||
reached, it will start sending the buffer again by auto-initializing the
|
||||
current offset and count registers with the values stored in the base offset
|
||||
and count registers. The usual method for achieving click-less output is to
|
||||
allocate a buffer and divide it into two blocks. Program the DMA controller
|
||||
with the length of the whole buffer, but program the SB16 with the length of
|
||||
a block. (Half of the buffer) An interrupt occurs for each sound card block,
|
||||
so two interrupts will occur each time the buffer is played, once at the
|
||||
midpoint (Start of the second block) and once at the end (In effect, the
|
||||
start of the first block) The interrupt handler should copy data into the
|
||||
block that was just finished so that the data is ready when it is needed for
|
||||
output. The programming procedure for an auto-initialized DMA transfer is
|
||||
identical to the procedure for a single-cycle DMA transfer, except that bit
|
||||
4 of the DMA mode register and bit 3 of the DSP command are set.
|
||||
|
||||
Upon interrupt when using auto-initialized DMA:
|
||||
1) Copy next chunk into output buffer block that just finished
|
||||
4) Acknowledge the interrupt with the SB by reading from port 2xE for
|
||||
8-bit sound or port 2xF for 16-bit sound.
|
||||
5) Acknowledge the end of interrupt with the PIC by writing 20h to port
|
||||
20h. If the sound card is on IRQ8-15, you must also write 20h to A0h.
|
||||
|
||||
To stop sound immediately:
|
||||
8-bit - Write DSP command D0h (Pause 8-bit DMA mode digitized sound I/O)
|
||||
16-bit - Write DSP command D5h (Pause 16-bit DMA mode digitized sound I/O)
|
||||
(Stops sound immediately, without an interrupt)
|
||||
|
||||
To stop the sound at the end of the currently block:
|
||||
8-bit - Write DSP command DAh (Stop 8-bit auto-init DMA sound I/O)
|
||||
16-bit - Write DSP command D9h (Stop 16-bit auto-init DMA sound I/O)
|
||||
(These two commands will stop the sound at the end of the current
|
||||
block. If your program is not prepared for an interrupt after output
|
||||
is finished, it may cause problems)
|
||||
|
||||
You can also end auto-initialized mode by reprogramming the DSP for
|
||||
single-cycle mode. The card then switches from A/I mode to S/C mode after
|
||||
the next interrupt. It will then contiue to play or record for the length
|
||||
specified, generate an interrupt and stop. This will allow you to stop
|
||||
output exactly at the end of the data, without requiring the remainder of
|
||||
the DMA buffer to be filled with silence. This technique may or may not
|
||||
be useful to you. I would recommend using the pause commands documented
|
||||
in in the immediate stop section unless another method is more suited to
|
||||
your purpose.
|
||||
|
||||
/----------------------------------------------------------------------------
|
||||
| References |
|
||||
\------------/
|
||||
|
||||
Title: Developer Kit for the Sound Blaster Series, Second Edition.
|
||||
Publishers: Creative Technology Ltd.
|
||||
|
||||
Title: Intel 486 Microcomputer Model 401 Board Technical Ref. Manual
|
||||
Publisher: Intel Corporation
|
||||
Order-number: 504366-002
|
||||
|
||||
Title: 8237A High Performance Programmable DMA Controller specs
|
||||
Publisher: Intel Corporation
|
||||
Order-number: 231466-005
|
||||
|
||||
Title: 8259A Programmable Interrupt Controller specs
|
||||
Publisher: Intel Corporation
|
||||
Order-number: 231468-003
|
||||
374
study/sabre/os/files/Sound/SoundBlaster/SBDETECT.ASM
Normal file
374
study/sabre/os/files/Sound/SoundBlaster/SBDETECT.ASM
Normal file
@@ -0,0 +1,374 @@
|
||||
WAIT_TIME EQU 000FFh
|
||||
DSP_INTRQ_CMD EQU 000F2h
|
||||
|
||||
DATA SEGMENT WORD PUBLIC
|
||||
|
||||
EXTRN SBInt : WORD;
|
||||
EXTRN SBIrq : WORD;
|
||||
|
||||
ORG_INT2_ADDX DD 0;
|
||||
ORG_INT3_ADDX DD 0;
|
||||
ORG_INT5_ADDX DD 0;
|
||||
ORG_INT7_ADDX DD 0;
|
||||
|
||||
DATA ENDS
|
||||
|
||||
CODE SEGMENT WORD PUBLIC
|
||||
ASSUME CS:CODE,DS:DATA
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; ResetDSP - reset the DSP
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
ResetDSP PROC
|
||||
|
||||
MOV DX,SBInt
|
||||
ADD DL,6 ; DX = DSP reset port 2x6h
|
||||
MOV AL,1
|
||||
OUT DX,AL ; write 1, then wait 3 micro-seconds
|
||||
|
||||
IN AL,DX ; read value from DSP
|
||||
RDSP05:
|
||||
INC AL
|
||||
JNZ RDSP05 ; wait until AL = 0
|
||||
|
||||
OUT DX,AL ; write 0
|
||||
|
||||
MOV CL,20H ; set reset timeout value
|
||||
|
||||
RDSP10:
|
||||
CALL ReadDSPTime ; read from DSP
|
||||
CMP AL,0AAH ; if byte is 0AAh then
|
||||
JE RDSP20 ; DSP is reset, exit
|
||||
|
||||
LOOP RDSP10 ; not reset, try again
|
||||
|
||||
MOV AX,2 ; set I/O failure error
|
||||
JMP SHORT RDSP90 ; exit;
|
||||
|
||||
RDSP20:
|
||||
XOR AX,AX ; clear AX, no error
|
||||
|
||||
RDSP90:
|
||||
OR AX,AX ; set flags for return
|
||||
|
||||
RET
|
||||
|
||||
ResetDSP ENDP
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; ReadDSPTime - read from DSP with timeout
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
ReadDSPTime PROC
|
||||
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
|
||||
MOV DX,SBInt
|
||||
ADD DL,0EH ; DX = DSP data available port 2xEh
|
||||
|
||||
MOV CX,WAIT_TIME ; load timeout value into CX
|
||||
|
||||
RDT10:
|
||||
IN AL,DX ; check to see if DSP is ready
|
||||
OR AL,AL
|
||||
JS RDT20 ; if sign set, then DSP read ready
|
||||
|
||||
LOOP RDT10 ; not ready, keep waiting
|
||||
|
||||
STC ; set error, DSP read timeout
|
||||
JMP SHORT RDT90 ; exit
|
||||
|
||||
RDT20:
|
||||
SUB DL,4 ; DX = DSP read data port 2xAh
|
||||
IN AL,DX ; read byte from DSP
|
||||
CLC ; clear error
|
||||
|
||||
RDT90:
|
||||
POP DX
|
||||
POP CX
|
||||
|
||||
RET
|
||||
|
||||
ReadDSPTime ENDP
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; CheckSBInt - detect DMA interrupt
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
PUBLIC CheckSBInt
|
||||
|
||||
CheckSBInt PROC FAR
|
||||
|
||||
push bp
|
||||
mov bp,sp
|
||||
|
||||
MOV AL,2 ; setup end of DMA
|
||||
MOV DX,OFFSET DUMMY_DMA_INT2 ; interrupts for all
|
||||
MOV BX,OFFSET DATA:ORG_INT2_ADDX ; possible IRQs
|
||||
CALL SetupInterrupt ; (2, 3, 5, and 7)
|
||||
|
||||
MOV AL,3
|
||||
MOV DX,OFFSET DUMMY_DMA_INT3
|
||||
MOV BX,OFFSET DATA:ORG_INT3_ADDX
|
||||
CALL SetupInterrupt
|
||||
|
||||
MOV AL,5
|
||||
MOV DX,OFFSET DUMMY_DMA_INT5
|
||||
MOV BX,OFFSET DATA:ORG_INT5_ADDX
|
||||
CALL SetupInterrupt
|
||||
|
||||
MOV AL,7
|
||||
MOV DX,OFFSET DUMMY_DMA_INT7
|
||||
MOV BX,OFFSET DATA:ORG_INT7_ADDX
|
||||
CALL SetupInterrupt
|
||||
|
||||
MOV SBIrq,0 ; reset current IRQ
|
||||
|
||||
MOV DX,SBInt
|
||||
ADD DX,0CH ; DX = DSP write port 2xCh
|
||||
MOV AL,DSP_INTRQ_CMD ; AL = interrupt request command
|
||||
CALL WriteDSP ; write command to DSP
|
||||
|
||||
XOR AX,AX ; assume success
|
||||
MOV CX,WAIT_TIME ; load timeout value into CX
|
||||
CLD
|
||||
|
||||
VI10:
|
||||
CMP SBIrq,0 ; see if interrupt has been changed
|
||||
JNE VI90 ; if so, continue
|
||||
|
||||
LOOP VI10 ; if not, keep waiting
|
||||
|
||||
MOV AX,0FFh ; set DMA failure error
|
||||
|
||||
VI90:
|
||||
PUSH AX ; save result variable
|
||||
|
||||
MOV AL,2 ; restore end of DMA
|
||||
MOV BX,OFFSET DATA:ORG_INT2_ADDX ; interrupts
|
||||
CALL RestoreInterrupt
|
||||
|
||||
MOV AL,3
|
||||
MOV BX,OFFSET DATA:ORG_INT3_ADDX
|
||||
CALL RestoreInterrupt
|
||||
|
||||
MOV AL,5
|
||||
MOV BX,OFFSET DATA:ORG_INT5_ADDX
|
||||
CALL RestoreInterrupt
|
||||
|
||||
MOV AL,7
|
||||
MOV BX,OFFSET DATA:ORG_INT7_ADDX
|
||||
CALL RestoreInterrupt
|
||||
|
||||
POP AX ; restore result
|
||||
|
||||
OR AX,AX
|
||||
|
||||
mov sp,bp
|
||||
pop bp
|
||||
|
||||
RET
|
||||
|
||||
CheckSBInt ENDP
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; WriteDSP
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
WriteDSP PROC
|
||||
|
||||
PUSH CX
|
||||
|
||||
MOV AH,AL ; save value in AL for later
|
||||
|
||||
MOV CX,WAIT_TIME
|
||||
|
||||
WD10:
|
||||
IN AL,DX ; check to see if DSP is ready
|
||||
OR AL,AL
|
||||
JNS WD20 ; if sign set, DSP not write ready
|
||||
LOOP WD10
|
||||
|
||||
WD20:
|
||||
MOV AL,AH ; restore AL
|
||||
OUT DX,AL ; send byte to DSP
|
||||
|
||||
POP CX
|
||||
|
||||
RET
|
||||
|
||||
WriteDSP ENDP
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; SetupInterrupt
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
SetupInterrupt PROC
|
||||
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
|
||||
CLI
|
||||
|
||||
MOV CL,AL ; preserve interrupt number for use
|
||||
|
||||
ADD AL,8 ; calculate interrupt vector addx
|
||||
CBW
|
||||
SHL AL,1
|
||||
SHL AL,1
|
||||
MOV DI,AX
|
||||
|
||||
PUSH ES ; setup and preserve interrupt
|
||||
XOR AX,AX
|
||||
MOV ES,AX
|
||||
MOV AX,ES:[DI]
|
||||
MOV [BX],AX
|
||||
MOV ES:[DI],DX
|
||||
|
||||
MOV AX,ES:[DI+2]
|
||||
MOV [BX+2],AX
|
||||
MOV ES:[DI+2],CS
|
||||
|
||||
POP ES
|
||||
|
||||
MOV AH,1 ; enable interrupt control mask-bit
|
||||
SHL AH,CL
|
||||
NOT AH
|
||||
|
||||
IN AL,21H
|
||||
AND AL,AH
|
||||
OUT 21H,AL
|
||||
|
||||
STI
|
||||
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
|
||||
RET
|
||||
|
||||
SetupInterrupt ENDP
|
||||
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; RestoreInterrupt
|
||||
;
|
||||
; ENTRY: AL = INTERRUPT NUM
|
||||
; BX = offset to stored addx
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
RestoreInterrupt PROC
|
||||
|
||||
CLI
|
||||
|
||||
MOV CL,AL
|
||||
|
||||
ADD AL,8 ; calculate interrupt vector addx
|
||||
CBW
|
||||
SHL AL,1
|
||||
SHL AL,1
|
||||
MOV DI,AX
|
||||
|
||||
PUSH ES ; restore interrupt vector
|
||||
XOR AX,AX
|
||||
MOV ES,AX
|
||||
MOV AX,[BX]
|
||||
MOV ES:[DI],AX
|
||||
|
||||
MOV AX,[BX+2]
|
||||
MOV ES:[DI+2],AX
|
||||
|
||||
POP ES
|
||||
|
||||
MOV AH,1
|
||||
SHL AH,CL
|
||||
|
||||
IN AL,21H
|
||||
OR AL,AH
|
||||
OUT 21H,AL
|
||||
|
||||
STI
|
||||
|
||||
RET
|
||||
|
||||
RestoreInterrupt ENDP
|
||||
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
;
|
||||
; DUMMY INTERRUPTS - used for interrupt detection
|
||||
;
|
||||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
DUMMY_DMA_INT2 PROC FAR
|
||||
|
||||
PUSH DX
|
||||
MOV DX,2
|
||||
JMP SHORT DUMMY_DMA_ISR
|
||||
|
||||
DUMMY_DMA_INT2 ENDP
|
||||
|
||||
|
||||
DUMMY_DMA_INT3 PROC FAR
|
||||
|
||||
PUSH DX
|
||||
MOV DX,3
|
||||
JMP SHORT DUMMY_DMA_ISR
|
||||
|
||||
DUMMY_DMA_INT3 ENDP
|
||||
|
||||
|
||||
DUMMY_DMA_INT5 PROC FAR
|
||||
|
||||
PUSH DX
|
||||
MOV DX,5
|
||||
JMP SHORT DUMMY_DMA_ISR
|
||||
|
||||
DUMMY_DMA_INT5 ENDP
|
||||
|
||||
|
||||
DUMMY_DMA_INT7 PROC FAR
|
||||
|
||||
PUSH DX
|
||||
MOV DX,7
|
||||
|
||||
DUMMY_DMA_ISR:
|
||||
PUSH AX
|
||||
PUSH DS
|
||||
|
||||
MOV AX,DATA
|
||||
MOV DS,AX
|
||||
|
||||
MOV SBIrq,DX ; update interrupt variable with
|
||||
; number of interrupt called
|
||||
MOV DX,SBInt
|
||||
ADD DX,0EH ; DX = DSP data available port 2xEh
|
||||
IN AL,DX ; acknowledge DSP interrupt
|
||||
|
||||
MOV AL,20H ; send EOI (end of interrupt) to
|
||||
OUT 20H,AL ; interrupt controller port 20h
|
||||
|
||||
POP DS
|
||||
POP AX
|
||||
POP DX
|
||||
IRET ; interrupt return
|
||||
|
||||
DUMMY_DMA_INT7 ENDP
|
||||
|
||||
CODE ENDS
|
||||
|
||||
END
|
||||
BIN
study/sabre/os/files/Sound/SoundBlaster/SBPROG10.ZIP
Normal file
BIN
study/sabre/os/files/Sound/SoundBlaster/SBPROG10.ZIP
Normal file
Binary file not shown.
184
study/sabre/os/files/Sound/SoundBlaster/SB_DSP.ASM
Normal file
184
study/sabre/os/files/Sound/SoundBlaster/SB_DSP.ASM
Normal file
@@ -0,0 +1,184 @@
|
||||
;---------------------------------------------------------------------------
|
||||
; SB_DSP.ASM -- Programmer's library for the Sound Blaster DSP interface
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
IDEAL
|
||||
MODEL small
|
||||
|
||||
DATASEG
|
||||
SB_IO_Port DW 0220h ;These values are kept here to avoid add
|
||||
DSP_Reset DW 0226h ;instructions in code that may be time-
|
||||
DSP_RDData DW 022Ah ;sensitive.
|
||||
DSP_Command DW 022Ch
|
||||
DSP_RDAvail DW 022Eh
|
||||
|
||||
DSP_WRData EQU DSP_Command ;Aliases for the same variable name
|
||||
DSP_Status EQU DSP_Command
|
||||
|
||||
CODESEG
|
||||
|
||||
PUBLIC _dsp_reset,_dsp_voice,_set_SB_address,_dsp_dma_prepare,_dsp_time
|
||||
|
||||
MACRO await_DSP
|
||||
LOCAL @@Wait_Ready
|
||||
push ax dx
|
||||
@@Wait_Ready:
|
||||
mov dx,[DSP_Status]
|
||||
in al,dx
|
||||
and al,128
|
||||
jnz @@Wait_Ready
|
||||
pop dx ax
|
||||
ENDM MACRO
|
||||
|
||||
|
||||
MACRO ten_microsec_delay
|
||||
LOCAL @@KT ;If you know of a better, more accurate,
|
||||
push cx ;more reliable, just plain smarter, way
|
||||
mov cx,20000 ;to do this, PLEASE TELL ME.
|
||||
@@KT: ;
|
||||
nop ;(The idea is to kill 10 microseconds.)
|
||||
loop @@KT ;
|
||||
pop cx ;email: heathh@cco.caltech.edu
|
||||
ENDM ten_microsec_delay
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; void far dsp_time(int pacing)
|
||||
;---------------------------------------------------------------------------
|
||||
; pacing = 255 - (1,000,000 / frequency)
|
||||
;---------------------------------------------------------------------------
|
||||
PROC _dsp_time FAR
|
||||
ARG delay:WORD
|
||||
push bp
|
||||
mov bp,sp
|
||||
push ax dx
|
||||
|
||||
await_DSP
|
||||
mov dx,[DSP_Command]
|
||||
mov al,040h
|
||||
out dx,al
|
||||
|
||||
await_DSP
|
||||
mov dx,[DSP_Command]
|
||||
mov ax,[delay]
|
||||
out dx,al
|
||||
pop dx ax
|
||||
pop bp
|
||||
ret
|
||||
ENDP _dsp_time
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; void far dsp_reset(void)
|
||||
;---------------------------------------------------------------------------
|
||||
PROC _dsp_reset FAR
|
||||
push ax dx
|
||||
|
||||
mov dx,[DSP_Reset]
|
||||
mov al,1
|
||||
out dx,al
|
||||
|
||||
ten_microsec_delay
|
||||
|
||||
mov al,0
|
||||
out dx,al
|
||||
|
||||
@@Wait_Ready:
|
||||
mov dx,[DSP_RDAvail]
|
||||
in al,dx
|
||||
and al,128
|
||||
jz @@Wait_Ready
|
||||
mov dx,[DSP_RDData]
|
||||
in al,dx
|
||||
cmp al,0AAh
|
||||
jne @@Wait_Ready
|
||||
|
||||
mov ax,165
|
||||
push ax
|
||||
call _dsp_time
|
||||
pop ax
|
||||
pop dx ax
|
||||
ret
|
||||
ENDP _dsp_reset
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; void far dsp_dma_prepare(int Dir,int Length)
|
||||
;---------------------------------------------------------------------------
|
||||
; Dir = 0 for Microphone Input, 1 for Speaker Output
|
||||
; Length = Length of data to be sampled/played
|
||||
;---------------------------------------------------------------------------
|
||||
PROC _dsp_dma_prepare FAR
|
||||
ARG Dir:WORD,Len:WORD
|
||||
push bp
|
||||
mov bp,sp
|
||||
push ax dx
|
||||
|
||||
await_DSP
|
||||
mov al,24h
|
||||
cmp [Dir],0
|
||||
jz @@Is_Read
|
||||
mov al,14h
|
||||
@@Is_Read:
|
||||
mov dx,[DSP_Command]
|
||||
out dx,al
|
||||
await_DSP
|
||||
mov ax,[Len]
|
||||
out dx,al
|
||||
await_DSP
|
||||
mov al,ah
|
||||
out dx,al
|
||||
|
||||
pop dx ax
|
||||
pop bp
|
||||
ret
|
||||
ENDP _dsp_dma_prepare
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; void far dsp_voice(Activity)
|
||||
;---------------------------------------------------------------------------
|
||||
; Activity = 0 for silent, 1 for audible
|
||||
;---------------------------------------------------------------------------
|
||||
PROC _dsp_voice FAR
|
||||
ARG Which:WORD
|
||||
push bp
|
||||
mov bp,sp
|
||||
push dx ax
|
||||
|
||||
await_DSP
|
||||
mov ax,[Which]
|
||||
and al,1 ;Want a 1/0 parameter
|
||||
xor al,1
|
||||
shl al,1
|
||||
or al,0D1h
|
||||
mov dx,[DSP_Command]
|
||||
out dx,al
|
||||
pop ax dx
|
||||
pop bp
|
||||
ret
|
||||
ENDP _dsp_voice
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; void far set_SB_address(int base)
|
||||
;---------------------------------------------------------------------------
|
||||
; Sets base port of SoundBlaster that other functions refer to.
|
||||
; Most likely value (and the default): 0x220
|
||||
;---------------------------------------------------------------------------
|
||||
PROC _set_SB_address FAR
|
||||
ARG Port:WORD
|
||||
push bp
|
||||
mov bp,sp
|
||||
push ax
|
||||
mov ax,[Port]
|
||||
mov [SB_IO_Port],ax
|
||||
add ax,6
|
||||
mov [DSP_Reset],ax
|
||||
add ax,4
|
||||
mov [DSP_RDData],ax
|
||||
add ax,2
|
||||
mov [DSP_Command],ax
|
||||
add ax,2
|
||||
mov [DSP_RDAvail],ax
|
||||
pop ax
|
||||
pop bp
|
||||
ret
|
||||
ENDP _set_SB_address
|
||||
END
|
||||
BIN
study/sabre/os/files/Sound/SoundBlaster/SOUNDX.ZIP
Normal file
BIN
study/sabre/os/files/Sound/SoundBlaster/SOUNDX.ZIP
Normal file
Binary file not shown.
Binary file not shown.
BIN
study/sabre/os/files/Sound/SoundBlaster/sbdsp.zip
Normal file
BIN
study/sabre/os/files/Sound/SoundBlaster/sbdsp.zip
Normal file
Binary file not shown.
216
study/sabre/os/files/Sound/dolby.v2.01.txt
Normal file
216
study/sabre/os/files/Sound/dolby.v2.01.txt
Normal file
@@ -0,0 +1,216 @@
|
||||
|
||||
How Dolby Stereo (aka Dolby Surround) works:
|
||||
(version 2.01, 4/22/94)
|
||||
|
||||
Don Munsil (don@munsil.com)
|
||||
|
||||
2.01 changes:
|
||||
|
||||
- Better explanation of inverting a sample.
|
||||
|
||||
2.0 changes:
|
||||
|
||||
- Added responses from Otto Chrons and Adrian Kwong.
|
||||
|
||||
- Cleaned up text considerably.
|
||||
|
||||
- Added more tips on practical aspects.
|
||||
|
||||
** Introduction:
|
||||
|
||||
Dolby Stereo is a system designed by Dolby Labs in the '70s for creating
|
||||
better movie sound, including surround-sound. The other benefits are
|
||||
increased directionality of front sounds and improved localization of
|
||||
on-screen sounds like dialog for the people sitting on the edges. The
|
||||
system is totally separate from Dolby noise-reduction systems like Dolby B
|
||||
and C. Remember that there is only one encoding process: Dolby Stereo,
|
||||
which can be decoded by a Dolby Surround, Dolby Pro-Logic, or THX
|
||||
decoder, for varying degrees of home-theatre "quality."
|
||||
|
||||
There are four output channels in Dolby Stereo: Left front, Right front,
|
||||
Center front, and Surround. These are encoded on two channels in such a
|
||||
way that the soundtrack can be played back on a standard stereo device, a
|
||||
mono device, or a Dolby decoder. (Or a THX system, which is a Dolby
|
||||
Pro-Logic decoder with specifications licensed by Lucasfilm).
|
||||
|
||||
A word is in order about THX. It is NOT different from Dolby Pro-Logic, at
|
||||
least not precisely. THX is a licensing and quality-control wing of
|
||||
LucasArts with the stated aim of improving movie sound and picture. It
|
||||
licenses the name THX for movie equipment, movie theatres, home equipment,
|
||||
and laserdiscs. The name means that the THX engineers certify it as good
|
||||
quality. There are a few processing steps in home THX that are not
|
||||
typically present in a plain Pro-Logic system, but they are merely
|
||||
enhancements to Dolby Pro-Logic decoding, not a different system.
|
||||
|
||||
The center channel is the most used one in a film. It contains all of the
|
||||
dialog, and most of the on-screen sound effects. It is important to have a
|
||||
center channel so that people on the edges of the theatre (or your living
|
||||
room) still hear the on-screen sound from the direction of the screen, not
|
||||
panned to one side or another. Without the center channel, people hear
|
||||
most of the sound coming from the nearest speaker. In addition, dialog
|
||||
tends to be clearer when it is localized in the center channel.
|
||||
|
||||
The surround channel is used for "ambient" effects: sounds that should
|
||||
envelop the listener. It is not a rear channel, and should not be used for
|
||||
directional sounds. In a properly setup system, the listener should not be
|
||||
able to tell where the surround speakers are located. In a movie theatre,
|
||||
there are generally many surround speakers around the back of the hall. In
|
||||
the home, this is impractical, so two speakers facing in such a way as to
|
||||
maximize reflected sound are used.
|
||||
|
||||
Any device capable of playing back two distinct channels can produce Dolby
|
||||
Stereo-compatible signals. This includes any stereo soundcard, stereo vcr,
|
||||
or even CD player or record (there are Dolby Stereo encoded CDs).
|
||||
|
||||
** Here's how:
|
||||
|
||||
I'll refer to the four output channels as LO, RO, CO, and SO, for left,
|
||||
right, center, and surround, respectively. The input channels (the ones
|
||||
coming from the source and into the decoder) I'll call LI and RI. (If you
|
||||
don't like acronyms, feel free to use search-and-replace to make this more
|
||||
readable.) :-)
|
||||
|
||||
The LO channel and RO channel are recorded normally on the LI and RI tape
|
||||
channels (we'll assume tape recording for example purposes). The CO
|
||||
channel is recorded on BOTH the LI and RI channel at exactly the same
|
||||
volume, in-phase (i.e., no special processing). The SO channel is recorded
|
||||
on LI and RI at the same volume, with inverted phase (i.e. every peak on
|
||||
one channel is a trough on the other).
|
||||
|
||||
There are a few interesting nuances here. Because the CO channel is
|
||||
recorded normally on LI and RI, it will still image in the center on any
|
||||
stereo playback system, as long as the listener is basically in the
|
||||
center. As the listener moves further left or right, the image moves in
|
||||
the same direction, which is a little distracting, but acceptable. This is
|
||||
what one gets with a simple "surround" decoder (in addition to the
|
||||
surround channel, of course). Without the Center channel, the imaging is
|
||||
fine for one or two people, but not so great for groups. Dolby Pro-Logic
|
||||
adds (among other things) the center channel.
|
||||
|
||||
Note that because of the inverted encoding scheme for the surround
|
||||
channel, it will disappear when played back on a mono system. Each peak is
|
||||
precisely canceled by a trough on the other channel, and all surround
|
||||
information is lost. This is another reason to put only ambient,
|
||||
non-essential sounds in the surround channel. Many systems are still mono
|
||||
(most VCRs, for example) and will not reproduce them.
|
||||
|
||||
The Dolby decoder reproduces a fairly good semblance of the original four
|
||||
channels from the two input channels, though there will always be leakage
|
||||
and crosstalk. Dolby Pro-Logic and THX circuitry have special processing
|
||||
that minimizes perceived crosstalk.
|
||||
|
||||
When the Dolby Stereo is mixed, the engineers listen to it running through
|
||||
a Pro-Logic decoder exactly like the one in the theatre or your home.
|
||||
Thus, they design the four channels specifically so they will decode
|
||||
properly. It is not a good idea to mix four distinct channels, then do the
|
||||
Pro-Logic encoding "blind" as a post-process, because the results will not
|
||||
be exactly the same as the original four distinct channels.
|
||||
|
||||
** Doing it on a soundcard (kinky as it sounds):
|
||||
|
||||
On a soundcard, sending signals to the center channel is a simple as
|
||||
playing the sound in dead-center (equal volume on both channels). Surround
|
||||
is a bit tougher. The sound must be played back inverted on one channel.
|
||||
One way would be to have two samples, with one pre-inverted. Another would
|
||||
be to invert one side on the fly. I have been told that DMP, a MOD music
|
||||
player by Otto Chrons, does just this. I haven't heard it myself.
|
||||
|
||||
Inverting a sample simply consists of negating it. If the sample values
|
||||
are unsigned, the negation will still give the desired result because of
|
||||
the nature of two's complement representation (though you should make
|
||||
sure your compiler is actually doing the appropriate negation -- in C,
|
||||
cast the value to signed, then negate it, then cast to unsigned to be
|
||||
absolutely sure.)
|
||||
|
||||
>>New addition: Otto Chrons (c142092@cc.tut.fi), author of DMP, emailed
|
||||
me the following:
|
||||
|
||||
You wrote an excellent article about Dolby Surround sound at csip.soundcard
|
||||
but I wanted to comment on few things. DMP does work with surround channel
|
||||
and the technique I use is extremely simple. Dolby standard state that
|
||||
you should do +90 and -90 phase shifting on left & right channels, but I've
|
||||
found out that doing a 0 and +180 shift works as well. So basically I
|
||||
put the original sound data out of the left speaker and negate the data
|
||||
on the right speaker. In my mixing routines this is accomplished by
|
||||
using ADD and SUB instructions respectively. So doing surround sound is
|
||||
as easy as doing mono!
|
||||
|
||||
>>End Chrons
|
||||
|
||||
** A few other issues to keep in mind:
|
||||
|
||||
>>Adrian Kwong (akwong@alfred.carleton.ca) had this to add:
|
||||
|
||||
You might want to add that the surround channel in a normal Dolby
|
||||
Surround setup is placed through Dolby A type noise decoding. It has
|
||||
something to do with making it 3dB larger following a specific
|
||||
frequency envelope. To make the surround appear at the correct
|
||||
volume, you'll need to "double" the signal to the surround channel.
|
||||
(+3dB is about 2x the signal)
|
||||
|
||||
>>End Kwong
|
||||
|
||||
One thing to keep in mind is that the Surround channel is typically not
|
||||
designed to handle a lot of bass. The speakers are generally small, and
|
||||
the amplifiers are lower wattage. On a film soundtrack, the low bass is
|
||||
generally filtered out of the soundtrack to avoid clipping.
|
||||
|
||||
In addition, the high frequencies are generally filtered out of the
|
||||
surround channel because higher frequencies are easier to localize, and
|
||||
the surround channel is not supposed to be directional. The end result is
|
||||
that the surround channel is only "supposed" to carry about 200-8000Hz,
|
||||
which is a fairly narrow spectrum.
|
||||
|
||||
It is difficult to get a sound to play on all four channels at once.
|
||||
Generally, on a film soundtrack, a "big" sound, like an explosion, is sent
|
||||
mainly to the surround channel. Since this will be lost in mono, a similar
|
||||
sound is sent to the left and right channels as well.
|
||||
|
||||
A technique often used with thunder effects is to put the main sound in
|
||||
the surround channel, followed by an echo in the front channels (or
|
||||
sometimes vice-versa). The Dolby stereo listeners hear the two-part
|
||||
thunder, and the mono listeners hear just the second bit (or a scaled-down
|
||||
version of the first).
|
||||
|
||||
Another technique is to slightly pitch-shift or delay sounds going to the
|
||||
different speakers, but results can be iffy. YMMV. The important thing is
|
||||
to do testing on a real Pro-Logic setup, and experiment until a good
|
||||
balance is reached.
|
||||
|
||||
One can also send frequency band-limited chunks of the sound to each channel,
|
||||
which will decode rather well. It requires that the bulk of each channel
|
||||
be using a different band of the frequency spectrum, which is not
|
||||
practical in some cases.
|
||||
|
||||
Keep in mind that there are many tricks of the trade that are used in film
|
||||
mixing that only Dolby really knows. They don't tell how they do it,
|
||||
because they want film companies to buy their technology, not the
|
||||
competition (e.g. UltraStereo, Chase Surround, StereoSurround). If anyone
|
||||
reading this has useful techniques (that are not trade secrets of Dolby)
|
||||
they would like to share, please email the author.
|
||||
|
||||
Fortunately, in computer sound, you don't have to make the soundtrack
|
||||
mono-compatible. You can ask the user if the sound system is Dolby
|
||||
Surround, and place sounds in the surround channel as needed. On a mono
|
||||
system, the sounds can all be sent to the single channel.
|
||||
|
||||
** Disclaimers:
|
||||
|
||||
All of this information is from me, and any errors are my own darn fault.
|
||||
None of this information has been endorsed by Dolby Labs. Dolby is a
|
||||
trademark of Dolby labs, and should not be used on a product without
|
||||
getting their permission. (Although I think if you called it "surround"
|
||||
people would get the idea.)
|
||||
|
||||
Please email suggestions/criticisms/additions/subtractions/
|
||||
multiplications/corrections to don@munsil.com.
|
||||
|
||||
This text is copyright 1993 by Don Munsil. It may be distributed freely,
|
||||
as long as modifications are attributed and marked clearly.
|
||||
|
||||
--
|
||||
------------------------------------------------------
|
||||
Don Munsil | I respect faith, but doubt is
|
||||
don@munsil.com | what gets you an education.
|
||||
| -- Wilson Mizner
|
||||
|
||||
1676
study/sabre/os/files/Sound/gusfaq-v1.55.txt
Normal file
1676
study/sabre/os/files/Sound/gusfaq-v1.55.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
study/sabre/os/files/Sound/guslib.zip
Normal file
BIN
study/sabre/os/files/Sound/guslib.zip
Normal file
Binary file not shown.
7
study/sabre/os/files/Sound/index.html
Normal file
7
study/sabre/os/files/Sound/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;url=/Linux.old/sabre/os/articles">
|
||||
</head>
|
||||
<body lang="zh-CN">
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user