21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_WINMM 27 #include "../../core/windows/SDL_windows.h" 32 #include "../SDL_audio_c.h" 35 #ifndef WAVE_FORMAT_IEEE_FLOAT 36 #define WAVE_FORMAT_IEEE_FLOAT 0x0003 39 #define DETECT_DEV_IMPL(iscap, typ, capstyp) \ 40 static void DetectWave##typ##Devs(void) { \ 41 const UINT iscapture = iscap ? 1 : 0; \ 42 const UINT devcount = wave##typ##GetNumDevs(); \ 45 for (i = 0; i < devcount; i++) { \ 46 if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ 47 char *name = WIN_StringToUTF8(caps.szPname); \ 49 SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \ 56 DETECT_DEV_IMPL(
SDL_FALSE, Out, WAVEOUTCAPS)
57 DETECT_DEV_IMPL(
SDL_TRUE, In, WAVEINCAPS)
60 WINMM_DetectDevices(
void)
67 CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
68 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
77 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
83 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
84 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
93 ReleaseSemaphore(this->hidden->audio_sem, 1,
NULL);
97 SetMMerror(
char *
function, MMRESULT code)
100 char errbuf[MAXERRORLENGTH];
101 wchar_t werrbuf[MAXERRORLENGTH];
106 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
107 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
114 WINMM_WaitDevice(
_THIS)
117 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
121 WINMM_GetDeviceBuf(
_THIS)
123 return (
Uint8 *) (this->hidden->
124 wavebuf[this->hidden->next_buffer].lpData);
128 WINMM_PlayDevice(
_THIS)
131 waveOutWrite(this->hidden->hout,
132 &this->hidden->wavebuf[this->hidden->next_buffer],
133 sizeof(this->hidden->wavebuf[0]));
134 this->hidden->next_buffer = (this->hidden->next_buffer + 1) %
NUM_BUFFERS;
138 WINMM_WaitDone(
_THIS)
145 if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
156 WINMM_CloseDevice(
_THIS)
159 if (this->hidden !=
NULL) {
162 if (this->hidden->audio_sem) {
163 CloseHandle(this->hidden->audio_sem);
164 this->hidden->audio_sem = 0;
169 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
170 waveOutUnprepareHeader(this->hidden->hout,
171 &this->hidden->wavebuf[i],
172 sizeof(this->hidden->wavebuf[i]));
173 this->hidden->wavebuf[
i].dwUser = 0xFFFF;
179 this->hidden->mixbuf =
NULL;
181 if (this->hidden->hin) {
182 waveInClose(this->hidden->hin);
183 this->hidden->hin = 0;
186 if (this->hidden->hout) {
187 waveOutClose(this->hidden->hout);
188 this->hidden->hout = 0;
197 PrepWaveFormat(
_THIS, UINT devId, WAVEFORMATEX *pfmt,
const int iscapture)
202 pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
204 pfmt->wFormatTag = WAVE_FORMAT_PCM;
209 pfmt->nSamplesPerSec = this->
spec.
freq;
210 pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
211 pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
214 return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
216 return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
221 WINMM_OpenDevice(
_THIS,
void *handle,
const char *devname,
int iscapture)
224 int valid_datatype = 0;
226 WAVEFORMATEX waveformat;
227 UINT devId = WAVE_MAPPER;
230 if (handle !=
NULL) {
232 const size_t val = ((
size_t) handle) - 1;
239 if (this->hidden ==
NULL) {
242 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
246 this->hidden->wavebuf[i].dwUser = 0xFFFF;
251 while ((!valid_datatype) && (test_format)) {
252 switch (test_format) {
258 if (PrepWaveFormat(
this, devId, &waveformat, iscapture)) {
271 if (!valid_datatype) {
272 WINMM_CloseDevice(
this);
281 result = waveInOpen(&this->hidden->hin, devId, &waveformat,
282 (DWORD_PTR) CaptureSound, (DWORD_PTR)
this,
285 result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
286 (DWORD_PTR) FillSound, (DWORD_PTR)
this,
290 if (result != MMSYSERR_NOERROR) {
291 WINMM_CloseDevice(
this);
292 return SetMMerror(
"waveOutOpen()", result);
299 result = waveOutGetDevCaps((UINT) this->hidden->hout,
300 &caps,
sizeof(caps));
301 if (result != MMSYSERR_NOERROR) {
302 WINMM_CloseDevice(
this);
303 return SetMMerror(
"waveOutGetDevCaps()", result);
305 printf(
"Audio device: %s\n", caps.szPname);
310 this->hidden->audio_sem =
311 CreateSemaphore(
NULL, NUM_BUFFERS - 1, NUM_BUFFERS,
NULL);
312 if (this->hidden->audio_sem ==
NULL) {
313 WINMM_CloseDevice(
this);
318 this->hidden->mixbuf =
320 if (this->hidden->mixbuf ==
NULL) {
321 WINMM_CloseDevice(
this);
326 sizeof(this->hidden->wavebuf[i]));
327 this->hidden->wavebuf[
i].dwBufferLength = this->
spec.
size;
328 this->hidden->wavebuf[
i].dwFlags = WHDR_DONE;
329 this->hidden->wavebuf[
i].lpData =
330 (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
331 result = waveOutPrepareHeader(this->hidden->hout,
332 &this->hidden->wavebuf[i],
333 sizeof(this->hidden->wavebuf[i]));
334 if (result != MMSYSERR_NOERROR) {
335 WINMM_CloseDevice(
this);
336 return SetMMerror(
"waveOutPrepareHeader()", result);
360 "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)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
void(* CloseDevice)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
#define SDL_arraysize(array)