21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_WINMM 27 #include "../../core/windows/SDL_windows.h" 33 #include "../SDL_audio_c.h" 36 #ifndef WAVE_FORMAT_IEEE_FLOAT 37 #define WAVE_FORMAT_IEEE_FLOAT 0x0003 40 #define DETECT_DEV_IMPL(iscap, typ, capstyp) \ 41 static void DetectWave##typ##Devs(void) { \ 42 const UINT iscapture = iscap ? 1 : 0; \ 43 const UINT devcount = wave##typ##GetNumDevs(); \ 46 for (i = 0; i < devcount; i++) { \ 47 if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ 48 char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \ 50 SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \ 57 DETECT_DEV_IMPL(
SDL_FALSE, Out, WAVEOUTCAPS)
58 DETECT_DEV_IMPL(
SDL_TRUE, In, WAVEINCAPS)
61 WINMM_DetectDevices(
void)
68 CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
69 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
78 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
84 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
85 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
94 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
98 SetMMerror(
char *
function, MMRESULT code)
101 char errbuf[MAXERRORLENGTH];
102 wchar_t werrbuf[MAXERRORLENGTH];
107 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
108 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
115 WINMM_WaitDevice(
_THIS)
118 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
122 WINMM_GetDeviceBuf(
_THIS)
124 return (
Uint8 *) (this->hidden->
125 wavebuf[this->hidden->next_buffer].lpData);
129 WINMM_PlayDevice(
_THIS)
132 waveOutWrite(this->hidden->hout,
133 &this->hidden->wavebuf[this->hidden->next_buffer],
134 sizeof(this->hidden->wavebuf[0]));
135 this->hidden->next_buffer = (this->hidden->next_buffer + 1) %
NUM_BUFFERS;
139 WINMM_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
141 const int nextbuf = this->hidden->next_buffer;
147 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
150 SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
153 result = waveInAddBuffer(this->hidden->hin,
154 &this->hidden->wavebuf[nextbuf],
155 sizeof (this->hidden->wavebuf[nextbuf]));
156 if (result != MMSYSERR_NOERROR) {
161 this->hidden->next_buffer = (nextbuf + 1) %
NUM_BUFFERS;
166 WINMM_FlushCapture(
_THIS)
169 if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
170 const int nextbuf = this->hidden->next_buffer;
172 waveInAddBuffer(this->hidden->hin,
173 &this->hidden->wavebuf[nextbuf],
174 sizeof (this->hidden->wavebuf[nextbuf]));
175 this->hidden->next_buffer = (nextbuf + 1) %
NUM_BUFFERS;
180 WINMM_CloseDevice(
_THIS)
184 if (this->hidden->hout) {
185 waveOutReset(this->hidden->hout);
189 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
190 waveOutUnprepareHeader(this->hidden->hout,
191 &this->hidden->wavebuf[i],
192 sizeof (this->hidden->wavebuf[i]));
196 waveOutClose(this->hidden->hout);
199 if (this->hidden->hin) {
200 waveInReset(this->hidden->hin);
204 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
205 waveInUnprepareHeader(this->hidden->hin,
206 &this->hidden->wavebuf[i],
207 sizeof (this->hidden->wavebuf[i]));
210 waveInClose(this->hidden->hin);
213 if (this->hidden->audio_sem) {
214 CloseHandle(this->hidden->audio_sem);
222 PrepWaveFormat(
_THIS, UINT devId, WAVEFORMATEX *pfmt,
const int iscapture)
227 pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
229 pfmt->wFormatTag = WAVE_FORMAT_PCM;
234 pfmt->nSamplesPerSec = this->
spec.
freq;
235 pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
236 pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
239 return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
241 return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
246 WINMM_OpenDevice(
_THIS,
void *handle,
const char *devname,
int iscapture)
249 int valid_datatype = 0;
251 WAVEFORMATEX waveformat;
252 UINT devId = WAVE_MAPPER;
255 if (handle !=
NULL) {
257 const size_t val = ((
size_t) handle) - 1;
264 if (this->hidden ==
NULL) {
271 this->hidden->wavebuf[i].dwUser = 0xFFFF;
276 while ((!valid_datatype) && (test_format)) {
277 switch (test_format) {
283 if (PrepWaveFormat(
this, devId, &waveformat, iscapture)) {
296 if (!valid_datatype) {
305 result = waveInOpen(&this->hidden->hin, devId, &waveformat,
306 (DWORD_PTR) CaptureSound, (DWORD_PTR)
this,
308 if (result != MMSYSERR_NOERROR) {
309 return SetMMerror(
"waveInOpen()", result);
312 result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
313 (DWORD_PTR) FillSound, (DWORD_PTR)
this,
315 if (result != MMSYSERR_NOERROR) {
316 return SetMMerror(
"waveOutOpen()", result);
325 result = waveInGetDevCaps((UINT) this->hidden->hout,
326 &caps, sizeof (caps));
327 if (result != MMSYSERR_NOERROR) {
328 return SetMMerror(
"waveInGetDevCaps()", result);
330 printf(
"Audio device: %s\n", caps.szPname);
333 result = waveOutGetDevCaps((UINT) this->hidden->hout,
334 &caps,
sizeof(caps));
335 if (result != MMSYSERR_NOERROR) {
336 return SetMMerror(
"waveOutGetDevCaps()", result);
338 printf(
"Audio device: %s\n", caps.szPname);
344 this->hidden->audio_sem =
345 CreateSemaphore(
NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS,
NULL);
346 if (this->hidden->audio_sem ==
NULL) {
351 this->hidden->mixbuf =
353 if (this->hidden->mixbuf ==
NULL) {
359 this->hidden->wavebuf[
i].dwBufferLength = this->
spec.
size;
360 this->hidden->wavebuf[
i].dwFlags = WHDR_DONE;
361 this->hidden->wavebuf[
i].lpData =
362 (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
365 result = waveInPrepareHeader(this->hidden->hin,
366 &this->hidden->wavebuf[i],
367 sizeof(this->hidden->wavebuf[i]));
368 if (result != MMSYSERR_NOERROR) {
369 return SetMMerror(
"waveInPrepareHeader()", result);
372 result = waveInAddBuffer(this->hidden->hin,
373 &this->hidden->wavebuf[i],
374 sizeof(this->hidden->wavebuf[i]));
375 if (result != MMSYSERR_NOERROR) {
376 return SetMMerror(
"waveInAddBuffer()", result);
379 result = waveOutPrepareHeader(this->hidden->hout,
380 &this->hidden->wavebuf[i],
381 sizeof(this->hidden->wavebuf[i]));
382 if (result != MMSYSERR_NOERROR) {
383 return SetMMerror(
"waveOutPrepareHeader()", result);
389 result = waveInStart(this->hidden->hin);
390 if (result != MMSYSERR_NOERROR) {
391 return SetMMerror(
"waveInStart()", result);
418 "winmm",
"Windows Waveform Audio", WINMM_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* DetectDevices)(void)
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
Uint16 SDL_AudioFormat
Audio format flags.
AudioBootStrap WINMM_bootstrap
SDL_AudioFormat SDL_NextAudioFormat(void)
#define SDL_AUDIO_ISFLOAT(x)
uint8_t Uint8
An unsigned 8-bit integer type.
#define SDL_AUDIO_BITSIZE(x)
#define SDL_static_cast(type, expression)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define SDL_assert(condition)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
void(* CloseDevice)(_THIS)
void(* FlushCapture)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
#define SDL_arraysize(array)