src/audio/windx5/SDL_dx5audio.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. HRESULT
  2. DX5_Unload
  3. DX5_Load
  4. Audio_DeleteDevice
  5. Audio_CreateDevice
  6. SetDSerror
  7. DX5_SoundFocus
  8. DX5_ThreadInit
  9. DX5_WaitAudio_BusyWait
  10. DX6_WaitAudio_EventWait
  11. DX5_PlayAudio
  12. DX5_GetAudioBuf
  13. DX5_WaitDone
  14. DX5_CloseAudio
  15. CreatePrimary
  16. CreateSecondary
  17. CreateAudioEvent
  18. DX5_OpenAudio

   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: SDL_dx5audio.c,v 1.1.2.2 2001/02/10 07:20:03 hercules Exp $";
  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);
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
 112 {
 113         if ( DSoundDLL != NULL ) {
 114                 FreeLibrary(DSoundDLL);
 115                 DSoundCreate = NULL;
 116                 DSoundDLL = NULL;
 117         }
 118 }
 119 static int DX5_Load(void)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 139 {
 140         DX5_Unload();
 141         free(device->hidden);
 142         free(device);
 143 }
 144 
 145 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 246 {
 247         mainwin = hwnd;
 248 }
 249 
 250 static void DX5_ThreadInit(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 251 {
 252         SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 253 }
 254 
 255 static void DX5_WaitAudio_BusyWait(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 496         LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize)
 497 {
 498         HRESULT result;
 499         DSBUFFERDESC format;
 500         const int numchunks = 2;
 501 
 502         /* Try to set primary mixing privileges */
 503         if ( focus ) {
 504                 result = IDirectSound_SetCooperativeLevel(sndObj,
 505                                         focus, DSSCL_PRIORITY);
 506         } else {
 507                 result = IDirectSound_SetCooperativeLevel(sndObj,
 508                                         GetDesktopWindow(), DSSCL_NORMAL);
 509         }
 510         if ( result != DS_OK ) {
 511 #ifdef DEBUG_SOUND
 512                 SetDSerror("DirectSound SetCooperativeLevel", result);
 513 #endif
 514                 return(-1);
 515         }
 516 
 517         /* Try to create the secondary buffer */
 518         memset(&format, 0, sizeof(format));
 519         format.dwSize = sizeof(format);
 520         format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
 521 #ifdef USE_POSITION_NOTIFY
 522         format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
 523 #endif
 524         if ( ! focus ) {
 525                 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
 526         }
 527         format.dwBufferBytes = numchunks*chunksize;
 528         if ( (format.dwBufferBytes < DSBSIZE_MIN) ||
 529              (format.dwBufferBytes > DSBSIZE_MAX) ) {
 530                 SDL_SetError("Sound buffer size must be between %d and %d",
 531                                 DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks);
 532                 return(-1);
 533         }
 534         format.dwReserved = 0;
 535         format.lpwfxFormat = wavefmt;
 536         result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
 537         if ( result != DS_OK ) {
 538                 SetDSerror("DirectSound CreateSoundBuffer", result);
 539                 return(-1);
 540         }
 541         IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
 542 
 543         /* We're ready to go */
 544         return(numchunks);
 545 }
 546 
 547 /* This function tries to set position notify events on the mixing buffer */
 548 #ifdef USE_POSITION_NOTIFY
 549 static int CreateAudioEvent(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 550 {
 551         LPDIRECTSOUNDNOTIFY notify;
 552         DSBPOSITIONNOTIFY *notify_positions;
 553         int i, retval;
 554         HRESULT result;
 555 
 556         /* Default to fail on exit */
 557         retval = -1;
 558         notify = NULL;
 559 
 560         /* Query for the interface */
 561         result = IDirectSoundBuffer_QueryInterface(mixbuf,
 562                         &IID_IDirectSoundNotify, (void *)&notify);
 563         if ( result != DS_OK ) {
 564                 goto done;
 565         }
 566 
 567         /* Allocate the notify structures */
 568         notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS*
 569                                         sizeof(*notify_positions));
 570         if ( notify_positions == NULL ) {
 571                 goto done;
 572         }
 573 
 574         /* Create the notify event */
 575         audio_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 576         if ( audio_event == NULL ) {
 577                 goto done;
 578         }
 579 
 580         /* Set up the notify structures */
 581         for ( i=0; i<NUM_BUFFERS; ++i ) {
 582                 notify_positions[i].dwOffset = i*mixlen;
 583                 notify_positions[i].hEventNotify = audio_event;
 584         }
 585         result = IDirectSoundNotify_SetNotificationPositions(notify,
 586                                         NUM_BUFFERS, notify_positions);
 587         if ( result == DS_OK ) {
 588                 retval = 0;
 589         }
 590 done:
 591         if ( notify != NULL ) {
 592                 IDirectSoundNotify_Release(notify);
 593         }
 594         return(retval);
 595 }
 596 #endif /* USE_POSITION_NOTIFY */
 597 
 598 static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec)
     /* [<][>][^][v][top][bottom][index][help] */
 599 {
 600         HRESULT      result;
 601         WAVEFORMATEX waveformat;
 602 
 603         /* Set basic WAVE format parameters */
 604         memset(&waveformat, 0, sizeof(waveformat));
 605         waveformat.wFormatTag = WAVE_FORMAT_PCM;
 606 
 607         /* Determine the audio parameters from the AudioSpec */
 608         switch ( spec->format & 0xFF ) {
 609                 case 8:
 610                         /* Unsigned 8 bit audio data */
 611                         spec->format = AUDIO_U8;
 612                         silence = 0x80;
 613                         waveformat.wBitsPerSample = 8;
 614                         break;
 615                 case 16:
 616                         /* Signed 16 bit audio data */
 617                         spec->format = AUDIO_S16;
 618                         silence = 0x00;
 619                         waveformat.wBitsPerSample = 16;
 620                         break;
 621                 default:
 622                         SDL_SetError("Unsupported audio format");
 623                         return(-1);
 624         }
 625         waveformat.nChannels = spec->channels;
 626         waveformat.nSamplesPerSec = spec->freq;
 627         waveformat.nBlockAlign =
 628                 waveformat.nChannels * (waveformat.wBitsPerSample/8);
 629         waveformat.nAvgBytesPerSec = 
 630                 waveformat.nSamplesPerSec * waveformat.nBlockAlign;
 631 
 632         /* Update the fragment size as size in bytes */
 633         SDL_CalculateAudioSpec(spec);
 634 
 635         /* Open the audio device */
 636         result = DSoundCreate(NULL, &sound, NULL);
 637         if ( result != DS_OK ) {
 638                 SetDSerror("DirectSoundCreate", result);
 639                 return(-1);
 640         }
 641 
 642         /* Create the audio buffer to which we write */
 643         NUM_BUFFERS = -1;
 644         if ( mainwin ) {
 645                 NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf,
 646                                                 &waveformat, spec->size);
 647         }
 648         if ( NUM_BUFFERS < 0 ) {
 649                 NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf,
 650                                                 &waveformat, spec->size);
 651                 if ( NUM_BUFFERS < 0 ) {
 652                         return(-1);
 653                 }
 654 #ifdef DEBUG_SOUND
 655                 fprintf(stderr, "Using secondary audio buffer\n");
 656 #endif
 657         }
 658 #ifdef DEBUG_SOUND
 659         else
 660                 fprintf(stderr, "Using primary audio buffer\n");
 661 #endif
 662 
 663         /* The buffer will auto-start playing in DX5_WaitAudio() */
 664         playing = 0;
 665         mixlen = spec->size;
 666 
 667 #ifdef USE_POSITION_NOTIFY
 668         /* See if we can use DirectX 6 event notification */
 669         if ( CreateAudioEvent(this) == 0 ) {
 670                 this->WaitAudio = DX6_WaitAudio_EventWait;
 671         } else {
 672                 this->WaitAudio = DX5_WaitAudio_BusyWait;
 673         }
 674 #endif
 675         return(0);
 676 }
 677 

/* [<][>][^][v][top][bottom][index][help] */