mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-20 22:16:49 +01:00
directsound: Implemented audio capture support.
This commit is contained in:
parent
21c7fe0060
commit
b78ec97496
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
/* Allow access to a raw mixing buffer */
|
/* Allow access to a raw mixing buffer */
|
||||||
|
|
||||||
|
#include "SDL_assert.h"
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
#include "SDL_loadso.h"
|
#include "SDL_loadso.h"
|
||||||
#include "SDL_audio.h"
|
#include "SDL_audio.h"
|
||||||
@ -36,11 +37,13 @@
|
|||||||
|
|
||||||
/* DirectX function pointers for audio */
|
/* DirectX function pointers for audio */
|
||||||
static void* DSoundDLL = NULL;
|
static void* DSoundDLL = NULL;
|
||||||
typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
|
typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
|
||||||
typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
|
typedef HRESULT (WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
|
||||||
typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
|
typedef HRESULT (WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
|
||||||
|
typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
|
||||||
static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
|
static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
|
||||||
static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
|
static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
|
||||||
|
static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 = NULL;
|
||||||
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
|
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -48,6 +51,7 @@ DSOUND_Unload(void)
|
|||||||
{
|
{
|
||||||
pDirectSoundCreate8 = NULL;
|
pDirectSoundCreate8 = NULL;
|
||||||
pDirectSoundEnumerateW = NULL;
|
pDirectSoundEnumerateW = NULL;
|
||||||
|
pDirectSoundCaptureCreate8 = NULL;
|
||||||
pDirectSoundCaptureEnumerateW = NULL;
|
pDirectSoundCaptureEnumerateW = NULL;
|
||||||
|
|
||||||
if (DSoundDLL != NULL) {
|
if (DSoundDLL != NULL) {
|
||||||
@ -76,6 +80,7 @@ DSOUND_Load(void)
|
|||||||
loaded = 1; /* will reset if necessary. */
|
loaded = 1; /* will reset if necessary. */
|
||||||
DSOUNDLOAD(DirectSoundCreate8);
|
DSOUNDLOAD(DirectSoundCreate8);
|
||||||
DSOUNDLOAD(DirectSoundEnumerateW);
|
DSOUNDLOAD(DirectSoundEnumerateW);
|
||||||
|
DSOUNDLOAD(DirectSoundCaptureCreate8);
|
||||||
DSOUNDLOAD(DirectSoundCaptureEnumerateW);
|
DSOUNDLOAD(DirectSoundCaptureEnumerateW);
|
||||||
#undef DSOUNDLOAD
|
#undef DSOUNDLOAD
|
||||||
|
|
||||||
@ -197,7 +202,7 @@ DSOUND_WaitDevice(_THIS)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
|
while ((cursor / this->spec.size) == this->hidden->lastchunk) {
|
||||||
/* FIXME: find out how much time is left and sleep that long */
|
/* FIXME: find out how much time is left and sleep that long */
|
||||||
SDL_Delay(1);
|
SDL_Delay(1);
|
||||||
|
|
||||||
@ -239,9 +244,8 @@ DSOUND_PlayDevice(_THIS)
|
|||||||
if (this->hidden->locked_buf) {
|
if (this->hidden->locked_buf) {
|
||||||
IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
|
IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
|
||||||
this->hidden->locked_buf,
|
this->hidden->locked_buf,
|
||||||
this->hidden->mixlen, NULL, 0);
|
this->spec.size, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint8 *
|
static Uint8 *
|
||||||
@ -265,7 +269,7 @@ DSOUND_GetDeviceBuf(_THIS)
|
|||||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
cursor /= this->hidden->mixlen;
|
cursor /= this->spec.size;
|
||||||
#ifdef DEBUG_SOUND
|
#ifdef DEBUG_SOUND
|
||||||
/* Detect audio dropouts */
|
/* Detect audio dropouts */
|
||||||
{
|
{
|
||||||
@ -281,17 +285,17 @@ DSOUND_GetDeviceBuf(_THIS)
|
|||||||
#endif
|
#endif
|
||||||
this->hidden->lastchunk = cursor;
|
this->hidden->lastchunk = cursor;
|
||||||
cursor = (cursor + 1) % this->hidden->num_buffers;
|
cursor = (cursor + 1) % this->hidden->num_buffers;
|
||||||
cursor *= this->hidden->mixlen;
|
cursor *= this->spec.size;
|
||||||
|
|
||||||
/* Lock the audio buffer */
|
/* Lock the audio buffer */
|
||||||
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
||||||
this->hidden->mixlen,
|
this->spec.size,
|
||||||
(LPVOID *) & this->hidden->locked_buf,
|
(LPVOID *) & this->hidden->locked_buf,
|
||||||
&rawlen, NULL, &junk, 0);
|
&rawlen, NULL, &junk, 0);
|
||||||
if (result == DSERR_BUFFERLOST) {
|
if (result == DSERR_BUFFERLOST) {
|
||||||
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
||||||
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
||||||
this->hidden->mixlen,
|
this->spec.size,
|
||||||
(LPVOID *) & this->
|
(LPVOID *) & this->
|
||||||
hidden->locked_buf, &rawlen, NULL,
|
hidden->locked_buf, &rawlen, NULL,
|
||||||
&junk, 0);
|
&junk, 0);
|
||||||
@ -310,7 +314,7 @@ DSOUND_WaitDone(_THIS)
|
|||||||
|
|
||||||
/* Wait for the playing chunk to finish */
|
/* Wait for the playing chunk to finish */
|
||||||
if (stream != NULL) {
|
if (stream != NULL) {
|
||||||
SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
|
SDL_memset(stream, this->spec.silence, this->spec.size);
|
||||||
DSOUND_PlayDevice(this);
|
DSOUND_PlayDevice(this);
|
||||||
}
|
}
|
||||||
DSOUND_WaitDevice(this);
|
DSOUND_WaitDevice(this);
|
||||||
@ -319,83 +323,106 @@ DSOUND_WaitDone(_THIS)
|
|||||||
IDirectSoundBuffer_Stop(this->hidden->mixbuf);
|
IDirectSoundBuffer_Stop(this->hidden->mixbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
DSOUND_CaptureFromDevice(_THIS, void *buffer, int buflen)
|
||||||
|
{
|
||||||
|
struct SDL_PrivateAudioData *h = this->hidden;
|
||||||
|
DWORD junk, cursor, ptr1len, ptr2len;
|
||||||
|
VOID *ptr1, *ptr2;
|
||||||
|
|
||||||
|
SDL_assert(buflen == this->spec.size);
|
||||||
|
|
||||||
|
while (SDL_TRUE) {
|
||||||
|
if (SDL_AtomicGet(&this->shutdown)) { /* in case the buffer froze... */
|
||||||
|
SDL_memset(buffer, this->spec.silence, buflen);
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((cursor / this->spec.size) == h->lastchunk) {
|
||||||
|
SDL_Delay(1); /* FIXME: find out how much time is left and sleep that long */
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IDirectSoundCaptureBuffer_Lock(h->capturebuf, h->lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_assert(ptr1len == this->spec.size);
|
||||||
|
SDL_assert(ptr2 == NULL);
|
||||||
|
SDL_assert(ptr2len == 0);
|
||||||
|
|
||||||
|
SDL_memcpy(buffer, ptr1, ptr1len);
|
||||||
|
|
||||||
|
if (IDirectSoundCaptureBuffer_Unlock(h->capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->lastchunk = (h->lastchunk + 1) % h->num_buffers;
|
||||||
|
|
||||||
|
return ptr1len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DSOUND_FlushCapture(_THIS)
|
||||||
|
{
|
||||||
|
struct SDL_PrivateAudioData *h = this->hidden;
|
||||||
|
DWORD junk, cursor;
|
||||||
|
if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) == DS_OK) {
|
||||||
|
h->lastchunk = cursor / this->spec.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DSOUND_CloseDevice(_THIS)
|
DSOUND_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
if (this->hidden->mixbuf != NULL) {
|
if (this->hidden->mixbuf != NULL) {
|
||||||
|
IDirectSoundBuffer_Stop(this->hidden->mixbuf);
|
||||||
IDirectSoundBuffer_Release(this->hidden->mixbuf);
|
IDirectSoundBuffer_Release(this->hidden->mixbuf);
|
||||||
}
|
}
|
||||||
if (this->hidden->sound != NULL) {
|
if (this->hidden->sound != NULL) {
|
||||||
IDirectSound_Release(this->hidden->sound);
|
IDirectSound_Release(this->hidden->sound);
|
||||||
}
|
}
|
||||||
|
if (this->hidden->capturebuf != NULL) {
|
||||||
|
IDirectSoundCaptureBuffer_Stop(this->hidden->capturebuf);
|
||||||
|
IDirectSoundCaptureBuffer_Release(this->hidden->capturebuf);
|
||||||
|
}
|
||||||
|
if (this->hidden->capture != NULL) {
|
||||||
|
IDirectSoundCapture_Release(this->hidden->capture);
|
||||||
|
}
|
||||||
SDL_free(this->hidden);
|
SDL_free(this->hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function tries to create a secondary audio buffer, and returns the
|
/* This function tries to create a secondary audio buffer, and returns the
|
||||||
number of audio chunks available in the created buffer.
|
number of audio chunks available in the created buffer. This is for
|
||||||
|
playback devices, not capture.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
CreateSecondary(_THIS, HWND focus)
|
CreateSecondary(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
|
||||||
{
|
{
|
||||||
LPDIRECTSOUND sndObj = this->hidden->sound;
|
LPDIRECTSOUND sndObj = this->hidden->sound;
|
||||||
LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
|
LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
|
||||||
Uint32 chunksize = this->spec.size;
|
|
||||||
const int numchunks = 8;
|
|
||||||
HRESULT result = DS_OK;
|
HRESULT result = DS_OK;
|
||||||
DSBUFFERDESC format;
|
DSBUFFERDESC format;
|
||||||
LPVOID pvAudioPtr1, pvAudioPtr2;
|
LPVOID pvAudioPtr1, pvAudioPtr2;
|
||||||
DWORD dwAudioBytes1, dwAudioBytes2;
|
DWORD dwAudioBytes1, dwAudioBytes2;
|
||||||
WAVEFORMATEX wfmt;
|
|
||||||
|
|
||||||
SDL_zero(wfmt);
|
|
||||||
|
|
||||||
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
|
||||||
wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
|
||||||
} else {
|
|
||||||
wfmt.wFormatTag = WAVE_FORMAT_PCM;
|
|
||||||
}
|
|
||||||
|
|
||||||
wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
|
||||||
wfmt.nChannels = this->spec.channels;
|
|
||||||
wfmt.nSamplesPerSec = this->spec.freq;
|
|
||||||
wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
|
|
||||||
wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
|
|
||||||
|
|
||||||
/* Try to set primary mixing privileges */
|
|
||||||
if (focus) {
|
|
||||||
result = IDirectSound_SetCooperativeLevel(sndObj,
|
|
||||||
focus, DSSCL_PRIORITY);
|
|
||||||
} else {
|
|
||||||
result = IDirectSound_SetCooperativeLevel(sndObj,
|
|
||||||
GetDesktopWindow(),
|
|
||||||
DSSCL_NORMAL);
|
|
||||||
}
|
|
||||||
if (result != DS_OK) {
|
|
||||||
return SetDSerror("DirectSound SetCooperativeLevel", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to create the secondary buffer */
|
/* Try to create the secondary buffer */
|
||||||
SDL_zero(format);
|
SDL_zero(format);
|
||||||
format.dwSize = sizeof(format);
|
format.dwSize = sizeof(format);
|
||||||
format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
||||||
if (!focus) {
|
format.dwFlags |= DSBCAPS_GLOBALFOCUS;
|
||||||
format.dwFlags |= DSBCAPS_GLOBALFOCUS;
|
format.dwBufferBytes = bufsize;
|
||||||
} else {
|
format.lpwfxFormat = wfmt;
|
||||||
format.dwFlags |= DSBCAPS_STICKYFOCUS;
|
|
||||||
}
|
|
||||||
format.dwBufferBytes = numchunks * chunksize;
|
|
||||||
if ((format.dwBufferBytes < DSBSIZE_MIN) ||
|
|
||||||
(format.dwBufferBytes > DSBSIZE_MAX)) {
|
|
||||||
return SDL_SetError("Sound buffer size must be between %d and %d",
|
|
||||||
DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
|
|
||||||
}
|
|
||||||
format.dwReserved = 0;
|
|
||||||
format.lpwfxFormat = &wfmt;
|
|
||||||
result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
|
result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
|
||||||
if (result != DS_OK) {
|
if (result != DS_OK) {
|
||||||
return SetDSerror("DirectSound CreateSoundBuffer", result);
|
return SetDSerror("DirectSound CreateSoundBuffer", result);
|
||||||
}
|
}
|
||||||
IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
|
IDirectSoundBuffer_SetFormat(*sndbuf, wfmt);
|
||||||
|
|
||||||
/* Silence the initial audio buffer */
|
/* Silence the initial audio buffer */
|
||||||
result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
|
result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
|
||||||
@ -410,17 +437,64 @@ CreateSecondary(_THIS, HWND focus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We're ready to go */
|
/* We're ready to go */
|
||||||
return (numchunks);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function tries to create a capture buffer, and returns the
|
||||||
|
number of audio chunks available in the created buffer. This is for
|
||||||
|
capture devices, not playback.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
CreateCaptureBuffer(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
|
||||||
|
{
|
||||||
|
LPDIRECTSOUNDCAPTURE capture = this->hidden->capture;
|
||||||
|
LPDIRECTSOUNDCAPTUREBUFFER *capturebuf = &this->hidden->capturebuf;
|
||||||
|
DSCBUFFERDESC format;
|
||||||
|
// DWORD junk, cursor;
|
||||||
|
HRESULT result;
|
||||||
|
|
||||||
|
SDL_zero(format);
|
||||||
|
format.dwSize = sizeof (format);
|
||||||
|
format.dwFlags = DSCBCAPS_WAVEMAPPED;
|
||||||
|
format.dwBufferBytes = bufsize;
|
||||||
|
format.lpwfxFormat = wfmt;
|
||||||
|
|
||||||
|
result = IDirectSoundCapture_CreateCaptureBuffer(capture, &format, capturebuf, NULL);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return SetDSerror("DirectSound CreateCaptureBuffer", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IDirectSoundCaptureBuffer_Start(*capturebuf, DSCBSTART_LOOPING);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
IDirectSoundCaptureBuffer_Release(*capturebuf);
|
||||||
|
return SetDSerror("DirectSound Start", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* presumably this starts at zero, but just in case... */
|
||||||
|
result = IDirectSoundCaptureBuffer_GetCurrentPosition(*capturebuf, &junk, &cursor);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
IDirectSoundCaptureBuffer_Stop(*capturebuf);
|
||||||
|
IDirectSoundCaptureBuffer_Release(*capturebuf);
|
||||||
|
return SetDSerror("DirectSound GetCurrentPosition", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hidden->lastchunk = cursor / this->spec.size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
{
|
{
|
||||||
|
const DWORD numchunks = 8;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
SDL_bool valid_format = SDL_FALSE;
|
SDL_bool valid_format = SDL_FALSE;
|
||||||
SDL_bool tried_format = SDL_FALSE;
|
SDL_bool tried_format = SDL_FALSE;
|
||||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||||
LPGUID guid = (LPGUID) handle;
|
LPGUID guid = (LPGUID) handle;
|
||||||
|
DWORD bufsize;
|
||||||
|
|
||||||
/* Initialize all variables that we clean on shutdown */
|
/* Initialize all variables that we clean on shutdown */
|
||||||
this->hidden = (struct SDL_PrivateAudioData *)
|
this->hidden = (struct SDL_PrivateAudioData *)
|
||||||
@ -431,9 +505,22 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||||||
SDL_zerop(this->hidden);
|
SDL_zerop(this->hidden);
|
||||||
|
|
||||||
/* Open the audio device */
|
/* Open the audio device */
|
||||||
result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
|
if (iscapture) {
|
||||||
if (result != DS_OK) {
|
result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture, NULL);
|
||||||
return SetDSerror("DirectSoundCreate", result);
|
if (result != DS_OK) {
|
||||||
|
return SetDSerror("DirectSoundCaptureCreate8", result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return SetDSerror("DirectSoundCreate8", result);
|
||||||
|
}
|
||||||
|
result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
|
||||||
|
GetDesktopWindow(),
|
||||||
|
DSSCL_NORMAL);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return SetDSerror("DirectSound SetCooperativeLevel", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((!valid_format) && (test_format)) {
|
while ((!valid_format) && (test_format)) {
|
||||||
@ -443,12 +530,38 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||||||
case AUDIO_S32:
|
case AUDIO_S32:
|
||||||
case AUDIO_F32:
|
case AUDIO_F32:
|
||||||
tried_format = SDL_TRUE;
|
tried_format = SDL_TRUE;
|
||||||
|
|
||||||
this->spec.format = test_format;
|
this->spec.format = test_format;
|
||||||
|
|
||||||
/* Update the fragment size as size in bytes */
|
/* Update the fragment size as size in bytes */
|
||||||
SDL_CalculateAudioSpec(&this->spec);
|
SDL_CalculateAudioSpec(&this->spec);
|
||||||
this->hidden->num_buffers = CreateSecondary(this, NULL);
|
|
||||||
if (this->hidden->num_buffers > 0) {
|
bufsize = numchunks * this->spec.size;
|
||||||
valid_format = SDL_TRUE;
|
if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) {
|
||||||
|
SDL_SetError("Sound buffer size must be between %d and %d",
|
||||||
|
(DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks,
|
||||||
|
DSBSIZE_MAX / numchunks);
|
||||||
|
} else {
|
||||||
|
int rc;
|
||||||
|
WAVEFORMATEX wfmt;
|
||||||
|
SDL_zero(wfmt);
|
||||||
|
if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
|
||||||
|
wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||||
|
} else {
|
||||||
|
wfmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
}
|
||||||
|
|
||||||
|
wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||||
|
wfmt.nChannels = this->spec.channels;
|
||||||
|
wfmt.nSamplesPerSec = this->spec.freq;
|
||||||
|
wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
|
||||||
|
wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
|
||||||
|
|
||||||
|
rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
|
||||||
|
if (rc == 0) {
|
||||||
|
this->hidden->num_buffers = numchunks;
|
||||||
|
valid_format = SDL_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -462,8 +575,7 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||||||
return SDL_SetError("DirectSound: Unsupported audio format");
|
return SDL_SetError("DirectSound: Unsupported audio format");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The buffer will auto-start playing in DSOUND_WaitDevice() */
|
/* Playback buffers will auto-start playing in DSOUND_WaitDevice() */
|
||||||
this->hidden->mixlen = this->spec.size;
|
|
||||||
|
|
||||||
return 0; /* good to go. */
|
return 0; /* good to go. */
|
||||||
}
|
}
|
||||||
@ -490,11 +602,14 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
|
|||||||
impl->WaitDevice = DSOUND_WaitDevice;
|
impl->WaitDevice = DSOUND_WaitDevice;
|
||||||
impl->WaitDone = DSOUND_WaitDone;
|
impl->WaitDone = DSOUND_WaitDone;
|
||||||
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
|
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
|
||||||
|
impl->CaptureFromDevice = DSOUND_CaptureFromDevice;
|
||||||
|
impl->FlushCapture = DSOUND_FlushCapture;
|
||||||
impl->CloseDevice = DSOUND_CloseDevice;
|
impl->CloseDevice = DSOUND_CloseDevice;
|
||||||
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
|
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
|
||||||
|
|
||||||
impl->Deinitialize = DSOUND_Deinitialize;
|
impl->Deinitialize = DSOUND_Deinitialize;
|
||||||
|
|
||||||
|
impl->HasCaptureSupport = SDL_TRUE;
|
||||||
|
|
||||||
return 1; /* this audio target is available. */
|
return 1; /* this audio target is available. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,9 @@ struct SDL_PrivateAudioData
|
|||||||
{
|
{
|
||||||
LPDIRECTSOUND sound;
|
LPDIRECTSOUND sound;
|
||||||
LPDIRECTSOUNDBUFFER mixbuf;
|
LPDIRECTSOUNDBUFFER mixbuf;
|
||||||
|
LPDIRECTSOUNDCAPTURE capture;
|
||||||
|
LPDIRECTSOUNDCAPTUREBUFFER capturebuf;
|
||||||
int num_buffers;
|
int num_buffers;
|
||||||
int mixlen;
|
|
||||||
DWORD lastchunk;
|
DWORD lastchunk;
|
||||||
Uint8 *locked_buf;
|
Uint8 *locked_buf;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user