My Job : program the sound code... What I did :
- Coded Sound portion of program entirely from scratch.
- Wrote Several Test Programs
| DMA_Type STRUCT
PageAddr db ? OffsetAddr db ? CountAddr db ? Reserved db ? ; used to align by 4 bytes DMA_Type ENDS |
Structure to hold information
for DMA addresses the structure if filled in with a table below see DMA_Table |
| WavHdrStruct STRUC
format db 'RIFF' filelen dd ? wavefmt db 'WAVEfmt_' fmt_len dd ? fmt_tag dw ? channel dw ? samprt dd ? ; sampeling rate bytesps dd ? ; bytes per second bkalign dw ? bitsps dw ? ; bits per sample data db 'data' datalen dd ? WavHdrStruct Ends |
taken from Sbtest.asm |
| SBP_MixerRead | Reads from the mixer data port on the sound card
al -> data read |
| SBP_MixerWrite | Writes to the mixer data port on the sound card
bl <- data to write |
| SBP_WaitRead | Polls the sound card to see if it is ready to be Read from |
| SBP_WaitWrite | polls the Sound Cards status register to see if it is ready
to be written to |
| SoundBuffer FIFO routines | |
| BufGetSndReadAddr | This returns the offset address that can be read from
(used for playing by SBP routiens) (used for recording or saving to disk or net by others) si -> returned with offset cx -> amount of data in the buffer that can be read |
| BufGetSndWriteAddr | This returns the offset address that can be written to
(used for recording by SBP routiens) (used for moving data that is going to be played by other routiens) di -> returned with offset cx -> max amount you can write |
| BufReadSndData | Reads Sound data from SBP_buf to SoundBuf,
(used for recording by SBP routiens) (used for moving data that is going to be played by other routiens) ; ax <- number bytes to xfer dx:[si] <- Start Of SBP_Buf or other location, offset of location to read from must be one continuous block (cannot overflow) es:[di] == Start of SoundBuf, offset of WriteAddr ax -> total data in buffer
|
| BufWriteSndData | Reads Sound data from SoundBuf to SBP_buf or someplace else,
(used for playing by SBP routiens) (used for recording or saving to disk or net by others) ax <- number bytes to xfer
ds:[si] == Start of SoundBuf, offset of ReadAddr ax -> total data in buffer
|
| BufSetup | Sets up the two buffers used to set up
sound x-fers
ie. (SoundBuf, and SBP_Buf) |
| BufReset | Resets the Sound Buffer to an intially empty state
|
| BufferMode | Used for finding out what mode SoundBuf
is in
al <- BufMode STOP 0, PLAY 1, REC 2 |
| DMA_Setup | Sets up a DMA transfer for a specifed DMA
Heavily adapted and reprogrammed from GPE {dma_vla.txt}
|
| SBP_ResetDSP | Resets the DSP on the Sound Blaster Pro/16
note : mic is set to zero volume to kill feedback |
| SBP_GetSettings | Polls SBP16 PnP settings,
if SB16 isn't there default setting are used later can change config for different settings |
| SBP_InstallINT | Installs the Sound Card's interrupt handeler
|
| SBP_INThandler | The Sound Card's interrupt handeler
|
| SBP_UninstallINT | UnInstalls the Sound Card's interrupt handeler
|
| SBP_SetSampleRate | Sets or Resets the sound cards sample rate which is held
in the Variable SBP_RATE SBP_RATE <- rate to play at or time const (if not SB16 |
| SBP_WriteDSPCmd | writes at byte (Low, High) to DSP
al <- command bx <- data |
| {SoundSetup} | Initalized the sound card and sets up the ISR proc
|
| {SoundDestroy} | Cleans up after the sound card when the program exits
|
| {SoundService} | This should be called fairlly frequently so buffers
can be updtated if needed, needed for playing WAVs or for starting new SoundPlays from other programs |
| {SoundPlayFlag} | Used to tell SoundService Routien that main program
would like to start playing as soon as the SoundBuf has enough data in it |
| {SoundPlay} | starts outputting sound for avialable data in SoundBuff
sound stops when output buffer is empty |
| SoundPlayCont | called by Sound Interrupt to continue outputting sound
sound stopps when output buffer is empty |
| SoundPlayEnd | Outputs sound of last part of SoundBuffer via the interrupt
|
| {SoundPlayWav} | Starts playing a WAVE file. to continue playing the file
SoundService must be called enough to reload the buffer ds:[dx] <- pointer to ASCIIZ string |
| SoundPlayWavCont | called only from SoundService when a wave file is in the
process of being played, copies new data to buffer |
| {SoundRec} | Inputs sound via the interrupt until SoundBuffer is full
or a SoundRecStop is called |
| SoundRecCont | Called by Interrupt to continue REC
|
| {SoundScope} | Shows a nifty sound scope, write to a block
of memory
asummes video mode is in 8 bits/pix mode ax <- ah = background color, al = forground color bx <- cols (horizontal) dx <- rows (vertical) es:[di] <- start location |
| {SoundSetInVol} | Set the mixers volume for 8-bit mono
bl <- Volume level bits 2-3 = mic Volume SPB, 1-3 SB 16 |
| {SoundSetOutVol} | Set the mixers volume for 8-bit mono
bl <- Volume level bits 0-3 = right Volume, 4-7 = left Volume |
| {SoundTest} | outputs a tone directly to card to see if
it will do anything at all ( no interrupts needed ) |
| {SoundStop} | Stops a Sound Transer and Halts DMA Interrupts
|
| ScreenDebug | Called whenever there is an error messege to print
si <- offset of error message |
; Sound Blaster Pro I/O port definition
SBP_Port dw 0220h
; 220 - 22F Default
SBP_INT db 0Dh
; INT 5h Default
SBP_INTMask db 00100000b
SBP_INTInst db 0
; zero = not installed
SBP_DMA db 5h
SBP_oldV dd ?
; saved interrupt vector
SBP_Rate dw SPB_DEFAULT_SAMPLE_RATE
SBP_PICOffMask db ?
; PIC mask to restore when exiting
SBP_PICOnMask db ?
; PIC mask to turn on Interrupt
; DMA register locations
DMA_Table DMA_Type {87h, 0h,
1h}, ; DMA 0
{83h, 2h, 3h}, ; DMA 1
{81h, 4h, 5h}, ; DMA 2
{82h, 6h, 7h}, ; DMA 3
{8Fh, 0C0h, 0C2h}, ; DMA 4
{8Bh, 0C4h, 0C6h}, ; DMA 5
{89h, 0C8h, 0CAh}, ; DMA 6
{8Ah, 0CCh, 0CEh} ; DMA 7
; Sound Buffer Tracking Vars
ReadAddr dw ?
; Offset for soundBuff
WriteAddr dw ?
; Offset for soundBuff
BufDataLength dw ?
; amount of new data in buffer
BufMode db 0
; 0 - none, 1 - Play, 2 - Rec
SBP_BufOffsetTP dw ?
; top half of offset
SBP_BufOffsetBT dw ?
; bottom half of offset
SBP_BufLen dw ?
; length of sound card buffer
SBP_DMAPage db ?
SBP_DMAOffset dw ?
SBP_Side db 0
; SBP is read/writing to 0 = top, 1 = bottom
SBP_SingleLen dw ?
; lenght of last single cycle xfer
; Wave file vars
WavRIFFstring db 'RIFF'
WavFMTstring db 'WAVEfmt '
WavDATAString db 'data'
WavHeader WavHdrStruct <
>
WavOldRate dw ?
; old sampling rate
WavLengthLeft dd ?
; File buffer vars
fileMode db ?
; WAV, NONE
fileBuffer db 1024 dup (?) ;1024
dup (?)
fileHandle dw ?
; Messages mostly errors
;
WriteTimeOutE_Msg db '00 ER: SB Write Timeout ','$'
; write timeout {SBP_WaitWrite}
ReadTimeOutE_Msg db '01 ER: SB Read Timeout','$'
;SB Card Read Timeout {SBP_WaitRead}','$'
DPS_ResetE_Msg db '02 ER: SB DSP not Reset ','$'
BufWOFlowE_Msg db '03 ER: SB Write Buf OF', '$'
; write buffer overflow
BufROFlowE_Msg db '04 ER: SB Read Buffer OF',
'$' ; read buffer overflow
SBP_IRQE_Msg db '05 ER: SB IRQ Not
Detected', '$'
SBP_DMAE_Msg db '06 ER: SB DMA Not
Detected', '$'
SBP_WavE_Msg db '07 ER: WAV
Not Readable', '$'
SBP_WavFileE_Msg db '08 ER: {WAV} File in use', '$'
; Sound Buffer for double buffered SBP data
SoundBuf
db 55000 dup (?) ; sound buffer number 2