home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 June B
/
Pcwk6b98.iso
/
Mpeg3
/
Dos
/
MP3
/
MPG12304.EXE
/
AUDIO.C
next >
Wrap
C/C++ Source or Header
|
1997-05-11
|
7KB
|
387 lines
#include <dos.h>
#include "audio.h"
#include "mpg123.h"
#include "mdma.h"
#include "mirq.h"
#define DMA_SIZE 32768
void interrupt far newhandler();
void SB_PlayStop(void);
void SB_PlayStart(void);
void SB_MixerStereo(void);
void SB_MixerMono(void);
BOOL SB_WaitDSPWrite(void);
BOOL SB_WaitDSPRead(void);
BOOL SB_WriteDSP(UBYTE);
UWORD SB_ReadDSP(void);
void SB_SpeakerOn(void);
void SB_SpeakerOff(void);
void SB_ResetDSP(void);
BOOL SB_Ping(void);
UWORD SB_GetDSPVersion(void);
BOOL SB_IsThere(void);
static UWORD sb_port; /* sb base port */
static DMAMEM *SB_DMAMEM;
static char *SB_DMABUF;
static UBYTE SB_TIMECONSTANT;
static UBYTE PIC1MSK;
static UBYTE PIC2MSK;
static UWORD sb_int; /* interrupt vector that belongs to sb_irq */
static UWORD sb_ver; /* DSP version number */
static UBYTE sb_irq; /* sb irq */
static UBYTE sb_lodma; /* 8 bit dma channel (1.0/2.0/pro) */
static UBYTE sb_hidma; /* 16 bit dma channel (16/16asp) */
static UBYTE sb_dma; /* current dma channel */
UWORD last=0;
UWORD curr=0;
BOOL playing=0;
int mixfreq;
PVI oldhandler;
int audio_open(struct audio_info_struct *ai)
{
ULONG t;
if(!SB_IsThere()){
fprintf(stderr,"SB not detected.");
return -1;
}
if(sb_ver<0x400){
fprintf(stderr,"SB16 not detected.");
return -1;
}
sb_dma=sb_hidma;
SB_DMAMEM=MDma_AllocMem(DMA_SIZE);
if(SB_DMAMEM==NULL){
fprintf(stderr,"Couldn't allocate page-contiguous dma-buffer");
return -1;
}
SB_DMABUF=(char *)MDma_GetPtr(SB_DMAMEM);
memset(SB_DMABUF,0,DMA_SIZE);
oldhandler=MIrq_SetHandler(sb_irq,newhandler);
return 0;
}
int audio_set_rate(struct audio_info_struct *ai)
{
mixfreq=ai->rate;
return 0;
}
int audio_set_channels(struct audio_info_struct *ai)
{
return 0; // not neccessary :)
}
int audio_play_samples(struct audio_info_struct *ai,short *src,int size)
{
UWORD todo,left;
left=size*2;
if (playing==0) SB_PlayStart();
wait:
curr=(DMA_SIZE-MDma_Todo(sb_dma))&0xfffc;
if(curr>last){
todo=curr-last;
if(todo>left)
{
memcpy(&SB_DMABUF[last],(char *)src,left);
last += left;
if(last>=DMA_SIZE) last=0;
return 0;
}
else
{
// memcpy(&SB_DMABUF[last],(char *)src,todo);
// last += todo;
// src += todo;
// left-=todo;
// WHAT THE FUCK IS WRONG WITH THIS???
goto wait;
}
}
else{
todo=DMA_SIZE-last;
if(todo>left)
{
memcpy(&SB_DMABUF[last],(char *)src,left);
last += left;
return 0;
}
else
{
memcpy(&SB_DMABUF[last],(char *)src,todo);
left-=todo;
last=0;
src+=todo;
goto wait;
}
}
}
int audio_close(struct audio_info_struct *ai)
{
SB_PlayStop();
MIrq_SetHandler(sb_irq,oldhandler);
MDma_FreeMem(SB_DMAMEM);
return 0;
}
void interrupt far newhandler(MIRQARGS)
{
inportb(sb_port+0xf);
MIrq_EOI(sb_irq);
}
BOOL SB_WaitDSPWrite(void)
/*
Waits until the DSP is ready to be written to.
returns FALSE on timeout
*/
{
UWORD timeout=32767;
while(timeout--){
if(!(inportb(DSP_WRITE_STATUS)&0x80)) return 1;
}
return 0;
}
BOOL SB_WaitDSPRead(void)
/*
Waits until the DSP is ready to read from.
returns FALSE on timeout
*/
{
UWORD timeout=32767;
while(timeout--){
if(inportb(DSP_DATA_AVAIL)&0x80) return 1;
}
return 0;
}
BOOL SB_WriteDSP(UBYTE data)
/*
Writes byte 'data' to the DSP.
returns FALSE on timeout.
*/
{
if(!SB_WaitDSPWrite()) return 0;
outportb(DSP_WRITE_DATA,data);
return 1;
}
UWORD SB_ReadDSP(void)
/*
Reads a byte from the DSP.
returns 0xffff on timeout.
*/
{
if(!SB_WaitDSPRead()) return 0xffff;
return(inportb(DSP_READ_DATA));
}
void SB_SpeakerOn(void)
/*
Enables DAC speaker output.
*/
{
SB_WriteDSP(0xd1);
}
void SB_SpeakerOff(void)
/*
Disables DAC speaker output
*/
{
SB_WriteDSP(0xd3);
}
void SB_ResetDSP(void)
/*
Resets the DSP.
*/
{
int t;
/* reset the DSP by sending 1, (delay), then 0 */
outportb(DSP_RESET,1);
for(t=0;t<8;t++) inportb(DSP_RESET);
outportb(DSP_RESET,0);
}
BOOL SB_Ping(void)
/*
Checks if a SB is present at the current baseport by
resetting the DSP and checking if it returned the value 0xaa.
returns: TRUE => SB is present
FALSE => No SB detected
*/
{
SB_ResetDSP();
return(SB_ReadDSP()==0xaa);
}
UWORD SB_GetDSPVersion(void)
/*
Gets SB-dsp version. returns 0xffff if dsp didn't respond.
*/
{
UWORD hi,lo;
if(!SB_WriteDSP(0xe1)) return 0xffff;
hi=SB_ReadDSP();
lo=SB_ReadDSP();
return((hi<<8)|lo);
}
static BOOL SB_IsThere(void)
{
char *envptr,c;
static char *endptr;
sb_port =0xffff;
sb_irq =0xff;
sb_lodma=0xff;
sb_hidma=0xff;
if((envptr=(char *)getenv("BLASTER"))==NULL) return 0;
while(1){
/* skip whitespace */
do c=*(envptr++); while(c==' ' || c=='\t');
/* reached end of string? -> exit */
if(c==0) break;
switch(c){
case 'a':
case 'A':
sb_port=strtol(envptr,&endptr,16);
break;
case 'i':
case 'I':
sb_irq=strtol(envptr,&endptr,10);
break;
case 'd':
case 'D':
sb_lodma=strtol(envptr,&endptr,10);
break;
case 'h':
case 'H':
sb_hidma=strtol(envptr,&endptr,10);
break;
default:
strtol(envptr,&endptr,16);
break;
}
envptr=endptr;
}
if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0;
/* determine interrupt vector */
sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8;
if(!SB_Ping()) return 0;
/* get dsp version. */
if((sb_ver=SB_GetDSPVersion())==0xffff) return 0;
return 1;
}
static void SB_PlayStart(void)
{
MIrq_OnOff(sb_irq,1);
if(!MDma_Start(sb_dma,SB_DMAMEM,DMA_SIZE,INDEF_WRITE)){
return;
}
SB_WriteDSP(0x41);
SB_WriteDSP(mixfreq>>8);
SB_WriteDSP(mixfreq&0xff);
SB_WriteDSP(0xb6);
SB_WriteDSP(0x30);
SB_WriteDSP(0xff);
SB_WriteDSP(0xef);
playing=1;
}
static void SB_PlayStop(void)
{
if ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc > last)
while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc>last);
while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc <last);
MDma_Stop(sb_dma);
MIrq_OnOff(sb_irq,0);
SB_SpeakerOff();
SB_ResetDSP();
SB_ResetDSP();
}