Programming the SoundBlaster 16 DSP
I am experimenting with using transparency in the images to allow irregularly-shaped diagrams without making assumptions about your browser's background color. If the DSP command or mode diagrams are blue, please contact me with information on your configuration so I can attempt to fix it.
Download SB16DOC.ZIP
(6,509 bytes)This information is distributed AS IS. The author specifically disclaims responsibility for any loss of profit or any consequential, incidental, or other damages resulting from the use or misuse of this information. This information may be freely distributed in any form as long as this disclaimer remains intact.
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 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.
You have to reset the DSP before you can program it. The DSP can be reset using the following procedure:
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.
To write a byte to the SB16, the following procedure should be used:
To read a byte from the SB16, the following procedure should be used:
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:
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:
LinearAddr := Seg(Ptr^)*16 + Ofs(Ptr^));
Port[MaskPort] := 4 + (Channel mod 4);
Port[ClrBytePtr] := AnyValue;
Port[ModePort] := Mode + (Channel mod 4);
Some often used modes are:
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;
Port[CountPort] := Lo(TransferLength-1);
Port[CountPort] := Hi(TransferLength-1);
Port[PagePort] := LinearAddr div 65536;
Port[MaskPort] := DMAChannel mod 4;
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:
To record or play back sound, you should use the following sequence:
Upon interrupt when using single-cycle DMA:
Command:
Common commands:
Mode:
The FIFO is used to eliminate inconsistencies in the sample period when the sound card is not able to get DMA when it needs it. With FIFO disabled, the card attempts DMA at precisely the instant that it needs a sample. If another device with a higher priority is accessing DMA, the sound card waits for the sample and the sampling rate may be decreased. The FIFO allows the DMA sample period to be more erratic without affecting the audio quality. The FIFO is cleared whenever a command is sent to the DSP. In Single-cycle mode, the DSP is constantly being reprogrammed. The FIFO may still contain data which has not been output when it cleared. To avoid this problem, the FIFO should be turned off for single-cycle mode. When in auto-initialized mode, the DSP is never reprogrammed. The FIFO can be left on and sound quality will be improved.
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:
To stop sound immediately:
Both commands stop sound immediately, without an interrupt.
To stop the sound at the end of the currently block:
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.
Thanks to Douglas Kaden at Creative Labs for information on 16-bit DMA, FIFO mode, and other topics.