- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
转载请注明出处:http://www.0xaa55.com/thread-1514-1-1.html
经过实际的测试,可以使DOSBOX、Virtual PC虚拟的DOS、Virtual Box虚拟的DOS、VMware虚拟的DOS播放WAV音乐(支持44100 Hz 16-bit CD音质)
这就是编写能播放音乐的DOS游戏所需的玩意儿了。
目前的代码对Sound Blaster 16(版本4.xx)的支持比较好,但是对低版本的(2.00以下"SBLO")支持不太好。现在已经解决了播放声音时有杂音的问题。原先的代码没有搞对时序。
但是现在遇到的问题是播放MIDI的时候,貌似不能在VMware虚拟的DOS中播放MIDI音乐。但是可以在DOSBOX中正常播放。
这个驱动是纯C写的。所以可以拿去给你的DOS游戏作为声音模块使用。
编译器用的是WATCOM C。
BIN:
demo.7z
(28.88 KB, 下载次数: 8)
整个程序的所有源码,回帖后即可下载。
编译器:WATCOM C
http://www.0xaa55.com/thread-1329-1-1.html
参考资料:
【PDF】Sound Blaster 16 声霸卡驱动编写向导 英文
http://www.0xaa55.com/thread-1500-1-1.html
【DOS】混合语言实现WAV文件播放的程序,声霸卡驱动源码
http://www.0xaa55.com/thread-125-1-1.html
【C语言】Midi文件播放器(可跨平台)
http://www.0xaa55.com/forum.php? ... =1489&fromuid=1
下面放出最关键的代码。- #include"sb.h"
- #include<dos.h>
- #include<time.h>
- #include<ctype.h>
- #include<conio.h>
- #include<stdio.h>
- #include<stdarg.h>
- #include<stdlib.h>
- #include<memory.h>
- SBInfo_t g_SBInfo={0};
- #define g_Port g_SBInfo.IOInfo.PortNum
- #define g_Version g_SBInfo.HWInfo.Version
- #define g_DMAL g_SBInfo.IOInfo.DMAL
- #define g_DMALAddr g_SBInfo.DMAInfo.DMALAddr
- #define g_DMALCount g_SBInfo.DMAInfo.DMALCount
- #define g_DMALPage g_SBInfo.DMAInfo.DMALPage
- #define g_DMAH g_SBInfo.IOInfo.DMAH
- #define g_DMAHAddr g_SBInfo.DMAInfo.DMAHAddr
- #define g_DMAHCount g_SBInfo.DMAInfo.DMAHCount
- #define g_DMAHPage g_SBInfo.DMAInfo.DMAHPage
- #define g_IRQ g_SBInfo.IOInfo.IRQ
- #define g_BufAddr g_SBInfo.pBufAddr
- #define g_BufSize g_SBInfo.BufSize
- #define g_bPlaying8 g_SBInfo.bPlaying8
- #define g_bPlaying16 g_SBInfo.bPlaying16
- #define g_bRecording8 g_SBInfo.bRecording8
- #define g_bRecording16 g_SBInfo.bRecording16
- #define g_bFirstBuf g_SBInfo.bFirstBuf
- #define g_OnBuffer g_SBInfo.pfnOnBuffer
- #define g_Print g_SBInfo.pfnOnDebugOutput
- #define Far2Phys(f) (((uint32_t)f & 0xFFFF) + ((uint32_t)f >> 12))
- #define SBPort_BaseBegin 0x210
- #define SBPort_BaseStep 0x10
- #define SBPort_BaseEnd 0x260
- #define SBPort_MixerRegNum 0x04
- #define SBPort_MixerRegVal 0x05
- #define SBPort_Reset 0x06
- #define SBPort_Read 0x0A
- #define SBPort_Write 0x0C
- #define SBPort_WBufState 0x0C
- #define SBPort_RBufState 0x0E
- #define SBPort_Ack8 0x0E
- #define SBPort_Ack16 0x0F
- #define SBMixer_VoiceVol 0x04
- #define SBMixer_MicVol 0x0A
- #define SBMixer_MasterVol 0x22
- //Programmable Interrupt Controller
- #define PIC_MASK 0x21
- #define PIC_MODE 0x20
- #define PIC2_MASK 0xA1
- #define PIC2_MODE 0xA0
- #define PIC_EOI 0x20
- #define PIC_SPECEOI 0x60
- #define PIC_IRQ0_7BEGIN 0x08
- #define PIC_IRQ8_FBEGIN 0x70
- #define PIC_INTNUM(x) ((x>7)?PIC_IRQ8_FBEGIN+(x):PIC_IRQ0_7BEGIN+(x))
- //DMA
- #define DMA8_FF_REG 0x0C
- #define DMA8_MASK_REG 0x0A
- #define DMA8_MODE_REG 0x0B
- #define DMA16_FF_REG 0xD8
- #define DMA16_MASK_REG 0xD4
- #define DMA16_MODE_REG 0xD6
- #define DMA0_ADDR 0x00
- #define DMA0_COUNT 0x01
- #define DMA0_PAGE 0x87
- #define DMA1_ADDR 0x02
- #define DMA1_COUNT 0x03
- #define DMA1_PAGE 0x83
- #define DMA2_ADDR 0x04
- #define DMA2_COUNT 0x05
- #define DMA2_PAGE 0x81
- #define DMA3_ADDR 0x06
- #define DMA3_COUNT 0x07
- #define DMA3_PAGE 0x82
- #define DMA4_ADDR 0xC0
- #define DMA4_COUNT 0xC2
- #define DMA4_PAGE 0x8F
- #define DMA5_ADDR 0xC4
- #define DMA5_COUNT 0xC6
- #define DMA5_PAGE 0x8B
- #define DMA6_ADDR 0xC8
- #define DMA6_COUNT 0xCA
- #define DMA6_PAGE 0x89
- #define DMA7_ADDR 0xCC
- #define DMA7_COUNT 0xCE
- #define DMA7_PAGE 0x8A
- //=============================================================================
- //Func: OnDebugOutput
- //Desc: Debug info output by Sound Blaster driver
- //-----------------------------------------------------------------------------
- void SBCallBack_t DefOnDebugOutput(char*format,...)
- {
- va_list ap;
- va_start(ap,format);
- vfprintf(stderr,format,ap);
- va_end(ap);
- }
- //=============================================================================
- //Func: SBIn
- //Desc: Read a byte at the Read Data port
- //-----------------------------------------------------------------------------
- SB_i(uint8_t,SBIn)(uint16_t uPortNum)
- {
- while(!(inp(uPortNum+SBPort_RBufState) & 0x80));
- return inp(uPortNum+SBPort_Read);
- }
- //=============================================================================
- //Func: SBOut
- //Desc: Write a byte to the Write Data port
- //-----------------------------------------------------------------------------
- SB_i(void,SBOut)(uint16_t uPortNum,uint8_t Data)
- {
- while(inp(uPortNum+SBPort_WBufState) & 0x80);
- outp(uPortNum+SBPort_Write,Data);
- }
- //=============================================================================
- //Func: SBGetMixerReg
- //Desc: Read a mixer register value
- //-----------------------------------------------------------------------------
- SB_i(uint8_t,SBGetMixerReg)(uint16_t uPortNum,uint8_t uMixerReg)
- {
- if(g_Version<SBVer_SBPro)
- return 0;
- outp(uPortNum+SBPort_MixerRegNum,uMixerReg);
- return inp(uPortNum+SBPort_MixerRegVal);
- }
- //=============================================================================
- //Func: SBSetMixerReg
- //Desc: Write a mixer register value
- //-----------------------------------------------------------------------------
- SB_i(void,SBSetMixerReg)(uint16_t uPortNum,uint8_t uMixerReg,uint8_t uVal)
- {
- if(g_Version<SBVer_SBPro)
- return;
- outp(uPortNum+SBPort_MixerRegNum,uMixerReg);
- outp(uPortNum+SBPort_MixerRegVal,uVal);
- }
- //=============================================================================
- //Func: SBReset
- //Desc: Initialize or reset the sound blaster
- //-----------------------------------------------------------------------------
- SB_i(bool_t,SBReset)(uint16_t uPortNum)
- {
- clock_t c;
-
- //Write a "1" to the Reset port (2x6h) and wait for atleast 3 ms
- outp(uPortNum+SBPort_Reset,1);
-
- //wait for 10 ms
- delay(10);
-
- //Write a "0" to the Reset port
- outp(uPortNum+SBPort_Reset,0);
-
- //Wait until it had finished initializing
- c=clock();
- while(!(inp(uPortNum+SBPort_RBufState) & 0x80))
- {
- //quit when out of time
- if(clock()-c>CLOCKS_PER_SEC*200/1000)
- return false;
- }
-
- if(inp(uPortNum+SBPort_Read)==0xAA)
- return true;
- return false;
- }
- //=============================================================================
- //Func: SBGetIOInfoByEnv
- //Desc: Retrieve the informations from %BLASTER%
- //-----------------------------------------------------------------------------
- SB_i(bool_t,SBGetIOInfoByEnv)(SBIOInfo_p pIOInfo,char*szEnv)
- {
- char Buf[5],SaveChar;
- bool_t DMAFound = false;
- bool_t IOPortFound = false;
- bool_t IRQFound = false;
- int i,mul;
-
- if(!szEnv)
- return false;
-
- do
- {
- switch(*szEnv)
- {
- case'A':// I/O base port address found
- case'a':
- szEnv++;
- for (i = 0; i < 3; i++) // Grab the digits
- {
- if(*szEnv==' ')
- break;
- Buf[i] = *szEnv;
- szEnv++;
- }
-
- // Convert to HEX
- mul = 1;
- pIOInfo->PortNum = 0;
- while(i--)
- {
- int Digit;
-
- if (Buf[i] >= '0' && Buf[i] <= '9')
- Digit = Buf[i] - '0';
- else if (Buf[i] >= 'A' && Buf[i] <= 'F')
- Digit = Buf[i] - 'A' + 10;
- else if (Buf[i] >= 'a' && Buf[i] <= 'f')
- Digit = Buf[i] - 'a' + 10;
- pIOInfo->PortNum += Digit * mul;
- mul <<= 4;
- }
- IOPortFound=true;
- break;
-
- case'D': // 8-bit DMA channel
- case'd':
- case'H': // 16-bit DMA channel
- case'h':
- case'I': // IRQ number
- case'i':
- SaveChar=*szEnv++;
- Buf[0]=*szEnv++;
- if(isdigit(*szEnv))
- {
- Buf[1]=*szEnv++;
- Buf[2]='\0';
- }
- else
- Buf[1]='\0';
- if(SaveChar=='D' || SaveChar=='d')
- {
- pIOInfo->DMAL = atoi(Buf);
- DMAFound=true;
- }
- else if(SaveChar=='H' || SaveChar=='h')
- {
- pIOInfo->DMAH = atoi(Buf);
- DMAFound=true;
- }
- else if(SaveChar=='I' || SaveChar=='i')
- {
- pIOInfo->IRQ = atoi(Buf);
- IRQFound=true;
- }
- break;
-
- default:
- szEnv++;
- }
- }while(*szEnv);
-
- if(!IOPortFound || !DMAFound || !IRQFound)
- {
- g_Print("Incorrect %%BLASTER%% env.\n");
- return false;
- }
- return true;
- }
- //=============================================================================
- //Func: SBGetHWInfo
- //Desc: Retrieve the hardware informations.
- //-----------------------------------------------------------------------------
- SB_i(void,SBGetHWInfo)(uint16_t uPortNum,SBHWInfo_p pHWInfo)
- {
- SBOut(uPortNum,0xE1);//get version
- pHWInfo->Version=SBIn(uPortNum);
- pHWInfo->Version<<=8;
- pHWInfo->Version|=SBIn(uPortNum);
- }
- //=============================================================================
- //Func: SBGetInfo
- //Desc: Retrieve the informations by IO.
- //Note: If failed getting info from BLASTER, the function will try to get the
- // info by read it from the mixer register. But only SB16 supports it.
- //-----------------------------------------------------------------------------
- SB_i(bool_t,SBGetInfo)(SBIOInfo_p pIOInfo,SBHWInfo_p pHWInfo)
- {
- if(SBGetIOInfoByEnv(pIOInfo,getenv("BLASTER")))
- {
- pIOInfo->InfoFromEnv=true;
- SBGetHWInfo(pIOInfo->PortNum,pHWInfo);
- return true;
- }
- else
- {
- uint16_t Port;
- uint8_t IRQBits;
- uint8_t DMABits;
-
- pIOInfo->InfoFromEnv=false;
-
- //Scan the port to determine the port of the sound blaster
- for(Port=SBPort_BaseBegin;
- Port<=SBPort_BaseEnd;
- Port+=SBPort_BaseStep)
- {
- if(!SBReset(Port))
- continue;
-
- pIOInfo->PortNum=Port;
-
- SBGetHWInfo(Port,pHWInfo);
-
- if(pHWInfo->Version<SBVer_SB16)
- {
- pIOInfo->IRQ=5;
- pIOInfo->DMAL=1;
- pIOInfo->DMAH=5;
- return true;
- }
-
- //Read the mixer registers
- IRQBits=SBGetMixerReg(Port,0x80);
- DMABits=SBGetMixerReg(Port,0x81);
-
- //Get IRQ number
- switch(IRQBits & 0xF)
- {
- case 1:
- pIOInfo->IRQ=2;
- break;
- case 2:
- pIOInfo->IRQ=5;
- break;
- case 4:
- pIOInfo->IRQ=7;
- break;
- case 8:
- pIOInfo->IRQ=10;
- break;
- default:
- continue;
- }
-
- //Get 8-bit DMA channel
- switch(DMABits & 0xF)
- {
- case 1:
- pIOInfo->DMAL=0;
- break;
- case 2:
- pIOInfo->DMAL=1;
- break;
- case 8:
- pIOInfo->DMAL=3;
- break;
- default:
- continue;
- }
-
- //Get 16-bit DMA channel
- switch(DMABits & 0xF0)
- {
- case 0x20:
- pIOInfo->DMAH=5;
- break;
- case 0x40:
- pIOInfo->DMAH=6;
- break;
- case 0x80:
- pIOInfo->DMAH=7;
- break;
- default:
- continue;
- }
-
- return true;
- }
-
- g_Print("Sound Blaster not found.\n");
- return false;
- }
- }
- //=============================================================================
- //Func: _SendEOI
- //Desc: Send end-of-interrupt to 8259
- //-----------------------------------------------------------------------------
- SB_i(void,_SendEOI)(uint8_t uIRQNum)
- {
- if(uIRQNum<8)
- outp(PIC_MODE,PIC_SPECEOI|uIRQNum);
- else
- outp(PIC2_MODE,PIC_SPECEOI|(uIRQNum-8));
- }
- //=============================================================================
- //Func: _SetPICMask
- //Desc: Set PIC mask bit for uIRQNum
- //-----------------------------------------------------------------------------
- SB_i(void,_SetPICMask)(uint8_t uIRQNum)
- {
- if(uIRQNum<8)
- outp(PIC_MASK,inp(PIC_MASK)|(1<<uIRQNum));
- else
- outp(PIC2_MASK,inp(PIC_MASK)|(1<<(uIRQNum-8)));
- }
- //=============================================================================
- //Func: _ClearPICMask
- //Desc: Clear PIC mask bit for uIRQNum
- //-----------------------------------------------------------------------------
- SB_i(void,_ClearPICMask)(uint8_t uIRQNum)
- {
- if(uIRQNum<8)
- outp(PIC_MASK,inp(PIC_MASK)&~(1<<uIRQNum));
- else
- outp(PIC2_MASK,inp(PIC_MASK)&~(1<<(uIRQNum-8)));
- }
- //=============================================================================
- //Func: _CallBufCB
- //Desc: Call the user specified callback function
- //-----------------------------------------------------------------------------
- SB_i(void,_CallBufCB)()
- {
- uint8_t far*pPtr=g_BufAddr;
- if(!g_bFirstBuf)
- {
- g_bFirstBuf=true;
- g_OnBuffer(pPtr,g_BufSize/2);
- }
- else
- {
- pPtr+=g_BufSize/2;
- g_bFirstBuf=false;
- g_OnBuffer(pPtr,g_BufSize/2);
- }
- }
- //=============================================================================
- //Func: _SBISR
- //Desc: Sound blaster interrupt handler.
- //-----------------------------------------------------------------------------
- SB_ISR(_SBISR)(void)
- {
- uint8_t uReason;
-
- if(g_Version>=SBVer_SB16)
- {
- uReason=SBGetMixerReg(g_Port,0x82);
-
- if(uReason & 0x01)
- {
- inp(g_Port+SBPort_Ack8);
- outp(DMA8_FF_REG,0);
- _CallBufCB();
- }
- if(uReason & 0x02)
- {
- inp(g_Port+SBPort_Ack16);
- outp(DMA16_FF_REG,0);
- _CallBufCB();
- }
- }
- else
- {
- inp(g_Port+SBPort_Ack8);
- outp(DMA8_FF_REG,0);
- }
-
- _SendEOI(g_IRQ);
- g_SBInfo.pfnISRSave();
- }
- //=============================================================================
- //Func: _InstallISR
- //Desc: Install the interrupt service routine
- //-----------------------------------------------------------------------------
- SB_i(void,_InstallISR)()
- {
- ISR_f OrgISR;
-
- OrgISR=_dos_getvect(PIC_INTNUM(g_IRQ));
- if(OrgISR!=_SBISR)
- {
- g_SBInfo.pfnISRSave=OrgISR;
- _dos_setvect(PIC_INTNUM(g_IRQ),_SBISR);
-
- _ClearPICMask(g_IRQ);
- }
- }
- //=============================================================================
- //Func: _RestoreISR
- //Desc: Restore the interrupt service routine to the old one.
- //-----------------------------------------------------------------------------
- SB_i(void,_RestoreISR)()
- {
- _dos_setvect(PIC_INTNUM(g_IRQ),g_SBInfo.pfnISRSave);
- }
- //=============================================================================
- //Func: SBInit
- //Desc: Initialize sound blaster.
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBInit)(DbgOut_f pfnOnDebugOutput)
- {
- if(pfnOnDebugOutput)
- g_Print=pfnOnDebugOutput;
- else
- g_Print=DefOnDebugOutput;
-
- if(!SBGetInfo(&(g_SBInfo.IOInfo),&(g_SBInfo.HWInfo)))
- return false;
-
- switch(g_DMAL)
- {
- case 0:
- g_DMALAddr= DMA0_ADDR;
- g_DMALCount=DMA0_COUNT;
- g_DMALPage= DMA0_PAGE;
- break;
- case 1:
- g_DMALAddr= DMA1_ADDR;
- g_DMALCount=DMA1_COUNT;
- g_DMALPage= DMA1_PAGE;
- break;
- case 3:
- g_DMALAddr= DMA3_ADDR;
- g_DMALCount=DMA3_COUNT;
- g_DMALPage= DMA3_PAGE;
- break;
- }
- switch(g_DMAH)
- {
- case 5:
- g_DMAHAddr= DMA5_ADDR;
- g_DMAHCount=DMA5_COUNT;
- g_DMAHPage= DMA5_PAGE;
- break;
- case 6:
- g_DMAHAddr= DMA6_ADDR;
- g_DMAHCount=DMA6_COUNT;
- g_DMAHPage= DMA6_PAGE;
- break;
- case 7:
- g_DMAHAddr= DMA7_ADDR;
- g_DMAHCount=DMA7_COUNT;
- g_DMAHPage= DMA7_PAGE;
- break;
- }
-
- _InstallISR();
- return true;
- }
- //=============================================================================
- //Func: _CheckDMAAddr
- //Desc: If the buffer crosses a page boundary, the func. returns false.
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_CheckDMAAddr)(void far*Base,uint16_t Count)
- {
- if((((uint32_t)Base & 0xFFFF)+Count) >> 16)
- return false;
-
- return true;
- }
- //=============================================================================
- //Func: _StopDMAL
- //Desc: Stop DMA
- //-----------------------------------------------------------------------------
- SB_i(void,_StopDMAL)()
- {
- outp(DMA8_MASK_REG,0x04 | g_DMAL);
- }
- //=============================================================================
- //Func: _StopDMAH
- //Desc: Stop DMA
- //-----------------------------------------------------------------------------
- SB_i(void,_StopDMAH)()
- {
- outp(DMA16_MASK_REG,0x04 | (g_DMAH-4));
- }
- //=============================================================================
- //Func: _StopDMAL
- //Desc: Stop DMA
- //-----------------------------------------------------------------------------
- SB_i(void,_StartDMAL)()
- {
- outp(DMA8_MASK_REG, g_DMAL);
- }
- //=============================================================================
- //Func: _StopDMAH
- //Desc: Stop DMA
- //-----------------------------------------------------------------------------
- SB_i(void,_StartDMAH)()
- {
- outp(DMA16_MASK_REG, (g_DMAH-4));
- }
- //=============================================================================
- //Func: _SetupDMAL
- //Desc: Setup DMA for playing
- //-----------------------------------------------------------------------------
- SB_i(void,_SetupDMAL)(void far*Base,uint16_t Count,bool_t Input)
- {
- uint32_t uPhysAddr=Far2Phys(Base);
- uint16_t uOffs=uPhysAddr & 0xFFFF;
- uint8_t uPage=uPhysAddr>>16;
-
- //Disable DMA
- _StopDMAL();
-
- //Clear FF
- outp(DMA8_FF_REG,0);
-
- //Set mode
- if(Input)
- outp(DMA8_MODE_REG,0x54 | g_DMAL);
- else
- outp(DMA8_MODE_REG,0x58 | g_DMAL);
-
- Count--;
- outp(g_DMALCount,(Count & 0xFF)); // LO byte of count
- outp(g_DMALCount,(Count >> 8)); // HI byte of count
-
- outp(g_DMALAddr, uOffs & 0xFF); // LO byte address of buffer
- outp(g_DMALAddr, uOffs >> 8); // HI byte address of buffer
- outp(g_DMALPage, uPage); // Physical page number
-
- //Enable DMA
- _StartDMAL();
- }
- //=============================================================================
- //Func: _SetupDMAH
- //Desc: Setup DMA for playing
- //-----------------------------------------------------------------------------
- SB_i(void,_SetupDMAH)(void far*Base,uint16_t Count,bool_t Input)
- {
- uint32_t uPhysAddr=Far2Phys(Base);
- uint16_t uOffs=(uPhysAddr>>1) & 0xFFFF;
- uint8_t uPage=uPhysAddr>>16;
-
- //Disable DMA
- _StopDMAH();
-
- //Clear FF
- outp(DMA16_FF_REG,0);
-
- //Set mode
- if(Input)
- outp(DMA16_MODE_REG,0x54 | (g_DMAH-4));
- else
- outp(DMA16_MODE_REG,0x58 | (g_DMAH-4));
- Count=Count/2-1;//Two bytes per transfer
- outp(g_DMAHCount,(Count & 0xFF)); // LO byte of count
- outp(g_DMAHCount,(Count >> 8)); // HI byte of count
-
- outp(g_DMAHAddr, uOffs & 0xFF); // LO byte address of buffer
- outp(g_DMAHAddr, uOffs >> 8); // HI byte address of buffer
- outp(g_DMAHPage, uPage); // Physical page number
-
- //Enable DMA
- _StartDMAH();
- }
- //=============================================================================
- //Func: SBShutDown
- //Desc: Shutdown the sound blaster, stop playing, restore IRQ
- //-----------------------------------------------------------------------------
- SB_f(void,SBShutDown)()
- {
- if(!g_Version)
- return;
- SBStop();
- SBReset(g_Port);
- _SetPICMask(g_IRQ);
- _RestoreISR();
- memset(&g_SBInfo,0,sizeof(g_SBInfo));
- }
- //=============================================================================
- //Func: SBDirectOut8
- //Desc: 8-bit direct mode single byte digitized sound output
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBDirectOut8)(uint8_t uByte)
- {
- SBOut(g_Port,0x10);
- SBOut(g_Port,uByte);
- return true;
- }
- //=============================================================================
- //Func: SBInByte8
- //Desc: 8-bit direct mode single byte digitized sound input
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBDirectIn8)(uint8_t*pByte)
- {
- SBOut(g_Port,0x20);
- *pByte=SBIn(g_Port);
- return true;
- }
- //=============================================================================
- //Func: _SBSetTimeConst
- //Desc: set digitized sound output sampling rate
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_SBSetTimeConst)(uint32_t SplRate,uint8_t uChannels)
- {
- if(SplRate<4000)
- {
- g_Print("The sampling rate is too low.\n");
- return false;
- }
-
- if(g_Version<SBVer_SBLO)
- {
- if(SplRate>13000)
- {
- g_Print("The sampling rate is too high for the current Sound Blast"
- "er.\n");
- return false;
- }
- }
-
- if(g_Version<SBVer_SBPro)
- {
- if(uChannels!=1)
- {
- g_Print("The current Sound Blaster doesn't support stereo digitize"
- "d sound data.\n");
- return false;
- }
- }
-
- if(SplRate>44100)
- {
- g_Print("The sampling rate is too high for the current Sound Blaster."
- "\n");
- return false;
- }
-
- if(uChannels!=1 && uChannels!=2)
- {
- g_Print("Invalid channel number.\n");
- return false;
- }
-
- SBOut(g_Port,0x40);
- SBOut(g_Port,256 - 1000000/(uChannels*SplRate));
- return true;
- }
- //=============================================================================
- //Func: SBSetOutSplRate
- //Desc: set digitized sound output sampling rate
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBSetOutSplRate)(uint32_t SplRate,uint8_t uChannels)
- {
- if(g_Version<SBVer_SB16)
- return _SBSetTimeConst(SplRate,uChannels);
- else
- {
- if(SplRate<5000)
- return _SBSetTimeConst(SplRate,uChannels);
- else if(SplRate>45000)
- {
- g_Print("The sampling rate is too high.\n");
- return false;
- }
-
- SBOut(g_Port,0x41);
- SBOut(g_Port,SplRate >> 8);
- SBOut(g_Port,SplRate & 0xFF);
- return true;
- }
- }
- //=============================================================================
- //Func: SBSetInSplRate
- //Desc: set digitized sound input sampling rate
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBSetInSplRate)(uint32_t SplRate,uint8_t uChannels)
- {
- if(g_Version<SBVer_SB16)
- return _SBSetTimeConst(SplRate,uChannels);
- else
- {
- if(SplRate<5000)
- return _SBSetTimeConst(SplRate,uChannels);
- else if(SplRate>45000)
- {
- g_Print("The sampling rate is too high.\n");
- return false;
- }
-
- SBOut(g_Port,0x42);
- SBOut(g_Port,SplRate >> 8);
- SBOut(g_Port,SplRate & 0xFF);
- return true;
- }
- }
- //=============================================================================
- //Func: _SBSetBlockSize
- //Desc: Set DSP block transfer size
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_SBSetBlockSize)(uint16_t BlockSize)
- {
- if(g_Version<SBVer_SBLO)
- {
- g_Print("The current sound blaster doesn't support auto-init mode.\n");
- return false;
- }
-
- SBOut(g_Port,0x48);
- SBOut(g_Port,BlockSize & 0xFF);
- SBOut(g_Port,BlockSize >> 8);
- return true;
- }
- //=============================================================================
- //Func: _Stop8
- //Desc: Pause 8-bit digitized sound ip
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_Stop8)()
- {
- SBOut(g_Port,0xD0);
- _StopDMAL();
- return true;
- }
- //=============================================================================
- //Func: _Start8
- //Desc: Continue 8-bit digitized sound ip
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_Start8)()
- {
- SBOut(g_Port,0xD4);
- _StartDMAL();
- return true;
- }
- //=============================================================================
- //Func: _Stop16
- //Desc: Pause 16-bit digitized sound ip
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_Stop16)()
- {
- if(g_Version<SBVer_SB16)
- {
- g_Print("The current sound blaster doesn't support 16-bit digitized so"
- "und data.\n");
- return false;
- }
- SBOut(g_Port,0xD5);
- _StopDMAH();
- return true;
- }
- //=============================================================================
- //Func: _Start16
- //Desc: Continue 16-bit digitized sound ip
- //-----------------------------------------------------------------------------
- SB_i(bool_t,_Start16)()
- {
- if(g_Version<SBVer_SB16)
- {
- g_Print("The current sound blaster doesn't support 16-bit digitized so"
- "und data.\n");
- return false;
- }
- SBOut(g_Port,0xD6);
- _StartDMAH();
- return true;
- }
- //=============================================================================
- //Func: SBStop
- //Desc: Stop(Pause) digitized sound ip
- //-----------------------------------------------------------------------------
- SB_f(void,SBStop)()
- {
- if(g_bPlaying8 || g_bRecording8)
- _Stop8();
- if(g_bPlaying16 || g_bRecording16)
- _Stop16();
- }
- //=============================================================================
- //Func: SBStart
- //Desc: Start(Continue) digitized sound ip
- //-----------------------------------------------------------------------------
- SB_f(void,SBStart)()
- {
- if(g_bPlaying8 || g_bRecording8)
- _Start8();
- if(g_bPlaying16 || g_bRecording16)
- _Start16();
- }
- //=============================================================================
- //Func: SBOut8
- //Desc: 8-bit auto-init mode digitized sound output
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBOut8)
- (
- void far*BufAddr,
- uint16_t BufSize,
- uint8_t uChannels,
- uint32_t SplRate,
- Buffer_f pfnOnBuffer
- )
- {
- //Double buffering
- uint16_t HalfSize;
-
- if(g_Version<SBVer_SBLO)//no auto-init
- {
- g_Print("The current Sound Blaster doesn't support auto-init mode.\n");
- return false;
- }
-
- if(g_Version<SBVer_SB16 & uChannels!=1)//no stereo
- {
- g_Print("The current Sound Blaster doesn't support stereo sound data."
- "\n");
- return false;
- }
-
- if(!_CheckDMAAddr(BufAddr,BufSize))
- {
- g_Print("DMA segbound wrapping.\n");
- return false;
- }
-
- if(!SBSetOutSplRate(SplRate,uChannels))
- return false;
-
- SBStop();
-
- g_SBInfo.pfnOnBuffer=pfnOnBuffer;
- g_BufAddr=BufAddr;
- g_BufSize=BufSize;
-
- g_bFirstBuf=false;
- _CallBufCB();
- _CallBufCB();
-
- _SetupDMAL(BufAddr,BufSize-uChannels,0);
-
- //Double buffering
- HalfSize=BufSize/2-uChannels;
-
- if(uChannels==1)
- {
- if(g_Version<SBVer_SB16)
- {
- _SBSetBlockSize(HalfSize);
- if(SplRate<=23000)//low speed
- SBOut(g_Port,0x1C);
- else
- {
- if(g_Version<SBVer_SBHI)
- return false;
-
- SBOut(g_Port,0x90);
- }
- }
- else
- {
- SBOut(g_Port,0xC4);//Output, auto-init, no fifo
- SBOut(g_Port,0x00);//mono, unsigned
- SBOut(g_Port,HalfSize & 0xFF);
- SBOut(g_Port,HalfSize >> 8);
- }
- }
- else if(uChannels==2)
- {
- SBOut(g_Port,0xC4);//Output, auto-init, no fifo
- SBOut(g_Port,0x20);//stereo, unsigned
- SBOut(g_Port,HalfSize & 0xFF);
- SBOut(g_Port,HalfSize >> 8);
- }
- else
- return false;
-
- g_bPlaying8=true;
- g_bPlaying16=false;
- g_bRecording8=false;
- g_bRecording16=false;
- return true;
- }
- //=============================================================================
- //Func: SBIn8
- //Desc: 8-bit auto-init mode digitized sound input
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBIn8)
- (
- void far*BufAddr,
- uint16_t BufSize,
- uint8_t uChannels,
- uint32_t SplRate,
- Buffer_f pfnOnBuffer
- )
- {
- if(g_Version<SBVer_SBLO)//no auto-init
- {
- g_Print("The current Sound Blaster doesn't support auto-init mode.\n");
- return false;
- }
-
- if(g_Version<SBVer_SB16 & uChannels!=1)//no stereo
- {
- g_Print("The current Sound Blaster doesn't support stereo sound data."
- "\n");
- return false;
- }
-
- if(!_CheckDMAAddr(BufAddr,BufSize))
- {
- g_Print("DMA segbound wrapping.\n");
- return false;
- }
-
- if(!SBSetInSplRate(SplRate,uChannels))
- return false;
-
- SBStop();
-
- g_SBInfo.pfnOnBuffer=pfnOnBuffer;
- g_BufAddr=BufAddr;
- g_BufSize=BufSize;
-
- g_bFirstBuf=false;
-
- //Double buffering
- _SetupDMAL(BufAddr,BufSize-uChannels,1);
-
- //Double buffering
- BufSize=BufSize/2-uChannels;
-
- if(uChannels==1)
- {
- if(g_Version<SBVer_SB16)
- {
- _SBSetBlockSize(BufSize);//Double buffer
- if(SplRate<=23000)//low speed
- SBOut(g_Port,0x2C);
- else
- {
- if(g_Version<SBVer_SBHI)
- return false;
-
- SBOut(g_Port,0x98);
- }
- }
- else
- {
- SBOut(g_Port,0xCC);//Input, auto-init, no fifo
- SBOut(g_Port,0x00);//mono, unsigned
- SBOut(g_Port,BufSize & 0xFF);
- SBOut(g_Port,BufSize >> 8);
- }
- }
- else if(uChannels==2)
- {
- SBOut(g_Port,0xCC);//Input, auto-init, no fifo
- SBOut(g_Port,0x20);//stereo, unsigned
- SBOut(g_Port,BufSize & 0xFF);
- SBOut(g_Port,BufSize >> 8);
- }
- else
- return false;
-
- g_bPlaying8=false;
- g_bPlaying16=false;
- g_bRecording8=true;
- g_bRecording16=false;
- return true;
- }
- //=============================================================================
- //Func: SBOut16
- //Desc: 16-bit auto-init mode digitized sound output
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBOut16)
- (
- void far*BufAddr,
- uint16_t BufSize,
- uint8_t uChannels,
- uint32_t SplRate,
- Buffer_f pfnOnBuffer
- )
- {
- //Double buffering
- uint16_t HalfSize;
-
- if(g_Version<SBVer_SB16)
- {
- g_Print("The current sound blaster doesn't support 16-bit digitized so"
- "und data.\n");
- return false;
- }
-
- if(uChannels!=1 && uChannels!=2)
- {
- g_Print("Invalid channel number.\n");
- return false;
- }
-
- if(!_CheckDMAAddr(BufAddr,BufSize))
- {
- g_Print("DMA segbound wrapping.\n");
- return false;
- }
-
- if(!SBSetOutSplRate(SplRate,uChannels))
- return false;
-
- SBStop();
-
- g_SBInfo.pfnOnBuffer=pfnOnBuffer;
- g_BufAddr=BufAddr;
- g_BufSize=BufSize;
-
- g_bFirstBuf=false;
- _CallBufCB();
- _CallBufCB();
-
- _SetupDMAH(BufAddr,BufSize,0);
-
- //Two bytes per sample, double buffering
- HalfSize=BufSize/4-1;
-
- SBOut(g_Port,0xB4);//Output, auto-init, no fifo
- SBOut(g_Port,uChannels==1?0x10:0x30);//stereo, unsigned
- SBOut(g_Port,HalfSize & 0xFF);
- SBOut(g_Port,HalfSize >> 8);
-
- g_bPlaying8=false;
- g_bPlaying16=true;
- g_bRecording8=false;
- g_bRecording16=false;
- return true;
- }
- //=============================================================================
- //Func: SBIn16
- //Desc: 16-bit auto-init mode digitized sound input
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBIn16)
- (
- void far*BufAddr,
- uint16_t BufSize,
- uint8_t uChannels,
- uint32_t SplRate,
- Buffer_f pfnOnBuffer
- )
- {
- if(g_Version<SBVer_SB16)
- {
- g_Print("The current sound blaster doesn't support 16-bit digitized so"
- "und data.\n");
- return false;
- }
-
- if(uChannels!=1 && uChannels!=2)
- {
- g_Print("Invalid channel number.\n");
- return false;
- }
-
- if(!_CheckDMAAddr(BufAddr,BufSize))
- {
- g_Print("DMA segbound wrapping.\n");
- return false;
- }
-
- if(!SBSetInSplRate(SplRate,uChannels))
- return false;
-
- SBStop();
-
- g_SBInfo.pfnOnBuffer=pfnOnBuffer;
- g_BufAddr=BufAddr;
- g_BufSize=BufSize;
-
- g_bFirstBuf=false;
- _SetupDMAH(BufAddr,BufSize,1);
-
- //Two bytes per sample, double buffering
- BufSize=BufSize/4-1;
-
- SBOut(g_Port,0xBC);//Input, auto-init, no fifo
- SBOut(g_Port,uChannels==1?0x10:0x30);//stereo, unsigned
- SBOut(g_Port,BufSize & 0xFF);
- SBOut(g_Port,BufSize >> 8);
-
- g_bPlaying8=false;
- g_bPlaying16=false;
- g_bRecording8=false;
- g_bRecording16=true;
- return true;
- }
- //=============================================================================
- //Func: SBSetVolume
- //Desc: Set speaker volume
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBSetVolume)(uint8_t Master,uint8_t Voice,uint8_t Mic)
- {
- if(g_Version<SBVer_SBPro)
- {
- g_Print("The current sound blaster doesn't have a mixer.\n");
- return false;
- }
- SBSetMixerReg(g_Port,SBMixer_MasterVol,Master);
- SBSetMixerReg(g_Port,SBMixer_VoiceVol,Voice);
- SBSetMixerReg(g_Port,SBMixer_MicVol,Mic);
- return true;
- }
- //=============================================================================
- //Func: SBSendMIDIByte
- //Desc: Output MIDI data to the MIDI port in non-UART mode
- //-----------------------------------------------------------------------------
- SB_f(bool_t,SBSendMIDIByte)(uint8_t MIDI_Byte)
- {
- SBOut(g_Port,0x38);
- SBOut(g_Port,MIDI_Byte);
- return true;
- }
复制代码
|
|