Sound Blaster DSP Playback: Commands, DMA Blocks, and IRQ Completion
Implement a bounded Sound Blaster playback lifecycle by probing DSP status, configuring DMA and IRQ ownership, acknowledging completion, and cleaning up.
Sound Blaster-compatible digital playback is an asynchronous transaction across three components: the host programs a DMA controller, the Sound Blaster Digital Signal Processor (DSP) starts a sample transfer, and the card raises an interrupt as the programmed block completes. The DSP does not turn a BLASTER variable into audio by itself. A correct DOS player has to confirm the card’s interface, respect command-ready handshakes, choose a DMA path supported by the card and sample format, own the selected IRQ, and release every resource during shutdown.
This deep dive focuses on the classic ISA Sound Blaster command interface documented by Creative. It is not a universal driver for every model, PnP configuration, PCI emulation, or clone. The exact DSP version determines which playback commands, sample formats, and high-DMA features are available. Read the programming guide for the specific card and probe its DSP version before selecting a command family.
Identify the interface before sending commands
The base I/O address, IRQ, 8-bit DMA channel, and optional 16-bit DMA channel are system configuration. They may come from jumpers, a setup utility, Plug-and-Play initialization, emulator settings, or a user-provided environment string. The BLASTER variable is a convention for communicating these values to applications; it is not a hardware detector and does not reserve the resources. Treat each value as untrusted until compared with the card and platform configuration.
For the common DSP port layout, the base-relative ports include reset at +6h, DSP read data at +Ah, DSP command/data writes at +Ch, read-status at +Eh, and a 16-bit interrupt-acknowledge port at +Fh. Do not write a copied base address to hardware until ownership is established. Another adapter could decode the same address, and a virtualized environment may expose a different interface.
A standard reset transaction asserts the DSP reset port, holds it for the minimum interval documented by Creative, deasserts reset, and waits with a deadline for the DSP’s documented AAh response. Failure to receive that response is a useful classification point: check the selected base, device presence, reset timing, and emulator or initializer configuration before debugging DMA. Never wait forever for the response byte.
Every DSP byte has a readiness condition
The write-status bit indicates whether the DSP can accept another byte. A command and each of its parameters must be written in order, with the documented readiness check before each write. A routine that writes several bytes back-to-back may work on a fast emulator and fail on a slower card or clone. Similarly, reads from the DSP must wait until the read-status bit says data is available; a timeout should report the base port and expected response rather than returning an arbitrary byte.
For example, an 8-bit single-cycle playback command such as 14h is followed by a 16-bit transfer length encoded as the documented count-minus-one value. The exact command is not a generic “play samples” call: it selects a particular DSP generation’s 8-bit output mode, while newer DSPs also offer commands that encode sample rate and other format details. Creative’s programming guide defines distinct command families. Select one supported by the card and sample format rather than combining a command from one generation with parameters from another.
On DSP 4.x devices, the sample-rate command family allows a rate to be supplied directly. Older command families use timing configuration differently. This version distinction matters because rate calculation and block semantics belong to the DSP command contract. Do not assume that every card accepts every command merely because the port map matches.
Configure the DMA controller before starting the DSP
The DMA controller transfers bytes between memory and the sound card without requiring the CPU to move every sample. The program must configure the correct controller and channel for the selected sample width and direction, clear the channel’s flip-flop where required, program the address and count, select the transfer mode, and unmask the channel only when the buffer is ready. On traditional PC/AT hardware, 8-bit DMA channels and 16-bit DMA channels have different address and count units. Channel 4 is reserved for cascading the second controller and is not a normal audio channel.
Sound Blaster cards can use separate low and high DMA assignments. A 16-bit sample transfer normally requires a supported high-DMA channel, while 8-bit playback uses the low-DMA controller. The card’s programming guide describes which channels are accepted and how configuration is exposed. A valid D field does not satisfy a command that requires a H channel. Select the DMA channel according to actual card capability and the sample width.
The buffer must also obey the selected DMA controller’s physical-address, alignment, and boundary restrictions. This is not a Sound Blaster-only rule; it is part of the host DMA contract. Keep the allocation and transfer-length validation in a dedicated helper, and reject buffers that cross an unsupported boundary or exceed the programmed count range. The separate article on ISA DMA boundaries covers the address-unit and page-register calculations in detail.
Completion means coordinating DMA and DSP state
For single-cycle playback, completion of the transfer causes the DSP to raise the selected IRQ. The host interrupt handler must acknowledge the correct DSP interrupt source using the method for the sample width and DSP generation, then coordinate with the interrupt controller and the program’s IRQ ownership. The common 8-bit and 16-bit acknowledge paths are not interchangeable. A mismatched acknowledge can leave the interrupt line asserted or make subsequent audio blocks stop working.
Keep the hardware interrupt handler short. It should acknowledge the device according to its contract, record completion or error state, and wake the foreground audio routine. Avoid calling DOS, allocating memory, printing text, or performing unbounded file I/O inside the ISR. If a previously installed handler must be chained, preserve the original vector and follow its chaining convention; if the program owns the IRQ directly, mask, restore, and unmask it in a carefully ordered sequence. The PIC’s end-of-interrupt requirement is a separate part of the IRQ delivery path, not a substitute for acknowledging the DSP.
The foreground loop can refill a second buffer or submit the next block after it observes completion. Double buffering reduces gaps only if the DMA and DSP modes support the intended sequence. Auto-initialize DMA repeats transfers, but then the application must distinguish block boundaries, stop conditions, and buffer ownership. A ring buffer that the ISR and foreground both modify needs an explicit producer/consumer index and an overflow policy.
Pseudocode for a single block
This intentionally omits machine-specific port intrinsics and ISR installation. It illustrates ordering, not a complete device driver:
verify configured base, IRQ, DSP version, DMA channel, and sample format
reset DSP and wait, with timeout, for the documented ready response
allocate and validate a DMA-safe physical buffer
fill buffer completely and compute the transfer count
install or register an IRQ handler using the platform's ownership rules
program DMA address, count, direction, and mode; unmask only after validation
send each DSP command byte only when write status reports ready
wait for completion with a bounded timeout while servicing the DOS-safe loop
in the IRQ handler, acknowledge the DSP source and record completion
stop/close the DSP mode, mask DMA, restore the previous vector, free the buffer
When a timeout occurs, stop the audio path before reusing memory. Otherwise, the DMA engine can continue reading a buffer after the application believes it has been released. Similarly, on a user abort, silence or halt the DSP according to the supported command set, mask the DMA channel, restore the IRQ vector and prior mask state, and only then free the sample buffer.
Failure modes that look alike
Silence does not have one cause. A DSP reset timeout suggests address, initialization, or hardware presence. A ready-bit timeout suggests the DSP is busy, wedged, or addressed incorrectly. A transfer that starts but plays noise can point to the sample format, signedness, rate, DMA count units, or buffer placement. A block that plays once and then stops can implicate an interrupt acknowledge or the wrong auto-init assumption. A sound effect that plays at the wrong speed can be a rate-command or clock mismatch even when DMA is correct.
Do not “fix” audio by changing several configuration values at once. Log the card model and DSP version, base, IRQ, both DMA channels, selected command, sample width/channel count/rate, physical buffer range, programmed count, completion count, and timeout phase. Compare identical sample data and configuration on a known emulator or card. A passing test establishes only the tested DSP, DMA, and IRQ combination.
Version and compatibility boundaries
Creative’s guide covers multiple generations and explicitly separates capabilities. The common port layout does not erase those differences. A clone may implement a subset or add undocumented behavior. PCI cards often depend on a compatibility driver or emulator; a historical ISA register sequence should not be issued to such a device unless its vendor documents that interface.
The old single-cycle commands, DSP 4.x rate commands, high-DMA paths, and auto-init operation should each be capability-gated. Use only documented version fields and known card behavior. Do not write DMA or IRQ configuration registers as an application shortcut; the card guide warns that setup software also needs to update related system configuration. Let the vendor’s initializer own device setup when required.
Acceptance tests
Test reset with a finite timeout, readiness before every command/data byte, and one known small buffer before introducing streaming. Validate 8-bit and 16-bit paths independently only if the actual card supports them. Confirm the correct IRQ acknowledge by observing repeated blocks, test stop and abort paths, and intentionally make the device unavailable in an emulator to ensure the program exits cleanly. Check memory is not freed while DMA can still access it and verify that the original vector and interrupt mask are restored.
The outcome is a playback lifecycle, not merely a port sequence: establish the card contract, validate memory and DMA, start a compatible DSP command, acknowledge the resulting IRQ, and tear down ownership safely. That structure turns a fragile legacy audio routine into a component whose failures can be localized and reported.
Related:
- ISA DMA on DOS PCs: Page Boundaries, Address Units, and Safe Buffers
- Fixing Sound Blaster Configuration Issues on FreeDOS
Sources: