|
Sound Playback Using Single Cycle DMA Mode Example 5 |
Mission : Discover a new way to get sound output. It's certainly a
better alternative than Direct Mode, but it still isn't as
high a quality as we want.
Download the Expansion Pack!
Introvoid SetupSBISR(); void GetSBIRQ(unsigned char); _go32_dpmi_seginfo OldSB,NewSB; char SetSB,SBIRQ; unsigned short SBMaskSave; |
...
extern SB16_ISR (_go32_dpmi_registers*);
ISRS::ISRS()
{SBIRQ=-1;
}
void ISRS::GetSBIRQ(unsigned char IRQ)
{SBIRQ=IRQ;
}
void ISRS::SetupSBISR()
{ SetSB=1;
if(SBIRQ>=0)
{cout<<"Please set the Sound Blaster IRQ Number in the ISR class!\n";
sleep(4);
exit(1);
}
_go32_dpmi_get_protected_mode_interrupt_vector(SBIRQ+8,&OldSB);
NewSB.pm_offset = (int)SB16_ISR;
NewSB.pm_selector=_go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&NewSB);
_go32_dpmi_set_protected_mode_interrupt_vector(SBIRQ+8,&NewSB);
SBMaskSave=inp(0x21);
short temp=(1<<SBIRQ);
outp(0x21,(SBMaskSave& ~temp));
}
|
void ISRS::ReturnISRs()
{
if(SetSB)
{short temp=inp(0x21);
temp|=(1<<SBIRQ);
outp(0x21,temp);
_go32_dpmi_set_protected_mode_interrupt_vector(SBIRQ+8,&OldSB);
_go32_dpmi_free_iret_wrapper(&NewSB);
}
} |
void SB16::SetupDMA()
{ disable();
if(ModeBits==8)
{dma.SetDMAChannel(BLASTER.DMAChan);
}
dma.DisableChannel();
dma.SetControlByteMask(DemandMode,AddressIncrement,SingleCycle,ReadTransfer);
dma.SetControlByte();
dma.ClearFlipFlop();
dma.SetBufferInfo();
dma.SetTransferLength(BUFFSIZE);
enable();
dma.EnableChannel();
} |
void SB16::SetupDSP()
{ SetupSingleCycleDSP();
}
|
// we have to assume that our settings match the sound card so we won't be
// requesting 8-stereo or 16 anything with under a 4.0 dsp
void SB16::SetupSingleCycleDSP()
{ if(ModeBits==8)
{ if(!ModeStereoMono)
{ SingleCycle8Mono(); //8 bit Mono
}
else
{ SingleCycle8Stereo(); //8 bit Stereo
}
}
else
{ if(!ModeStereoMono)
{ SingleCycle16Mono(); //16 bit Mono
}
else
{ SingleCycle16Stereo();//16 bit Stereo
}
}
}
|
...
#define NumberOfSounds 1
#define LoByte(x)(short)(x & 0x00FF)
#define HiByte(x)(short)((x&0xFF00)>>8)
void SB16::SingleCycle8Mono()
{ //make sure we use the right one, if dsp version is less that 4 then do old
if(DSPVersionNum<4)
{ OldSingleCycle();
}
else
{ SendFrequency();
WriteDSP(0xC0); //8 bit
WriteDSP(0x00); //Mono
SendLength();
}
}
void SB16::OldSingleCycle()
{ //has to be 8 mono
WriteDSP(DSP_TIME_CONSTANT);
WriteDSP(HiByte(OldTimeConstant()));//use only high byte
WriteDSP(0x14); //8 bit pcm output
SendLength();
}
unsigned short SB16::OldTimeConstant()
{ return 65536-(256000000/((ModeStereoMono+1)*SoundRate));
}
|
void SB16::SingleCycle8Stereo()
{ SendFrequency();
WriteDSP(0xC0); //8 bit
WriteDSP(0x20); //Stereo
SendLength();
}
void SB16::SingleCycle16Mono()
{ SendFrequency();
WriteDSP(0xB0); //16 bit
WriteDSP(0x00); //Mono
SendLength();
}
void SB16::SingleCycle16Stereo()
{ SendFrequency();
WriteDSP(0xB0); //16 bit
WriteDSP(0x20); //Stereo
SendLength();
}
|
void SB16::SendLength()
{ WriteDSP(LoByte(TransferLength-1));
WriteDSP(HiByte(TransferLength-1));
}
void SB16::SendFrequency()
{ WriteDSP(0x41);
WriteDSP(HiByte(SoundRate));
WriteDSP(LoByte(SoundRate));
}
|
void SB16::ServiceISR()
{disable();
if(TransferMode==1) //SS
{ ServiceSC();
}
else //AI
{ ServiceAI();
}
enable();
outp(0x20,0x20); //eoi command to PIC
}
|
void SB16::ServiceSC()
{ if(Done==0)
{FillWholeBuffer();
SetupDMA();
SetupDSP();
inp(DSPStatus);
}
}
void SB16::ServiceAI()
{
}
|
void SB16::SetModeBits(unsigned char Bits)
{ ModeBits=Bits;
}
void SB16::SetTransferMode(unsigned char mode)
{ TransferMode=mode;
}
void SB16::FillWholeBuffer()
{ unsigned char *d=(unsigned char*)dma.MK_FP(dma.phys>>4,0);
unsigned char *s = Sounds[0].Sound;
unsigned long amount;
amount=BUFFSIZE;
if(SoundSize < BUFFSIZE)
{amount=SoundSize;
Done=1;
TransferLength=SoundSize;
}
s+=place;
memmove((unsigned char *)d,(unsigned char *)s,amount);
SoundSize-=BUFFSIZE;
place+=BUFFSIZE;
}
|