zenilib: zenilib/jni/external/sdl/src/audio/winmm/SDL_winmm.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_winmm.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22
23 #if SDL_AUDIO_DRIVER_WINMM
24
25 /* Allow access to a raw mixing buffer */
26
27 #include "../../core/windows/SDL_windows.h"
28 #include <mmsystem.h>
29
30 #include "SDL_timer.h"
31 #include "SDL_audio.h"
32 #include "../SDL_audio_c.h"
33 #include "SDL_winmm.h"
34
35 #ifndef WAVE_FORMAT_IEEE_FLOAT
36 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
37 #endif
38
39 #define DETECT_DEV_IMPL(typ, capstyp) \
40 static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
41 const UINT devcount = wave##typ##GetNumDevs(); \
42 capstyp caps; \
43 UINT i; \
44 for (i = 0; i < devcount; i++) { \
45 if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
46 char *name = WIN_StringToUTF8(caps.szPname); \
47 if (name != NULL) { \
48 addfn(name); \
49 SDL_free(name); \
50 } \
51 } \
52 } \
53 }
54
55 DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
56 DETECT_DEV_IMPL(In, WAVEINCAPS)
57
58 static void
59 WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
60 {
61 if (iscapture) {
62 DetectWaveInDevs(addfn);
63 } else {
64 DetectWaveOutDevs(addfn);
65 }
66 }
67
68 static void CALLBACK
69 CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
70 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
71 {
72 SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
73
74 /* Only service "buffer is filled" messages */
75 if (uMsg != WIM_DATA)
76 return;
77
78 /* Signal that we have a new buffer of data */
79 ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
80 }
81
82
83 /* The Win32 callback for filling the WAVE device */
84 static void CALLBACK
85 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
86 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
87 {
88 SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
89
90 /* Only service "buffer done playing" messages */
91 if (uMsg != WOM_DONE)
92 return;
93
94 /* Signal that we are done playing a buffer */
95 ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
96 }
97
98 static int
99 SetMMerror(char *function, MMRESULT code)
100 {
101 size_t len;
102 char errbuf[MAXERRORLENGTH];
103 wchar_t werrbuf[MAXERRORLENGTH];
104
105 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
106 len = SDL_strlen(errbuf);
107
108 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
109 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
110 MAXERRORLENGTH - len, NULL, NULL);
111
112 return SDL_SetError("%s", errbuf);
113 }
114
115 static void
116 WINMM_WaitDevice(_THIS)
117 {
118 /* Wait for an audio chunk to finish */
119 WaitForSingleObject(this->hidden->audio_sem, INFINITE);
120 }
121
122 static Uint8 *
123 WINMM_GetDeviceBuf(_THIS)
124 {
125 return (Uint8 *) (this->hidden->
126 wavebuf[this->hidden->next_buffer].lpData);
127 }
128
129 static void
130 WINMM_PlayDevice(_THIS)
131 {
132 /* Queue it up */
133 waveOutWrite(this->hidden->hout,
134 &this->hidden->wavebuf[this->hidden->next_buffer],
135 sizeof(this->hidden->wavebuf[0]));
136 this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
137 }
138
139 static void
140 WINMM_WaitDone(_THIS)
141 {
142 int i, left;
143
144 do {
145 left = NUM_BUFFERS;
146 for (i = 0; i < NUM_BUFFERS; ++i) {
147 if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
148 --left;
149 }
150 }
151 if (left > 0) {
152 SDL_Delay(100);
153 }
154 } while (left > 0);
155 }
156
157 static void
158 WINMM_CloseDevice(_THIS)
159 {
160 /* Close up audio */
161 if (this->hidden != NULL) {
162 int i;
163
164 if (this->hidden->audio_sem) {
165 CloseHandle(this->hidden->audio_sem);
166 this->hidden->audio_sem = 0;
167 }
168
169 /* Clean up mixing buffers */
170 for (i = 0; i < NUM_BUFFERS; ++i) {
171 if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
172 waveOutUnprepareHeader(this->hidden->hout,
173 &this->hidden->wavebuf[i],
174 sizeof(this->hidden->wavebuf[i]));
175 this->hidden->wavebuf[i].dwUser = 0xFFFF;
176 }
177 }
178
179 /* Free raw mixing buffer */
180 SDL_free(this->hidden->mixbuf);
181 this->hidden->mixbuf = NULL;
182
183 if (this->hidden->hin) {
184 waveInClose(this->hidden->hin);
185 this->hidden->hin = 0;
186 }
187
188 if (this->hidden->hout) {
189 waveOutClose(this->hidden->hout);
190 this->hidden->hout = 0;
191 }
192
193 SDL_free(this->hidden);
194 this->hidden = NULL;
195 }
196 }
197
198 static SDL_bool
199 PrepWaveFormat(_THIS, UINT_PTR devId, WAVEFORMATEX *pfmt, const int iscapture)
200 {
201 SDL_zerop(pfmt);
202
203 if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
204 pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
205 } else {
206 pfmt->wFormatTag = WAVE_FORMAT_PCM;
207 }
208 pfmt->wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
209
210 pfmt->nChannels = this->spec.channels;
211 pfmt->nSamplesPerSec = this->spec.freq;
212 pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
213 pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
214
215 if (iscapture) {
216 return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
217 } else {
218 return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
219 }
220 }
221
222 static int
223 WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
224 {
225 SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
226 int valid_datatype = 0;
227 MMRESULT result;
228 WAVEFORMATEX waveformat;
229 UINT_PTR devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
230 char *utf8 = NULL;
231 int i;
232
233 if (devname != NULL) { /* specific device requested? */
234 if (iscapture) {
235 const int devcount = (int) waveInGetNumDevs();
236 WAVEINCAPS caps;
237 for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
238 result = waveInGetDevCaps(i, &caps, sizeof (caps));
239 if (result != MMSYSERR_NOERROR)
240 continue;
241 else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
242 continue;
243 else if (SDL_strcmp(devname, utf8) == 0)
244 devId = (UINT_PTR) i;
245 SDL_free(utf8);
246 }
247 } else {
248 const int devcount = (int) waveOutGetNumDevs();
249 WAVEOUTCAPS caps;
250 for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
251 result = waveOutGetDevCaps(i, &caps, sizeof (caps));
252 if (result != MMSYSERR_NOERROR)
253 continue;
254 else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
255 continue;
256 else if (SDL_strcmp(devname, utf8) == 0)
257 devId = (UINT_PTR) i;
258 SDL_free(utf8);
259 }
260 }
261
262 if (devId == WAVE_MAPPER) {
263 return SDL_SetError("Requested device not found");
264 }
265 }
266
267 /* Initialize all variables that we clean on shutdown */
268 this->hidden = (struct SDL_PrivateAudioData *)
269 SDL_malloc((sizeof *this->hidden));
270 if (this->hidden == NULL) {
271 return SDL_OutOfMemory();
272 }
273 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
274
275 /* Initialize the wavebuf structures for closing */
276 for (i = 0; i < NUM_BUFFERS; ++i)
277 this->hidden->wavebuf[i].dwUser = 0xFFFF;
278
279 if (this->spec.channels > 2)
280 this->spec.channels = 2; /* !!! FIXME: is this right? */
281
282 /* Check the buffer size -- minimum of 1/4 second (word aligned) */
283 if (this->spec.samples < (this->spec.freq / 4))
284 this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
285
286 while ((!valid_datatype) && (test_format)) {
287 switch (test_format) {
288 case AUDIO_U8:
289 case AUDIO_S16:
290 case AUDIO_S32:
291 case AUDIO_F32:
292 this->spec.format = test_format;
293 if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
294 valid_datatype = 1;
295 } else {
296 test_format = SDL_NextAudioFormat();
297 }
298 break;
299
300 default:
301 test_format = SDL_NextAudioFormat();
302 break;
303 }
304 }
305
306 if (!valid_datatype) {
307 WINMM_CloseDevice(this);
308 return SDL_SetError("Unsupported audio format");
309 }
310
311 /* Update the fragment size as size in bytes */
312 SDL_CalculateAudioSpec(&this->spec);
313
314 /* Open the audio device */
315 if (iscapture) {
316 result = waveInOpen(&this->hidden->hin, devId, &waveformat,
317 (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
318 CALLBACK_FUNCTION);
319 } else {
320 result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
321 (DWORD_PTR) FillSound, (DWORD_PTR) this,
322 CALLBACK_FUNCTION);
323 }
324
325 if (result != MMSYSERR_NOERROR) {
326 WINMM_CloseDevice(this);
327 return SetMMerror("waveOutOpen()", result);
328 }
329 #ifdef SOUND_DEBUG
330 /* Check the sound device we retrieved */
331 {
332 WAVEOUTCAPS caps;
333
334 result = waveOutGetDevCaps((UINT) this->hidden->hout,
335 &caps, sizeof(caps));
336 if (result != MMSYSERR_NOERROR) {
337 WINMM_CloseDevice(this);
338 return SetMMerror("waveOutGetDevCaps()", result);
339 }
340 printf("Audio device: %s\n", caps.szPname);
341 }
342 #endif
343
344 /* Create the audio buffer semaphore */
345 this->hidden->audio_sem =
346 CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
347 if (this->hidden->audio_sem == NULL) {
348 WINMM_CloseDevice(this);
349 return SDL_SetError("Couldn't create semaphore");
350 }
351
352 /* Create the sound buffers */
353 this->hidden->mixbuf =
354 (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
355 if (this->hidden->mixbuf == NULL) {
356 WINMM_CloseDevice(this);
357 return SDL_OutOfMemory();
358 }
359 for (i = 0; i < NUM_BUFFERS; ++i) {
360 SDL_memset(&this->hidden->wavebuf[i], 0,
361 sizeof(this->hidden->wavebuf[i]));
362 this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
363 this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
364 this->hidden->wavebuf[i].lpData =
365 (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
366 result = waveOutPrepareHeader(this->hidden->hout,
367 &this->hidden->wavebuf[i],
368 sizeof(this->hidden->wavebuf[i]));
369 if (result != MMSYSERR_NOERROR) {
370 WINMM_CloseDevice(this);
371 return SetMMerror("waveOutPrepareHeader()", result);
372 }
373 }
374
375 return 0; /* Ready to go! */
376 }
377
378
379 static int
380 WINMM_Init(SDL_AudioDriverImpl * impl)
381 {
382 /* Set the function pointers */
383 impl->DetectDevices = WINMM_DetectDevices;
384 impl->OpenDevice = WINMM_OpenDevice;
385 impl->PlayDevice = WINMM_PlayDevice;
386 impl->WaitDevice = WINMM_WaitDevice;
387 impl->WaitDone = WINMM_WaitDone;
388 impl->GetDeviceBuf = WINMM_GetDeviceBuf;
389 impl->CloseDevice = WINMM_CloseDevice;
390
391 return 1; /* this audio target is available. */
392 }
393
394 AudioBootStrap WINMM_bootstrap = {
395 "winmm", "Windows Waveform Audio", WINMM_Init, 0
396 };
397
398 #endif /* SDL_AUDIO_DRIVER_WINMM */
399
400 /* vi: set ts=4 sw=4 expandtab: */
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:45
NUM_BUFFERS
#define NUM_BUFFERS
Definition: alstream.c:48
SDL_FirstAudioFormat
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1226
tWAVEFORMATEX::nChannels
WORD nChannels
Definition: audiodefs.h:43
SDL_AddAudioDevice
void(* SDL_AddAudioDevice)(const char *name)
Definition: SDL_sysaudio.h:34
left
GLint left
Definition: glew.h:7291
SDL_AudioDriverImpl::WaitDevice
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:41
NULL
#define NULL
Definition: ftobjs.h:61
SDL_snprintf
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
tWAVEFORMATEX::nAvgBytesPerSec
DWORD nAvgBytesPerSec
Definition: audiodefs.h:45
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:116
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:43
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
len
GLenum GLsizei len
Definition: glew.h:7035
SDL_AudioDriverImpl::WaitDone
void(* WaitDone)(_THIS)
Definition: SDL_sysaudio.h:44
UINT
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
if
if(!yyg->yy_init)
Definition: glslang_lex.cpp:1037
WINMM_bootstrap
AudioBootStrap WINMM_bootstrap
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:39
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
SDL_config.h
SDL_NextAudioFormat
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1238
SDL_AUDIO_ISFLOAT
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:42
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioDriverImpl::DetectDevices
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
Definition: SDL_sysaudio.h:38
AudioBootStrap
Definition: SDL_sysaudio.h:128
result
GLuint64EXT * result
Definition: glew.h:12708
int
int
Definition: SDL_systhread.c:37
SDL_winmm.h
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
tWAVEFORMATEX
Definition: audiodefs.h:40
SDL_AUDIO_BITSIZE
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
AUDIO_S32
#define AUDIO_S32
Definition: SDL_audio.h:105
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:36
SDL_Delay
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
Definition: SDL_systimer.c:70
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
WIN_StringToUTF8
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:41
tWAVEFORMATEX::nBlockAlign
WORD nBlockAlign
Definition: audiodefs.h:46
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_strcmp
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
Definition: SDL_string.c:910
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1247
WAVE_FORMAT_PCM
#define WAVE_FORMAT_PCM
Definition: makehrtf.c:177
tWAVEFORMATEX::nSamplesPerSec
DWORD nSamplesPerSec
Definition: audiodefs.h:44
SDL_strlen
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
Definition: SDL_string.c:389
code
Definition: inftrees.h:24
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT
Definition: winmm.c:34
tWAVEFORMATEX::wBitsPerSample
WORD wBitsPerSample
Definition: audiodefs.h:47
SDL_audio.h
SDL_AudioDevice
Definition: SDL_sysaudio.h:91
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
tWAVEFORMATEX::wFormatTag
WORD wFormatTag
Definition: audiodefs.h:42
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:255
AUDIO_S16
#define AUDIO_S16
Definition: SDL_audio.h:96
AUDIO_F32
#define AUDIO_F32
Definition: SDL_audio.h:114
i
int i
Definition: pngrutil.c:1377
SDL_timer.h