VOGONS


First post, by Scali

User metadata
Rank l33t
Rank
l33t

As you may know, early Sound Blasters did not support the so-called 'Auto-Initialize' mode of playing samples via DMA.
They only supported what Creative called 'Single-Cycle' transfers.
This is basically the DSP transferring N bytes via DMA and playing them on the DAC, signaling an interrupt when the transfer is complete.
The problem here is that if you want to play samples that are longer than a single DMA buffer (max 64k), you'll have to restart the DSP immediately when the interrupt fires.
If you cannot do this fast enough (because you get the interrupt too late, or it takes too long to reprogram the DSP for the next transfer), this results in a tiny 'glitch' in the output.

Now, this has been the subject of various workarounds, myths and bugs in various software and hardware (think later SBs and clones), so I'd like to investigate exactly what is going on.
I've created a simple program to test various replay methods: https://www.dropbox.com/s/a38bc9ap8w5fqlv/SBDMA.zip?dl=0
I'd like you all to try it, and tell me which methods work, and which methods do not (or don't work well, eg clicks and pops in the output).
I have tested these on my 8088 machine with an SB Pro 2.0, with a v3.01 DSP.
It plays a short 64k 8-bit mono sample at 22050 Hz, in a loop. The sample is stored in the file 'sample.raw', and you can replace it with any sample you like. It will just load the first 64k of that file.
It plays the file in transfers of 1024 bytes each, so it restarts about 21.5 times per second. So you should listen to a 'rumble' of about 21.5 Hz in the signal.

I have created the following tests:

Single-cycle
This one is 'by the book', according to the Creative hardware programming manual:
Start a single-cycle transfer, and set up an interrupt handler for when it ends.
Inside the interrupt handler, I start the next single-cycle transfer as quickly as possible.

Single-cycle, no busy-wait for DSP after interrupt
This method is the same as above, with a small twist:
According to the programming manual, you need to check the status of the DSP and wait until it is not busy, before you send a new command.
During testing, I found that when the interrupt fires, I don't need to wait when I send the first command, because the DSP isn't busy: it's just signaled us that it's done.
I do still have to wait when I send the bytes containing the length of the transfer.
However, not waiting for the first write shaved off some cycles, and restarts the transfer more quickly.

Single-cycle hack
This method uses a common 'hack' from early software, as documented on the DOSBox-X site: https://github.com/joncampbell123/dosbox-x/wi … Nagging-the-DSP
In short, you simply don't wait for the interrupt to occur, but you restart the transfer in mid-flight.
Apparently this works on most hardware.
My implementation uses the timer interrupt that restarts the DSP roughly every 1024 samples, as the other methods.
I have found on my SB Pro 2.0, that I really do need to wait for the DSP not to be busy, before I send any commands, else I got very obvious pops and clicks.
So I have implemented it with full busy-waiting.
I have found that on my hardware it does not play quite seamlessly: you hear a bit of 'flutter' in the signal, it actually seems slightly worse than the second method.

Auto-init
This method should be seen as a 'reference' implementation.
It uses the Auto-Initialize mode supported by DSP v2.00 and higher, and is designed to be seamless. The DSP just continues playing endlessly (even if you would not acknowledge the interrupt it sends), and is not dependent on any CPU intervention.
If your card supports it, you can take this as a reference, and compare to the others, to see if you hear any subtle 'flutter', 'rumble' or other distortions caused by the other methods not being entirely seamless.
Any Sound Blaster 2.0 and newer will support this out-of-the-box.
Some Sound Blaster 1.0 and 1.5 cards may also support this, since Creative sold the DSP v2.00 as an aftermarket upgrade for these cards.

My conclusion so far is that I simply can't get perfect seamless playback on my 8088 with my SB Pro 2.0. The second method is close, but not perfect. I have yet to try it in a faster machine. A faster CPU may just handle the interrupt and reprogramming of the DSP just that bit faster to make it work.

This issue is also related to the Sound Blaster 16 and certain clones, see also this earlier topic on the matter: Sound Blaster 16 Bugs and Deficiencies Summary
And this blog by Great Hierophant: http://nerdlypleasures.blogspot.nl/2015/05/16 … t-playback.html
His recordings show that the Sound Blaster 16's DSP seems to be even worse at handling the single-cycle technique than the earlier cards were.

So if you have a real Sound Blaster (any kind), or any clone, I'd like to invite you to try my program, and post your findings here.
Thanks in advance!

PS: If you happen to have an SB1.x with DSP v1.xx, you could also help to settle the myth on OSDev: http://wiki.osdev.org/ISA_DMA
"Some expansion cards do not support auto-init DMA such as Sound Blaster 1.x. These devices will crash if used with auto-init DMA. Sound Blaster 2.0 and later do support auto-init DMA."
I don't think that is true. I don't think the DMA controller can crash any expansion card at all.
I think they may be confusing terminology here. You can put the DMA controller in 'auto-init', which is something different from the 'Auto-Initialize' mode of the SB.
Namely, the DMA being in auto-init just means it resets itself to the same buffer at the end of a transfer (and I don't see how that would crash the DSP, since to the DSP it is no different than when you'd reprogram it with the CPU for the next transfer).
Setting the SB in auto-init means you send it a different command. Perhaps the old DSPs crash on that command, because that command didn't exist yet.
My program checks the DSP version before it tries to run the auto-init test. So I don't expect it to crash any SB.
It has the DMA controller in auto-init mode for the entire test.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 1 of 53, by elianda

User metadata
Rank l33t
Rank
l33t

Can't you put in a few PIO played sample values while initializing the next DMA transfer?

Retronn.de - Vintage Hardware Gallery, Drivers, Guides, Videos. Now with file search
Youtube Channel
FTP Server - Driver Archive and more
DVI2PCIe alignment and 2D image quality measurement tool

Reply 2 of 53, by MobyGamer

User metadata
Rank Member
Rank
Member

I will test with both a 2.0 and a 1.5 card and report back.

Interestingly, the "Single-cycle, no busy-wait for DSP after interrupt" test hangs DOSBox. I don't think you should change the test; just reporting it in case this code may someday be expected to work with emulators.

Reply 3 of 53, by Scali

User metadata
Rank l33t
Rank
l33t

By the way, I forgot to mention: Press ESC to end the current test, it will then move on to the next.

And yea, as long as it works on real hardware, I'm not bothered with what DOSBox does. My build of DOSBox seems to work, but I have some custom SVN build of some time ago.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 4 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
elianda wrote:

Can't you put in a few PIO played sample values while initializing the next DMA transfer?

I'm afraid not.
Playing samples directly on an SB has to be done via the DSP as well, and you're still going to have to busy-wait before you output each sample.
So you can't do both at the same time. You either send a sample, or you send a new output buffer command.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 5 of 53, by keropi

User metadata
Rank l33t++
Rank
l33t++

it seems SB 1.5/2.0/Pro2 tests are covered, my SB1.5 is a v2 DSP too... so is there any other cards that needs testing?

🎵 🎧 PCMIDI MPU , OrpheusII , Action Rewind , Megacard and 🎶GoldLib soundcard website

Reply 6 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
keropi wrote:

it seems SB 1.5/2.0/Pro2 tests are covered, my SB1.5 is a v2 DSP too... so is there any other cards that needs testing?

The combination of card and CPU is interesting too.
Is your SB1.5 in a fast 286 or better? Perhaps a fast CPU has less trouble playing seamlessly. Or the other way around: perhaps on a fast CPU, the 'no wait' method may not work, because it will send the command too quickly.

