Creative Sound Blaster or 100% Compatible sound output library. (C) 2008-2011 Jonathan Campbell. Compiles with Open Watcom. What it supports: Any Sound Blaster or Sound Blaster compatible interface that communicates on ISA I/O ports 0x2x0-0x2xF (where X=2,4,6, or 8) using ISA DMA channels 0, 1, or 3 and 16-bit DMA on 0, 1, 3, 5, 6, or 7. Also supports and recognizes various known emulations of the Sound Blaster, including: - Gallant/SC400 Crystal Semiconductor CS4232-based cards - They emulate a SB16 with a SBPRO mixer, and a Windows Sound System interface on 0x530 or 0xE30. - Their Sound Blaster emulation also has a proprietary "plug & play" software configuration command set, supported by this library - Yamaha OPL3-SAx Sound Blaster emulation NOTICE: The sndsb.lib library by itself does not contain support for ISA Plug & Play Sound Blaster cards. The isapnp library is kind of large and building this library to depend on it only serves to add bloat to your program (especially if you will be targeting pre-486 hardware where PnP type hardware is very unlikely to be found). If you do want your program to support PnP type cards (especially if your code is intended for 486 and higher hardware) then you can link into your program sndsbpnp.lib and isapnp.lib to enable autodetection of ISA Plug & Play based Sound Blaster hardware. WARNING: Sound Blaster PnP support is written only to read back the resources assigned. Cards whos resources have not been assigned will be ignored. In the DOS world, the task of PnP resource assignment is generally given to a device driver or DOS utility that carries out configuration (such as: Creative PnP utilities). If you really want to, look at the PNPCFG.EXE utility provided here as an example of a minimalist Sound Blaster PnP resource assignment program. Then if you really want to, go ahead and write your program to auto-configure the card if necessary. I strongly recommend though that if you do that, you allow the user to turn it off, since the PnP device is likely sharing the system with perhaps several other ISA devices that could easily conflict with the one you're trying to auto-config! TABLE OF SUPPORTED CARDS ------------------------ YES = Card is supported, verified by actual h/w testing HWEMU = If listed with YES or LIKELY, the hardware itself responds to I/O ports like a Sound Blaster even though the chipset is something else entirely LIKELY = Card is supported, because the interface is Sound Blaster compatible, but I have not yet tested and verified that it works. If listed with SWEMU, then the software emulation is likely Sound Blaster compatible even though the actual hardware is not. MAYBE = Card might be Sound Blaster compatible, I don't really know PNP = Card is ISA Plug & Play compatible, if listed with YES or LIKELY the card will work with this library IF you first run an ISA PnP configuration utilty to assign it's resources and bring it online. PNPNC = Card is ISA Plug & Play compatible, but needs no configuration utility to enable Sound Blaster or Sound Blaster emulation SWEMU = Card is NOT Sound Blaster compatible, but comes with a DOS TSR that abuses EMM386.EXE and/or Virtual 8086 mode to emulate a Sound Blaster BIOS = Card is Sound Blaster compatible by emulation using motherboard audio, and can be enabled/disabled through the BIOS setup menu PCI = Card connects through PCI bus MORE = Card is Sound Blaster compatible and has additional functions that might be of interest NO = Card is NOT Sound Blaster compatible Finer details on every possible card I've tested is listed in the sndsb library source code. Creative Sound Blaster 1.5 (CT1320C) LIKELY Creative Sound Blaster 2.0 (CT1350) YES Creative Sound Blaster Pro (CT1330) LIKELY Creative Sound Blaster Pro 2 (CT16x0) LIKELY Creative Sound Blaster 16 LIKELY Creative Sound Blaster 16 ViBRA LIKELY Creative Sound Blaster 16 ViBRA PnP (CTL00F0) YES PNP Creative Sound Blaster 16 ViBRA PnP (CTL0070) YES PNP Creative Sound Blaster AWE64 PnP (CTL00C3) YES PNP MORE Creative Sound Blaster AWE64 Gold PnP (CTL00B2) YES PNP MORE Creative Sound Blaster Live! Value PCI LIKELY SWEMU Gallant SC-6000, Crystal Semiconductor CS4232 YES HWEMU VIA EPIA (????) [LOOK IT UP] YES BIOS HWEMU [*VIA EPIA] Yamaha OPL3-SAx YES HWEMU PNPNC [*1] Gravis Ultrasound MAX & SBOS 4.x YES SWEMU [*GUS] Gravis Ultrasound MAX & MEGA-EM YES SWEMU [*GUS] [*GUS] Gravis Ultrasound: The GUS basically pretends to be a Sound Blaster and other components by trapping certain I/O ports and reflecting to a TSR by NMI. Most often the ports overlap the GUS's. Emulation is terrible, especially MEGA-EM that only emulates a Sound Blaster 1.xx DSP and will literally hang the machine if you use any DSP command outside the supported set. DMA timing is terrible. Rather than a continuous stream as by Sound Blaster you see instead the DMA speed by and finish far before the audio finishes playing. If you're a DOS program depending on the DMA to match timing, you're not going to work too well. Also does not emulate auto-init. [*1] Yamaha OPL3-SAx: it is listed as PNPNC because the only one I have to test against is embedded on the motherboard of a laptop who's BIOS takes care of ISA PnP resource allocation. In fact the BIOS lists the sound card as one of the system nodes that can be enumerated using the PnP BIOS entry point. [*VIA EPIA] VIA EPIA: For whatever reason, despite the BIOS-supported emulation, I am unable to actually hear the sound output through the line out jack. The card seems to require a proprietary initialization procedure to enable the output. Other than that, DMA and IRQ activity suggests that it works fine. DSP VERSIONS ------------ - DSP 1.xx The code talks to the card in a manner compatible with the original Sound Blaster. - DSP 2.00 Sound Blaster 2.0 compatible operation. In this version Creative added auto-init playback which means the software only needs to acknowledge the interrupt instead of reprogramming the DSP to start another block. - DSP 2.01 Creative added the "high speed DAC" mode to enable playback up to 44100Hz mono (22050Hz stereo). On a real Sound Blaster 2.0 card I own, the DSP appears to have timing problems where in non-high speed mode any other use of the ISA bus can cause audible slowing down. - DSP 3.xx Sound Blaster Pro compatible output. Uses the mixer chip to enable stereo, which should also work on clone cards, but will remain monural on Sound Blaster 16 cards because Creative removed the control for some reason. Steroe playback on SB16 cards require DSP 4.xx playback mode. - DSP 4.xx Sound Blaster 16 compatible output. This enables 16-bit audio playback. Stereo playback on SB16 requires this mode, Pro stereo does not work. SB16 specific DSP commands also allow "flipped sign" playback. ADPCM playback only works with monural 8-bit audio. Direct DAC mode will only function properly with 8-bit monural audio. WARNINGS -------- Goldplay & Direct DAC modes: - These modes work by using the CPU and the IRQ 0 timer interrupt to play sound. If your machine is slow enough, the timer ISR can overwhelm the CPU and effectively make the UI unresponsive. This can happen for 16-bit builds on a slow enough configuration, but it is especially a problem with 32-bit builds due to the overhead involved with the 32-bit DOS extender. This program has a "watchdog timer" implemented into it's timer ISR to try and deal with timer overrun. In most cases if the ISR consumes all CPU the watchdog will time out, stop playing, and restore the tick rate to 18.2/sec so that the UI becomes usable again and you can safely stop playback and/or exit to DOS. But it is not 100% perfect, and what can happen instead is that the Sound Blaster ISR can get triggered in an infinite loop by a General Protection Fault (IRQ 5 and the GP# fault overlap thanks to politics between Intel and IBM), or the DOS extender can crash to DOS with an error message about overrunning the stack (with the timer and keyboard unresponsive!). When you enable Direct DAC or Goldplay mode in the 32-bit version, a warning message will remind you (once) of this potential pitfall, and allow you to cancel the selection. The final warning is that this method should never be used in an environment where everything is totally virtualized, especially from within a Windows DOS box. Windows 95/98 have problems as it is dealing with DOS games that reprogram the timer beyond 100Hz. Remember, if you play with Direct DAC mode or Goldplay mode, and the program hangs or crashes, don't blame me---you were warned! NOTES: Sun/Oracle virtualbox. Does not work, produces low frequency "warble". Also seems to cap the timer rate at about 4KHz, no matter what rate this program is trying to run at. NOTES: DOSBox 0.74. Does not work, produces low frequency "warble" though timer rate is correct. If you must hear Goldplay mode in action use the dosbox-x "branch" source code I posted in the Vogons forums, which contains a fix to make Goldplay mode work correctly in DOSBox (as well as allow many older demos to play music audibly). NOTES: Direct DAC mode also affects recording. The same ISR timer technique is used to issue DSP command 0x20 (Direct ADC input) and then read the result from the DSP. Experience says this technique maxes out at 11KHz, if overdriven the ISR might overrun the stack and crash. Goldplay mode, an explanation: In the demoscene from about 1991 to 1993 there was a short-lived audio/tracker library called Goldplay that supported Sound Blaster and Sound Blaster Pro in addition to Covox, Disney sound source and other legacy one-sample-at-a-time sound output methods. The libary was written to hook the timer interrupt and reprogram the timer to run at the sample rate needed to play audio, then write one sample from the interrupt. The obvious problem the programmer(s?) faced was that the code was written for audio output methods that needed the CPU to write to them at a constant rate, because the devices themselves had no way to pull in audio by themselves. So naturally the timer interrupt was a way to accomplish that. But then what do you do about the Sound Blaster, which uses DMA and for stereo output does not offer a way to manually write audio samples? Many demos at the time opted for the method of programming the timer ISR to twice the sample rate, then alternately writing DSP command 0x10 and the audio sample to play. But DSP command 0x10 cannot run faster than 22050Hz, and cannot play stereo. Goldplay programmers apparently decided to support Sound Blaster then using a simple hack. The library tells the DSP the block size is 65535 samples, then tells the DMA controller the buffer is 1 sample wide! This means that during playback the DMA controller is transmitting the same sample over the ISA bus. Then, from the timer ISR, the library just overwrites that one byte with the latest sample to transmit. The DMA controller sends the new byte next cycle, and the DSP gets "sound". The obvious problem of course is that the timer is very likely not running at the same rate as the DSP, and this trick usually results in slightly scratchy sound as a result of samples getting duplicated or dropped. Such a trick was possible, because systems at the time did not cache CPU I/O (286s), or did cache CPU I/O but had logic to keep the cache coherent between the DMA controller and the CPU (386, 486, Pentium motherboards). On today's hardware the PCI bus logic and CPU memory controller would have a lot of difficulty pulling a stunt like that, which is why you don't really see that kind of trickery anymore. For testing purposes, the test program emulates that hacked method of playback just to see if it's possible. So far, testing shows that it is, even in configurations the Goldplay library would have never used (such as "Goldplay mode" with 16-bit stereo PCM). NOTE: Even though the Goldplay library never recorded audio, this program can also be used to test whether one can record audio from the DSP in this manner. Apparently it's possible, on real hardware! Switch on Goldplay mode and then select "record" to see in action. ADPCM auto-init: On actual Creative hardware there are DSP commands to play sound data compressed using Creative's proprietary ADPCM compression method. On Sound Blaster 2.0 and higher DSPs, there are additional commands to play the data in an auto-init fashion. Most clones and emulators know the original ADPCM commands, but generally do not respond to the auto-init versions. If you enable auto-init ADPCM and playback causes nothing to happen, then your card/emulator does not recognize it. DOSBox 0.74: Supports and decodes ADPCM, does not recognize auto-init ADPCM VirtualBox: Does not support ADPCM at all Virtual PC: Does not support ADPCM at all Yamaha OPL3-SAx: Supports 4-bit ADPCM, cycles DMA for 2.6/2-bit silently, does not recognize auto-init ADPCM ADPCM reset step per IRQ: DOSBox 0.74 emulates Sound Blaster ADPCM playback perfectly, except for one difference observed on genuine Creative hardware: Once per IRQ, even in auto-init mode, the DSP resets the step value, while DOSBox does not. A program that is unaware of the reset will produce audio that generally sounds OK but can audibly "flutter" depending on how often the IRQ occurs. This fluttering effect is caused by the ADPCM data compressed with one step size, and the SB decoding with the wrong step size, until ADPCM limits knock them back into sync. So when Creative documents the DSP commands as having a "reference byte" version and a version that "decodes using accumulated reference byte" consider they only mention the reference byte for good reason: the DSP does not preserve any other ADPCM state. Probably to make decoding from an arbitrary point in VOC files more predictable, I suppose. You can test for proper behavior by loading an 8-bit monural WAV file, setting the audio to 2.6 or 2 bit ADPCM, and playing it. On real hardware, it should sound fine, while in DOSBox, it should audibly flutter like a badly tuned FM radio. Switching off ADPCM reset per block should cause the opposite: DOSBox sounds fine, while on real Creative hardware it should audibly flutter. NOTE: The code has been tweaked to produce the best ADPCM output by ear on real SB16 hardware. Creative's ADPCM compression overall though is crap, so in the end it's difficult to tell whether the flutter happens because of errors in my code or because resetting the step size leaves little to no room to properly encode the waveform at the reset point. All I know is that the reset values in my code seem to produce the least amount of audible flutter, even though nothing I can do eliminates it completely. One way to eliminate flutter is to change the IRQ interval to the large setting, so that the DSP plays a larger amount of data before resetting at the next block. Sound Blaster Pro stereo: When Creative first implemented stereo in the Pro cards, they added a bit to a mixer register that enables/disables it. The program sends a time constant representing twice the sample rate, then flips on stereo, and... stereo playback happens. Most clone cards made afterwards emulate this bit quite well, even the cards that implement SB16 commands such as the Gallant SC-6000 chipsets. But Creative for some reason removed that function on the Sound Blaster 16 cards and designed them instead to require the DSP 4.xx 0xBx-0xCx DSP commands to play back in stereo. The result is that DOS programs written around the Pro and it's stereo bit produce scratchy monural audio on the SB16, while ironically producing correct stereo output on clone cards! In this program, DSP mode 3.xx attempts to play stereo using DSP 3.x commands and the stereo bit, while DSP 4.xx uses the SB16 command set and does not set the stereo bit. If you have DSP 3.xx mode set and stereo audio sounds funny, then you have true Creative SB16 hardware and you need to reconfigure to DSP 4.xx mode. ISA Plug & Play compatibility: If your SB16 is the ISA PnP variety, it will be automatically detected. However if neither the BIOS nor any DOS utilities have assigned resources, this program will not be able to make use of the card. To resolve the issue, try: - Using the PNPCFG program provided to assign resources. - Use DOS utilities provided by the manufacturer to assign resources. Creative for example offers a DOS utility to test and assign resources to their Sound Blaster cards (both PnP and legacy versions) - If your BIOS offers the option, see if the setup menu offers ISA PnP resource assignment. Some BIOSes will automatically (try) to assign resources. One BIOS I test against likes to assign my SB16 ViBRAX/V to IRQ 2 and DMA channel 0! ISA PnP compatability verified with: Sound Blaster 16 ViBRAC Sound Blaster 16 ViBRAX/V Sound Blaster AWE 32 Sound Blaster AWE 64 Gold Microsoft Virtual PC Sound Blaster 16 emulation Some cards, for whatever reason, do not appear to have working 16-bit DMA transfer capability. Attempting to play 16-bit audio when the 16-bit DMA channel is 5, 6, or 7 will result in nothing at all. If that happens, try assigning both 8- and 16-bit DMA channels to DMA 0, 1, or 3. Non-ISA Plug & Play card software configuration: Some SB16 cards (or clones) are not ISA Plug & Play compatible, but do have some proprietary method of configuring DMA and IRQ resources. For these cards the PNPCFG utility will not work. You will instead need to identify the card, and then run the appropriate tool to initialize them: Sound Blaster 16 (non PnP) - Run the TEST program. Select the card. Note that if it has not been assigned resources the DMA and IRQ fields will read -1. Go to the device menu, and select Configure card. The program should indicate you are using a non-PnP SB16 and should offer options to configure IRQ and DMA channel settings. When you are finished, hit ENTER. NOTE: IRQ and DMA settings are changeable, while the base I/O address is NOT changeable. This method will also NOT work with PnP versions of Sound Blaster 16 hardware, nor will it work within Microsoft Virtual PC 2007 (emulated PnP SB16). NOTE: This is the recommended way to reconfigure Sound Blaster 16 support in DOSBox, VirtualBox, and Bochs emulators as they emulate Sound Blaster 16 functions but without ISA PnP. Gallant SC6600/Crystal CS4321 "SC-4000" cards - Uses a jumper to configure the base I/O address, but all other resources are assigned by non-standard DSP commands. The card emulates a weird hybrid of Sound Blaster functions: a Pro-style mixer and a DSP that reports itself as a Pro (v3.5) yet it also supports SB16 DSP commands and 16-bit playback. The card also maps the CS4321 crystal codec to a configurable WSS address (usually 530h). Run the TEST program. Select the card. Note that if it has not been assigned resources the DMA and IRQ fields will read -1. Go to the device menu, and select Configure card. The program should indicate you are using a SC-6000 card and offer options to change IRQ, DMA, and WSS I/O port resources. When you are finished, hit ENTER. PCI motherboard issues: Some motherboards block or only allow certain IRQ and DMA channels to work across the PCI-ISA bridge. Normally the IRQs blocked are IRQ 9, 10, 11, 13, 14, and 15 depending on whether your BIOS has assigned them to motherboard resources or PCI peripheral devices, while IRQ 3, 4, 5, 6, and 7 are normally left open. BIOSes that assign IRQs to either PCI or ISA normally allow you to change the assignment manually in the setup menu. The 32-bit protected mode version has SB IRQ problems when configured to IRQ 8, 9, 10, etc... On some 486/Pentium boards and ViBRA SB16 cards there seem to be some horrible reliability problems between the BIOS, the DOS extender, and the upper IRQs. The IRQ may work the first few times but after that nothing fires and the Sound Blaster DSP stops playback waiting around for our ISR to return acknowledgement. UPDATE: Independent testing reveals that it is a problem with the DOS4/GW DOS extender. The issue mentioned above is reproducible on a lot of other hardware such as a Dell Pentium III test machine. There are several ways to handle this: - Stop using DOS4/GW and run the program using open source DOS extender DOS32a, which doesn't seem to have this problem. - Use the 16-bit real mode versions. On the same systems they do not appear to have any problems. - Use a PNP configuration utility to move the IRQ down to 5, 7, etc. 16-bit real mode large model hack, the SB IRQ indicator: For reasons beyond my comprehension, the 16-bit large model builds had a mysterious bug where half the time the subroutine would fail to redraw the IRQ indicator. This was visible on screen as erratic jumpy movement of the 'x' in the indicator. At one point, this indicator was responsible for several severe memory corruption issues that would eventually crash the machine! So, the 16-bit large model version redraws it instead from the main loop. This means though that if the main loop is unable to function, the IRQ indicator will not function and will be unable to show you if the DSP is still signalling interrupts. 16-bit real mode small model, and 32-bit protected mode builds, are able to retain redrawing the indicator from the Sound Blaster ISR. Even if the main UI hangs, you will still be able to see IRQ activity in the upper left corner of your screen. Flip sign mode: In the DOS/Windows world there are two de-facto "standard" PCM formats widely used. One is 8-bit unsigned PCM, using byte values 0 to 255 (with 128 at center) to represent the waveform. The other is 16-bit signed PCM, with -32768 to 32767 (with 0 at center). The SB16 DSP commands 0xBx-0xCx have bitfields to indicate 16-bit playback, as well as whether the audio data is signed or unsigned. In most cases, it is told to play either unsigned 8-bit or signed 16-bit data, and clone cards support that command as well. What clones and emulators get wrong though, are situations where the DOS program instead instructs the DSP to play signed 8-bit PCM, or unsigned 16-bit PCM. Note that the same DSP command is used for playback and recording. When enabled, the program will flip the sign bit before sending to the card, and then tell the SB16 DSP that it is the opposite signed/unsigned mode. If your card fully supports the DSP commands, it should make no audible change in the sound. If your card is a clone or an emulator that is not aware of the bits, you will hear loud static. DOSBox 0.74: Fully supported Bochs: Not fully supported. Loud static. Gallant SC-6000 clone: Fully supported ESS 688 auto-init does not fire IRQ: ESS chipsets work perfectly fine with auto-init and single-cycle modes, EXCEPT that for whatever reason, the chipset does not fire the IRQ if playing or recording 16-bit PCM and using auto-init DSP mode. If designing a game to use this library, this may be something to keep in mind if you are considering having music playback or synthesis occur from an IRQ---you cannot rely on using the SB IRQ to do this on ESS chipsets. BUGS ---- 1] Direct DAC and Goldplay modes (anything using the timer ISR to play) can overwhelm the CPU and effectively freeze the UI, forcing the user to push reset button. FIXED. Timer ISR has watchdog counter. When it hits zero, it forcibly stops playback and resets timer to 18.2/sec tick rate. The UI, if functional, will otherwise reset the watchdog and therefore allow the audio to keep playing. This way, if your CPU is too slow, the program will auto-recover within 5-10 seconds so that you can safely stop playback and/or exit the program. 2] Audio playback occassionally skips 1-4 seconds forward. Audio recording occassionally repeats a 1-4 second section to disk. FIXED. The DMA counter readback code failed to consider the 8237 does not necessarily latch the value during reading, causing reads to occassionally give bad or incorrect readback values that confuse the DMA tracking logic and cause it to over-refill the buffer. The 8237 library has been updated to read the counter twice, and re-read until the value counts down as expected. 3] The IRQ indicator would randomly draw or not draw in the 16-bit real mode large build. It would also cause random memory corruption that would eventually crash the computer. FIXED, and FIXED. Changing the method by which "SB-IRQ" was written fixed the memory corruption issue, though it doesn't explain the random corruption, and it still didn't fix the random updating problem. Instead, the code was written to have the main loop do the IRQ state update. 16-bit small model, and 32-bit flat mode builds retain the code to redraw IRQ state from within the ISR. 4] On a Pentium motherboard (with Award bios dated 1995) having PCI, ISA slots and Pentium 133MHz MMX processor, the 32-bit build cannot reliably service Sound Blaster DSP interrupt if IRQ is assigned to IRQ 8 or higher. Playback will work for awhile, then stop. A raw dump of the mixer shows byte 0x82 set to 0x41 (which means the DSP is waiting for acknowledgement, and therefore the IRQ was not serviced). 16-bit builds are not affected by this bug. NOT FIXED. I noticed the problem is reproducible on a lot more than just that one motherboard, and testing reveals that it is a problem with the DOS4/GW DOS extender. You can resolve the issue by replacing the DOS extender with one that does not have this problem, such as DOS32a (http://www.sf.net/projects/dos32a). 5] Goldplay record/playback mode doesn't work when EMM386.EXE is resident and active. FIXED. It turns out pointing DMA at the Sound Blaster context structure was a bad idea. It happens to work in non-EMM386.EXE situations because the struct usually ended up below 16MB. But EMM386.EXE does not virtualize locations above 1MB, so DMA was effectively playing some unrelated data. Goldplay mode now allocates a separate (16-byte long) DMA buffer. 6] Selecting "Device" -> "Trigger IRQ" when playing or selecting 16-bit audio causes computer to lock up. 32-bit builds trigger a crash dump in DOS32a and DOS4G/W. FIXED. The Sound Blaster DSP expects one form of acknowledgement for 8-bit I/O, and another form for 16-bit I/O. The code used the 8-bit version at all times. If that is done, the Sound Blaster DSP re-fires the IRQ expecting the ISR to take care of 16-bit I/O. Since the program never does, the IRQ re-fires until the stack overflows and the program crashes. 7] Audio plays twice as fast or skips every other second when playing audio on Gravis Ultrasound SBOS/MEGA-EM installations. SBOS compatibility: FIXED [16-bit real mode small model]. FIXED??? [16-bit real mode large model]. At least it seemed to fix itself, or at least stopped skipping ahead with noise every time the DMA pointer crossed the end of the buffer. Perhaps the phase of the moon changed during testing, who the fuck knows? >:[ FIXED, sort of [32-bit protected mode]. The test program now hooks the NMI interrupt from protected mode so it can reflect it back to real mode. However, the NMI handler doesn't seem to be able to trigger the SB IRQ in protected mode, so playback will stall after playing a short piece of the audio. The above NMI hack will work with DOS4/GW and DOS32a. However if EMM386.EXE is resident and active, DOS4/GW will hard crash and reboot the system upon receipt of an NMI interrupt. If your program needs EMM386.EXE to be active, consider using DOS32a instead. If EMM386.EXE is not active, and the test program does not hook the NMI, DOS4/GW simply does not reflect the interrupt and the program will not reliably detect the virtual sound card. MEGA-EM compatibility: FIXED [16-bit real mode small model]. NOT FIXED [16-bit real mode large model]. Despite extremely careful DMA controller programming, running this program seems to invoke EMM386.EXE's panic screen complaining about the program attemping to do a 64KB DMA transfer (WHAT?!). Adding D=64 to the EMM386.EXE device line in your CONFIG.SYS seems to resolve the issue. NOT FIXED [32-bit protected mode]. NMI interrupt causes DOS extenders to panic. Hooking the NMI interrupt from protected mode to reflect back to real mode doesn't resolve DOS4G/W causing a hard reset on NMI, but when run under DOS32a the NMI emulation magic apparently fails to work, and the test program fails to see the emulated sound card. While effort has been made to support SBOS and MEGA-EM emulation, I consider full compatibility a low priority. I have no patience for twitchy TSRs that have stability issues, shitty Sound Blaster emulation, and bizarre DMA bugs. 8] When playing audio through SBOS, switching to ADPCM mode causes the program to hang and crash. NOT FIXED. I have no patience with SBOS and I do not forsee any need to use ADPCM mode with it. If you must use ADPCM playback with the Ultrasound, use MEGA-EM, which at least does a reasonable job faking the ADPCM playback without causing a hard crash. 9] When playing ADPCM audio with MEGA-EM, the audio sounds buzzy and distorted, or tinny and quiet like static. NOT FIXED. MEGA-EM attempts to fake ADPCM playback, but the programmers obviously had no documentation on what exactly the ADPCM format did (back then, who did?). Gravis SBOS bugs this code has to deal with: - The people who wrote SBOS evidently failed to take into consideration the interpolation used by the GF1 chip, thus there are audible pops and buzzing at the boundaries of DSP blocks not because of any errors but because of the GF1 interpolating into undefined samples - SBOS's use of INT 02h (NMI) causes DOS4/GW to hard reset and DOS32a to crash to the DOS prompt with an exception report. You can avoid the hard crash with DOS32a at least by hooking INT 02h from protected mode to reflect to real mode, but the NMI handler doesn't seem to be able to issue the SB IRQ back into your protected mode program - I also noticed their NMI handler occasionally seems to not carry out the DMA transfer at all. Instead it does the transfer within the NMI handler. For programs that rely on the DMA pointer to advance audio this is bad news, and something to watch for. DSP alias port -------------- A long time ago I stumbled upon an old demo written by the Eletromotive force (EMF_ID.ZIP) that I thought was interesting, but could never get the Sound Blaster mode working. Every time I tried, the demo hung after prompting for Sound Blaster setup. It wasn't until I ran it in DOSBox that I eventually figured out what was wrong: the demo relied on using the ALIAS of the DSP port, meaning that it read status from and wrote DSP commands to port 0x22D instead of 0x22C. I immediately plugged in an old Sound Blaster (DSP 2.0) and confirmed that all I/O ports do in fact appear on both the original and the alias ports, as if the card only decodes 4 bits and pays attention to the top 3 while ignoring the LSB. If you have an old Sound Blaster card, you might enable DSP alias port mode to instruct the library to use port 0x22D to see if it actually works. If it works, you have an original Sound Blaster that aliases it's I/O ports. List of cards and whether or not ports alias: --------------------------------------------- Sound Blaster (DSP 1.x) PROBABLY Sound Blaster (DSP 2.01) YES Sound Blaster Pro (DSP 3.x) PROBABLY NOT Sound Blaster 16 (DSP 4.x) NO ESS Plug and Play AudioDrive YES (DSP PORTS ONLY) Backwards mode -------------- Besides the EMF_ID fix mentioned above (in DSP alias port), the demo also appears to use DMA decrement mode. What that means is that, instead of pointing the DMA controller at the first byte and rendering audio forwards, it instead points the DMA controller at the last byte and renders audio backwards, then tells the DMA controller to decrement the address after every byte (instead of incrementing) so that the backwards audio is played forwards. If you want to play files backwards or want to test whether your motherboard supports DMA decrement mode, you can go into the "parameters" page and set "direction" to "backwards". if you hear the audio perfectly in reverse, then your motherboard supports the "decrement" bit of the DMA controller's mode register. I consider it an additional test of robustness if you set both DMA and the DSP into single-cycle non-auto-init mode and playback does not exhibit any glitches. WARNING: Backwards mode should be used with 8-bit PCM only! 16-bit PCM backwards playback is NOT RECOMMENDED, especially if your sound card is configured to use an 8-bit DMA channel to carry it (byte order is backwards and LOUD STATIC will result!). If you are using a 16-bit DMA channel, then theoretically it MIGHT work, but there are no guarantees. To consider why it might work, think about how the DMA controller uses the low 15 bits to determine the memory address, then imagine how the DMA controller loads 16 bits from memory (PROBABLY in the correct byte order!) and sends it to the sound card. * TODO, NOT YET IMPLEMENTED * - Recording in backwards mode (use backwards DMA to record, then write data FORWARDS to the WAV file) - ADPCM playback with DMA backwards mode (compress to ADPCM backwards, then write compressed ADPCM backwards!) What is "nagging the DSP? ------------------------- I recently patched up DOSBox-X to support the Triton "Crystal Dream" demo's Sound Blaster support. In the process of doing so, I learned a few funny things about both DOSBox source code and the Sound Blaster. First, the Crystal Dream demo uses the Goldplay technique, where the Sound Blaster is told the DSP block size is 65536 bytes, but the ISA DMA controller is put into auto-init mode and told the DMA transfer length is 1 byte (2 bytes if stereo). But what Crystal Dream does beyond that is interesting in it's own right. First of all, my initial assumption that the demo was hooking the wrong IRQ was wrong. I looked at the interrupt vector table while it was running and I saw that it hooked IRQ 0, and IRQ 1, but didn't hook any other interrupts. Which means that, when the Sound Blaster signals an IRQ, the demo doesn't respond to that IRQ at all. At the same time, the demo uses the single-cycle DSP playback commands, which means that at some point, the DSP will finish the block and the demo needs to start another one to keep playing. So how does it keep the audio going this way despite no IRQ handler? It turns out, digging into the IRQ 0 hook it sets up, the demo starts audio by sending DSP command 0x14 at the start. Then, the IRQ 0 handler not only renders music but also polls the DSP write status port 0x22C. If the DSP reports itself busy, the demo resets a counter, else when the DSP is not busy, it decrements the counter. When the counter gets low enough, the demo uses the IRQ 0 interrupt to send another DSP command block (0x14,xx,xx). The fact that the Sound Blaster has not yet finished playing the last block at this point is irrelevent. So, about 10-20 times a second, the demo is constantly interrupting DSP playback to start DSP playback, and the audio keeps going. Now on actual hardware apparently, this works perfectly fine. In fact, the advantage of the technique is that it allows audio without any small pops or crackles normally associated with the CPU and interrupt system taking too long to start another block, even on the original Sound Blaster. The other advantage is that, by doing it all from IRQ 0 and effectively interrupting the DSP constantly the DSP never fires the IRQ normally associated with completing a block, so the demo never has to concern itself with IRQ detection logic (never mind it assumes DMA channel 1). When I coded support code for this in DOSBox's emulation, I coined it "nagging the DSP", because the demo is constantly nagging the DSP to keep playing in a rude manner (but it works!) To test this case, the sndsb library and test program allow you to enable that mode to see how well your Sound Blaster handles that kind of playback. To actually trigger the behavior, you will need to enable DSP nag mode, and switch DSP playback into single-cycle mode (where by default it is in autoinit mode). DSP auto-init vs DMA auto-init ------------------------------ Despite similar sounding names the two options control entirely different things. DMA auto-init concerns itself with the auto-init bit on the ISA DMA controller, which if set, causes the DMA controller to automatically restart a DMA block when it reaches the end. DSP auto-init concerns which set of DSP commands are used to start playback. The Sound Blaster family has two sets: single cycle, and auto-init. Single-cycle commands play a block of audio, then fire an IRQ and stop. Continuing playback requires the CPU to send another command to start playback again. Auto-init commands are usually only sent once. Once the command is sent, the DSP keeps playing (sending an IRQ every so many bytes) until it is told to stop. This is the recommended way to play audio on Sound Blaster hardware, although the original Sound Blaster does not support auto-init DSP modes, and many clones and emulations do not handle it well either. Sound Blaster 16 auto-init/FIFO modes ------------------------------------- Sound Blaster 16 cards (DSP 4.xx) support a new set of commands that includes bits to specify whether the DSP plays the audio as single-cycle or auto-init, as well as whether or not it will enable the FIFO. Under normal circumstances, you would not use the FIFO for single-cycle and use the FIFO in auto-init. The option is given to you however to see what happens if you, say, switch off the FIFO in auto-init, or enable the FIFO in single-cycle. Note that clones implementing SB16 DSP commands support only the most common commands and do not support the uncommon combinations mentioned above. SC-6000 cards for example support FIFO & auto-init but do not support single-cycle or non-FIFO auto-init forms of the command. Most clones do not emulate the SB16 anyway, even those produced in the late years (1996-1999) of the ISA bus and DOS support. If you're wondering by the way what happens, single-cycle DSP playback with the FIFO enabled tends to miss some samples. The DSP acts as if it completes the block early with data still in the FIFO, and then forgets the contents of the FIFO. Auto-init without FIFO apparently has no effect, but I would bet that if the ISA bus was busy with another device the lack of FIFO might cause some audible effects. ESS 688, changing the IRQ and PnP BIOS conflicts ------------------------------------------------ If you change the IRQ from this test program, understand that if the ESS chipset is listed by the PnP BIOS, the original IRQ (now wrong) will be used from the PnP BIOS enumeration and IRQ will appear not to work. To avoid this, run the test program with /nopnp every time after changing the IRQ. ESS chipsets and the ESS control register raw mode -------------------------------------------------- For debugging purposes, the program allows you to poke at the ESS registers as raw byte values. Understand that doing this may cause temporary issues with the hardware or cause problems and hangs with the software. Poke at the registers at your own risk. By default, only registers 0xA0-0xB9 are shown for ESS 688 chipsets. Registers 0x00-0x9F do not exist, and on ESS 688 chipsets, the DSP will not return any data for registers 0xBA-0xBF so they are blocked off. If you want to make sure that the registers exist, type 'p' to trigger a re-detection cycle. Know that for undefined registers, the program may hang temporarily waiting for DSP timeouts. ESS 688 undocumented registers ------------------------------ Perhaps this is simply lack of documentation in the ES1869 datasheet, but there are additional registers not listed. 0xA0 Unknown (only 4 bits are changeable) 0xA3 Unknown (all 8 bits changeable) 0xA6 Left (master? PCM?) volume 0xA7 Right (master? PCM?) volume 0xA8 Unknown (but bit 0 appears to enable/disable audio output) 0xA9 Unknown (all 8 bits changeable) 0xAA Master volume? (also changed when you write 0xAB) 0xAB Master volume? (writing this also changes 0xAA) 0xAC Unknown (all 8 bits changeable) 0xAD Unknown (all 8 bits changeable) 0xAE Unknown (all 8 bits changeable) 0xAF Unknown (all 8 bits changeable) 0xB0 Unknown (always reads 0xB0, writes change register 0xA0 instead) 0xB3 Unknown (only bit 0 is changeable) ESS 1869 undocumented registers (as seen on a Compaq branded ESS 1887) ---------------------------------------------------------------------- 0xA0 Unknown (only 2:0 bits are changeable) 0xA3 Unknown (all 8 bits changeable) 0xA6 Zero (not changeable) 0xA7 Zero (not changeable) 0xA8 This actually is documented, but some weird behavior observed with bits 1:0. In the datasheet, bit 0 is a mono/stereo select. Actual behavior with 1:0: 00 = only one audio channel played 01 = normal stereo playback 02 = chip output is difference between L-R rather than sum. perhaps a good way to hear the Dobly "surround" channel of movie audio, or to filter out the vocals of most music, or to hear just how destructive your MP3 encoder is to audio you "can't hear". 03 = normal stereo playback 0xA9 Unknown, bits 6:4 and 2:0 are writable, bits 3 and 7 have a mind of their own 0xAA-0xAF Zero (not changeable) 0xB0 Unknown (always reads 0xB0, writes change register 0xA0 instead) 0xB3 Unknown (only bit 0 is changeable) ESS sample & filter clock divider behavior ------------------------------------------ This isn't mentioned in ESS's datasheets, but if you set the sample rate divider to 0xFF (or 0x7F) the DAC stops (does not cycle samples) and will stay that way until you enter another divider. It doesn't appear to harm the chip in any way. Note that 0x00 is also a valid clock divider (in which case the DAC just plays the audio really slow). The divider for their lowpass filter appears to have the same behavior. Setting the divider to 0x00 turns the audio into a very low bandwidth signal (as you'd expect) while 0xFF silences output entirely.