Mercurial > sdl-ios-xcode
annotate src/audio/windx5/SDL_dx5audio.c @ 641:df178851293b
Date: 28 Jun 2003 22:42:52 +0100
From: Alan Swanson
Subject: Re: [SDL] New XFree 4.3 Video Mode Patch
I have a wee amendment that moves the qsort in set_best_resolution
to only occur after failing to find an exact match only. This would
make absolutely sure we get a user set mode.
While I've never had any problems for my normal resolutions (1280x1024,
1024x768, 800x600 & 640,480) while closely examining the output from
qsort I've noticed it doesn't seem to sort the modes fully. These is
one definite wrong at 1152x768 and a few that just look wrong to me.
From a program (attached) I made to examine this more easily. X has
sorted its mode list using the same method as ours (plus frequency),
and our user modes get inserted without any other movement.
On the patch I've made I've also changed cmpmodes to sort on vertical
resolution and then horizontal. Ie vertical is now most significant
bit.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 28 Jun 2003 21:52:26 +0000 |
parents | a1284fd544aa |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
217
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Allow access to a raw mixing buffer */ | |
29 | |
30 #include <stdio.h> | |
31 | |
32 #include "SDL_types.h" | |
33 #include "SDL_error.h" | |
34 #include "SDL_timer.h" | |
35 #include "SDL_audio.h" | |
36 #include "SDL_audio_c.h" | |
37 #include "SDL_dx5audio.h" | |
38 | |
39 /* Define this if you want to use DirectX 6 DirectSoundNotify interface */ | |
40 //#define USE_POSITION_NOTIFY | |
41 | |
42 /* DirectX function pointers for audio */ | |
43 HRESULT (WINAPI *DSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); | |
44 | |
45 /* Audio driver functions */ | |
46 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
47 static void DX5_ThreadInit(_THIS); | |
48 static void DX5_WaitAudio_BusyWait(_THIS); | |
49 #ifdef USE_POSITION_NOTIFY | |
50 static void DX6_WaitAudio_EventWait(_THIS); | |
51 #endif | |
52 static void DX5_PlayAudio(_THIS); | |
53 static Uint8 *DX5_GetAudioBuf(_THIS); | |
54 static void DX5_WaitDone(_THIS); | |
55 static void DX5_CloseAudio(_THIS); | |
56 | |
57 /* Audio driver bootstrap functions */ | |
58 | |
59 static int Audio_Available(void) | |
60 { | |
61 HINSTANCE DSoundDLL; | |
62 int dsound_ok; | |
63 | |
64 /* Version check DSOUND.DLL (Is DirectX okay?) */ | |
65 dsound_ok = 0; | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
66 DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); |
0 | 67 if ( DSoundDLL != NULL ) { |
68 /* We just use basic DirectSound, we're okay */ | |
69 /* Yay! */ | |
70 /* Unfortunately, the sound drivers on NT have | |
71 higher latencies than the audio buffers used | |
72 by many SDL applications, so there are gaps | |
73 in the audio - it sounds terrible. Punt for now. | |
74 */ | |
75 OSVERSIONINFO ver; | |
76 ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); | |
77 GetVersionEx(&ver); | |
78 switch (ver.dwPlatformId) { | |
79 case VER_PLATFORM_WIN32_NT: | |
80 if ( ver.dwMajorVersion > 4 ) { | |
81 /* Win2K */ | |
82 dsound_ok = 1; | |
83 } else { | |
84 /* WinNT */ | |
85 dsound_ok = 0; | |
86 } | |
87 break; | |
88 default: | |
89 /* Win95 or Win98 */ | |
90 dsound_ok = 1; | |
91 break; | |
92 } | |
93 /* Now check for DirectX 5 or better - otherwise | |
94 * we will fail later in DX5_OpenAudio without a chance | |
95 * to fall back to the DIB driver. */ | |
96 if (dsound_ok) { | |
97 /* DirectSoundCaptureCreate was added in DX5 */ | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
98 if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) |
0 | 99 dsound_ok = 0; |
100 | |
101 } | |
102 /* Clean up.. */ | |
103 FreeLibrary(DSoundDLL); | |
104 } | |
105 return(dsound_ok); | |
106 } | |
107 | |
108 /* Functions for loading the DirectX functions dynamically */ | |
109 static HINSTANCE DSoundDLL = NULL; | |
110 | |
111 static void DX5_Unload(void) | |
112 { | |
113 if ( DSoundDLL != NULL ) { | |
114 FreeLibrary(DSoundDLL); | |
115 DSoundCreate = NULL; | |
116 DSoundDLL = NULL; | |
117 } | |
118 } | |
119 static int DX5_Load(void) | |
120 { | |
121 int status; | |
122 | |
123 DX5_Unload(); | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
124 DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); |
0 | 125 if ( DSoundDLL != NULL ) { |
126 DSoundCreate = (void *)GetProcAddress(DSoundDLL, | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
127 TEXT("DirectSoundCreate")); |
0 | 128 } |
129 if ( DSoundDLL && DSoundCreate ) { | |
130 status = 0; | |
131 } else { | |
132 DX5_Unload(); | |
133 status = -1; | |
134 } | |
135 return status; | |
136 } | |
137 | |
138 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
139 { | |
140 DX5_Unload(); | |
141 free(device->hidden); | |
142 free(device); | |
143 } | |
144 | |
145 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
146 { | |
147 SDL_AudioDevice *this; | |
148 | |
149 /* Load DirectX */ | |
150 if ( DX5_Load() < 0 ) { | |
151 return(NULL); | |
152 } | |
153 | |
154 /* Initialize all variables that we clean on shutdown */ | |
155 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
156 if ( this ) { | |
157 memset(this, 0, (sizeof *this)); | |
158 this->hidden = (struct SDL_PrivateAudioData *) | |
159 malloc((sizeof *this->hidden)); | |
160 } | |
161 if ( (this == NULL) || (this->hidden == NULL) ) { | |
162 SDL_OutOfMemory(); | |
163 if ( this ) { | |
164 free(this); | |
165 } | |
166 return(0); | |
167 } | |
168 memset(this->hidden, 0, (sizeof *this->hidden)); | |
169 | |
170 /* Set the function pointers */ | |
171 this->OpenAudio = DX5_OpenAudio; | |
172 this->ThreadInit = DX5_ThreadInit; | |
173 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
174 this->PlayAudio = DX5_PlayAudio; | |
175 this->GetAudioBuf = DX5_GetAudioBuf; | |
176 this->WaitDone = DX5_WaitDone; | |
177 this->CloseAudio = DX5_CloseAudio; | |
178 | |
179 this->free = Audio_DeleteDevice; | |
180 | |
181 return this; | |
182 } | |
183 | |
184 AudioBootStrap DSOUND_bootstrap = { | |
185 "dsound", "Win95/98/2000 DirectSound", | |
186 Audio_Available, Audio_CreateDevice | |
187 }; | |
188 | |
189 static void SetDSerror(const char *function, int code) | |
190 { | |
191 static const char *error; | |
453
a6fa62b1be09
Updated for embedded Visual C++ 4.0
Sam Lantinga <slouken@libsdl.org>
parents:
375
diff
changeset
|
192 static char errbuf[1024]; |
0 | 193 |
194 errbuf[0] = 0; | |
195 switch (code) { | |
196 case E_NOINTERFACE: | |
197 error = | |
198 "Unsupported interface\n-- Is DirectX 5.0 or later installed?"; | |
199 break; | |
200 case DSERR_ALLOCATED: | |
201 error = "Audio device in use"; | |
202 break; | |
203 case DSERR_BADFORMAT: | |
204 error = "Unsupported audio format"; | |
205 break; | |
206 case DSERR_BUFFERLOST: | |
207 error = "Mixing buffer was lost"; | |
208 break; | |
209 case DSERR_CONTROLUNAVAIL: | |
210 error = "Control requested is not available"; | |
211 break; | |
212 case DSERR_INVALIDCALL: | |
213 error = "Invalid call for the current state"; | |
214 break; | |
215 case DSERR_INVALIDPARAM: | |
216 error = "Invalid parameter"; | |
217 break; | |
218 case DSERR_NODRIVER: | |
219 error = "No audio device found"; | |
220 break; | |
221 case DSERR_OUTOFMEMORY: | |
222 error = "Out of memory"; | |
223 break; | |
224 case DSERR_PRIOLEVELNEEDED: | |
225 error = "Caller doesn't have priority"; | |
226 break; | |
227 case DSERR_UNSUPPORTED: | |
228 error = "Function not supported"; | |
229 break; | |
230 default: | |
231 sprintf(errbuf, "%s: Unknown DirectSound error: 0x%x", | |
232 function, code); | |
233 break; | |
234 } | |
235 if ( ! errbuf[0] ) { | |
236 sprintf(errbuf, "%s: %s", function, error); | |
237 } | |
238 SDL_SetError("%s", errbuf); | |
239 return; | |
240 } | |
241 | |
242 /* DirectSound needs to be associated with a window */ | |
243 static HWND mainwin = NULL; | |
244 /* */ | |
245 void DX5_SoundFocus(HWND hwnd) | |
246 { | |
247 mainwin = hwnd; | |
248 } | |
249 | |
250 static void DX5_ThreadInit(_THIS) | |
251 { | |
252 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); | |
253 } | |
254 | |
255 static void DX5_WaitAudio_BusyWait(_THIS) | |
256 { | |
257 DWORD status; | |
258 DWORD cursor, junk; | |
259 HRESULT result; | |
260 | |
261 /* Semi-busy wait, since we have no way of getting play notification | |
262 on a primary mixing buffer located in hardware (DirectX 5.0) | |
263 */ | |
264 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); | |
265 if ( result != DS_OK ) { | |
266 if ( result == DSERR_BUFFERLOST ) { | |
267 IDirectSoundBuffer_Restore(mixbuf); | |
268 } | |
269 #ifdef DEBUG_SOUND | |
270 SetDSerror("DirectSound GetCurrentPosition", result); | |
271 #endif | |
272 return; | |
273 } | |
274 cursor /= mixlen; | |
275 | |
276 while ( cursor == playing ) { | |
277 /* FIXME: find out how much time is left and sleep that long */ | |
278 SDL_Delay(10); | |
279 | |
280 /* Try to restore a lost sound buffer */ | |
281 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
282 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
283 IDirectSoundBuffer_Restore(mixbuf); | |
284 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
285 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
286 break; | |
287 } | |
288 } | |
289 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
290 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
291 if ( result == DS_OK ) { | |
292 continue; | |
293 } | |
294 #ifdef DEBUG_SOUND | |
295 SetDSerror("DirectSound Play", result); | |
296 #endif | |
297 return; | |
298 } | |
299 | |
300 /* Find out where we are playing */ | |
301 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
302 &cursor, &junk); | |
303 if ( result != DS_OK ) { | |
304 SetDSerror("DirectSound GetCurrentPosition", result); | |
305 return; | |
306 } | |
307 cursor /= mixlen; | |
308 } | |
309 } | |
310 | |
311 #ifdef USE_POSITION_NOTIFY | |
312 static void DX6_WaitAudio_EventWait(_THIS) | |
313 { | |
314 DWORD status; | |
315 HRESULT result; | |
316 | |
317 /* Try to restore a lost sound buffer */ | |
318 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
319 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
320 IDirectSoundBuffer_Restore(mixbuf); | |
321 IDirectSoundBuffer_GetStatus(mixbuf, &status); | |
322 if ( (status&DSBSTATUS_BUFFERLOST) ) { | |
323 return; | |
324 } | |
325 } | |
326 if ( ! (status&DSBSTATUS_PLAYING) ) { | |
327 result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); | |
328 if ( result != DS_OK ) { | |
329 #ifdef DEBUG_SOUND | |
330 SetDSerror("DirectSound Play", result); | |
331 #endif | |
332 return; | |
333 } | |
334 } | |
335 WaitForSingleObject(audio_event, INFINITE); | |
336 } | |
337 #endif /* USE_POSITION_NOTIFY */ | |
338 | |
339 static void DX5_PlayAudio(_THIS) | |
340 { | |
341 /* Unlock the buffer, allowing it to play */ | |
342 if ( locked_buf ) { | |
343 IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); | |
344 } | |
345 | |
346 } | |
347 | |
348 static Uint8 *DX5_GetAudioBuf(_THIS) | |
349 { | |
350 DWORD cursor, junk; | |
351 HRESULT result; | |
352 DWORD rawlen; | |
353 | |
354 /* Figure out which blocks to fill next */ | |
355 locked_buf = NULL; | |
356 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); | |
357 if ( result == DSERR_BUFFERLOST ) { | |
358 IDirectSoundBuffer_Restore(mixbuf); | |
359 result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, | |
360 &cursor, &junk); | |
361 } | |
362 if ( result != DS_OK ) { | |
363 SetDSerror("DirectSound GetCurrentPosition", result); | |
364 return(NULL); | |
365 } | |
366 cursor /= mixlen; | |
367 playing = cursor; | |
368 cursor = (cursor+1)%NUM_BUFFERS; | |
369 cursor *= mixlen; | |
370 | |
371 /* Lock the audio buffer */ | |
372 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
373 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
374 if ( result == DSERR_BUFFERLOST ) { | |
375 IDirectSoundBuffer_Restore(mixbuf); | |
376 result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, | |
377 (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); | |
378 } | |
379 if ( result != DS_OK ) { | |
380 SetDSerror("DirectSound Lock", result); | |
381 return(NULL); | |
382 } | |
383 return(locked_buf); | |
384 } | |
385 | |
386 static void DX5_WaitDone(_THIS) | |
387 { | |
388 Uint8 *stream; | |
389 | |
390 /* Wait for the playing chunk to finish */ | |
391 stream = this->GetAudioBuf(this); | |
392 if ( stream != NULL ) { | |
393 memset(stream, silence, mixlen); | |
394 this->PlayAudio(this); | |
395 } | |
396 this->WaitAudio(this); | |
397 | |
398 /* Stop the looping sound buffer */ | |
399 IDirectSoundBuffer_Stop(mixbuf); | |
400 } | |
401 | |
402 static void DX5_CloseAudio(_THIS) | |
403 { | |
404 if ( sound != NULL ) { | |
405 if ( mixbuf != NULL ) { | |
406 /* Clean up the audio buffer */ | |
407 IDirectSoundBuffer_Release(mixbuf); | |
408 mixbuf = NULL; | |
409 } | |
410 if ( audio_event != NULL ) { | |
411 CloseHandle(audio_event); | |
412 audio_event = NULL; | |
413 } | |
414 IDirectSound_Release(sound); | |
415 sound = NULL; | |
416 } | |
417 } | |
418 | |
469 | 419 #ifdef USE_PRIMARY_BUFFER |
0 | 420 /* This function tries to create a primary audio buffer, and returns the |
421 number of audio chunks available in the created buffer. | |
422 */ | |
423 static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, | |
424 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
425 { | |
426 HRESULT result; | |
427 DSBUFFERDESC format; | |
428 DSBCAPS caps; | |
429 int numchunks; | |
430 | |
431 /* Try to set primary mixing privileges */ | |
432 result = IDirectSound_SetCooperativeLevel(sndObj, focus, | |
433 DSSCL_WRITEPRIMARY); | |
434 if ( result != DS_OK ) { | |
435 #ifdef DEBUG_SOUND | |
436 SetDSerror("DirectSound SetCooperativeLevel", result); | |
437 #endif | |
438 return(-1); | |
439 } | |
440 | |
441 /* Try to create the primary buffer */ | |
442 memset(&format, 0, sizeof(format)); | |
443 format.dwSize = sizeof(format); | |
444 format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); | |
217
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
445 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 446 #ifdef USE_POSITION_NOTIFY |
447 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
448 #endif | |
449 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
450 if ( result != DS_OK ) { | |
451 #ifdef DEBUG_SOUND | |
452 SetDSerror("DirectSound CreateSoundBuffer", result); | |
453 #endif | |
454 return(-1); | |
455 } | |
456 | |
457 /* Check the size of the fragment buffer */ | |
458 memset(&caps, 0, sizeof(caps)); | |
459 caps.dwSize = sizeof(caps); | |
460 result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); | |
461 if ( result != DS_OK ) { | |
462 #ifdef DEBUG_SOUND | |
463 SetDSerror("DirectSound GetCaps", result); | |
464 #endif | |
465 IDirectSoundBuffer_Release(*sndbuf); | |
466 return(-1); | |
467 } | |
468 if ( (chunksize > caps.dwBufferBytes) || | |
469 ((caps.dwBufferBytes%chunksize) != 0) ) { | |
470 /* The primary buffer size is not a multiple of 'chunksize' | |
471 -- this hopefully doesn't happen when 'chunksize' is a | |
472 power of 2. | |
473 */ | |
474 IDirectSoundBuffer_Release(*sndbuf); | |
475 SDL_SetError( | |
476 "Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", | |
477 caps.dwBufferBytes, chunksize); | |
478 return(-1); | |
479 } | |
480 numchunks = (caps.dwBufferBytes/chunksize); | |
481 | |
482 /* Set the primary audio format */ | |
483 result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
484 if ( result != DS_OK ) { | |
485 #ifdef DEBUG_SOUND | |
486 SetDSerror("DirectSound SetFormat", result); | |
487 #endif | |
488 IDirectSoundBuffer_Release(*sndbuf); | |
489 return(-1); | |
490 } | |
491 return(numchunks); | |
492 } | |
469 | 493 #endif /* USE_PRIMARY_BUFFER */ |
0 | 494 |
495 /* This function tries to create a secondary audio buffer, and returns the | |
496 number of audio chunks available in the created buffer. | |
497 */ | |
498 static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, | |
499 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
500 { | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
501 const int numchunks = 2; |
0 | 502 HRESULT result; |
503 DSBUFFERDESC format; | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
504 LPVOID pvAudioPtr1, pvAudioPtr2; |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
505 DWORD dwAudioBytes1, dwAudioBytes2; |
0 | 506 |
507 /* Try to set primary mixing privileges */ | |
508 if ( focus ) { | |
509 result = IDirectSound_SetCooperativeLevel(sndObj, | |
510 focus, DSSCL_PRIORITY); | |
511 } else { | |
512 result = IDirectSound_SetCooperativeLevel(sndObj, | |
513 GetDesktopWindow(), DSSCL_NORMAL); | |
514 } | |
515 if ( result != DS_OK ) { | |
516 #ifdef DEBUG_SOUND | |
517 SetDSerror("DirectSound SetCooperativeLevel", result); | |
518 #endif | |
519 return(-1); | |
520 } | |
521 | |
522 /* Try to create the secondary buffer */ | |
523 memset(&format, 0, sizeof(format)); | |
524 format.dwSize = sizeof(format); | |
525 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; | |
526 #ifdef USE_POSITION_NOTIFY | |
527 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
528 #endif | |
529 if ( ! focus ) { | |
530 format.dwFlags |= DSBCAPS_GLOBALFOCUS; | |
217
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
531 } else { |
add626b825bb
Use the sticky focus flag so audio isn't muted when application is switched.
Sam Lantinga <slouken@libsdl.org>
parents:
118
diff
changeset
|
532 format.dwFlags |= DSBCAPS_STICKYFOCUS; |
0 | 533 } |
534 format.dwBufferBytes = numchunks*chunksize; | |
535 if ( (format.dwBufferBytes < DSBSIZE_MIN) || | |
536 (format.dwBufferBytes > DSBSIZE_MAX) ) { | |
537 SDL_SetError("Sound buffer size must be between %d and %d", | |
538 DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); | |
539 return(-1); | |
540 } | |
541 format.dwReserved = 0; | |
542 format.lpwfxFormat = wavefmt; | |
543 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
544 if ( result != DS_OK ) { | |
545 SetDSerror("DirectSound CreateSoundBuffer", result); | |
546 return(-1); | |
547 } | |
548 IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
549 | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
550 /* Silence the initial audio buffer */ |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
551 result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
552 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
553 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
554 DSBLOCK_ENTIREBUFFER); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
555 if ( result == DS_OK ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
556 if ( wavefmt->wBitsPerSample == 8 ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
557 memset(pvAudioPtr1, 0x80, dwAudioBytes1); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
558 } else { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
559 memset(pvAudioPtr1, 0x00, dwAudioBytes1); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
560 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
561 IDirectSoundBuffer_Unlock(*sndbuf, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
562 (LPVOID)pvAudioPtr1, dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
563 (LPVOID)pvAudioPtr2, dwAudioBytes2); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
564 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
565 |
0 | 566 /* We're ready to go */ |
567 return(numchunks); | |
568 } | |
569 | |
570 /* This function tries to set position notify events on the mixing buffer */ | |
571 #ifdef USE_POSITION_NOTIFY | |
572 static int CreateAudioEvent(_THIS) | |
573 { | |
574 LPDIRECTSOUNDNOTIFY notify; | |
575 DSBPOSITIONNOTIFY *notify_positions; | |
576 int i, retval; | |
577 HRESULT result; | |
578 | |
579 /* Default to fail on exit */ | |
580 retval = -1; | |
581 notify = NULL; | |
582 | |
583 /* Query for the interface */ | |
584 result = IDirectSoundBuffer_QueryInterface(mixbuf, | |
585 &IID_IDirectSoundNotify, (void *)¬ify); | |
586 if ( result != DS_OK ) { | |
587 goto done; | |
588 } | |
589 | |
590 /* Allocate the notify structures */ | |
591 notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS* | |
592 sizeof(*notify_positions)); | |
593 if ( notify_positions == NULL ) { | |
594 goto done; | |
595 } | |
596 | |
597 /* Create the notify event */ | |
598 audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); | |
599 if ( audio_event == NULL ) { | |
600 goto done; | |
601 } | |
602 | |
603 /* Set up the notify structures */ | |
604 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
605 notify_positions[i].dwOffset = i*mixlen; | |
606 notify_positions[i].hEventNotify = audio_event; | |
607 } | |
608 result = IDirectSoundNotify_SetNotificationPositions(notify, | |
609 NUM_BUFFERS, notify_positions); | |
610 if ( result == DS_OK ) { | |
611 retval = 0; | |
612 } | |
613 done: | |
614 if ( notify != NULL ) { | |
615 IDirectSoundNotify_Release(notify); | |
616 } | |
617 return(retval); | |
618 } | |
619 #endif /* USE_POSITION_NOTIFY */ | |
620 | |
621 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
622 { | |
623 HRESULT result; | |
624 WAVEFORMATEX waveformat; | |
625 | |
626 /* Set basic WAVE format parameters */ | |
627 memset(&waveformat, 0, sizeof(waveformat)); | |
628 waveformat.wFormatTag = WAVE_FORMAT_PCM; | |
629 | |
630 /* Determine the audio parameters from the AudioSpec */ | |
631 switch ( spec->format & 0xFF ) { | |
632 case 8: | |
633 /* Unsigned 8 bit audio data */ | |
634 spec->format = AUDIO_U8; | |
635 silence = 0x80; | |
636 waveformat.wBitsPerSample = 8; | |
637 break; | |
638 case 16: | |
639 /* Signed 16 bit audio data */ | |
640 spec->format = AUDIO_S16; | |
641 silence = 0x00; | |
642 waveformat.wBitsPerSample = 16; | |
643 break; | |
644 default: | |
645 SDL_SetError("Unsupported audio format"); | |
646 return(-1); | |
647 } | |
648 waveformat.nChannels = spec->channels; | |
649 waveformat.nSamplesPerSec = spec->freq; | |
650 waveformat.nBlockAlign = | |
651 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
652 waveformat.nAvgBytesPerSec = | |
653 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
654 | |
655 /* Update the fragment size as size in bytes */ | |
656 SDL_CalculateAudioSpec(spec); | |
657 | |
658 /* Open the audio device */ | |
659 result = DSoundCreate(NULL, &sound, NULL); | |
660 if ( result != DS_OK ) { | |
661 SetDSerror("DirectSoundCreate", result); | |
662 return(-1); | |
663 } | |
664 | |
665 /* Create the audio buffer to which we write */ | |
666 NUM_BUFFERS = -1; | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
667 #ifdef USE_PRIMARY_BUFFER |
0 | 668 if ( mainwin ) { |
669 NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, | |
670 &waveformat, spec->size); | |
671 } | |
375
17976f0f503f
Use secondary audio buffers to avoid problems on various soundcards
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
672 #endif /* USE_PRIMARY_BUFFER */ |
0 | 673 if ( NUM_BUFFERS < 0 ) { |
674 NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, | |
675 &waveformat, spec->size); | |
676 if ( NUM_BUFFERS < 0 ) { | |
677 return(-1); | |
678 } | |
679 #ifdef DEBUG_SOUND | |
680 fprintf(stderr, "Using secondary audio buffer\n"); | |
681 #endif | |
682 } | |
683 #ifdef DEBUG_SOUND | |
684 else | |
685 fprintf(stderr, "Using primary audio buffer\n"); | |
686 #endif | |
687 | |
688 /* The buffer will auto-start playing in DX5_WaitAudio() */ | |
689 playing = 0; | |
690 mixlen = spec->size; | |
691 | |
692 #ifdef USE_POSITION_NOTIFY | |
693 /* See if we can use DirectX 6 event notification */ | |
694 if ( CreateAudioEvent(this) == 0 ) { | |
695 this->WaitAudio = DX6_WaitAudio_EventWait; | |
696 } else { | |
697 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
698 } | |
699 #endif | |
700 return(0); | |
701 } | |
702 |