engine/fteqtv/sp_dsound.c

252 lines
5.9 KiB
C

#include "qtv.h"
#ifdef COMMENTARY
#include <dsound.h>
static HANDLE hInstDS;
static HRESULT (WINAPI *pDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
typedef struct {
soundplay_t funcs;
LPDIRECTSOUND ds;
LPDIRECTSOUNDBUFFER dsbuf;
int buffersize;
int writepos;
int readpos;
int sampbytes;
} dsplay_t;
int DSOUND_UpdatePlayback(soundplay_t *sp, int samplechunks, char *buffer)
{
int ret;
dsplay_t *dsp = (dsplay_t*)sp;
char *sbuf;
int sbufsize;
int writable;
int remaining = samplechunks;
if (!samplechunks)
return 0;
IDirectSoundBuffer_GetCurrentPosition(dsp->dsbuf, &dsp->readpos, NULL);
dsp->readpos /= dsp->sampbytes;
while (ret = IDirectSoundBuffer_Lock(dsp->dsbuf, 0, dsp->buffersize*dsp->sampbytes, (void**)&sbuf, &sbufsize, NULL, NULL, 0))
{
if (!FAILED(ret))
break;
if (ret == DSERR_BUFFERLOST)
printf("Buffer lost\n");
else
break;
// if (FAILED(IDirectSoundBuffer_Resore(dsp->dsbuf)))
// return 0;
}
//memset(sbuf, 0, sbufsize);
writable = remaining;
if (writable > sbufsize/dsp->sampbytes - dsp->writepos)
writable = sbufsize/dsp->sampbytes - dsp->writepos;
memcpy(sbuf+dsp->writepos*dsp->sampbytes, buffer, writable*dsp->sampbytes);
remaining -= writable;
buffer += writable*dsp->sampbytes;
dsp->writepos += writable;
dsp->writepos %= dsp->buffersize;
if (samplechunks > 0)
{
writable = remaining;
if (writable > dsp->readpos)
writable = dsp->readpos;
memcpy(sbuf, buffer, writable*dsp->sampbytes);
remaining -= writable;
dsp->writepos += writable;
dsp->writepos %= dsp->buffersize;
}
IDirectSoundBuffer_Unlock(dsp->dsbuf, sbuf, sbufsize, NULL, 0);
printf("%i %i\n", 100*dsp->readpos / dsp->buffersize, 100*dsp->writepos / dsp->buffersize);
return samplechunks - remaining;
}
void DSOUND_Shutdown(soundplay_t *dsp)
{
}
soundplay_t *SND_InitPlayback(int speed, int bits)
{
int ret;
DSBCAPS caps;
DSBUFFERDESC bufdesc;
LPDIRECTSOUND ds;
dsplay_t *hnd;
WAVEFORMATEX format;
if (!hInstDS)
{
hInstDS = LoadLibrary("dsound.dll");
if (hInstDS == NULL)
{
printf ("Couldn't load dsound.dll\n");
return NULL;
}
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
printf ("Couldn't get DS proc addr\n");
return NULL;
}
// pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA");
}
ds = NULL;
pDirectSoundCreate(NULL, &ds, NULL);
if (!ds)
return NULL;
hnd = malloc(sizeof(*hnd));
memset(hnd, 0, sizeof(*hnd));
hnd->funcs.update = DSOUND_UpdatePlayback;
hnd->funcs.close = DSOUND_Shutdown;
hnd->ds = ds;
hnd->sampbytes = bits/8;
if (FAILED(IDirectSound_SetCooperativeLevel (hnd->ds, GetDesktopWindow(), DSSCL_EXCLUSIVE)))
printf("SetCooperativeLevel failed\n");
memset(&bufdesc, 0, sizeof(bufdesc));
bufdesc.dwSize = sizeof(bufdesc);
// bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS; //so we hear it if quake is loaded
bufdesc.dwFlags |= DSBCAPS_PRIMARYBUFFER; //so we can set speed
bufdesc.dwFlags |= DSBCAPS_CTRLVOLUME;
bufdesc.lpwfxFormat = NULL;
bufdesc.dwBufferBytes = 0;
format.wFormatTag = WAVE_FORMAT_PCM;
format.cbSize = 0;
format.nChannels = 1;
format.wBitsPerSample = bits;
format.nSamplesPerSec = speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);
if (!hnd->dsbuf)
{
printf("Couldn't create primary buffer\n");
DSOUND_Shutdown(&hnd->funcs);
return NULL;
}
if (FAILED(IDirectSoundBuffer_SetFormat(hnd->dsbuf, &format)))
printf("SetFormat failed\n");
//and now make a secondary buffer
bufdesc.dwFlags = 0;
bufdesc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
bufdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
bufdesc.dwFlags |= DSBCAPS_GLOBALFOCUS;
bufdesc.dwBufferBytes = speed * format.nChannels * hnd->sampbytes;
bufdesc.lpwfxFormat = &format;
ret = IDirectSound_CreateSoundBuffer(hnd->ds, &bufdesc, &hnd->dsbuf, NULL);
if (!hnd->dsbuf)
{
printf("Couldn't create secondary buffer\n");
DSOUND_Shutdown(&hnd->funcs);
return NULL;
}
memset(&caps, 0, sizeof(caps));
caps.dwSize = sizeof(caps);
IDirectSoundBuffer_GetCaps(hnd->dsbuf, &caps);
hnd->buffersize = caps.dwBufferBytes / hnd->sampbytes;
//clear out the buffer
{
char *buffer;
int buffersize=0;
IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
ret = IDirectSoundBuffer_Lock(hnd->dsbuf, 0, hnd->buffersize*hnd->sampbytes, (void**)&buffer, &buffersize, NULL, NULL, 0);
memset(buffer, 0, buffersize);
IDirectSoundBuffer_Unlock(hnd->dsbuf, buffer, buffersize, NULL, 0);
IDirectSoundBuffer_Stop(hnd->dsbuf);
}
//DSERR_INVALIDPARAM
IDirectSoundBuffer_Play(hnd->dsbuf, 0, 0, DSBPLAY_LOOPING);
IDirectSoundBuffer_GetCurrentPosition(hnd->dsbuf, &hnd->readpos, &hnd->writepos);
hnd->writepos = hnd->readpos + speed / 2; //position our write position a quater of a second infront of the read position
printf("%i %i\n", 100*hnd->readpos / hnd->buffersize, 100*hnd->writepos / hnd->buffersize);
return &hnd->funcs;
}
/*
void soundtest(void)
{
int speed = 22100*2;
int bits = 16;
int i;
int sampsavailable;
short buffer[1024];
soundcapt_t *capt;
soundplay_t *play;
capt = SND_InitCapture (speed, bits);
if (!capt)
{
printf("Failed to init capturer\n");
exit(0);
}
play = SND_InitPlayback (speed, bits);
if (!play)
{
printf("Failed to init playback\n");
exit(0);
}
for(;;)
{
for (i = 0; i < sizeof(buffer)/sizeof(buffer[0]); i++)
buffer[i] = rand();
sampsavailable = capt->update(capt, sizeof(buffer)/(bits/8), (char*)buffer);
play->update(play, sampsavailable, (char*)buffer);
Sleep(1);
}
}
*/
#endif