Mercurial > sdl-ios-xcode
annotate src/audio/windx5/SDL_dx5audio.c @ 172:37e3ca9254c7
Date: Sat, 8 Sep 2001 04:42:23 +0200
From: Max Horn <max@quendi.de>
Subject: SDL/OSX: Joystick; Better key handling
I just finished implementing improved keyhandling for OS X (in fact
the code should be easily ported to the "normal" MacOS part of SDL, I
just had no chance yet). Works like this:
First init the mapping table statically like before. Them, it queries
the OS for the "official" key table, then iterates over all 127
scancode and gets the associates ascii code. It ignores everythng
below 32 (has to, as it would lead to many problems if we did not...
e.g. both ESC and NUM LOCk produce an ascii code 27 on my keyboard),
and all stuff above 127 is mapped to SDLK_WORLD_* simply in the order
it is encountered.
In addition, caps lock is now working, too.
The code work flawless for me, but since I only have one keyboard, I
may have not encountered some serious problem... but I am pretty
confident that it is better than the old code in most cases.
The joystick driver works fine for me, too. I think it can be added
to CVS already. It would simply be helpful if more people would test
it. Hm, I wonder if Maelstrom or GLTron has Joystick support? That
would be a wonderful test application :)
I also took the liberty of modifying some text files like BUGS,
README.CVS, README.MacOSX (which now contains the OS X docs I long
promised)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 11 Sep 2001 19:00:18 +0000 |
parents | 7c47e511459d |
children | add626b825bb |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
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 | |
20 slouken@devolution.com | |
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; | |
66 DSoundDLL = LoadLibrary("DSOUND.DLL"); | |
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 */ | |
98 if (!GetProcAddress(DSoundDLL, "DirectSoundCaptureCreate")) | |
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(); | |
124 DSoundDLL = LoadLibrary("DSOUND.DLL"); | |
125 if ( DSoundDLL != NULL ) { | |
126 DSoundCreate = (void *)GetProcAddress(DSoundDLL, | |
127 "DirectSoundCreate"); | |
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; | |
192 static char errbuf[BUFSIZ]; | |
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 | |
419 /* This function tries to create a primary audio buffer, and returns the | |
420 number of audio chunks available in the created buffer. | |
421 */ | |
422 static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, | |
423 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
424 { | |
425 HRESULT result; | |
426 DSBUFFERDESC format; | |
427 DSBCAPS caps; | |
428 int numchunks; | |
429 | |
430 /* Try to set primary mixing privileges */ | |
431 result = IDirectSound_SetCooperativeLevel(sndObj, focus, | |
432 DSSCL_WRITEPRIMARY); | |
433 if ( result != DS_OK ) { | |
434 #ifdef DEBUG_SOUND | |
435 SetDSerror("DirectSound SetCooperativeLevel", result); | |
436 #endif | |
437 return(-1); | |
438 } | |
439 | |
440 /* Try to create the primary buffer */ | |
441 memset(&format, 0, sizeof(format)); | |
442 format.dwSize = sizeof(format); | |
443 format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); | |
444 #ifdef USE_POSITION_NOTIFY | |
445 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
446 #endif | |
447 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
448 if ( result != DS_OK ) { | |
449 #ifdef DEBUG_SOUND | |
450 SetDSerror("DirectSound CreateSoundBuffer", result); | |
451 #endif | |
452 return(-1); | |
453 } | |
454 | |
455 /* Check the size of the fragment buffer */ | |
456 memset(&caps, 0, sizeof(caps)); | |
457 caps.dwSize = sizeof(caps); | |
458 result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); | |
459 if ( result != DS_OK ) { | |
460 #ifdef DEBUG_SOUND | |
461 SetDSerror("DirectSound GetCaps", result); | |
462 #endif | |
463 IDirectSoundBuffer_Release(*sndbuf); | |
464 return(-1); | |
465 } | |
466 if ( (chunksize > caps.dwBufferBytes) || | |
467 ((caps.dwBufferBytes%chunksize) != 0) ) { | |
468 /* The primary buffer size is not a multiple of 'chunksize' | |
469 -- this hopefully doesn't happen when 'chunksize' is a | |
470 power of 2. | |
471 */ | |
472 IDirectSoundBuffer_Release(*sndbuf); | |
473 SDL_SetError( | |
474 "Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", | |
475 caps.dwBufferBytes, chunksize); | |
476 return(-1); | |
477 } | |
478 numchunks = (caps.dwBufferBytes/chunksize); | |
479 | |
480 /* Set the primary audio format */ | |
481 result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
482 if ( result != DS_OK ) { | |
483 #ifdef DEBUG_SOUND | |
484 SetDSerror("DirectSound SetFormat", result); | |
485 #endif | |
486 IDirectSoundBuffer_Release(*sndbuf); | |
487 return(-1); | |
488 } | |
489 return(numchunks); | |
490 } | |
491 | |
492 /* This function tries to create a secondary audio buffer, and returns the | |
493 number of audio chunks available in the created buffer. | |
494 */ | |
495 static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, | |
496 LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) | |
497 { | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
498 const int numchunks = 2; |
0 | 499 HRESULT result; |
500 DSBUFFERDESC format; | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
501 LPVOID pvAudioPtr1, pvAudioPtr2; |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
502 DWORD dwAudioBytes1, dwAudioBytes2; |
0 | 503 |
504 /* Try to set primary mixing privileges */ | |
505 if ( focus ) { | |
506 result = IDirectSound_SetCooperativeLevel(sndObj, | |
507 focus, DSSCL_PRIORITY); | |
508 } else { | |
509 result = IDirectSound_SetCooperativeLevel(sndObj, | |
510 GetDesktopWindow(), DSSCL_NORMAL); | |
511 } | |
512 if ( result != DS_OK ) { | |
513 #ifdef DEBUG_SOUND | |
514 SetDSerror("DirectSound SetCooperativeLevel", result); | |
515 #endif | |
516 return(-1); | |
517 } | |
518 | |
519 /* Try to create the secondary buffer */ | |
520 memset(&format, 0, sizeof(format)); | |
521 format.dwSize = sizeof(format); | |
522 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; | |
523 #ifdef USE_POSITION_NOTIFY | |
524 format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; | |
525 #endif | |
526 if ( ! focus ) { | |
527 format.dwFlags |= DSBCAPS_GLOBALFOCUS; | |
528 } | |
529 format.dwBufferBytes = numchunks*chunksize; | |
530 if ( (format.dwBufferBytes < DSBSIZE_MIN) || | |
531 (format.dwBufferBytes > DSBSIZE_MAX) ) { | |
532 SDL_SetError("Sound buffer size must be between %d and %d", | |
533 DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); | |
534 return(-1); | |
535 } | |
536 format.dwReserved = 0; | |
537 format.lpwfxFormat = wavefmt; | |
538 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); | |
539 if ( result != DS_OK ) { | |
540 SetDSerror("DirectSound CreateSoundBuffer", result); | |
541 return(-1); | |
542 } | |
543 IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); | |
544 | |
118
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
545 /* Silence the initial audio buffer */ |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
546 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
|
547 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
548 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
549 DSBLOCK_ENTIREBUFFER); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
550 if ( result == DS_OK ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
551 if ( wavefmt->wBitsPerSample == 8 ) { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
552 memset(pvAudioPtr1, 0x80, dwAudioBytes1); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
553 } else { |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
554 memset(pvAudioPtr1, 0x00, dwAudioBytes1); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
555 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
556 IDirectSoundBuffer_Unlock(*sndbuf, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
557 (LPVOID)pvAudioPtr1, dwAudioBytes1, |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
558 (LPVOID)pvAudioPtr2, dwAudioBytes2); |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
559 } |
7c47e511459d
Fix noise when starting audio under DX5 (thanks Jesse!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
560 |
0 | 561 /* We're ready to go */ |
562 return(numchunks); | |
563 } | |
564 | |
565 /* This function tries to set position notify events on the mixing buffer */ | |
566 #ifdef USE_POSITION_NOTIFY | |
567 static int CreateAudioEvent(_THIS) | |
568 { | |
569 LPDIRECTSOUNDNOTIFY notify; | |
570 DSBPOSITIONNOTIFY *notify_positions; | |
571 int i, retval; | |
572 HRESULT result; | |
573 | |
574 /* Default to fail on exit */ | |
575 retval = -1; | |
576 notify = NULL; | |
577 | |
578 /* Query for the interface */ | |
579 result = IDirectSoundBuffer_QueryInterface(mixbuf, | |
580 &IID_IDirectSoundNotify, (void *)¬ify); | |
581 if ( result != DS_OK ) { | |
582 goto done; | |
583 } | |
584 | |
585 /* Allocate the notify structures */ | |
586 notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS* | |
587 sizeof(*notify_positions)); | |
588 if ( notify_positions == NULL ) { | |
589 goto done; | |
590 } | |
591 | |
592 /* Create the notify event */ | |
593 audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); | |
594 if ( audio_event == NULL ) { | |
595 goto done; | |
596 } | |
597 | |
598 /* Set up the notify structures */ | |
599 for ( i=0; i<NUM_BUFFERS; ++i ) { | |
600 notify_positions[i].dwOffset = i*mixlen; | |
601 notify_positions[i].hEventNotify = audio_event; | |
602 } | |
603 result = IDirectSoundNotify_SetNotificationPositions(notify, | |
604 NUM_BUFFERS, notify_positions); | |
605 if ( result == DS_OK ) { | |
606 retval = 0; | |
607 } | |
608 done: | |
609 if ( notify != NULL ) { | |
610 IDirectSoundNotify_Release(notify); | |
611 } | |
612 return(retval); | |
613 } | |
614 #endif /* USE_POSITION_NOTIFY */ | |
615 | |
616 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
617 { | |
618 HRESULT result; | |
619 WAVEFORMATEX waveformat; | |
620 | |
621 /* Set basic WAVE format parameters */ | |
622 memset(&waveformat, 0, sizeof(waveformat)); | |
623 waveformat.wFormatTag = WAVE_FORMAT_PCM; | |
624 | |
625 /* Determine the audio parameters from the AudioSpec */ | |
626 switch ( spec->format & 0xFF ) { | |
627 case 8: | |
628 /* Unsigned 8 bit audio data */ | |
629 spec->format = AUDIO_U8; | |
630 silence = 0x80; | |
631 waveformat.wBitsPerSample = 8; | |
632 break; | |
633 case 16: | |
634 /* Signed 16 bit audio data */ | |
635 spec->format = AUDIO_S16; | |
636 silence = 0x00; | |
637 waveformat.wBitsPerSample = 16; | |
638 break; | |
639 default: | |
640 SDL_SetError("Unsupported audio format"); | |
641 return(-1); | |
642 } | |
643 waveformat.nChannels = spec->channels; | |
644 waveformat.nSamplesPerSec = spec->freq; | |
645 waveformat.nBlockAlign = | |
646 waveformat.nChannels * (waveformat.wBitsPerSample/8); | |
647 waveformat.nAvgBytesPerSec = | |
648 waveformat.nSamplesPerSec * waveformat.nBlockAlign; | |
649 | |
650 /* Update the fragment size as size in bytes */ | |
651 SDL_CalculateAudioSpec(spec); | |
652 | |
653 /* Open the audio device */ | |
654 result = DSoundCreate(NULL, &sound, NULL); | |
655 if ( result != DS_OK ) { | |
656 SetDSerror("DirectSoundCreate", result); | |
657 return(-1); | |
658 } | |
659 | |
660 /* Create the audio buffer to which we write */ | |
661 NUM_BUFFERS = -1; | |
662 if ( mainwin ) { | |
663 NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, | |
664 &waveformat, spec->size); | |
665 } | |
666 if ( NUM_BUFFERS < 0 ) { | |
667 NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, | |
668 &waveformat, spec->size); | |
669 if ( NUM_BUFFERS < 0 ) { | |
670 return(-1); | |
671 } | |
672 #ifdef DEBUG_SOUND | |
673 fprintf(stderr, "Using secondary audio buffer\n"); | |
674 #endif | |
675 } | |
676 #ifdef DEBUG_SOUND | |
677 else | |
678 fprintf(stderr, "Using primary audio buffer\n"); | |
679 #endif | |
680 | |
681 /* The buffer will auto-start playing in DX5_WaitAudio() */ | |
682 playing = 0; | |
683 mixlen = spec->size; | |
684 | |
685 #ifdef USE_POSITION_NOTIFY | |
686 /* See if we can use DirectX 6 event notification */ | |
687 if ( CreateAudioEvent(this) == 0 ) { | |
688 this->WaitAudio = DX6_WaitAudio_EventWait; | |
689 } else { | |
690 this->WaitAudio = DX5_WaitAudio_BusyWait; | |
691 } | |
692 #endif | |
693 return(0); | |
694 } | |
695 |