#include <stdio.h>
#include <windows.h>
#include <dsound.h>
#include "cpuintrf.h"
#include "oss.h"
#include "ao.h"
static INT16 samples[44100*4];
void (*m1sdr_Callback)(unsigned long dwSamples, short *samples);
unsigned long cbUserData;
static int hw_present, playtime;
LPDIRECTSOUND lpDS; LPDIRECTSOUNDBUFFER lpPDSB; LPDIRECTSOUNDBUFFER lpSecB;
int nDSoundSamRate=44100; int nDSoundSegCount=16; static int cbLoopLen=0;
int nDSoundFps=600; int nDSoundSegLen=0; short *DSoundNextSound=NULL; unsigned char bDSoundOkay=0; unsigned char bDSoundPlaying=0;
#define WRAP_INC(x) { x++; if (x>=nDSoundSegCount) x=0; }
static int nDSoundNextSeg=0;
void m1sdr_SetSamplesPerTick(UINT32 spf)
{
if (spf != (nDSoundFps/10))
{
m1sdr_Exit();
nDSoundFps = spf * 10;
m1sdr_Init(nDSoundSamRate);
}
}
void m1sdr_TimeCheck(void)
{
int nPlaySeg=0, nFollowingSeg=0;
DWORD nPlay=0, nWrite=0;
int nRet=0;
if (!lpDS) return;
IDirectSoundBuffer_GetCurrentPosition(lpSecB, &nPlay, &nWrite);
nPlaySeg=nPlay/(nDSoundSegLen<<2);
if (nPlaySeg>nDSoundSegCount-1) nPlaySeg=nDSoundSegCount-1;
if (nPlaySeg<0) nPlaySeg=0;
if (nDSoundNextSeg == nPlaySeg)
{
Sleep(200); goto End;
}
nFollowingSeg = nDSoundNextSeg;
WRAP_INC(nFollowingSeg)
while (nDSoundNextSeg != nPlaySeg)
{
void *pData=NULL,*pData2=NULL; DWORD cbLen=0,cbLen2=0;
nRet = IDirectSoundBuffer_Lock(lpSecB, nDSoundNextSeg*(nDSoundSegLen<<2), nDSoundSegLen<<2, &pData, &cbLen, &pData2, &cbLen2, 0);
if (nRet>=0 && pData!=NULL)
{
memcpy(pData, samples, nDSoundSegLen<<2);
}
if (nRet>=0) IDirectSoundBuffer_Unlock(lpSecB, pData, cbLen, pData2, 0);
if (m1sdr_Callback)
{
m1sdr_Callback(nDSoundSegLen, samples);
playtime++;
}
else
{
memset(samples, 0, nDSoundSegLen*4);
}
nDSoundNextSeg = nFollowingSeg;
WRAP_INC(nFollowingSeg)
}
End:
return;
}
INT16 m1sdr_Init(int sample_rate)
{
DSBUFFERDESC dsbuf;
WAVEFORMATEX format;
nDSoundSamRate = sample_rate;
lpDS = NULL;
lpPDSB = NULL;
lpSecB = NULL;
nDSoundSegLen=(nDSoundSamRate*10+(nDSoundFps>>1))/nDSoundFps;
cbLoopLen=(nDSoundSegLen*nDSoundSegCount)<<2;
if (DS_OK != DirectSoundCreate(NULL, &lpDS, NULL))
{
printf("Unable to create DirectSound object!\n");
return(0);
}
if (DS_OK != IDirectSound_SetCooperativeLevel(lpDS, GetForegroundWindow(), DSSCL_PRIORITY))
{
printf("Unable to set cooperative level!\n");
return(0);
}
memset(&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.wBitsPerSample = 16;
format.nSamplesPerSec = nDSoundSamRate;
format.nBlockAlign = 4; format.cbSize = 0;
format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
memset(&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpPDSB, NULL))
{
printf("Unable to create primary buffer!");
return(0);
}
if (DS_OK != IDirectSoundBuffer_SetFormat(lpPDSB, &format))
{
printf("Unable to set primary buffer format!\n");
return(0);
}
IDirectSoundBuffer_Play(lpPDSB, 0, 0, DSBPLAY_LOOPING);
memset(&dsbuf, 0, sizeof(DSBUFFERDESC));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
dsbuf.dwBufferBytes = cbLoopLen;
dsbuf.lpwfxFormat = (LPWAVEFORMATEX)&format;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpSecB, NULL))
{
printf("Unable to create secondary buffer\n");
return(0);
}
{
LPVOID ptr; DWORD len;
IDirectSoundBuffer_Lock(lpSecB, 0, 0, &ptr, &len, NULL, NULL, DSBLOCK_ENTIREBUFFER);
ZeroMemory(ptr, len);
IDirectSoundBuffer_Unlock(lpSecB, ptr, len, 0, 0);
}
ZeroMemory(samples, nDSoundSegLen<<2);
bDSoundOkay=1;
return(1);
}
void m1sdr_Exit(void)
{
if (lpSecB)
{
IDirectSoundBuffer_Stop(lpSecB);
IDirectSoundBuffer_Release(lpSecB);
lpSecB = NULL;
}
if (lpPDSB)
{
IDirectSoundBuffer_Stop(lpPDSB);
IDirectSoundBuffer_Release(lpPDSB);
lpPDSB = NULL;
}
if (lpDS)
{
IDirectSound_Release(lpDS);
lpDS = NULL;
}
}
void m1sdr_PlayStart(void)
{
IDirectSound_SetCooperativeLevel(lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
IDirectSoundBuffer_SetCurrentPosition(lpSecB, 0);
IDirectSoundBuffer_Play(lpSecB, 0, 0, DSBPLAY_LOOPING);
playtime = 0;
}
void m1sdr_PlayStop(void)
{
DSBUFFERDESC dsbuf;
WAVEFORMATEX format;
IDirectSoundBuffer_Stop(lpSecB);
IDirectSoundBuffer_Release(lpSecB);
memset(&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.wBitsPerSample = 16;
format.nSamplesPerSec = nDSoundSamRate;
format.nBlockAlign = 4; format.cbSize = 0;
format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
memset(&dsbuf, 0, sizeof(DSBUFFERDESC));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
dsbuf.dwBufferBytes = cbLoopLen;
dsbuf.lpwfxFormat = (LPWAVEFORMATEX)&format;
if (DS_OK != IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpSecB, NULL))
{
printf("Unable to create secondary buffer\n");
return;
}
{
LPVOID ptr; DWORD len;
IDirectSoundBuffer_Lock(lpSecB, 0, 0, &ptr, &len, NULL, NULL, DSBLOCK_ENTIREBUFFER);
ZeroMemory(ptr, len);
IDirectSoundBuffer_Unlock(lpSecB, ptr, len, 0, 0);
}
}
INT32 m1sdr_HwPresent(void)
{
return hw_present;
}
INT16 m1sdr_IsThere(void)
{
if(DS_OK == DirectSoundCreate(NULL, &lpDS, NULL))
{
IDirectSound_Release(lpDS);
hw_present = 1;
return(1);
}
else
{
hw_present = 0;
return(0);
}
}
void m1sdr_SetCallback(void *fn)
{
if (fn == (void *)NULL)
{
printf("ERROR: NULL CALLBACK!\n");
}
m1sdr_Callback = (void (*)(unsigned long, signed short *))fn;
}
void m1sdr_FlushAudio(void)
{
memset(samples, 0, nDSoundSegLen * 4);
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
m1sdr_TimeCheck();
}
short *m1sdr_GetSamples(void)
{
return samples;
}
int m1sdr_GetPlayTime(void)
{
int rv;
int fps = nDSoundFps / 10;
rv = playtime / fps;
return rv; }
int m1sdr_GetPlayTimeTicks(void)
{
return playtime;
}