Other than that, testing on any clones is welcome too, or SB16 or newer. They seem to suffer from popping and clicking, much worse than the minor 'flutter' or 'rumble' that I get on my SB Pro 2.0 (which you probably barely even notice if it's not 21.5 times a second, but rather once every few seconds).

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 7 of 53, by keropi

User metadata
Rank l33t++
Rank
l33t++

SB1.5 is in my 10mhz V20 XT, CT1350 in a 286/16 and a CT1600 in 386DX/40 and p233mmx - anything of value?
I do have some CT2230s and a couple of Sound Galave BXII cards as well - even a single clone that I "upgraded" with a real 3812+dac combo.
Could be a few days though for test other than p233mmx and 286/16

🎵 🎧 PCMIDI MPU , OrpheusII , Action Rewind , Megacard and 🎶GoldLib soundcard website

Reply 8 of 53, by MobyGamer

User metadata
Rank Member
Rank
Member

I just tested with an SB 2.0 in an IBM 5160 with a sine wave and heard the following:

Single-cycle: Heard audible beating at the buffer boundaries.
Single-cycle, no busy-wait for DSP after interrupt: Heard audible beating at the buffer boundaries, but at a different phase than the previous test.
Single-cycle hack: Heard audible beating, but it oscillated between phases (!) If both the SB and PIT used the same crystal, this would work, but of course they're on different clocks.
Auto-init: Played perfectly.

A better test would be a 1.0/1.5 card but I can't get to that for a few days. Hoping someone else here can step up.

Reply 9 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
keropi wrote:

SB1.5 is in my 10mhz V20 XT, CT1350 in a 286/16 and a CT1600 in 386DX/40 and p233mmx - anything of value?
I do have some CT2230s and a couple of Sound Galave BXII cards as well - even a single clone that I "upgraded" with a real 3812+dac combo.
Could be a few days though for test other than p233mmx and 286/16

I'd say they're all interesting:
The SB1.5 and CT1350 to see if they plays more seamlessly than the SB Pro 2.0 (possibly because of the V20 and 286).
The CT1600 with a fast CPU to see if that is more seamlessly than using an 8088 (we've tested CT1600, but only on 8088 at 4.77 MHz so far).
And the clones to see how well they are cloned.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 10 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
MobyGamer wrote:
I just tested with an SB 2.0 in an IBM 5160 with a sine wave and heard the following: […]
Show full quote

I just tested with an SB 2.0 in an IBM 5160 with a sine wave and heard the following:

Single-cycle: Heard audible beating at the buffer boundaries.
Single-cycle, no busy-wait for DSP after interrupt: Heard audible beating at the buffer boundaries, but at a different phase than the previous test.
Single-cycle hack: Heard audible beating, but it oscillated between phases (!) If both the SB and PIT used the same crystal, this would work, but of course they're on different clocks.
Auto-init: Played perfectly.

Thanks. Exactly the same results as I got (with an SB Pro 2.0).
I would recommend others to also test with your sine wave sample.

MobyGamer wrote:

A better test would be a 1.0/1.5 card but I can't get to that for a few days. Hoping someone else here can step up.

Yes, there are still a few questions unanswered:
1) Can an SB 1.x, 2.0 or Pro play seamlessly with a fast enough CPU.
2) If so, which of the techniques give seamless results (or perhaps a technique that I have not implemented (correctly) yet?).
3) Do the SB 1.x and possibly SB 2.0 play more seamlessly than an SB Pro 2.0.
4) Does an SB 1.x with DSP v1.xx crash during one of the tests, as claimed by OSDev?

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 11 of 53, by James-F

User metadata
Rank Oldbie
Rank
Oldbie

Awesome thread!
I haven't fired my Pentium in a few months now, first year college takes more than I though it would.
But I definitely will test this with my SB16, SBPro2, SB2 and SB1.5.

I have created a 500Hz sinewave test tone and exported to 8-bit Unsigned, Mono, 22050kHz, it sounds correct in DOSBox.

EDIT:

Results with my P233 MMX:

SBPro2:
Auto-init is completely click free.
Hack has more noisy clicking than other modes.
Same behavior with L1 disabled for 486 speed.

SB2.0 & SB1.5.
Exactly the same as the SBPro2.

SB16 (CT2230):
Auto-init is completely click free.
Hack is cleaner than regular single-cycle on the SB16 !!?
Same behavior with L1 disabled for 486 speed.

Attachments

  • Filename
    Samples.7z
    File size
    47.69 KiB
    Downloads
    71 downloads
    File license
    Fair use/fair dealing exception


my important / useful posts are here

Reply 12 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
James-F wrote:
Results with my P233 MMX: […]
Show full quote

Results with my P233 MMX:

SBPro2:
Auto-init is completely click free.
Hack has more noisy clicking than other modes except auto-init.
Same behavior with L1 disabled for 486 speed.

SB2.0 & SB1.5.
Exactly the same as the SBPro2.

Thanks for testing!
A few quick questions:
1) So you hear subtle clicking with the first two 'single-cycle' modes? The 'no wait' version is no worse than the 'official' version?
2) Does your SB 1.5 have a v2.00 DSP? (if not, it should have skipped the auto-init test).

I guess I'm starting to lean towards the opinion that the 'hacks' used by Goldplay and various demos aren't actually delivering seamless playback, and serve no purpose compared to a properly optimized interrupt handler. The interrupt handler is still not entirely seamless, but 'acceptable', and seems to be as good as it gets on first-generation hardware.

