Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
328 lines (281 loc) · 9.69 KB

SDL_dibaudio.c

File metadata and controls

328 lines (281 loc) · 9.69 KB
 
Apr 26, 2001
Apr 26, 2001
1
/*
Apr 8, 2011
Apr 8, 2011
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Apr 26, 2001
Apr 26, 2001
20
*/
Feb 21, 2006
Feb 21, 2006
21
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
22
23
24
/* Allow access to a raw mixing buffer */
Jan 25, 2011
Jan 25, 2011
25
#include "../../core/windows/SDL_windows.h"
Apr 26, 2001
Apr 26, 2001
26
27
28
#include <mmsystem.h>
#include "SDL_timer.h"
Feb 10, 2006
Feb 10, 2006
29
#include "SDL_audio.h"
Feb 16, 2006
Feb 16, 2006
30
#include "../SDL_audio_c.h"
Apr 26, 2001
Apr 26, 2001
31
#include "SDL_dibaudio.h"
May 23, 2001
May 23, 2001
32
33
34
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
#include "win_ce_semaphore.h"
#endif
Apr 26, 2001
Apr 26, 2001
35
Oct 17, 2006
Oct 17, 2006
36
37
38
39
40
41
42
#if defined(_WIN32_WCE)
#define WINDOWS_OS_NAME "Windows CE/PocketPC"
#elif defined(WIN64)
#define WINDOWS_OS_NAME "Win64"
#else
#define WINDOWS_OS_NAME "Win32"
#endif
Apr 26, 2001
Apr 26, 2001
43
44
/* The Win32 callback for filling the WAVE device */
Jul 10, 2006
Jul 10, 2006
45
46
47
static void CALLBACK
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
DWORD dwParam1, DWORD dwParam2)
Apr 26, 2001
Apr 26, 2001
48
{
Jul 10, 2006
Jul 10, 2006
49
SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
Apr 26, 2001
Apr 26, 2001
50
Jul 10, 2006
Jul 10, 2006
51
52
53
/* Only service "buffer done playing" messages */
if (uMsg != WOM_DONE)
return;
Apr 26, 2001
Apr 26, 2001
54
Jul 10, 2006
Jul 10, 2006
55
/* Signal that we are done playing a buffer */
May 23, 2001
May 23, 2001
56
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
Oct 17, 2006
Oct 17, 2006
57
ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
May 23, 2001
May 23, 2001
58
#else
Oct 17, 2006
Oct 17, 2006
59
ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
May 23, 2001
May 23, 2001
60
#endif
Apr 26, 2001
Apr 26, 2001
61
62
}
Jul 10, 2006
Jul 10, 2006
63
64
static void
SetMMerror(char *function, MMRESULT code)
Apr 26, 2001
Apr 26, 2001
65
{
Jul 10, 2006
Jul 10, 2006
66
67
68
size_t len;
char errbuf[MAXERRORLENGTH];
wchar_t werrbuf[MAXERRORLENGTH];
Apr 26, 2001
Apr 26, 2001
69
Jul 10, 2006
Jul 10, 2006
70
71
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
len = SDL_strlen(errbuf);
May 23, 2001
May 23, 2001
72
Jul 10, 2006
Jul 10, 2006
73
74
75
waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
MAXERRORLENGTH - len, NULL, NULL);
May 23, 2001
May 23, 2001
76
Jul 10, 2006
Jul 10, 2006
77
SDL_SetError("%s", errbuf);
Apr 26, 2001
Apr 26, 2001
78
79
80
}
/* Set high priority for the audio thread */
Jul 10, 2006
Jul 10, 2006
81
static void
Oct 17, 2006
Oct 17, 2006
82
WINWAVEOUT_ThreadInit(_THIS)
Apr 26, 2001
Apr 26, 2001
83
{
Jul 10, 2006
Jul 10, 2006
84
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
Apr 26, 2001
Apr 26, 2001
85
86
}
Jul 10, 2006
Jul 10, 2006
87
void
Oct 17, 2006
Oct 17, 2006
88
WINWAVEOUT_WaitDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
89
{
Jul 10, 2006
Jul 10, 2006
90
/* Wait for an audio chunk to finish */
May 23, 2001
May 23, 2001
91
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
Oct 17, 2006
Oct 17, 2006
92
WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
May 23, 2001
May 23, 2001
93
#else
Oct 17, 2006
Oct 17, 2006
94
WaitForSingleObject(this->hidden->audio_sem, INFINITE);
May 23, 2001
May 23, 2001
95
#endif
Apr 26, 2001
Apr 26, 2001
96
97
}
Jul 10, 2006
Jul 10, 2006
98
Uint8 *
Oct 17, 2006
Oct 17, 2006
99
WINWAVEOUT_GetDeviceBuf(_THIS)
Apr 26, 2001
Apr 26, 2001
100
{
Jan 10, 2009
Jan 10, 2009
101
102
return (Uint8 *) (this->hidden->
wavebuf[this->hidden->next_buffer].lpData);
Apr 26, 2001
Apr 26, 2001
103
104
}
Jul 10, 2006
Jul 10, 2006
105
void
Oct 17, 2006
Oct 17, 2006
106
WINWAVEOUT_PlayDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
107
{
Jul 10, 2006
Jul 10, 2006
108
/* Queue it up */
Oct 17, 2006
Oct 17, 2006
109
110
waveOutWrite(this->hidden->sound,
&this->hidden->wavebuf[this->hidden->next_buffer],
Oct 28, 2006
Oct 28, 2006
111
sizeof(this->hidden->wavebuf[0]));
Oct 17, 2006
Oct 17, 2006
112
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
Apr 26, 2001
Apr 26, 2001
113
114
}
Jul 10, 2006
Jul 10, 2006
115
void
Oct 17, 2006
Oct 17, 2006
116
WINWAVEOUT_WaitDone(_THIS)
Apr 26, 2001
Apr 26, 2001
117
{
Jul 10, 2006
Jul 10, 2006
118
119
120
121
122
int i, left;
do {
left = NUM_BUFFERS;
for (i = 0; i < NUM_BUFFERS; ++i) {
Oct 17, 2006
Oct 17, 2006
123
if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
Jul 10, 2006
Jul 10, 2006
124
125
126
127
128
129
--left;
}
}
if (left > 0) {
SDL_Delay(100);
}
Aug 27, 2008
Aug 27, 2008
130
} while (left > 0);
Apr 26, 2001
Apr 26, 2001
131
132
}
Jul 10, 2006
Jul 10, 2006
133
void
Oct 17, 2006
Oct 17, 2006
134
WINWAVEOUT_CloseDevice(_THIS)
Apr 26, 2001
Apr 26, 2001
135
{
Jul 10, 2006
Jul 10, 2006
136
/* Close up audio */
Oct 17, 2006
Oct 17, 2006
137
138
139
140
if (this->hidden != NULL) {
int i;
if (this->hidden->audio_sem) {
May 23, 2001
May 23, 2001
141
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
Oct 17, 2006
Oct 17, 2006
142
CloseSynchHandle(this->hidden->audio_sem);
May 23, 2001
May 23, 2001
143
#else
Oct 17, 2006
Oct 17, 2006
144
CloseHandle(this->hidden->audio_sem);
May 23, 2001
May 23, 2001
145
#endif
Oct 17, 2006
Oct 17, 2006
146
147
this->hidden->audio_sem = 0;
}
Jul 10, 2006
Jul 10, 2006
148
Oct 17, 2006
Oct 17, 2006
149
150
151
if (this->hidden->sound) {
waveOutClose(this->hidden->sound);
this->hidden->sound = 0;
Jul 10, 2006
Jul 10, 2006
152
}
Oct 17, 2006
Oct 17, 2006
153
154
155
156
157
158
/* Clean up mixing buffers */
for (i = 0; i < NUM_BUFFERS; ++i) {
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
waveOutUnprepareHeader(this->hidden->sound,
&this->hidden->wavebuf[i],
Oct 28, 2006
Oct 28, 2006
159
sizeof(this->hidden->wavebuf[i]));
Oct 17, 2006
Oct 17, 2006
160
161
162
163
164
165
166
167
168
169
170
171
this->hidden->wavebuf[i].dwUser = 0xFFFF;
}
}
if (this->hidden->mixbuf != NULL) {
/* Free raw mixing buffer */
SDL_free(this->hidden->mixbuf);
this->hidden->mixbuf = NULL;
}
SDL_free(this->hidden);
this->hidden = NULL;
Jul 10, 2006
Jul 10, 2006
172
}
Apr 26, 2001
Apr 26, 2001
173
174
}
Jul 10, 2006
Jul 10, 2006
175
int
Oct 17, 2006
Oct 17, 2006
176
WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
Apr 26, 2001
Apr 26, 2001
177
{
Oct 17, 2006
Oct 17, 2006
178
179
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
Jul 10, 2006
Jul 10, 2006
180
181
MMRESULT result;
WAVEFORMATEX waveformat;
Oct 17, 2006
Oct 17, 2006
182
183
184
185
int i;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
Oct 28, 2006
Oct 28, 2006
186
SDL_malloc((sizeof *this->hidden));
Oct 17, 2006
Oct 17, 2006
187
188
189
190
191
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
Jul 10, 2006
Jul 10, 2006
192
193
194
/* Initialize the wavebuf structures for closing */
for (i = 0; i < NUM_BUFFERS; ++i)
Oct 17, 2006
Oct 17, 2006
195
196
197
198
this->hidden->wavebuf[i].dwUser = 0xFFFF;
while ((!valid_datatype) && (test_format)) {
valid_datatype = 1;
Oct 18, 2006
Oct 18, 2006
199
this->spec.format = test_format;
Oct 17, 2006
Oct 17, 2006
200
switch (test_format) {
Oct 28, 2006
Oct 28, 2006
201
202
203
204
205
206
207
208
209
case AUDIO_U8:
case AUDIO_S16:
case AUDIO_S32:
break; /* valid. */
default:
valid_datatype = 0;
test_format = SDL_NextAudioFormat();
break;
Oct 17, 2006
Oct 17, 2006
210
211
212
213
214
215
216
217
}
}
if (!valid_datatype) {
WINWAVEOUT_CloseDevice(this);
SDL_SetError("Unsupported audio format");
return 0;
}
Jul 10, 2006
Jul 10, 2006
218
219
/* Set basic WAVE format parameters */
Oct 28, 2006
Oct 28, 2006
220
SDL_memset(&waveformat, '\0', sizeof(waveformat));
Jul 10, 2006
Jul 10, 2006
221
waveformat.wFormatTag = WAVE_FORMAT_PCM;
Oct 17, 2006
Oct 17, 2006
222
waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
Jul 10, 2006
Jul 10, 2006
223
Oct 17, 2006
Oct 17, 2006
224
if (this->spec.channels > 2)
Oct 28, 2006
Oct 28, 2006
225
this->spec.channels = 2; /* !!! FIXME: is this right? */
Oct 17, 2006
Oct 17, 2006
226
227
228
waveformat.nChannels = this->spec.channels;
waveformat.nSamplesPerSec = this->spec.freq;
Jul 10, 2006
Jul 10, 2006
229
230
231
232
233
234
waveformat.nBlockAlign =
waveformat.nChannels * (waveformat.wBitsPerSample / 8);
waveformat.nAvgBytesPerSec =
waveformat.nSamplesPerSec * waveformat.nBlockAlign;
/* Check the buffer size -- minimum of 1/4 second (word aligned) */
Oct 17, 2006
Oct 17, 2006
235
236
if (this->spec.samples < (this->spec.freq / 4))
this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
Jul 10, 2006
Jul 10, 2006
237
238
/* Update the fragment size as size in bytes */
Oct 17, 2006
Oct 17, 2006
239
SDL_CalculateAudioSpec(&this->spec);
Jul 10, 2006
Jul 10, 2006
240
241
/* Open the audio device */
Oct 17, 2006
Oct 17, 2006
242
result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
Jul 10, 2006
Jul 10, 2006
243
244
245
(DWORD_PTR) FillSound, (DWORD_PTR) this,
CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
Oct 17, 2006
Oct 17, 2006
246
WINWAVEOUT_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
247
SetMMerror("waveOutOpen()", result);
Oct 17, 2006
Oct 17, 2006
248
return 0;
Jul 10, 2006
Jul 10, 2006
249
}
Apr 26, 2001
Apr 26, 2001
250
#ifdef SOUND_DEBUG
Jul 10, 2006
Jul 10, 2006
251
252
253
254
/* Check the sound device we retrieved */
{
WAVEOUTCAPS caps;
Oct 17, 2006
Oct 17, 2006
255
256
result = waveOutGetDevCaps((UINT) this->hidden->sound,
&caps, sizeof(caps));
Jul 10, 2006
Jul 10, 2006
257
if (result != MMSYSERR_NOERROR) {
Oct 17, 2006
Oct 17, 2006
258
WINWAVEOUT_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
259
SetMMerror("waveOutGetDevCaps()", result);
Oct 17, 2006
Oct 17, 2006
260
return 0;
Jul 10, 2006
Jul 10, 2006
261
262
263
}
printf("Audio device: %s\n", caps.szPname);
}
Apr 26, 2001
Apr 26, 2001
264
265
#endif
Jul 10, 2006
Jul 10, 2006
266
/* Create the audio buffer semaphore */
Oct 28, 2006
Oct 28, 2006
267
this->hidden->audio_sem =
May 23, 2001
May 23, 2001
268
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
Oct 28, 2006
Oct 28, 2006
269
CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
May 23, 2001
May 23, 2001
270
#else
Oct 28, 2006
Oct 28, 2006
271
CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
May 23, 2001
May 23, 2001
272
#endif
Oct 17, 2006
Oct 17, 2006
273
274
if (this->hidden->audio_sem == NULL) {
WINWAVEOUT_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
275
SDL_SetError("Couldn't create semaphore");
Oct 17, 2006
Oct 17, 2006
276
return 0;
Jul 10, 2006
Jul 10, 2006
277
278
279
}
/* Create the sound buffers */
Oct 28, 2006
Oct 28, 2006
280
281
this->hidden->mixbuf =
(Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
Oct 18, 2006
Oct 18, 2006
282
if (this->hidden->mixbuf == NULL) {
Oct 17, 2006
Oct 17, 2006
283
284
285
WINWAVEOUT_CloseDevice(this);
SDL_OutOfMemory();
return 0;
Jul 10, 2006
Jul 10, 2006
286
287
}
for (i = 0; i < NUM_BUFFERS; ++i) {
Oct 17, 2006
Oct 17, 2006
288
SDL_memset(&this->hidden->wavebuf[i], '\0',
Oct 28, 2006
Oct 28, 2006
289
sizeof(this->hidden->wavebuf[i]));
Oct 17, 2006
Oct 17, 2006
290
291
292
this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
this->hidden->wavebuf[i].lpData =
Oct 28, 2006
Oct 28, 2006
293
(LPSTR) & this->hidden->mixbuf[i * this->spec.size];
Oct 17, 2006
Oct 17, 2006
294
295
result = waveOutPrepareHeader(this->hidden->sound,
&this->hidden->wavebuf[i],
Oct 28, 2006
Oct 28, 2006
296
sizeof(this->hidden->wavebuf[i]));
Jul 10, 2006
Jul 10, 2006
297
if (result != MMSYSERR_NOERROR) {
Oct 17, 2006
Oct 17, 2006
298
WINWAVEOUT_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
299
SetMMerror("waveOutPrepareHeader()", result);
Oct 17, 2006
Oct 17, 2006
300
return 0;
Jul 10, 2006
Jul 10, 2006
301
302
303
}
}
Oct 28, 2006
Oct 28, 2006
304
return 1; /* Ready to go! */
Apr 26, 2001
Apr 26, 2001
305
}
Jul 10, 2006
Jul 10, 2006
306
Oct 17, 2006
Oct 17, 2006
307
308
static int
Oct 28, 2006
Oct 28, 2006
309
WINWAVEOUT_Init(SDL_AudioDriverImpl * impl)
Oct 17, 2006
Oct 17, 2006
310
311
312
313
314
315
316
317
318
{
/* Set the function pointers */
impl->OpenDevice = WINWAVEOUT_OpenDevice;
impl->ThreadInit = WINWAVEOUT_ThreadInit;
impl->PlayDevice = WINWAVEOUT_PlayDevice;
impl->WaitDevice = WINWAVEOUT_WaitDevice;
impl->WaitDone = WINWAVEOUT_WaitDone;
impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
impl->CloseDevice = WINWAVEOUT_CloseDevice;
Oct 28, 2006
Oct 28, 2006
319
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */
Oct 17, 2006
Oct 17, 2006
320
Jan 26, 2010
Jan 26, 2010
321
return 1; /* this audio target is available. */
Oct 17, 2006
Oct 17, 2006
322
323
324
325
326
327
}
AudioBootStrap WINWAVEOUT_bootstrap = {
"waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0
};
Jul 10, 2006
Jul 10, 2006
328
/* vi: set ts=4 sw=4 expandtab: */