comparison src/audio/windib/SDL_dibaudio.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents 84de7511f79f
children 4ad1e863d100
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
35 #include "win_ce_semaphore.h" 35 #include "win_ce_semaphore.h"
36 #endif 36 #endif
37 37
38 38
39 /* Audio driver functions */ 39 /* Audio driver functions */
40 static int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec); 40 static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec);
41 static void DIB_ThreadInit(_THIS); 41 static void DIB_ThreadInit(_THIS);
42 static void DIB_WaitAudio(_THIS); 42 static void DIB_WaitAudio(_THIS);
43 static Uint8 *DIB_GetAudioBuf(_THIS); 43 static Uint8 *DIB_GetAudioBuf(_THIS);
44 static void DIB_PlayAudio(_THIS); 44 static void DIB_PlayAudio(_THIS);
45 static void DIB_WaitDone(_THIS); 45 static void DIB_WaitDone(_THIS);
46 static void DIB_CloseAudio(_THIS); 46 static void DIB_CloseAudio(_THIS);
47 47
48 /* Audio driver bootstrap functions */ 48 /* Audio driver bootstrap functions */
49 49
50 static int Audio_Available(void) 50 static int
51 { 51 Audio_Available(void)
52 return(1); 52 {
53 } 53 return (1);
54 54 }
55 static void Audio_DeleteDevice(SDL_AudioDevice *device) 55
56 { 56 static void
57 SDL_free(device->hidden); 57 Audio_DeleteDevice(SDL_AudioDevice * device)
58 SDL_free(device); 58 {
59 } 59 SDL_free(device->hidden);
60 60 SDL_free(device);
61 static SDL_AudioDevice *Audio_CreateDevice(int devindex) 61 }
62 { 62
63 SDL_AudioDevice *this; 63 static SDL_AudioDevice *
64 64 Audio_CreateDevice(int devindex)
65 /* Initialize all variables that we clean on shutdown */ 65 {
66 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 66 SDL_AudioDevice *this;
67 if ( this ) { 67
68 SDL_memset(this, 0, (sizeof *this)); 68 /* Initialize all variables that we clean on shutdown */
69 this->hidden = (struct SDL_PrivateAudioData *) 69 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
70 SDL_malloc((sizeof *this->hidden)); 70 if (this) {
71 } 71 SDL_memset(this, 0, (sizeof *this));
72 if ( (this == NULL) || (this->hidden == NULL) ) { 72 this->hidden = (struct SDL_PrivateAudioData *)
73 SDL_OutOfMemory(); 73 SDL_malloc((sizeof *this->hidden));
74 if ( this ) { 74 }
75 SDL_free(this); 75 if ((this == NULL) || (this->hidden == NULL)) {
76 } 76 SDL_OutOfMemory();
77 return(0); 77 if (this) {
78 } 78 SDL_free(this);
79 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 79 }
80 80 return (0);
81 /* Set the function pointers */ 81 }
82 this->OpenAudio = DIB_OpenAudio; 82 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
83 this->ThreadInit = DIB_ThreadInit; 83
84 this->WaitAudio = DIB_WaitAudio; 84 /* Set the function pointers */
85 this->PlayAudio = DIB_PlayAudio; 85 this->OpenAudio = DIB_OpenAudio;
86 this->GetAudioBuf = DIB_GetAudioBuf; 86 this->ThreadInit = DIB_ThreadInit;
87 this->WaitDone = DIB_WaitDone; 87 this->WaitAudio = DIB_WaitAudio;
88 this->CloseAudio = DIB_CloseAudio; 88 this->PlayAudio = DIB_PlayAudio;
89 89 this->GetAudioBuf = DIB_GetAudioBuf;
90 this->free = Audio_DeleteDevice; 90 this->WaitDone = DIB_WaitDone;
91 91 this->CloseAudio = DIB_CloseAudio;
92 return this; 92
93 this->free = Audio_DeleteDevice;
94
95 return this;
93 } 96 }
94 97
95 AudioBootStrap WAVEOUT_bootstrap = { 98 AudioBootStrap WAVEOUT_bootstrap = {
96 "waveout", "Win95/98/NT/2000 WaveOut", 99 "waveout", "Win95/98/NT/2000 WaveOut",
97 Audio_Available, Audio_CreateDevice 100 Audio_Available, Audio_CreateDevice
98 }; 101 };
99 102
100 103
101 /* The Win32 callback for filling the WAVE device */ 104 /* The Win32 callback for filling the WAVE device */
102 static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, 105 static void CALLBACK
103 DWORD dwParam1, DWORD dwParam2) 106 FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
104 { 107 DWORD dwParam1, DWORD dwParam2)
105 SDL_AudioDevice *this = (SDL_AudioDevice *)dwInstance; 108 {
106 109 SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
107 /* Only service "buffer done playing" messages */ 110
108 if ( uMsg != WOM_DONE ) 111 /* Only service "buffer done playing" messages */
109 return; 112 if (uMsg != WOM_DONE)
110 113 return;
111 /* Signal that we are done playing a buffer */ 114
112 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 115 /* Signal that we are done playing a buffer */
113 ReleaseSemaphoreCE(audio_sem, 1, NULL); 116 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
114 #else 117 ReleaseSemaphoreCE(audio_sem, 1, NULL);
115 ReleaseSemaphore(audio_sem, 1, NULL); 118 #else
116 #endif 119 ReleaseSemaphore(audio_sem, 1, NULL);
117 } 120 #endif
118 121 }
119 static void SetMMerror(char *function, MMRESULT code) 122
120 { 123 static void
121 size_t len; 124 SetMMerror(char *function, MMRESULT code)
122 char errbuf[MAXERRORLENGTH]; 125 {
126 size_t len;
127 char errbuf[MAXERRORLENGTH];
123 #ifdef _WIN32_WCE 128 #ifdef _WIN32_WCE
124 wchar_t werrbuf[MAXERRORLENGTH]; 129 wchar_t werrbuf[MAXERRORLENGTH];
125 #endif 130 #endif
126 131
127 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); 132 SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
128 len = SDL_strlen(errbuf); 133 len = SDL_strlen(errbuf);
129 134
130 #ifdef _WIN32_WCE 135 #ifdef _WIN32_WCE
131 /* UNICODE version */ 136 /* UNICODE version */
132 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH-len); 137 waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
133 WideCharToMultiByte(CP_ACP,0,werrbuf,-1,errbuf+len,MAXERRORLENGTH-len,NULL,NULL); 138 WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
134 #else 139 MAXERRORLENGTH - len, NULL, NULL);
135 waveOutGetErrorText(code, errbuf+len, (UINT)(MAXERRORLENGTH-len)); 140 #else
136 #endif 141 waveOutGetErrorText(code, errbuf + len, (UINT) (MAXERRORLENGTH - len));
137 142 #endif
138 SDL_SetError("%s",errbuf); 143
144 SDL_SetError("%s", errbuf);
139 } 145 }
140 146
141 /* Set high priority for the audio thread */ 147 /* Set high priority for the audio thread */
142 static void DIB_ThreadInit(_THIS) 148 static void
143 { 149 DIB_ThreadInit(_THIS)
144 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 150 {
145 } 151 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
146 152 }
147 void DIB_WaitAudio(_THIS) 153
148 { 154 void
149 /* Wait for an audio chunk to finish */ 155 DIB_WaitAudio(_THIS)
150 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 156 {
151 WaitForSemaphoreCE(audio_sem, INFINITE); 157 /* Wait for an audio chunk to finish */
152 #else 158 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
153 WaitForSingleObject(audio_sem, INFINITE); 159 WaitForSemaphoreCE(audio_sem, INFINITE);
154 #endif 160 #else
155 } 161 WaitForSingleObject(audio_sem, INFINITE);
156 162 #endif
157 Uint8 *DIB_GetAudioBuf(_THIS) 163 }
158 { 164
159 Uint8 *retval; 165 Uint8 *
160 166 DIB_GetAudioBuf(_THIS)
161 retval = (Uint8 *)(wavebuf[next_buffer].lpData); 167 {
162 return retval; 168 Uint8 *retval;
163 } 169
164 170 retval = (Uint8 *) (wavebuf[next_buffer].lpData);
165 void DIB_PlayAudio(_THIS) 171 return retval;
166 { 172 }
167 /* Queue it up */ 173
168 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); 174 void
169 next_buffer = (next_buffer+1)%NUM_BUFFERS; 175 DIB_PlayAudio(_THIS)
170 } 176 {
171 177 /* Queue it up */
172 void DIB_WaitDone(_THIS) 178 waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0]));
173 { 179 next_buffer = (next_buffer + 1) % NUM_BUFFERS;
174 int i, left; 180 }
175 181
176 do { 182 void
177 left = NUM_BUFFERS; 183 DIB_WaitDone(_THIS)
178 for ( i=0; i<NUM_BUFFERS; ++i ) { 184 {
179 if ( wavebuf[i].dwFlags & WHDR_DONE ) { 185 int i, left;
180 --left; 186
181 } 187 do {
182 } 188 left = NUM_BUFFERS;
183 if ( left > 0 ) { 189 for (i = 0; i < NUM_BUFFERS; ++i) {
184 SDL_Delay(100); 190 if (wavebuf[i].dwFlags & WHDR_DONE) {
185 } 191 --left;
186 } while ( left > 0 ); 192 }
187 } 193 }
188 194 if (left > 0) {
189 void DIB_CloseAudio(_THIS) 195 SDL_Delay(100);
190 { 196 }
191 int i; 197 }
192 198 while (left > 0);
193 /* Close up audio */ 199 }
194 if ( audio_sem ) { 200
195 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 201 void
196 CloseSynchHandle(audio_sem); 202 DIB_CloseAudio(_THIS)
197 #else 203 {
198 CloseHandle(audio_sem); 204 int i;
199 #endif 205
200 } 206 /* Close up audio */
201 if ( sound ) { 207 if (audio_sem) {
202 waveOutClose(sound); 208 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
203 } 209 CloseSynchHandle(audio_sem);
204 210 #else
205 /* Clean up mixing buffers */ 211 CloseHandle(audio_sem);
206 for ( i=0; i<NUM_BUFFERS; ++i ) { 212 #endif
207 if ( wavebuf[i].dwUser != 0xFFFF ) { 213 }
208 waveOutUnprepareHeader(sound, &wavebuf[i], 214 if (sound) {
209 sizeof(wavebuf[i])); 215 waveOutClose(sound);
210 wavebuf[i].dwUser = 0xFFFF; 216 }
211 } 217
212 } 218 /* Clean up mixing buffers */
213 /* Free raw mixing buffer */ 219 for (i = 0; i < NUM_BUFFERS; ++i) {
214 if ( mixbuf != NULL ) { 220 if (wavebuf[i].dwUser != 0xFFFF) {
215 SDL_free(mixbuf); 221 waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
216 mixbuf = NULL; 222 wavebuf[i].dwUser = 0xFFFF;
217 } 223 }
218 } 224 }
219 225 /* Free raw mixing buffer */
220 int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec) 226 if (mixbuf != NULL) {
221 { 227 SDL_free(mixbuf);
222 MMRESULT result; 228 mixbuf = NULL;
223 int i; 229 }
224 WAVEFORMATEX waveformat; 230 }
225 231
226 /* Initialize the wavebuf structures for closing */ 232 int
227 sound = NULL; 233 DIB_OpenAudio(_THIS, SDL_AudioSpec * spec)
228 audio_sem = NULL; 234 {
229 for ( i = 0; i < NUM_BUFFERS; ++i ) 235 MMRESULT result;
230 wavebuf[i].dwUser = 0xFFFF; 236 int i;
231 mixbuf = NULL; 237 WAVEFORMATEX waveformat;
232 238
233 /* Set basic WAVE format parameters */ 239 /* Initialize the wavebuf structures for closing */
234 SDL_memset(&waveformat, 0, sizeof(waveformat)); 240 sound = NULL;
235 waveformat.wFormatTag = WAVE_FORMAT_PCM; 241 audio_sem = NULL;
236 242 for (i = 0; i < NUM_BUFFERS; ++i)
237 /* Determine the audio parameters from the AudioSpec */ 243 wavebuf[i].dwUser = 0xFFFF;
238 switch ( spec->format & 0xFF ) { 244 mixbuf = NULL;
239 case 8: 245
240 /* Unsigned 8 bit audio data */ 246 /* Set basic WAVE format parameters */
241 spec->format = AUDIO_U8; 247 SDL_memset(&waveformat, 0, sizeof(waveformat));
242 waveformat.wBitsPerSample = 8; 248 waveformat.wFormatTag = WAVE_FORMAT_PCM;
243 break; 249
244 case 16: 250 /* Determine the audio parameters from the AudioSpec */
245 /* Signed 16 bit audio data */ 251 switch (spec->format & 0xFF) {
246 spec->format = AUDIO_S16; 252 case 8:
247 waveformat.wBitsPerSample = 16; 253 /* Unsigned 8 bit audio data */
248 break; 254 spec->format = AUDIO_U8;
249 default: 255 waveformat.wBitsPerSample = 8;
250 SDL_SetError("Unsupported audio format"); 256 break;
251 return(-1); 257 case 16:
252 } 258 /* Signed 16 bit audio data */
253 waveformat.nChannels = spec->channels; 259 spec->format = AUDIO_S16;
254 waveformat.nSamplesPerSec = spec->freq; 260 waveformat.wBitsPerSample = 16;
255 waveformat.nBlockAlign = 261 break;
256 waveformat.nChannels * (waveformat.wBitsPerSample/8); 262 default:
257 waveformat.nAvgBytesPerSec = 263 SDL_SetError("Unsupported audio format");
258 waveformat.nSamplesPerSec * waveformat.nBlockAlign; 264 return (-1);
259 265 }
260 /* Check the buffer size -- minimum of 1/4 second (word aligned) */ 266 waveformat.nChannels = spec->channels;
261 if ( spec->samples < (spec->freq/4) ) 267 waveformat.nSamplesPerSec = spec->freq;
262 spec->samples = ((spec->freq/4)+3)&~3; 268 waveformat.nBlockAlign =
263 269 waveformat.nChannels * (waveformat.wBitsPerSample / 8);
264 /* Update the fragment size as size in bytes */ 270 waveformat.nAvgBytesPerSec =
265 SDL_CalculateAudioSpec(spec); 271 waveformat.nSamplesPerSec * waveformat.nBlockAlign;
266 272
267 /* Open the audio device */ 273 /* Check the buffer size -- minimum of 1/4 second (word aligned) */
268 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, 274 if (spec->samples < (spec->freq / 4))
269 (DWORD_PTR)FillSound, (DWORD_PTR)this, CALLBACK_FUNCTION); 275 spec->samples = ((spec->freq / 4) + 3) & ~3;
270 if ( result != MMSYSERR_NOERROR ) { 276
271 SetMMerror("waveOutOpen()", result); 277 /* Update the fragment size as size in bytes */
272 return(-1); 278 SDL_CalculateAudioSpec(spec);
273 } 279
274 280 /* Open the audio device */
281 result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat,
282 (DWORD_PTR) FillSound, (DWORD_PTR) this,
283 CALLBACK_FUNCTION);
284 if (result != MMSYSERR_NOERROR) {
285 SetMMerror("waveOutOpen()", result);
286 return (-1);
287 }
275 #ifdef SOUND_DEBUG 288 #ifdef SOUND_DEBUG
276 /* Check the sound device we retrieved */ 289 /* Check the sound device we retrieved */
277 { 290 {
278 WAVEOUTCAPS caps; 291 WAVEOUTCAPS caps;
279 292
280 result = waveOutGetDevCaps((UINT)sound, &caps, sizeof(caps)); 293 result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps));
281 if ( result != MMSYSERR_NOERROR ) { 294 if (result != MMSYSERR_NOERROR) {
282 SetMMerror("waveOutGetDevCaps()", result); 295 SetMMerror("waveOutGetDevCaps()", result);
283 return(-1); 296 return (-1);
284 } 297 }
285 printf("Audio device: %s\n", caps.szPname); 298 printf("Audio device: %s\n", caps.szPname);
286 } 299 }
287 #endif 300 #endif
288 301
289 /* Create the audio buffer semaphore */ 302 /* Create the audio buffer semaphore */
290 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 303 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
291 audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); 304 audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
292 #else 305 #else
293 audio_sem = CreateSemaphore(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); 306 audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
294 #endif 307 #endif
295 if ( audio_sem == NULL ) { 308 if (audio_sem == NULL) {
296 SDL_SetError("Couldn't create semaphore"); 309 SDL_SetError("Couldn't create semaphore");
297 return(-1); 310 return (-1);
298 } 311 }
299 312
300 /* Create the sound buffers */ 313 /* Create the sound buffers */
301 mixbuf = (Uint8 *)SDL_malloc(NUM_BUFFERS*spec->size); 314 mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size);
302 if ( mixbuf == NULL ) { 315 if (mixbuf == NULL) {
303 SDL_SetError("Out of memory"); 316 SDL_SetError("Out of memory");
304 return(-1); 317 return (-1);
305 } 318 }
306 for ( i = 0; i < NUM_BUFFERS; ++i ) { 319 for (i = 0; i < NUM_BUFFERS; ++i) {
307 SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); 320 SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i]));
308 wavebuf[i].lpData = (LPSTR) &mixbuf[i*spec->size]; 321 wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size];
309 wavebuf[i].dwBufferLength = spec->size; 322 wavebuf[i].dwBufferLength = spec->size;
310 wavebuf[i].dwFlags = WHDR_DONE; 323 wavebuf[i].dwFlags = WHDR_DONE;
311 result = waveOutPrepareHeader(sound, &wavebuf[i], 324 result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
312 sizeof(wavebuf[i])); 325 if (result != MMSYSERR_NOERROR) {
313 if ( result != MMSYSERR_NOERROR ) { 326 SetMMerror("waveOutPrepareHeader()", result);
314 SetMMerror("waveOutPrepareHeader()", result); 327 return (-1);
315 return(-1); 328 }
316 } 329 }
317 } 330
318 331 /* Ready to go! */
319 /* Ready to go! */ 332 next_buffer = 0;
320 next_buffer = 0; 333 return (0);
321 return(0); 334 }
322 } 335
336 /* vi: set ts=4 sw=4 expandtab: */