Programming the SoundBlaster

OFFSETS
Channel Carrier Modulator
1 00h 03h
2 01h 04h
3 02h 05h
4 08h 0Bh
5 09h 0Ch
6 0Ah 0Dh
7 10h 13h
8 11h 14h
9 12h 15h
Add the offset to from the table above to the address of the register you want to get all the register values. 

Here are maps of the bits in each register. The upper-left cell of each table will tell you what the base address of the register is. Add this value to the offset of the table above to get the proper register value.
20h
Bit 7 6 5 4 3 2 1 0
Use  AM Vibrato     Octave Shift
 
40h
Bit 7 6 5 4 3 2 1 0
Use   Scaling     Output Level    
 
60h
Bit 7 6 5 4 3 2 1 0
Use    Attack Rate    Decay Rate 
 
80h
Bit 7 6 5 4 3 2 1 0
Use Sustain Level Release Time
 
In register 40h, scaling is how quickly the output level rises as the pitch does. 0 = no rise, 1 = 1.5 dB/octave, 2 = 3 dB/octave, 3 = 6 dB/octave. Output level is the volume. 63 is the lowest volume, 0 dB (muted) and 0, the loudest volume, is 47 dB. This is not backwards. 0 is highest and 63 is lowest. 


The Amplitude Modulation and Vibrato, if applied can be adjusted in register BDh. Here is a bit map and explanation for register BDh. DO NOT try to use the offsets with BDh to get different channels' settings, this register sets the AM and Vibrato depths for all the channels.
BDh
Bit 7 6 5 4 3 2 1 0
Use AM Vibrato
When 6 is set, vibrato will be 14%. When bit 6 is clear, vibrato will be 7%. When 7 is set, AM will be 4.8 dB. When bit 7 is clear, AM will be 1 dB.




Here are the numeric representations of common music notes.
Note Number
C# 16Bh
D 181h
D# 198h
E 1B0h
F 1CAh
F# 1E5h
G 202h
G# 220h
A 241h
A# 263h
B 287h
C 2AEh

To set a note, you use the A0h and B0h registers. A0h is channel 1, A1h is channel to, and so on up to A8h is channel 9. Same for B0h. Here are bit maps of the registers.
A0h
Bit 7 6 5 4 3 2 1 0
Use 8 LSB of note
 
B0h
Bit 7 6 5 4 3 2 1 0
Use n/a Switch Octave 2 MSB

Obviously, some explanations are needed. Bit 5 in B0h is the switch. When set, the note starts playing, and when cleared, stops. Octave is just that. MSB and LSB mean most significant byte and least significant byte, respectively. The LSB are the last 2 digits of the note's hexadecimal (see note values chart above) and the MSB is the first digit of the hexadecimal. For example, G#'s MSB is 2h and it's LSB is 20h.


Here is a diagram of an FM sound showing the phases. X axis is time, Y axis is volume.


Here are some CONST statements you can add right to your program:


CONST BaseAddr = &H220 'Change if your sound card uses another base address
CONST RegAddr = BaseAddr + 8, DataAddr = BaseAddr + 9
Those should work. Just remember RegAddr = BaseAddr + 8, and DataAddr = BaseAddr + 9. You may want to create a SUB called SetReg so you don't have to type the actual OUT statements, just SetReg reg%, data%. In the SetReg SUB, put 2 OUT statements, like this:

SUB SetReg (Reg, Value)
  OUT RegAddr, Reg
  OUT DataAddr, Value
END SUB
Just use that code and it should work.