Skip to content

Instantly share code, notes, and snippets.

@usysrc
Created October 31, 2014 13:19
Show Gist options
  • Save usysrc/796fb490776e2d6d95b3 to your computer and use it in GitHub Desktop.
Save usysrc/796fb490776e2d6d95b3 to your computer and use it in GitHub Desktop.
The Ad Lib Music Synthesizer Card, P R O G R A M M I N G G U I D E, Written by Tero Töttö
┌──────────────────────────────────────────────────────────────────────────────┐
│ │
│ The Ad Lib Music Synthesizer Card │
│ │
│ P R O G R A M M I N G G U I D E │
│ │
│ │
│ Written by Tero Töttö │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
CHAPTER 1: DESCRIPTION OF THE SYNTHESIZER 1
Operators 1
Operating Modes 1
Melodic and Percussive Mode 2
CHAPTER 2: PROGRAMMING THE SYNTHESIZER 3
Card location in I/O channel 3
Card addresses 3
CHAPTER 3: ALMSC REGISTER MAP 4
Status Register 4
Write registers 4
Operator offsets 4
Channel formation 5
CHAPTER 4: ALMSC REGISTER REFERENCE 6
Status Register 6
Registers 01h - 04h 6
Registers 08h - 55h 7
Registers 60h - BDh 8
Registers C0h - F5h 9
APPENDIX A: INSTRUMENT BANK (.BNK) FILE STRUCTURE 10
APPENDIX B: NOTE FREQUENCIES 11
DISCLAIMER: IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING
ANY LOST OF PROFITS, LOST SAVINGS OR OTHER INCIDENTIAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF YOUR USE OR INABILITY TO
USE THIS MANUAL, OR FOR ANY OTHER CLAIM BY ANY OTHER PARTY.
TRADEMARKS: Ad Lib is registered trademark of Ad Lib Inc.
COPYRIGHT: This manual can be distributed freely if not modified.
DESCRIPTION OF THE SYNTHESIZER (1)
──────────────────────────────
Ad Lib Synthesizer is made up of oscillators and envelope generators. An
oscillator, an envelope generator, and a level controller are linked together
to form an "operator":
┌────────────┐ ┌────────────────────┐ ┌──────────────────┐
│ Oscillator ├─>│ Envelope Generator ├─>│ Level Controller ├──> OUTPUT
└────────────┘ └────────────────────┘ └──────────────────┘
The Ad Lib Music Synthesizer card (ALMSC) contains 18 operators which are
generally grouped into pairs in order to produce instrumental sounds. The
operators can be combined in three different ways:
* FM synthesis uses two operators in series. The first operator,
the modulator, modulates the second operator, the carrier, via
its modulation data input.
┌─────────────┐ ┌─────────────┐
Frequency │ Operator │ │ Operator │
Modulation │ 1. ├─>│ 2. ├─> SPEAKER
synthesis │ (Modulator) │ │ (Carrier) │
└─────────────┘ └─────────────┘
* Additive synthesis uses two operators in parallel, adding both
outputs together. This method of synthesis is not as interesting
as FM synthesis, but it can generate good organ-type sounds.
┌─────────────┐
│ Operator │
│ 1. ├──┐
│ │ │
Additive └─────────────┘ │
synthesis ├─> SPEAKER
┌─────────────┐ │
│ Operator │ │
│ 2. ├──┘
│ │
└─────────────┘
* Composite sine wave synthesis (CSW) may be used to generate speech
or other related sounds by playing all 9 voices simultaneously. When
using this method, the card cannot generate any other sounds. This
mode is not explained here, because other methods have proved to
provide better quality speech.
The ALMSC produces either 9 melodic sounds or 6 melodic sounds and 5 (2)
percussion instruments. For the 9 melodic sounds, the operators are
grouped in pairs. For the percussion mode, the opearators are arranged
as follows:
* 6 melodic instruments (12 operators)
* 1 Bass Drum (2 operators)
* 1 Snare Drum (1 operator)
* 1 Tom-Tom (1 operator)
* 1 Cymbal (1 operator)
* 1 Hi-Hat (1 operator)
Because ALMSC has only 9 registers for frequency information (one for
each melodic channel), Cymbal and Hi-Hat pitches are fixed.
In percussion mode, a white noise generator is used to create rhythm sounds.
This white noise generator uses voices 7 and 8 (Snare Drum and Tom-Tom)
frequency information (Block, Frequency Number, Multiplication), and the proper
phase output. Various rhythm sounds are produced by combining this output signal
with white noise. The result is then sent to the operators. Best ratio for the
two frequencies is 3:1 (Snare Drum frequency = 3 * Tom-Tom frequency). Finally,
envelope information is multiplied with the wave table output. As the envelope
is set for one operator which corresponds to a single rhythm instrument, the
values are set in the parameter registers in the same manner as for melodic
instruments.
PROGRAMMING THE SYNTHESIZER (3)
───────────────────────────
The ALMSC may be located at four different addresses:
218h , 288h , 318h , 388h
The port address is currently hard-wired to 388h, but jumpers may be added in
the future, so you should take into account the possibility of using different
addresses when programming. Later on this manual, I will refer only to the
address 388h.
The card decodes two addresses:
388h - Index register (write), Status register (read)
389h - Data register (write only)
The index register is used to select the register address, and then data is
written to data register. Status register returns the state of two timers on
the card.
Because of the nature of the card, you must wait 3.3 μsec after a register
select write, and 23 μsec after a data write. Best way to handle this is to read
ALMSC status register in loop, because bus speed is always the same regardless
of processor speed. 6 reads after register select write and 36 reads after data
write should do the job.
ALMSC REGISTER MAP: (4)
───────────────────
Status Register (388h):
┌───────────────────────────────────────────────────────────────────────┐
│ D7 D6 D5 D4 D3 D2 D1 D0 │
├────────┼────────┼────────┼────────┴────────┴────────┴────────┴────────┤
│IRQFlag │ T1Flag │ T2Flag │ │
└────────┴────────┴────────┴────────────────────────────────────────────┘
Write Registers (389h):
┌─────┬───────────────────────────────────────────────────────────────────────┐
│ REG │ D7 D6 D5 D4 D3 D2 D1 D0 │
├─────┼────────┴────────┼────────┼────────┴────────┴────────┴────────┴────────┤
│ 01 │ │WSEnable│ Test Register │
├─────┼─────────────────┴────────┴────────────────────────────────────────────┤
│ 02 │ Timer 1 Count (80 μsec resolution) │
├─────┼───────────────────────────────────────────────────────────────────────┤
│ 03 │ Timer 2 Count (320 μsec resolution) │
├─────┼────────┬────────┬────────┬──────────────────────────┬────────┬────────┤
│ 04 │IRQReset│ T1Mask │ T2Mask │ │T2 Start│T1 Start│
├─────┼────────┼────────┼────────┴──────────────────────────┴────────┴────────┤
│ 08 │ CSW │NOTE-SEL│ │
├─────┼────────┼────────┼────────┬────────┬───────────────────────────────────┤
│20-35│Tremolo │Vibrato │Sustain │ KSR │ Frequency Multiplication Factor │
├─────┼────────┴────────┼────────┴────────┴───────────────────────────────────┤
│40-55│ Key Scale Level │ Output Level │
├─────┼─────────────────┴─────────────────┬───────────────────────────────────┤
│60-75│ Attack Rate │ Decay Rate │
├─────┼───────────────────────────────────┼───────────────────────────────────┤
│80-95│ Sustain Level │ Release Rate │
├─────┼───────────────────────────────────┴───────────────────────────────────┤
│A0-A8│ Frequency Number ( Lower 8 bits ) │
├─────┼─────────────────┬────────┬──────────────────────────┬─────────────────┤
│B0-B8│ │ KEY-ON │ Block Number │ F-Num (hi bits) │
├─────┼────────┬────────┼────────┼────────┬────────┬────────┼────────┬────────┤
│ BD │Trem Dep│Vibr Dep│PercMode│ BD On │ SD On │ TT On │ CY On │ HH On │
├─────┼────────┴────────┴────────┴────────┼────────┴────────┴────────┼────────┤
│C0-C8│ │FeedBack Modulation Factor│Additive│
├─────┼───────────────────────────────────┴─────────────────┬────────┴────────┤
│E0-F5│ │ Waveform Select │
└─────┴─────────────────────────────────────────────────────┴─────────────────┘
For some of the parameters, there is one register per output channel. For those
parameters, channel number can be used as an offset into the map. For many
parameters, there is one register per operator. However, there are holes in the
address map so that in this case, the operator number CANNOT be used as an
offset. The operator offsets for those registers are (in hex form):
┌─────┬────────────────────────────────────────────────────────────────────────┐
│ OPR │ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 │
├─────┼────────────────────────────────────────────────────────────────────────┤
│ OFS │ 00 01 02 03 04 05 08 09 0A 0B 0C 0D 10 11 12 13 14 15 │
└─────┴────────────────────────────────────────────────────────────────────────┘
The next two tables illustrates which operators together form a channel: (5)
┌───────────────────────────────────────────────────┐
│ M E L O D I C M O D E │
├──────┬────┬────┬────┬────┬────┬────┬────┬────┬────┤
│ CHAN │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │
├──────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤
│ OPR1 │ 1 │ 2 │ 3 │ 7 │ 8 │ 9 │ 13 │ 14 │ 15 │
│ OPR2 │ 4 │ 5 │ 6 │ 10 │ 11 │ 12 │ 16 │ 17 │ 18 │
└──────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
┌─────────────────────────────────────────────────────────────┐
│ P E R C U S S I O N M O D E │
├──────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┤
│ CHAN │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ BD │ SD │ TT │ CY │ HH │
├──────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┼────┤
│ OPR1 │ 1 │ 2 │ 3 │ 7 │ 8 │ 9 │ 13 │ 17 │ 15 │ 18 │ 14 │
│ OPR2 │ 4 │ 5 │ 6 │ 10 │ 11 │ 12 │ 16 │ │ │ │ │
└──────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ALMSC REGISTER REFERENCE: (6)
─────────────────────────
Status Register:
D7 IRQ Flag. Set if D5 and/or D6 are/is set.
D6 Timer 1 Flag. Set when the preset time in Timer 1 has elapsed.
D5 Timer 2 Flag. Set when the preset time in Timer 2 has elapsed.
Timer interrupts are not wired, but the timers can be used to detect
the presence of the card as follows:
1. Reset T1 and T2: write 60h to register 4.
2. Reset the IRQ: write 80h to register 4.
3. Read status register: read at 388h. Save the result.
4. Set timer 1 to FFh: write FFh to register 2.
5. Unmask and start timer 1: write 21h to register 4.
6. Wait in a delay loop for at least 80 μsec.
7. Read status register: read at 388h. Save the result.
8. Reset T1,T2 and IRQ as in steps 1 and 2.
9. Test the results of the two reads: the first should
be 0, the second should be C0h. If either is incorrect,
then the ALMSC is not presents.
NOTE1: You should AND the result bytes with E0h because
the unused bits are undefined.
NOTE2: This testing method doesn't work in SoundBlaster.
01: Test Register / WSE:
D5 Waveform Select Enable. If clear, all channels will use normal
sine wave. If set, register E0-F5 (WS) contents will be used.
D4-D0 Test Register, must be reset to zero before any operation.
02: Timer 1 Count:
Upward 8 bit counter with a resolution of 80 μsec. If an overflow
occurs, the status register bit is set, and the preset value is
loaded into the timer again.
03: Timer 2 Count:
Same as Timer 1, but with a resolution of 320 μsec.
04: IRQ-Reset / Mask / Start:
D7 IRQ-Reset. Resets timer and IRQ flags in status register.
All other bits are ignored when this bit is set.
D6 Timer 1 Mask. If 1, status register is not affected in overflow.
D5 Timer 2 Mask. Same as above.
D1 Timer 2 Start. Timer on/off.
D0 Timer 1 Start. Same as above.
08: CSW / NOTE-SEL: (7)
D7 Composite sine wave mode on/off.
D6 NOTE-SEL. Controls the split point of the keyboard. When 0, the
keyboard split is the second bit from the bit 8 of the F-Number.
When 1, the MSb of the F-Number is used.
20-35: Tremolo / Vibrato / Sustain / KSR / Frequency Multiplication Factor:
D7 Tremolo (Amplitude vibrato) on/off.
D6 Frequency vibrato on/off.
D5 Sound Sustaining. When 1, operator's frequency will be held at
its sustain level until a KEY-OFF is done.
D4 Envelope scaling (KSR) on/off. When 1, higher notes are shorter
than lower notes.
D3-D0 Frequency Multiplication Factor (MULTI):
┌───────┬────────┐
│ MULTI │ Factor │
├───────┼────────┤
│ 0 │ ½ │
│ 1 │ 1 │
│ 2 │ 2 │
│ 3 │ 3 │
│ 4 │ 4 │
│ 5 │ 5 │
│ 6 │ 6 │
│ 7 │ 7 │
│ 8 │ 8 │
│ 9 │ 9 │
│ 10 │ 10 │
│ 11 │ 10 │
│ 12 │ 12 │
│ 13 │ 12 │
│ 14 │ 15 │
│ 15 │ 15 │
└───────┴────────┘
40-55: Key Scale Level / Output Level:
D7-D6 Key Scale Level. Attenuates output level towards higher pitch:
┌─────┬─────────────┐
│ KSL │ Attenuation │
├─────┼─────────────┤
│ 0 │ - │
│ 1 │ 1.5 dB/oct │
│ 2 │ 3.0 dB/oct │
│ 3 │ 6.0 dB/oct │
└─────┴─────────────┘
D5-D0 Output Level. Attenuates the operators output level. In additive
synthesis, varying the output level of any operator varies the
volume of its corresponding channel. In FM synthesis, varying
the output level of the carrier varies the volume of the channel.
Varying the output of then modulator will change the frequency
spectrum produced by the carrier.
60-75: Attack Rate / Decay Rate: (8)
D7-D4 Attack Rate. Determines the rising time for the sound. The
higher the value, the faster the attack.
D3-D0 Decay Rate. Determines the diminishing time for the sound.
The higher the value, the shorter the decay.
80-95: Sustain Level / Release Rate:
D7-D4 Sustain Level. Determines the point at which the sound ceases
to decay and chages to a sound having a constant level. The
sustain level is expressed as a fraction of the maximum level.
Note that the Sustain-bit in the register 20-35 must be set for
this to have an effect.
D3-D0 Release Rate. Determines the rate at which the sound disappears
after KEY-OFF. The higher the value, the shorter the release.
A0-A8: Frequency Number:
Determines the pitch of the note. Highest bits of F-Number are stored
in the register below.
B0-B8: Key On / Block Number / F-Num(hi bits):
D5 KEY-ON. When 1, channels output is enabled.
D4-D2 Block Number. Roughly determines the octave.
D1-D0 Frequency Number. 2 highest bits of the above register.
The following formula is used to determine F-Number and Block:
F-Num = Music Frequency * 2^(20-Block) / 49716 Hz
BD: Trem Dep / Vibr Dep / PercMode / BD/SD/TT/CY/HH On:
D7 Tremolo (Amplitude Vibrato) Depth. 0 = 1.0dB, 1 = 4.8dB.
D6 Frequency Vibrato Depth. 0 = 7 cents, 1 = 14 cents.
A "cent" is 1/100 of a semi-tone.
D5 Percussion Mode. 0 = Melodic Mode, 1 = Percussion Mode.
D4 BD On. KEY-ON of the Bass Drum channel.
D3 SD On. KEY-ON of the Snare Drum channel.
D2 TT On. KEY-ON of the Tom-Tom channel.
D1 CY On. KEY-ON of the Cymbal channel.
D0 HH On. KEY-ON of the Hi-Hat channel.
C0-C8: FeedBack Modulation Factor / Additive: (9)
D3-D1 FeedBack Modulation Factor:
┌───────┬────────┐
│ MULTI │ Factor │
├───────┼────────┤
│ 0 │ 0 │
│ 1 │ π/16 │
│ 2 │ π/8 │
│ 3 │ π/4 │
│ 4 │ π/2 │
│ 5 │ π │
│ 6 │ 2∙π │
│ 7 │ 4∙π │
└───────┴────────┘
D0 Additive. 1 = Additive synthesis, 0 = Frequency Modulation
E0-F5: Waveform Select:
D7-D2 Not used
D1-D0 WaveForm Select (WS):
┌────┬────────────┐
│ WS │ WaveForm │
├────┼────────────┤
│ 00 │ Sine │
│ 01 │ Half-Sine │
│ 10 │ Abs-Sine │
│ 11 │ Pulse-Sine │
└────┴────────────┘
APPENDIX A: INSTRUMENT BANK (.BNK) FILE STRUCTURE (10)
─────────────────────────────────────────────────
Field Size Type Description
───────────────────────────────────────────────────────────────────────────────
HEADER SECTION
1 1 byte file version, major
2 1 byte file version, minor
3 6 byte signature: "ADLIB-"
4 2 integer number of list entries used
5 2 integer total number of list entries in file
6 4 longint absolute offset in file of start of name list
7 4 longint absolute offset in file of start of data
8 8 byte pad (set to zero)
INSTRUMENT NAME SECTION RECORD
1 2 integer index into data section
2 1 byte flag: 0 if record used, else 1
3 9 byte instrument name (max 8 chars + NULL)
DATA SECTION RECORD
1 1 byte mode (0=melodic,1=percussion)
2 1 byte voice number (if percussion mode)
modulator (operator 0) parameters:
3 1 byte key scale level
4 1 byte frequency multiplier
5 1 byte feedback modulation factor
6 1 byte attack rate
7 1 byte sustain level
8 1 byte sound sustaining
9 1 byte dacay rate
10 1 byte release rate
11 1 byte output level
12 1 byte amplitude vibrato (tremolo)
13 1 byte frequency vibrato
14 1 byte envelope scaling
15 1 byte 0=FM synthesis, 1=additive synthesis
carrier (operator 1) parameters (for melodic channels and bassdrum only):
3 1 byte key scale level
4 1 byte frequency multiplier
5 1 byte feedback modulation factor
6 1 byte attack rate
7 1 byte sustain level
8 1 byte sound sustaining
9 1 byte dacay rate
10 1 byte release rate
11 1 byte output level
12 1 byte amplitude vibrato (tremolo)
13 1 byte frequency vibrato
14 1 byte envelope scaling
15 1 byte unused
29 1 byte waveform for modulator
30 1 byte waveform for carrier
APPENDIX B: NOTE FREQUENCIES (11)
────────────────────────────
The following table contains frequencies in Hertz for the notes in octaves
1 to 8. Middle C is in octave 5.
┌──────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ NOTE │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │
├──────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│ C │ 16.352 │ 32.703 │ 65.406 │ 130.81 │*261.63*│ 523.25 │ 1046.5 │ 2093.0 │
│ C# │ 17.324 │ 34.648 │ 69.295 │ 138.59 │ 277.18 │ 554.37 │ 1108.7 │ 2217.5 │
│ D │ 18.354 │ 36.708 │ 73.416 │ 146.83 │ 293.66 │ 587.33 │ 1174.7 │ 2349.3 │
│ D# │ 19.445 │ 38.890 │ 77.781 │ 155.56 │ 311.13 │ 622.25 │ 1244.5 │ 2489.0 │
│ E │ 20.601 │ 41.203 │ 82.406 │ 164.81 │ 329.63 │ 659.26 │ 1318.5 │ 2637.0 │
│ F │ 21.826 │ 43.653 │ 87.307 │ 174.61 │ 349.23 │ 698.46 │ 1396.9 │ 2793.8 │
│ F# │ 23.124 │ 46.249 │ 92.499 │ 184.99 │ 369.99 │ 739.99 │ 1480.0 │ 2960.0 │
│ G │ 24.499 │ 48.999 │ 97.998 │ 195.99 │ 391.99 │ 783.99 │ 1568.0 │ 3136.0 │
│ G# │ 25.956 │ 51.913 │ 103.82 │ 207.65 │ 415.31 │ 830.61 │ 1661.2 │ 3322.4 │
│ A │ 27.500 │ 55.000 │ 110.00 │ 220.00 │ 440.00 │ 880.00 │ 1760.0 │ 3520.0 │
│ A# │ 29.135 │ 58.270 │ 116.54 │ 233.08 │ 466.16 │ 932.32 │ 1864.7 │ 3729.3 │
│ B │ 30.867 │ 61.735 │ 123.47 │ 246.94 │ 493.88 │ 987.77 │ 1975.5 │ 3951.1 │
└──────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment