?? sound.cpp
字號:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <mmsystem.h>
#pragma hdrstop
#include <stdlib.h>
#include <dsound.h>
#include "Sound.h"
#include "rom.h"
static CRITICAL_SECTION cs;
static HWAVEOUT dev=NULL;
static HANDLE bufs[2];
static unsigned char* bufPtr[2];
static HANDLE bufHdr[2];
static int curBlock=0;
static int ready;
static int bufPos,bufCycles,bufLVal,bufRVal;
static WAVEHDR* wh;
static int sampleCycles=(8192*1024)/22050;
void CALLBACK WaveCallback(HWAVE hWave, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
WAVEHDR *wh;
HGLOBAL hg; MMRESULT res; if(uMsg == WOM_DONE) { EnterCriticalSection( &cs ); wh = (WAVEHDR *)dwParam1; waveOutUnprepareHeader(dev, wh, sizeof (WAVEHDR)); //Deallocate the buffer memory hg = GlobalHandle(wh->lpData); GlobalUnlock(hg); GlobalFree(hg); //Deallocate the header memory hg = GlobalHandle(wh); GlobalUnlock(hg); GlobalFree(hg); ready++; LeaveCriticalSection( &cs ); }}
LPDIRECTSOUND lpDS;
LPDIRECTSOUNDBUFFER lpBuf;
LPDIRECTSOUNDNOTIFY lpDSNot;
HANDLE sndEv[2];
unsigned char buf[2048];
int bufIndx=0;
static int playing;
static int left;
void CreateSoundBuffer();
void EnableDirectSound(HWND hWnd)
{
DirectSoundCreate(NULL,&lpDS,NULL);
lpDS->SetCooperativeLevel(hWnd,DSSCL_NORMAL);
CreateSoundBuffer();
}
void EnableSound(HWND hWnd)
{
if (soundEnable) return;
if (!waveOutGetNumDevs())
{
MessageBox(NULL,"No audio devices present","Error",
MB_OK|MB_ICONSTOP);
return;
}
soundEnable=1;
ready=3; bufPos=0;
bufCycles=0; bufLVal=0; bufRVal=0;
// EnableDirectSound(hWnd);
// return;
WAVEFORMATEX outFormatex;
outFormatex.wFormatTag=WAVE_FORMAT_PCM;
outFormatex.wBitsPerSample=8;
outFormatex.nChannels=2;
outFormatex.nSamplesPerSec=22050;
outFormatex.nAvgBytesPerSec=44100;
outFormatex.nBlockAlign=2;
if (waveOutOpen(&dev,WAVE_MAPPER,&outFormatex,(DWORD)
WaveCallback,0,CALLBACK_FUNCTION)!=MMSYSERR_NOERROR)
{
MessageBox(NULL,"Could not open audio device","Error",
MB_OK|MB_ICONSTOP);
return;
}
waveOutReset(dev);
InitializeCriticalSection(&cs);
bufs[curBlock]=GlobalAlloc(GMEM_MOVEABLE,2048);
bufPtr[curBlock]=(unsigned char *)GlobalLock(bufs[curBlock]);
bufHdr[curBlock]=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(WAVEHDR));
wh=(WAVEHDR*)GlobalLock(bufHdr[curBlock]);
wh->dwBufferLength=2048;
wh->lpData=bufPtr[curBlock];
}
void DisableSound()
{
if (!soundEnable)
return;
if(dev)
{ while (ready<2) Sleep(50); waveOutReset(dev); //reset the device waveOutClose(dev); //close the device dev=NULL; } DeleteCriticalSection(&cs); soundEnable=0;
}
void CreateSoundBuffer()
{
DSBUFFERDESC d;
WAVEFORMATEX wf;
char *ptr;
unsigned long n;
wf.wFormatTag=WAVE_FORMAT_PCM;
wf.nChannels=2;
wf.nSamplesPerSec=22050;
wf.nAvgBytesPerSec=22050*2;
wf.nBlockAlign=2;
wf.wBitsPerSample=8;
wf.cbSize=0;
memset(&d,0,sizeof(d));
d.dwSize=sizeof(d);
d.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GLOBALFOCUS;
d.dwBufferBytes=4096;
d.lpwfxFormat=&wf;
lpDS->CreateSoundBuffer(&d,&lpBuf,NULL);
sndEv[0]=CreateEvent(NULL,FALSE,FALSE,NULL);
sndEv[1]=CreateEvent(NULL,FALSE,FALSE,NULL);
DSBPOSITIONNOTIFY pn[2];
pn[0].dwOffset=0;
pn[0].hEventNotify=sndEv[0];
pn[1].dwOffset=d.dwBufferBytes/2;
pn[1].hEventNotify=sndEv[1];
lpBuf->QueryInterface(IID_IDirectSoundNotify,(void**)&lpDSNot);
lpDSNot->SetNotificationPositions(2,pn);
bufIndx=0;
playing=0;
left=2;
}
void DirectSoundOutput(int l,int r)
{
buf[bufIndx++]=l;
buf[bufIndx++]=r;
if (bufIndx>=2048)
{
bufIndx=0;
int i;
if (playing)
{
i=MsgWaitForMultipleObjects(2,sndEv,FALSE,INFINITE,0);
i-=WAIT_OBJECT_0;
}
else
i=1;
if (i==0)
{
short *ptr1,*ptr2;
unsigned long len1,len2;
lpBuf->Lock(2048,2048,(void**)&ptr1,&len1,
(void**)&ptr2,&len2,0);
memcpy(ptr1,buf,len1);
lpBuf->Unlock(ptr1,len1,ptr2,len2);
}
else
{
short *ptr1,*ptr2;
unsigned long len1,len2;
lpBuf->Lock(0,2048,(void**)&ptr1,&len1,
(void**)&ptr2,&len2,0);
memcpy(ptr1,buf,len1);
lpBuf->Unlock(ptr1,len1,ptr2,len2);
}
if (!playing)
{
lpBuf->Play(0,0,DSBPLAY_LOOPING);
playing=1;
}
}
}
void SoundDoOut(int l,int r,int cycles)
{
bufLVal+=l*cycles;
bufRVal+=r*cycles;
bufCycles+=cycles;
if (bufCycles>=sampleCycles)
{
// DirectSoundOutput(bufRVal/sampleCycles,bufLVal/sampleCycles);
// bufCycles=0;
// bufLVal=0; bufRVal=0;
// return;
bufPtr[curBlock][bufPos]=bufRVal/sampleCycles;
bufPtr[curBlock][bufPos+1]=bufLVal/sampleCycles;
bufCycles=0;
bufPos+=2;
bufLVal=0; bufRVal=0;
if (bufPos>=2048)
{
while (!ready)
Sleep(3);
ready--;
waveOutPrepareHeader(dev,wh,sizeof(WAVEHDR));
waveOutWrite(dev,wh,sizeof(WAVEHDR));
curBlock=(curBlock+1)&1;
bufs[curBlock]=GlobalAlloc(GMEM_MOVEABLE,2048);
bufPtr[curBlock]=(unsigned char *)GlobalLock(bufs[curBlock]);
bufHdr[curBlock]=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(WAVEHDR));
wh=(WAVEHDR*)GlobalLock(bufHdr[curBlock]);
wh->dwBufferLength=2048;
wh->lpData=bufPtr[curBlock];
bufPos=0;
}
}
}
void SoundOutBits(int l,int r,int cycles)
{
if (!soundEnable) return;
while ((bufCycles+cycles)>sampleCycles)
{
int left=sampleCycles-bufCycles;
SoundDoOut(l,r,left);
cycles-=left;
}
SoundDoOut(l,r,cycles);
}
int snd1Enable,snd1Freq,snd1Vol,snd1Len,snd1SwpCnt=0;
int snd1EnvCnt=0,snd1Bit=0,snd1ValL=0,snd1ValR=0,snd1Cnt=0;
int snd2Enable,snd2Freq,snd2Vol,snd2Len;
int snd2EnvCnt=0,snd2Bit=0,snd2ValL=0,snd2ValR=0,snd2Cnt=0;
int snd3Enable,snd3Freq,snd3Len,snd3Bit=0,snd3Cnt=0;
int snd3ValL=0,snd3ValR=0;
int snd4Enable,snd4Freq,snd4Vol,snd4Len;
int snd4EnvCnt=0,snd4Bit=0,snd4ValL=0,snd4ValR=0,snd4Cnt=0;
extern int sndRegChange;
static int bit[4][8]={{1,0,0,0,0,0,0},{1,1,0,0,0,0,0,0},
{1,1,1,1,0,0,0,0},{1,1,1,1,1,1,0,0}};
static int vol[16]={0,8,17,25,34,42,51,59,68,76,85,93,102,110,119,127};
#define HZ(x) ((8192*1024)/(x))
void SoundUpdate(int cycles)
{
static int swpClk=0;
static int envClk=0;
static int lenClk=0;
static int freqClk=0;
static int freq4Clk=0;
int l=0,r=0;
if (!soundEnable) return;
if (!restrictSpeed) return;
if (sndRegChange)
{
snd1Freq=hiRam[0x13]|((hiRam[0x14]&7)<<8);
snd2Freq=hiRam[0x18]|((hiRam[0x19]&7)<<8);
snd3Freq=hiRam[0x1d]|((hiRam[0x1e]&7)<<8);
switch(hiRam[0x22]&7)
{
case 0: snd4Freq=((512*1024)*2)>>((hiRam[0x22]>>4)+1); break;
case 1: snd4Freq=(512*1024)>>((hiRam[0x22]>>4)+1); break;
case 2: snd4Freq=((512*1024)/2)>>((hiRam[0x22]>>4)+1); break;
case 3: snd4Freq=((512*1024)/3)>>((hiRam[0x22]>>4)+1); break;
case 4: snd4Freq=((512*1024)/4)>>((hiRam[0x22]>>4)+1); break;
case 5: snd4Freq=((512*1024)/5)>>((hiRam[0x22]>>4)+1); break;
case 6: snd4Freq=((512*1024)/6)>>((hiRam[0x22]>>4)+1); break;
case 7: snd4Freq=((512*1024)/7)>>((hiRam[0x22]>>4)+1); break;
}
snd4Freq=HZ(snd4Freq);
snd3Enable=(hiRam[0x1a]&0x80)?1:0;
snd1Vol=hiRam[0x12]>>4;
if (hiRam[0x14]&0x80)
{
snd1Len=64-(hiRam[0x11]&63);
snd1Cnt=0;
hiRam[0x14]&=0x7f;
snd1Enable=1;
}
snd2Vol=hiRam[0x17]>>4;
if (hiRam[0x19]&0x80)
{
snd2Len=64-(hiRam[0x16]&63);
snd2Cnt=0;
hiRam[0x19]&=0x7f;
snd2Enable=1;
}
if (hiRam[0x1e]&0x80)
{
snd3Len=(256-((int)((unsigned char)hiRam[0x1b])))<<7;
snd3Cnt=0;
hiRam[0x1e]&=0x7f;
}
snd4Vol=hiRam[0x21]>>4;
if (hiRam[0x23]&0x80)
{
snd4Len=64-(hiRam[0x20]&63);
hiRam[0x23]&=0x7f;
snd4Enable=1;
}
sndRegChange=0;
}
if ((snd1Enable)&&(hiRam[0x10]&0x70))
{
swpClk+=cycles;
if (swpClk>=HZ(128))
{
swpClk-=HZ(128);
snd1SwpCnt++;
if (snd1SwpCnt>=((hiRam[0x10]>>4)&7))
{
snd1SwpCnt=0;
if (hiRam[0x10]&8)
{
snd1Freq-=snd1Freq>>(hiRam[0x10]&7);
if (snd1Freq<0) snd1Freq=0;
}
else
{
snd1Freq+=snd1Freq>>(hiRam[0x10]&7);
if (snd1Freq>2047)
{
snd1Freq=2047;
snd1Enable=0;
}
}
}
}
}
envClk+=cycles;
if (envClk>=HZ(64))
{
envClk-=HZ(64);
if ((snd1Enable)&&(hiRam[0x12]&7))
{
snd1EnvCnt++;
if (snd1EnvCnt>=(hiRam[0x12]&7))
{
snd1EnvCnt=0;
if (hiRam[0x12]&8)
{
snd1Vol++;
if (snd1Vol>0xf) snd1Vol=0xf;
hiRam[0x12]=(hiRam[0x12]&0xf)|(snd1Vol<<4);
}
else
{
snd1Vol--;
if (snd1Vol<0) snd1Vol=0;
hiRam[0x12]=(hiRam[0x12]&0xf)|(snd1Vol<<4);
}
}
}
if ((snd2Enable)&&(hiRam[0x17]&7))
{
snd2EnvCnt++;
if (snd2EnvCnt>=(hiRam[0x17]&7))
{
snd2EnvCnt=0;
if (hiRam[0x17]&8)
{
snd2Vol++;
if (snd2Vol>0xf) snd2Vol=0xf;
hiRam[0x17]=(hiRam[0x17]&0xf)|(snd2Vol<<4);
}
else
{
snd2Vol--;
if (snd2Vol<0) snd2Vol=0;
hiRam[0x17]=(hiRam[0x17]&0xf)|(snd2Vol<<4);
}
}
}
if ((snd4Enable)&&(hiRam[0x21]&7))
{
snd4EnvCnt++;
if (snd4EnvCnt>=(hiRam[0x21]&7))
{
snd4EnvCnt=0;
if (hiRam[0x21]&8)
{
snd4Vol++;
if (snd4Vol>0xf) snd4Vol=0xf;
hiRam[0x21]=(hiRam[0x21]&0xf)|(snd4Vol<<4);
}
else
{
snd4Vol--;
if (snd4Vol<0) snd4Vol=0;
hiRam[0x21]=(hiRam[0x21]&0xf)|(snd4Vol<<4);
}
}
}
}
lenClk+=cycles;
if (lenClk>=HZ(256))
{
lenClk-=HZ(256);
if (snd1Enable)
{
snd1Len--;
if ((snd1Len<=0)&&(hiRam[0x14]&0x40))
snd1Enable=0;
}
if (snd2Enable)
{
snd2Len--;
if ((snd2Len<=0)&&(hiRam[0x19]&0x40))
snd2Enable=0;
}
if (snd3Enable)
{
snd3Len--;
if ((snd3Len<=0)&&(hiRam[0x1e]&0x40))
{
snd3Enable=0;
hiRam[0xff1a]&=0x7f;
}
}
if (snd4Enable)
{
snd4Len--;
if ((snd4Len<=0)&&(hiRam[0x23]&0x40))
snd4Enable=0;
}
}
hiRam[0x13]=snd1Freq&0xff;
hiRam[0x14]=(hiRam[0x14]&0xf8)|((snd1Freq>>8)&7);
freqClk+=cycles;
if (freqClk>=4)
{
int n=freqClk>>2;
freqClk-=n<<2;
if (snd1Enable)
{
snd1Cnt+=n;
while (snd1Cnt>=((2048-snd1Freq)<<4))
snd1Cnt-=((2048-snd1Freq)<<4);
}
if (snd2Enable)
{
snd2Cnt+=n;
while (snd2Cnt>=((2048-snd2Freq)<<4))
snd2Cnt-=((2048-snd2Freq)<<4);
}
if (snd3Enable)
{
snd3Cnt+=n;
while (snd3Cnt>=((2048-snd3Freq)<<5))
snd3Cnt-=((2048-snd3Freq)<<5);
}
}
if (snd1Enable)
{
int stage=(snd1Cnt/(2048-snd1Freq))>>1;
if (stage>7) stage=7;
snd1Bit=bit[hiRam[0x11]>>6][stage];
}
if (hiRam[0x25]&1) l+=snd1Bit?vol[snd1Vol]:-vol[snd1Vol];
if (hiRam[0x25]&0x10) r+=snd1Bit?vol[snd1Vol]:-vol[snd1Vol];
if (snd2Enable)
{
int stage=(snd2Cnt/(2048-snd2Freq))>>1;
if (stage>7) stage=7;
snd2Bit=bit[hiRam[0x16]>>6][stage];
}
if (hiRam[0x25]&2) l+=snd2Bit?vol[snd2Vol]:-vol[snd2Vol];
if (hiRam[0x25]&0x20) r+=snd2Bit?vol[snd2Vol]:-vol[snd2Vol];
if (snd3Enable)
{
int stage=snd3Cnt/(2048-snd3Freq);
if (stage>31) stage=31;
snd3Bit=hiRam[0x30+(stage>>1)];
if (stage&1)
snd3Bit&=0xf;
else
snd3Bit>>=4;
switch ((hiRam[0x1c]>>5)&3)
{
case 0: snd3Bit=8; break;
case 1: break;
case 2: snd3Bit=8|(snd3Bit>>1); break;
case 3: snd3Bit=0xc|(snd3Bit>>2); break;
}
}
if (hiRam[0x25]&4) l+=(snd3Bit<<4)-0x80;
if (hiRam[0x25]&0x40) r+=(snd3Bit<<4)-0x80;
if (snd4Enable)
{
freq4Clk+=cycles;
if (freq4Clk>=snd4Freq)
{
freq4Clk=freq4Clk%snd4Freq;
snd4Bit=rand()&1;
}
}
if (hiRam[0x25]&8) l+=snd4Bit?vol[snd4Vol]:-vol[snd4Vol];
if (hiRam[0x25]&0x80) r+=snd4Bit?vol[snd4Vol]:-vol[snd4Vol];
l>>=2;
if (l<-128) l=-128;
if (l>127) l=127;
l+=0x80;
r>>=2;
if (r<-128) r=-128;
if (r>127) r=127;
r+=0x80;
SoundOutBits(l,r,cycles);
}
void SoundSetCycles(int n)
{
sampleCycles=n;
}
//---------------------------------------------------------------------------
#pragma package(smart_init)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -