SoundBlaster 16 and extended memory

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

I have attached my implementation. I have cleaned it up a bit but it is still very raw. Basically it is a Frankenstein's monster of code that I have pulled from different sources including some of my own custom routines. As I mentioned before the code works in DOSBox and Bochs. If you are testing in DOSBox, please be sure that the SoundBlaster is set to use IRQ5. Also my OS is using "Unreal" mode so please keep that in mind.

Usage:

Code: Select all

	mov byte [SoundBlaster.PlayAsync], byte 1 ; Play the audio and return immediately
	push dword [WaveBuffer] ; Buffer to WAV
	call SoundBlaster.Play
Additional code that you will need:

Code: Select all

Memory.AudioSegment: equ 0x2000

Memory.ClearGeneralRegisters:
	xor eax, eax
	xor ebx, ebx
	xor ecx, ecx
	xor edx, edx
	xor esi, esi
	xor edi, edi
	ret


Memory.CopyBytesToFar.Params.SourceAddress equ 10 ; 4 bytes
Memory.CopyBytesToFar.Params.DestinationSeg equ 8 ; 2 bytes
Memory.CopyBytesToFar.Params.DestinationPtr equ 6 ; 2 bytes
Memory.CopyBytesToFar.Params.ByteSize equ 4 ; 2 bytes
Memory.CopyBytesToFar.ParamsSize equ 10
Memory.CopyBytesToFar.LocalsSize equ 0
Memory.CopyBytesToFar:
	; Prologue
	enter Memory.CopyBytesToFar.LocalsSize, 0
	pushad
	push es
	call Memory.ClearGeneralRegisters
	
	mov dword esi, dword [ebp + Memory.CopyBytesToFar.Params.SourceAddress]
	mov word es, word [ebp + Memory.CopyBytesToFar.Params.DestinationSeg] 
	mov word di, word [ebp + Memory.CopyBytesToFar.Params.DestinationPtr]
	mov word cx, word [ebp + Memory.CopyBytesToFar.Params.ByteSize]
	add word cx, word di
	
	; Loop through each byte and assign 0
Memory.CopyBytesToFar.1:
	mov byte al, byte [esi]
	mov byte [es:di], byte al
	inc word di
	inc dword esi
	cmp word di, word cx
	jb Memory.CopyBytesToFar.1
	
	; Epilogue
	pop es
	popad
	leave
	ret Memory.CopyBytesToFar.ParamsSize
Attachments
sb2.asm
SoundBlaster 16 Assembly File
(18.69 KiB) Downloaded 42 times
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

Although I like they way that this code is organized, it is a little hard to read through. I think that I'd eventually get used to it though...

But just scanning through it once, the only thing I noticed was that I don't see where you are checking the Interrupt Status Register to make sure that the interrupt actually came from the SoundBlaster, and not from somewhere else.

I doubt that this is your issue, but you might want to add a few lines to check this register before filling the buffer. Just set register 0x04 to 0x82, and read from register 0x05 to get the interrupt status. I can't remember which bit is the 16-bit interrupt flag, but I can find it if you need it.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

Thanks for the info. Do you know what the correct value I should be checking for? VirtualBox returns 0x01, DOSBox returns 0x21, and Bochs returns 0x41.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

I was afraid you were going to ask...

According to the spec sheet I've got, the Interrupt Status Register has three bits:

Bit 0: 8-bit DMA / MIDI
Bit 1: 16-bit DMA
Bit 2: MPU-401

So, you should be waiting for a 0x02, if you have everything set up correctly, and if you are playing 16-bit audio... Wait for a 0x01 if you are sending 8-bit audio.

When you read from the base register 0x0F, it should clear bit 1. (This is the bug that I found and had them fix in both BOCHS and VirtualBox). When you read from 0x0E, it should clear bit 0.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

Ok, bit 0 is being set across the board which makes sense because I am sending 8 bit audio to the sound card. In other words everything appears to be working in spite of the fact that VirtualBox isn't playing any audio.
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

If you are sending 8-bit audio, then I think you are using the wrong interrupt acknowledge register. Try using 0x0E instead of 0x0F, and see if that helps.

EDIT: I tested out VirtualBox with the SoundBlaster 16 with a WindowsXP guest, and everything seemed to work properly, except when I use Media Player to play an MP3, it plays correctly, but when I click "Stop" or close Media Player, the audio just loops the buffer forever. If I click "Pause", the audio stops correctly. Just thought I'd mention it. I've successfully played 16-bit audio in my OS as well, so I know that it works well enough.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

I got it working in VirtualBox... well sort of. It looks like I needed to set my interrupt handler prior to ResetDSP and turning the speakers on. However the issue now is that the audio appears to play out of order, almost like it is jumping around (forwards and backwards). This doesn't happen in DOSBox or Bochs with my latest changes. I am using an audio clip that is over a minute long so I don't know if that has something to do with it also (Star Trek: TNG intro).
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

If your audio is skipping around, my best guess is that your logic for keeping track of which "half" of the buffer you should be filling may be getting out of sync. If it is only happening in VirtualBox, it is probably due to a timing issue. For testing purposes, I wrote code to generate a sine wave to use as test audio data. You could even generate a wave that increases in frequency to help figure out what is actually going on by listening to the tone. Writing debug information to the screen would help as well. See if you can figure out what is actually happening, and let us know what you find.

Edit: Did you add code to ignore interrupts if they weren't sent by the sound blaster? Actually, instead of ignoring it, you should probably jump to the old IRQ 5 handler that you are keeping in memory...
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

Playing a sounds that repeats itself very quickly works but I think it is because it is difficult to know whether or not there is an issue. I tried a bunch of different audio samples and I discovered that once the audio has been playing about 836 KB of the audio file it beings to jump around. The direction that which it jumps is inconsistent however. It mostly jumps forwards but occasionally will jump backwards.

I been trying lower quality wave files (8,000 Hz vs. 44,000 Hz) also and because the bit rate is lower the issue doesn't happen until you are roughly 100 seconds into listening to the audio. When listening to audio at 44,000 Hz, the issue starts happening about 20 seconds in.

I tested the interrupts being sent by SoundBlaster for VirtualBox and they are all the same value (=0).

EDIT: Ok, so I decided to port an existing program that uses a different means to play the audio over the SoundBlaster 16. The program takes the audio buffer and splits it in half and plays the first half, gets the interrupt notification and then plays the 2nd half, notification, 1st half again, etc. The result: program works in DOSBox and Bochs, but doesn't play any audio in VirtualBox! I am really starting to believe that that there is a genuine issue with VirtualBox playing audio over the SoundBlaster 16.

Link to program that I ported: http://www.o3one.org/hwdocs/soundblaste ... ASTP12.EXE
Source code: http://www.o3one.org/hwdocs/soundblaste ... ASTP12.ASM
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

Ok, so I decided to port an existing program that uses a different means to play the audio over the SoundBlaster 16.
Just looking through that code, I'm not sure why they are trying to convert 8-bit audio to 16-bit, instead of just writing it to the soundblaster as 8-bit data. Maybe I'm misreading it. They may be trying to send 16-bit data over the 8-bit DMA channel, which also doesn't make much sense. Maybe they are trying to maintain compatibility with the older SoundBlaster models...

In any case, I'm not surprised that this code doesn't work in VirtualBox, since it seems to be trying to misuse the DMA channel.

I'm going to test out Windows XP Media Player again and see if I can get the audio to start failing after playing for an extended period of time. If not, then I think that will prove that the VirtualBox emulation is stable in at least in one situation.

EDIT: Other than the audio looping that I mentioned above when clicking Stop in Media Player, everything seems to work fine in XP. I tried playing audio from an audio CD for 5 minutes, including stopping and starting repeatedly to try to get it to "hiccup", playing 2 different WAV files for 5 minutes with no issues, and streaming live internet radio for 20 minutes with no glitches at all.

So I'm going to go ahead and say that, obviously, there is a way to get the SoundBlaster to work properly in VirtualBox. I'm not sure what that way is, as of yet, but I haven't spent too much time looking into it. I've had pretty good luck in my OS using 16-bit 44100 sample rate stereo audio, and 16-bit DMA transfers.

I recommend trying to pinpoint the exact moment when things start going wrong, and trying to determine what triggers the audio to start glitching. I'll go ahead and point out that the window for filling the "just finished" half of the buffer is pretty small, so if your code takes more than a few milliseconds after the IRQ is raised, you will get audio glitches due to the soundblaster playing the old audio data, and it will probably be out-of-sync from then on. Are there any other processes running, or threads that might be causing any locking issues?