Also, it might be that SB1.0 and 1.5 with a v1.xx DSP are very rare, as the v2.00 DSP was sold as an aftermarket upgrade (and perhaps also factory-installed on later models?), and may be more common.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 13 of 53, by James-F

User metadata
Rank Oldbie
Rank
Oldbie

So you hear subtle clicking with the first two 'single-cycle' modes?

Yes, but it's not subtle compared to auto-init.

The 'no wait' version is no worse than the 'official' version?

It is exactly the same.

Does your SB 1.5 have a v2.00 DSP?

Yes.
I think you're right about DSP 1.x being rare and more SB1.x with DSP 2.x have been produced.

Strangely the Hack version is much cleaner on the SB16 compared to older cards.
But the SB16 has the single-cycle bug with games that older cards to not exhibit.

I attached recorded output of the sound cards, in order that sbdma.exe plays them.

Attachments

  • Filename
    SBPro2.mp3
    File size
    250.32 KiB
    Downloads
    88 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    SB16.mp3
    File size
    268.6 KiB
    Downloads
    86 downloads
    File license
    Fair use/fair dealing exception


my important / useful posts are here

Reply 14 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
James-F wrote:

Yes, but it's not subtle compared to auto-init.

Well, I would call this subtle. It's not a huge 'pop' sound.
But indeed, it's not entirely seamless.

James-F wrote:

It is exactly the same.

Good, then this confirms that this is a valid technique.
I was a bit worried that on a fast PC, the DSP may still be busy when you send the first command after an interrupt. But apparently it is not, so this is the preferred way, since on an 8088 it is noticeably better than the first version.
In fact, I'd say that on an 8088 this is about as good as your recordings.

James-F wrote:

Strangely the Hack version is much cleaner on the SB16 compared to older cards.

Yes, it's not perfect, but nearly.

James-F wrote:

But the SB16 has the single-cycle bug with games that older cards to not exhibit.

Yes, it also seems worse at the first two tests. I guess either it doesn't signal its interrupt as quickly as the earlier models, or its busy cycles are even longer than the early cards were.

James-F wrote:

I attached recorded output of the sound cards, in order that sbdma.exe plays them.

Thanks, that was a big help.

I think I can conclude the following now:
1) Seamless playback with the single cycle mode is just physically impossible.
2) Not waiting for busy DSP after an interrupt works correctly on DSP v2.00 and above, and is the fastest way to reprogram the DSP.
3) Hacks such as 'nagging the DSP' are not an improvement over using the interrupt, and should be avoided.
4) For any DSP that supports it, auto-init is the way to go. Single-cycle should only be used as a fallback for DSP v1.xx.

That still leaves us with 2 open questions:
1) Does a v1.xx DSP also work correctly when not waiting for busy after the interrupt?
2) Will a v1.xx DSP crash when the DMA controller is in auto-init mode?

I expect the answer to 1) to be a 'yes', and 2) to be a 'no', but I'd like to make sure.

By the way, we have also confirmed that Creative's own software (VOXKIT/CT-VOICE.DRV) cannot play the sine wave without glitches on real hardware. We've analyzed the code, and found no special trickery in there. The software apparently sends large .VOC files 16k at a time, and reprograms the DSP and DMA controller for the next 16k in the interrupt handler. Exactly as stated in the programming manual.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 15 of 53, by elianda

User metadata
Rank l33t
Rank
l33t

Is there a way to abort the DMA playback early?
If yes would such abort + restart have a different setup timing?
(would be IRQ less and require some timing)

Retronn.de - Vintage Hardware Gallery, Drivers, Guides, Videos. Now with file search
Youtube Channel
FTP Server - Driver Archive and more
DVI2PCIe alignment and 2D image quality measurement tool

Reply 16 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
elianda wrote:

Is there a way to abort the DMA playback early?

I believe the only way to stop DMA playback is to reset the DSP, which takes quite some time.

elianda wrote:

If yes would such abort + restart have a different setup timing?
(would be IRQ less and require some timing)

Well, one thing I can think of is to mask the SB interrupt, and instead poll the DMA controller.
As soon as the DMA controller is finished, you reprogram the SB for another transfer. In theory that can be faster than the interrupt.
In practice I don't know if it is going to work any better than the 'nagging the DSP' trick currently.
Only one way to find out. I'll add another test-case.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 17 of 53, by elianda

