Welcome to TFM's SB Music Page.
TFM's Sound Blaster PAGE
The FM Chips
As well as producing digital effects, using the ADC the Sound Blaster is able
to synthesise music, using it's two FM chips (OPL4) These chips are able to
create musical notes. As apposed to Digital Samples the FM chips aren't
sent the amplitude at regular intervals. Instead the sound is synthesised
using a two part FM wave synthesis system.
The Sound Blaster can make the sound of nine melodic instruments at a time,
or six melodic and five rhythm instruments.
Each instrument or voice is created by two operators. There are two methods
in which they can be combined to make the final sound.
(i) Additative synthesis. Using this method the waves
Produced by each operator are added, to give the final sound.
This method only alows organ like sounds to be created.
(ii) Frequency Modulation. One operator is used as a carrier and
the other as a modulator. The carrier creates a tone and this
tone is fed into the modulator to modify it. The output from
the modulator can also be fed into itself causing feedback.
Which ever metod of synthesis is used the general method of controling the
FM chips is the same. The FM chips are controled by changing the values of
the Sound Blasters Registers. Each FM chip (Left and Right) is controled by
102 registers. Setting the register contents can be very daunting. Before
discussing the register positions I will discuss the method by which they
Setting The FM Chip Registers
The Sound Blaster uses the following ports to control it's FM chips.
388h (read/write) Index/Status port (Both Channels) (Adlib)
389h (write only) Data Port (Both Channels) (Adlib)
2x8h (read/write) Index/Status port (Both Channels)
2x9h (write only) Data Port (Both Channels)
2x0h (read/write) Index/Status port (Left Channel)
2x1h (write only) Data Port (Left Channel)
2x2h (read/write) Index/Status port (Right Channel)
2x3h (write only) Data Port (Right Channel)
In the above list the x in the port numbers is set by the base port of the
card (set by jumpers on the card.)
e.g. if the baseport is 220h then 2x8h means 228h.
The ports 388h and 389h are supported to alow backward compatibility with
the Adlib sound card. As the Adlib had only one FM chip, all values are
written to both the left and right channels.
The ports 2x8h and 2x9h are the new equivilents of 388h and 389h.
To set a register to a value:-
(i) Send the register number to the index port
(ii) Wait 3.3 micro seconds before any SB I/O
(this can be achieved by reading the status
port 6 times)
(iii) Send the data to the data port
(iv) Wait 23.3 micro seconds before any SB I/O
(this can be achieved by reading the status
port 35 times)
N.B. If you don't wait between writes the SB locks up!
When you read the status port the value returned is defined as
7 Set if either the Fast or Slow counter has overflowed
6 Set if the Fast counter has overflowed
5 Set if the Slow counter has overflowed
See below for details about counters
Not all of the registers are used. Here are the registers and what they do.
Reg Name Bits Usage
1 Test 0-7 You must load the value 0 into this register
before programing the SB
2 Fast Counter 0-7 When the fast counter is started the value
stored here is loaded into it. The counter
is incremented every 80 microseconds. When
it reaches 255 the value stored in this
register is re-loaded, the bit in the status
byte is set (see below) and the counter
TIME = (256-reg(2)) * 0.08 microseconds
3 Slow Counter 0-7 This is used in the save way as reg 2,except
the number is used for the slow counter,
which is incremented every 320 microseconds.
TIME = (256-reg(2)) * 0.32 microseconds
4 Counter 7 If this bit is set the flags in the status
Controler byte are re-set to 0.
6 If this bit is set the status byte doesn't
give info about the fast counter.
5 If this bit is set the status byte doesn't
1 When this bit is set the slow counter is
started and the value from reg(3) is loaded
0 When this bit is set the fast counter is
started and the value from reg(2) is loaded
8 General 7 If bit is set then composite mode is used
Control otherwise normal mode is used.
6 This bit is used to determine the split point??
20-35 Operator 7 AM When this is set there are intensity
Settings fluctuations in the signal (3.7Hz)
6 VIB When this is set there are pitch
fluctuations in the signal (6.4Hz)
5 EG-TYP When this is set the voice is
sustained while it is enabled if
not, it drops to 0 at the release
4 KSR When this is set the high notes are
0-3 MULTI This setting determines the value
by which the frequency is multiplied
the range is 0-15, and if it is set to
0 it is halved (a freq of 0 is bolloks)
40-55 Operator 6-7 KSL Set the volume decrease per octave
Settings 0 = 0dB
1 = 3dB
2 = 1.5dB
3 = 6dB
TL These bits set the Total Volume Level
0 is the highest and 63 is 0dB
Volume = (63-TL) * 0.75dB
60-75 Operator 4-7 AR Attack Rate (Rate at which the sound
Settings Reaches the maximum volume).
0-3 DR Decay Rate (Rate at which the sound
Drops to the Sustain Volume).
80-95 Operator 4-7 SL Sustain Level, level at which the
Settings volume stays while it is held on
(unless EG-TYP = 0). 15 is the
minimum (0dB) and 0 is maximum.
RR Release Rate. The rate at which
the sound drops from the sustain
level to 0.
A0-A8 F-NO 0-7 These nine bytes control the frequency of
the nine instruments. These bytes hold the
eight least significant bits of the freq.
Reg(B0-B8) contain the two other bits.
B0-B8 Voice Settings 5 KEY When set the voice is turned on
when it is reset the voice falls
to 0 at the RR (Unless EG-TYP is
set, when it falls to 0 at the RR
as soon as the SL is reached).
2-4 Octave These bits select the octave
Middle C is in octave 4.
0-1 F-NO These are the two most significant
bits of the frequency
BD Vibro and 7 VIB This is the intensity of the
Rhythm settings amplitude fluctuation.
0 = max 1dB
1 = max 4.8dB
see Reg (20-35)
6 FREQ This is the intensity of the
0 = max 7%
1 = max 14%
see Reg (20-35)
5 RHYTHM If this bit is set then the rhythm
instruments are used.
0-4 R_KEY Rhythm key bits, these turn the
rhythm instruments on and off
0 High Hat
1 Top Cymbal
3 Snare Drum
4 Bass Drum
C0-C8 Modeulator 1-3 FB Feed Back 0=none, 7=maximum
Settings 0 FM 1 Selects Additive synthesis
0 FM synthesis
E0-F5 Wave Select 0-1 This selects one of the types of sine waves
\ _ /
1=modulus _ _
/ \ / \
2=positive only _
3=positive gradient only
/ | /|
Don't ask, coz I don't know what it does!
The registers which are described above alow you to change the status
of the FM chips.
The registers can be seperated into four types
Global Registers 1,2,3,4,8,BD
These are easy to use and they effect all voices.
Modulator Settings C0-C8
These are relatively straight forward. There is one register for each
modulator, so reg A5 controls voice 5.
Voice Settings A0-A8 and B0-B8
These are also relatively straight forward. In melody mode there is one
register for each voice, so reg A5 controls voice 5.
In Rhythm mode the first six instruments are the same, then the Bass drum
is controled by the seventh registers (A6 and B6). The Tom-tom uses the
ninth registers. The other rhythm instruments can't be programed in this way
and, so the eigth registers do nothing.
Operator Settings 20-35, 40-55, 60-75, 80-95 and E0-F5
These registers use the most complex addressing system. To address the
correct modulator/carrier for each instrument you will need to use a
lookup table. In the table below the numbers are the offsets from the
Voice Carrier Modulator
1 03 00
2 04 01
3 05 02
4 0B 08
5 0C 09
6 0D 0A
7 13 10
8 14 11
9 15 12
When in Rhythm mode the rhythm instruments are controled by the following
registers (Again offsets from the base)
Bass Drum 13 and 16 (It uses two operators)
Snare Drum 17
Top Cymbal 18
In the duration of a piece of music, most of the registers are not touched.
The registers which are used the most are A0-A8 and B0-B8. These values
are changed to turn the instruments on and off, and to set their frequencies.
The other values, which really define the instruments are set up at the
To play high quality music you need a good method of creating the timing
between notes. There are two methods, by which you can do this.
Using the PIT
The PIT (Programable Interrupt timer) is a part of the computer, which can
be programed to create interrupts with fixed time gaps.
The PIT's counter is incremented 1234DDh times a second (If I remember
correctly!). When it reaches a value (set by writting a value to it's port)
The PIT has three channels. The first is responsible for the clock. It is
set to produce an interrupt (number 8) 18.2 times a second. The second is
hooked up to the DRAM on you're PC (it handles memory refreshes). The Third
channel is used to control the PC speaker.
The channel which you will want to use is channel 0.
You can simply hook the interrupt, you will then recieve control 18.2 times
a second, and as long as you execute a FAR JMP to the origional handler, each
time, and restore the interrupt vector at the end, you will not mess up the
The complication is that you may not want to play a note 18.2 times a second,
or even a multiple of 18.2 times a second. In this case you must re-program
the timer, and make sure that you still call the origional timer interrupt
vector 18.2 times a second.
e.g.If you want control 36.4 times a second you will need to reprogram the
timer. The counter is incremented 1234DDh times a second, so you will need
to cause an interrupt after 1234DDh/36.4=5000h increments. So you need
to re-program the timer
Set Port 43h to 34h (Set it up)
Write the Least Significant Byte of the counter value to port 40h (in this
example this is 0h)
Write the Most Significant Byte of the counter value to port 40h (in this
example this is 50h)
Then hook the interrupt, keep a running total of the number of clock ticks,
(in this case you add 5000h to the counter for each interrupt.) When the
counter passes 10000h (the origional counter value) deduct 10000h from your
counter and call the origional routine (with a FAR JMP.)
In your interrupt handler you will have to set up the new notes for each
Using the Sound Blaster's Counter
Simply use the counter to time it, checking the status bit in the main
loop of your program, to see if new notes are needed. This could be
in-accurate if your program doesn't check the status regularaly.