EDIT2:
The program takes the audio buffer and splits it in half and plays the first half, gets the interrupt notification and then plays the 2nd half, notification, 1st half again, etc.
This is the recommended way to fill the soundblaster buffer, since you only have one buffer to work with. Fill the entire buffer, then tell the soundblaster to play half of the buffer, and wait for the interrupt, then refill the first half while the soundblaster plays the second half. On the next interrupt, you simply fill the last half of the buffer. Depending on the parameters that you send with the Play command, the sound blaster will continue to play audio from the buffer until you send a pause or a stop command. All you need to do is acknowledge the interrupt.
Last edited by SpyderTL on Thu Sep 03, 2015 9:48 pm, edited 1 time in total.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

You are probably right saying that there is a way to get it to work, but there is an extreme lack of code samples in assembly floating around the internet. My OS is single threaded so there isn't much going on.

Question, does your audio work from your OS in VirtualBox?
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: SoundBlaster 16 and extended memory

Post by SpyderTL »

vbguyny wrote:Question, does your audio work from your OS in VirtualBox?
Yes, and no. If I generate the audio data programmatically, it seems to work fine. (Sine wave, square wave, etc.)

If I'm streaming data from an audio CD, it works for a few seconds, then locks up with the buffer repeating. However, I'm pretty sure it's due to the buffer not being filled fast enough when reading from the CD-Drive, since I'm only loading one block (2352 bytes) at a time.

I'll run some tests to see if I get any glitches when playing a sine wave for several minutes.

EDIT: So here is what I found last night... I get different results for different wave form data generators, which only makes sense if I have a bug somewhere in my code. The sine wave generator works best, and runs without any glitches for several minutes. The triangle wave is the worst, glitching after only a few seconds. I'm not sure what is going on, as the code is (or should be) identical except for the few fpu instructions.

What is weird is that instead of clicking or looping, like you'd expect, the frequency actually changes several times, and then finally goes quiet. I pass the frequency and the sample rate on the command line, and it starts out correct, but after a few seconds (or minutes) the frequency suddenly changes, and stays that way for a few seconds/minutes, then it changes again for a while, and then finally, eventually, goes quiet, I assume, forever.

I'm printing the interrupts received from the sound blaster (and verified with the ISR register) to the screen, and at no point do these interrupts (appear to) change frequency or stop.

I tried the same code on Bochs, but I'm not detecting any sound blaster at all. I'm not sure if I just don't have it configured properly, or if my detect code isn't finding it. I'm currently installing WinXP on Bochs so that I can test the SoundBlaster and troubleshoot my setup as well. Let me know if you had to do anything special to get the SoundBlaster working in Bochs on your end.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

First you need to have the latest and greatest version of Bochs installed ( 2.6.8 ) and below are the lines that I have in my .bxrc file which work for me:

Code: Select all

sound: driver="default", waveout=none, wavein=none
speaker: enabled=1, mode=sound
sb16: enabled=1, midimode=0, wavemode=1, dmatimer=600000
I have discovered a strange issue with Bochs and that is I cannot stop the audio from playing! It seems that the acknowledge interrupt is called so quickly that by the stop is called, the audio memory that Bochs uses is filled with the entire audio clip and won't stop until the audio has finished playing or if I close out of Bochs!
vbguyny
Member
Member
Posts: 48
Joined: Wed Aug 12, 2015 6:30 pm

Re: SoundBlaster 16 and extended memory

Post by vbguyny »

Yea so, apparently there is no issue with my code. However there is an issue with the way that VirtualBox is writing to memory while in "Unreal" mode. What I did to come to this conclusion is that I loaded the entire WAV file (4 MB) into memory and quickly wrote it back to disk in another file name. Then I played back the resulting file in my Host OS (VLC under Windows 7) and the audio had the same issues as when I played it in my OS.
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: SoundBlaster 16 and extended memory

Post by Octocontrabass »

vbguyny wrote:However there is an issue with the way that VirtualBox is writing to memory while in "Unreal" mode.
It sounds to me like you haven't enabled A20. VirtualBox can run DOS, so it shouldn't have any trouble with unreal mode.
Post Reply