User metadata
Rank l33t
Rank
l33t

What about if you increase the gap to a known time, cut the 'skipped' samples from the digital part and replace the output while reinit of the DSP by some OPL generated signal?
I mean you just want to have the voltage level at the output and it's source can be the OPL as well.
Since the card has no mixer there is a fixed relation between digital and OPL.

Retronn.de - Vintage Hardware Gallery, Drivers, Guides, Videos. Now with file search
Youtube Channel
FTP Server - Driver Archive and more
DVI2PCIe alignment and 2D image quality measurement tool

Reply 18 of 53, by Cloudschatze

User metadata
Rank Oldbie
Rank
Oldbie
Scali wrote:

...the v2.00 DSP was sold as an aftermarket upgrade (and perhaps also factory-installed on later models?)...

My remaining SB1.5 came with the v2.00 DSP factory-installed. While I haven't been able to pinpoint the exact release date of this DSP version, both my card and its MCU have production dates of Q1, 1991.

Here is one of the better references regarding the v2.00 upgrade, and the early Sound Blaster cards in general:
Microsoft KB75632 - Anatomy of the Sound Blaster

And here is some additional, but decidedly less-technical/accurate information:

Sound Blaster: The Official Book wrote:

You may be interested or surprised to know that some versions of Sound Blaster 1.5 come with version 2.00 of the DSP chip. DSP 2.00 is faster than the 1.05 version and is Windows 3.1 compatible. Version 1.05 was the latest technology when Windows 3.1 was published, but Windows 3.1 requires more sound processing power than the 1.05 version could provide. As a result, a DSP 2.00 is offered by Creative Labs as an upgrade to the Sound Blaster's original DSP, to conform with Windows 3.1 requirements for sound processing power.

Note: If you are running Windows 3.1 without the DSP upgrade from 1.05 to 2.00, you will find that digital sound playback in Windows can waver and stumble. You may also find that some games, such as Wing Commander II, may lock up your system unexpectedly. Both of these problems are caused by the inability of DSP 1.05 to process sound fast enough. If you currently have a Sound Blaster 1.0 or 1.5 with the 1.05 DSP, you can upgrade to a 2.00 DSP by calling Creative Labs. At this writing, the cost of the DSP 2.00 is $30 plus shipping and handling and any applicable sales tax.

Reply 19 of 53, by Scali

User metadata
Rank l33t
Rank
l33t
Cloudschatze wrote:
My remaining SB1.5 came with the v2.00 DSP factory-installed. While I haven't been able to pinpoint the exact release date of th […]
Show full quote
Scali wrote:

...the v2.00 DSP was sold as an aftermarket upgrade (and perhaps also factory-installed on later models?)...

My remaining SB1.5 came with the v2.00 DSP factory-installed. While I haven't been able to pinpoint the exact release date of this DSP version, both my card and its MCU have production dates of Q1, 1991.

Here is one of the better references regarding the v2.00 upgrade, and the early Sound Blaster cards in general:
Microsoft KB75632 - Anatomy of the Sound Blaster

And here is some additional, but decidedly less-technical/accurate information:

Thanks for the info.
The Microsoft article is very specific about the clicking on DSP v1.xx cards.
I suppose if there was a valid workaround, that Microsoft would have implemented it. I assume that they worked closely with Creative, when developing the MPC standard and the multimedia extensions for Windows.
In fact, perhaps the reason that DSP v2.00 exists at all might be because of Creative's and Microsoft's work on this MPC standard, trying to solve the clicking in a robust way. Apparently Microsoft even had to update the DMA driver for Windows 3.0, because they hadn't implemented auto-init in the original version.

The other quote is also interesting. It specifically says that Wing Commander II can crash DSP v1.05. Question remains: why? Apparently it does not crash in Windows (just clicks), or many other games.
This may be related to OSDev's claiming that DSP v1.xx can crash. Although I'm still not convinced that the DMA controller would have anything to do with it. I would be more inclined to think that it is related to calling and acknowledging interrupts.

I hope someone here has an SB with DSP v1.xx, so we can see what my test program does on it. I guess it would be most interesting to leave each individual test running for at least a few minutes, to see if it locks up or not.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/