src/audio/SDL_audio.c
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
equal deleted inserted replaced
1667:1fddae038bc8 1668:4da1ee79c9af
   110     NULL
   110     NULL
   111 };
   111 };
   112 SDL_AudioDevice *current_audio = NULL;
   112 SDL_AudioDevice *current_audio = NULL;
   113 
   113 
   114 /* Various local functions */
   114 /* Various local functions */
   115 int SDL_AudioInit (const char *driver_name);
   115 int SDL_AudioInit(const char *driver_name);
   116 void SDL_AudioQuit (void);
   116 void SDL_AudioQuit(void);
   117 
   117 
   118 #if SDL_AUDIO_DRIVER_AHI
   118 #if SDL_AUDIO_DRIVER_AHI
   119 static int audio_configured = 0;
   119 static int audio_configured = 0;
   120 #endif
   120 #endif
   121 
   121 
   122 /* The general mixing thread function */
   122 /* The general mixing thread function */
   123 int SDLCALL
   123 int SDLCALL
   124 SDL_RunAudio (void *audiop)
   124 SDL_RunAudio(void *audiop)
   125 {
   125 {
   126     SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
   126     SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
   127     Uint8 *stream;
   127     Uint8 *stream;
   128     int stream_len;
   128     int stream_len;
   129     void *udata;
   129     void *udata;
   132 #if SDL_AUDIO_DRIVER_AHI
   132 #if SDL_AUDIO_DRIVER_AHI
   133     int started = 0;
   133     int started = 0;
   134 
   134 
   135 /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
   135 /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
   136 
   136 
   137     D (bug ("Task audio started audio struct:<%lx>...\n", audiop));
   137     D(bug("Task audio started audio struct:<%lx>...\n", audiop));
   138 
   138 
   139     D (bug ("Before Openaudio..."));
   139     D(bug("Before Openaudio..."));
   140     if (audio->OpenAudio (audio, &audio->spec) == -1) {
   140     if (audio->OpenAudio(audio, &audio->spec) == -1) {
   141         D (bug ("Open audio failed...\n"));
   141         D(bug("Open audio failed...\n"));
   142         return (-1);
   142         return (-1);
   143     }
   143     }
   144     D (bug ("OpenAudio...OK\n"));
   144     D(bug("OpenAudio...OK\n"));
   145 #endif
   145 #endif
   146 
   146 
   147     /* Perform any thread setup */
   147     /* Perform any thread setup */
   148     if (audio->ThreadInit) {
   148     if (audio->ThreadInit) {
   149         audio->ThreadInit (audio);
   149         audio->ThreadInit(audio);
   150     }
   150     }
   151     audio->threadid = SDL_ThreadID ();
   151     audio->threadid = SDL_ThreadID();
   152 
   152 
   153     /* Set up the mixing function */
   153     /* Set up the mixing function */
   154     fill = audio->spec.callback;
   154     fill = audio->spec.callback;
   155     udata = audio->spec.userdata;
   155     udata = audio->spec.userdata;
   156 
   156 
   157 #if SDL_AUDIO_DRIVER_AHI
   157 #if SDL_AUDIO_DRIVER_AHI
   158     audio_configured = 1;
   158     audio_configured = 1;
   159 
   159 
   160     D (bug ("Audio configured... Checking for conversion\n"));
   160     D(bug("Audio configured... Checking for conversion\n"));
   161     SDL_mutexP (audio->mixer_lock);
   161     SDL_mutexP(audio->mixer_lock);
   162     D (bug ("Semaphore obtained...\n"));
   162     D(bug("Semaphore obtained...\n"));
   163 #endif
   163 #endif
   164 
   164 
   165     if (audio->convert.needed) {
   165     if (audio->convert.needed) {
   166         if (audio->convert.src_format == AUDIO_U8) {
   166         if (audio->convert.src_format == AUDIO_U8) {
   167             silence = 0x80;
   167             silence = 0x80;
   173         silence = audio->spec.silence;
   173         silence = audio->spec.silence;
   174         stream_len = audio->spec.size;
   174         stream_len = audio->spec.size;
   175     }
   175     }
   176 
   176 
   177 #if SDL_AUDIO_DRIVER_AHI
   177 #if SDL_AUDIO_DRIVER_AHI
   178     SDL_mutexV (audio->mixer_lock);
   178     SDL_mutexV(audio->mixer_lock);
   179     D (bug ("Entering audio loop...\n"));
   179     D(bug("Entering audio loop...\n"));
   180 #endif
   180 #endif
   181 
   181 
   182 #ifdef __OS2__
   182 #ifdef __OS2__
   183     /* Increase the priority of this thread to make sure that
   183     /* Increase the priority of this thread to make sure that
   184        the audio will be continuous all the time! */
   184        the audio will be continuous all the time! */
   185 #ifdef USE_DOSSETPRIORITY
   185 #ifdef USE_DOSSETPRIORITY
   186     if (SDL_getenv ("SDL_USE_TIMECRITICAL_AUDIO")) {
   186     if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
   187 #ifdef DEBUG_BUILD
   187 #ifdef DEBUG_BUILD
   188         printf
   188         printf
   189             ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
   189             ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
   190              SDL_ThreadID ());
   190              SDL_ThreadID());
   191 #endif
   191 #endif
   192         DosSetPriority (PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
   192         DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
   193     } else {
   193     } else {
   194 #ifdef DEBUG_BUILD
   194 #ifdef DEBUG_BUILD
   195         printf
   195         printf
   196             ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
   196             ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
   197              SDL_ThreadID ());
   197              SDL_ThreadID());
   198 #endif
   198 #endif
   199         DosSetPriority (PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
   199         DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
   200     }
   200     }
   201 #endif
   201 #endif
   202 #endif
   202 #endif
   203 
   203 
   204     /* Loop, filling the audio buffers */
   204     /* Loop, filling the audio buffers */
   210                 stream = audio->convert.buf;
   210                 stream = audio->convert.buf;
   211             } else {
   211             } else {
   212                 continue;
   212                 continue;
   213             }
   213             }
   214         } else {
   214         } else {
   215             stream = audio->GetAudioBuf (audio);
   215             stream = audio->GetAudioBuf(audio);
   216             if (stream == NULL) {
   216             if (stream == NULL) {
   217                 stream = audio->fake_stream;
   217                 stream = audio->fake_stream;
   218             }
   218             }
   219         }
   219         }
   220         SDL_memset (stream, silence, stream_len);
   220         SDL_memset(stream, silence, stream_len);
   221 
   221 
   222         if (!audio->paused) {
   222         if (!audio->paused) {
   223             SDL_mutexP (audio->mixer_lock);
   223             SDL_mutexP(audio->mixer_lock);
   224             (*fill) (udata, stream, stream_len);
   224             (*fill) (udata, stream, stream_len);
   225             SDL_mutexV (audio->mixer_lock);
   225             SDL_mutexV(audio->mixer_lock);
   226         }
   226         }
   227 
   227 
   228         /* Convert the audio if necessary */
   228         /* Convert the audio if necessary */
   229         if (audio->convert.needed) {
   229         if (audio->convert.needed) {
   230             SDL_ConvertAudio (&audio->convert);
   230             SDL_ConvertAudio(&audio->convert);
   231             stream = audio->GetAudioBuf (audio);
   231             stream = audio->GetAudioBuf(audio);
   232             if (stream == NULL) {
   232             if (stream == NULL) {
   233                 stream = audio->fake_stream;
   233                 stream = audio->fake_stream;
   234             }
   234             }
   235             SDL_memcpy (stream, audio->convert.buf, audio->convert.len_cvt);
   235             SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
   236         }
   236         }
   237 
   237 
   238         /* Ready current buffer for play and change current buffer */
   238         /* Ready current buffer for play and change current buffer */
   239         if (stream != audio->fake_stream) {
   239         if (stream != audio->fake_stream) {
   240             audio->PlayAudio (audio);
   240             audio->PlayAudio(audio);
   241         }
   241         }
   242 
   242 
   243         /* Wait for an audio buffer to become available */
   243         /* Wait for an audio buffer to become available */
   244         if (stream == audio->fake_stream) {
   244         if (stream == audio->fake_stream) {
   245             SDL_Delay ((audio->spec.samples * 1000) / audio->spec.freq);
   245             SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
   246         } else {
   246         } else {
   247             audio->WaitAudio (audio);
   247             audio->WaitAudio(audio);
   248         }
   248         }
   249     }
   249     }
   250 
   250 
   251     /* Wait for the audio to drain.. */
   251     /* Wait for the audio to drain.. */
   252     if (audio->WaitDone) {
   252     if (audio->WaitDone) {
   253         audio->WaitDone (audio);
   253         audio->WaitDone(audio);
   254     }
   254     }
   255 #if SDL_AUDIO_DRIVER_AHI
   255 #if SDL_AUDIO_DRIVER_AHI
   256     D (bug ("WaitAudio...Done\n"));
   256     D(bug("WaitAudio...Done\n"));
   257 
   257 
   258     audio->CloseAudio (audio);
   258     audio->CloseAudio(audio);
   259 
   259 
   260     D (bug ("CloseAudio..Done, subtask exiting...\n"));
   260     D(bug("CloseAudio..Done, subtask exiting...\n"));
   261     audio_configured = 0;
   261     audio_configured = 0;
   262 #endif
   262 #endif
   263 #ifdef __OS2__
   263 #ifdef __OS2__
   264 #ifdef DEBUG_BUILD
   264 #ifdef DEBUG_BUILD
   265     printf ("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID ());
   265     printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
   266 #endif
   266 #endif
   267 #endif
   267 #endif
   268     return (0);
   268     return (0);
   269 }
   269 }
   270 
   270 
   271 static void
   271 static void
   272 SDL_LockAudio_Default (SDL_AudioDevice * audio)
   272 SDL_LockAudio_Default(SDL_AudioDevice * audio)
   273 {
   273 {
   274     if (audio->thread && (SDL_ThreadID () == audio->threadid)) {
   274     if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
   275         return;
   275         return;
   276     }
   276     }
   277     SDL_mutexP (audio->mixer_lock);
   277     SDL_mutexP(audio->mixer_lock);
   278 }
   278 }
   279 
   279 
   280 static void
   280 static void
   281 SDL_UnlockAudio_Default (SDL_AudioDevice * audio)
   281 SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
   282 {
   282 {
   283     if (audio->thread && (SDL_ThreadID () == audio->threadid)) {
   283     if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
   284         return;
   284         return;
   285     }
   285     }
   286     SDL_mutexV (audio->mixer_lock);
   286     SDL_mutexV(audio->mixer_lock);
   287 }
   287 }
   288 
   288 
   289 static Uint16
   289 static Uint16
   290 SDL_ParseAudioFormat (const char *string)
   290 SDL_ParseAudioFormat(const char *string)
   291 {
   291 {
   292     Uint16 format = 0;
   292     Uint16 format = 0;
   293 
   293 
   294     switch (*string) {
   294     switch (*string) {
   295     case 'U':
   295     case 'U':
   301         format |= 0x8000;
   301         format |= 0x8000;
   302         break;
   302         break;
   303     default:
   303     default:
   304         return 0;
   304         return 0;
   305     }
   305     }
   306     switch (SDL_atoi (string)) {
   306     switch (SDL_atoi(string)) {
   307     case 8:
   307     case 8:
   308         string += 1;
   308         string += 1;
   309         format |= 8;
   309         format |= 8;
   310         break;
   310         break;
   311     case 16:
   311     case 16:
   312         string += 2;
   312         string += 2;
   313         format |= 16;
   313         format |= 16;
   314         if (SDL_strcmp (string, "LSB") == 0
   314         if (SDL_strcmp(string, "LSB") == 0
   315 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   315 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   316             || SDL_strcmp (string, "SYS") == 0
   316             || SDL_strcmp(string, "SYS") == 0
   317 #endif
   317 #endif
   318             ) {
   318             ) {
   319             format |= 0x0000;
   319             format |= 0x0000;
   320         }
   320         }
   321         if (SDL_strcmp (string, "MSB") == 0
   321         if (SDL_strcmp(string, "MSB") == 0
   322 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   322 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   323             || SDL_strcmp (string, "SYS") == 0
   323             || SDL_strcmp(string, "SYS") == 0
   324 #endif
   324 #endif
   325             ) {
   325             ) {
   326             format |= 0x1000;
   326             format |= 0x1000;
   327         }
   327         }
   328         break;
   328         break;
   331     }
   331     }
   332     return format;
   332     return format;
   333 }
   333 }
   334 
   334 
   335 int
   335 int
   336 SDL_GetNumAudioDrivers (void)
   336 SDL_GetNumAudioDrivers(void)
   337 {
   337 {
   338     return (SDL_arraysize (bootstrap) - 1);
   338     return (SDL_arraysize(bootstrap) - 1);
   339 }
   339 }
   340 
   340 
   341 const char *
   341 const char *
   342 SDL_GetAudioDriver (int index)
   342 SDL_GetAudioDriver(int index)
   343 {
   343 {
   344     if (index >= 0 && index < SDL_GetNumAudioDrivers ()) {
   344     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   345         return (bootstrap[index]->name);
   345         return (bootstrap[index]->name);
   346     }
   346     }
   347     return (NULL);
   347     return (NULL);
   348 }
   348 }
   349 
   349 
   350 int
   350 int
   351 SDL_AudioInit (const char *driver_name)
   351 SDL_AudioInit(const char *driver_name)
   352 {
   352 {
   353     SDL_AudioDevice *audio;
   353     SDL_AudioDevice *audio;
   354     int i = 0, idx;
   354     int i = 0, idx;
   355 
   355 
   356     /* Check to make sure we don't overwrite 'current_audio' */
   356     /* Check to make sure we don't overwrite 'current_audio' */
   357     if (current_audio != NULL) {
   357     if (current_audio != NULL) {
   358         SDL_AudioQuit ();
   358         SDL_AudioQuit();
   359     }
   359     }
   360 
   360 
   361     /* Select the proper audio driver */
   361     /* Select the proper audio driver */
   362     audio = NULL;
   362     audio = NULL;
   363     idx = 0;
   363     idx = 0;
   364 #if SDL_AUDIO_DRIVER_ESD
   364 #if SDL_AUDIO_DRIVER_ESD
   365     if ((driver_name == NULL) && (SDL_getenv ("ESPEAKER") != NULL)) {
   365     if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
   366         /* Ahem, we know that if ESPEAKER is set, user probably wants
   366         /* Ahem, we know that if ESPEAKER is set, user probably wants
   367            to use ESD, but don't start it if it's not already running.
   367            to use ESD, but don't start it if it's not already running.
   368            This probably isn't the place to do this, but... Shh! :)
   368            This probably isn't the place to do this, but... Shh! :)
   369          */
   369          */
   370         for (i = 0; bootstrap[i]; ++i) {
   370         for (i = 0; bootstrap[i]; ++i) {
   371             if (SDL_strcmp (bootstrap[i]->name, "esd") == 0) {
   371             if (SDL_strcmp(bootstrap[i]->name, "esd") == 0) {
   372 #ifdef HAVE_PUTENV
   372 #ifdef HAVE_PUTENV
   373                 const char *esd_no_spawn;
   373                 const char *esd_no_spawn;
   374 
   374 
   375                 /* Don't start ESD if it's not running */
   375                 /* Don't start ESD if it's not running */
   376                 esd_no_spawn = getenv ("ESD_NO_SPAWN");
   376                 esd_no_spawn = getenv("ESD_NO_SPAWN");
   377                 if (esd_no_spawn == NULL) {
   377                 if (esd_no_spawn == NULL) {
   378                     putenv ("ESD_NO_SPAWN=1");
   378                     putenv("ESD_NO_SPAWN=1");
   379                 }
   379                 }
   380 #endif
   380 #endif
   381                 if (bootstrap[i]->available ()) {
   381                 if (bootstrap[i]->available()) {
   382                     audio = bootstrap[i]->create (0);
   382                     audio = bootstrap[i]->create(0);
   383                     break;
   383                     break;
   384                 }
   384                 }
   385 #ifdef HAVE_UNSETENV
   385 #ifdef HAVE_UNSETENV
   386                 if (esd_no_spawn == NULL) {
   386                 if (esd_no_spawn == NULL) {
   387                     unsetenv ("ESD_NO_SPAWN");
   387                     unsetenv("ESD_NO_SPAWN");
   388                 }
   388                 }
   389 #endif
   389 #endif
   390             }
   390             }
   391         }
   391         }
   392     }
   392     }
   393 #endif /* SDL_AUDIO_DRIVER_ESD */
   393 #endif /* SDL_AUDIO_DRIVER_ESD */
   394     if (audio == NULL) {
   394     if (audio == NULL) {
   395         if (driver_name != NULL) {
   395         if (driver_name != NULL) {
   396 #if 0                           /* This will be replaced with a better driver selection API */
   396 #if 0                           /* This will be replaced with a better driver selection API */
   397             if (SDL_strrchr (driver_name, ':') != NULL) {
   397             if (SDL_strrchr(driver_name, ':') != NULL) {
   398                 idx = atoi (SDL_strrchr (driver_name, ':') + 1);
   398                 idx = atoi(SDL_strrchr(driver_name, ':') + 1);
   399             }
   399             }
   400 #endif
   400 #endif
   401             for (i = 0; bootstrap[i]; ++i) {
   401             for (i = 0; bootstrap[i]; ++i) {
   402                 if (SDL_strncmp (bootstrap[i]->name, driver_name,
   402                 if (SDL_strncmp(bootstrap[i]->name, driver_name,
   403                                  SDL_strlen (bootstrap[i]->name)) == 0) {
   403                                 SDL_strlen(bootstrap[i]->name)) == 0) {
   404                     if (bootstrap[i]->available ()) {
   404                     if (bootstrap[i]->available()) {
   405                         audio = bootstrap[i]->create (idx);
   405                         audio = bootstrap[i]->create(idx);
   406                     }
   406                     }
   407                     break;
   407                     break;
   408                 }
   408                 }
   409             }
   409             }
   410         } else {
   410         } else {
   411             for (i = 0; bootstrap[i]; ++i) {
   411             for (i = 0; bootstrap[i]; ++i) {
   412                 if (bootstrap[i]->available ()) {
   412                 if (bootstrap[i]->available()) {
   413                     audio = bootstrap[i]->create (idx);
   413                     audio = bootstrap[i]->create(idx);
   414                     if (audio != NULL) {
   414                     if (audio != NULL) {
   415                         break;
   415                         break;
   416                     }
   416                     }
   417                 }
   417                 }
   418             }
   418             }
   419         }
   419         }
   420         if (audio == NULL) {
   420         if (audio == NULL) {
   421             if (driver_name) {
   421             if (driver_name) {
   422                 SDL_SetError ("%s not available", driver_name);
   422                 SDL_SetError("%s not available", driver_name);
   423             } else {
   423             } else {
   424                 SDL_SetError ("No available audio device");
   424                 SDL_SetError("No available audio device");
   425             }
   425             }
   426 #if 0                           /* Don't fail SDL_Init() if audio isn't available.
   426 #if 0                           /* Don't fail SDL_Init() if audio isn't available.
   427                                    SDL_OpenAudio() will handle it at that point.  *sigh*
   427                                    SDL_OpenAudio() will handle it at that point.  *sigh*
   428                                  */
   428                                  */
   429             return (-1);
   429             return (-1);
   443 
   443 
   444 /*
   444 /*
   445  * Get the current audio driver name
   445  * Get the current audio driver name
   446  */
   446  */
   447 const char *
   447 const char *
   448 SDL_GetCurrentAudioDriver ()
   448 SDL_GetCurrentAudioDriver()
   449 {
   449 {
   450     if (current_audio) {
   450     if (current_audio) {
   451         return current_audio->name;
   451         return current_audio->name;
   452     }
   452     }
   453     return (NULL);
   453     return (NULL);
   454 }
   454 }
   455 
   455 
   456 int
   456 int
   457 SDL_OpenAudio (SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   457 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   458 {
   458 {
   459     SDL_AudioDevice *audio;
   459     SDL_AudioDevice *audio;
   460     const char *env;
   460     const char *env;
   461 
   461 
   462     /* Start up the audio driver, if necessary */
   462     /* Start up the audio driver, if necessary */
   463     if (!current_audio) {
   463     if (!current_audio) {
   464         if ((SDL_InitSubSystem (SDL_INIT_AUDIO) < 0) ||
   464         if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
   465             (current_audio == NULL)) {
   465             (current_audio == NULL)) {
   466             return (-1);
   466             return (-1);
   467         }
   467         }
   468     }
   468     }
   469     audio = current_audio;
   469     audio = current_audio;
   470 
   470 
   471     if (audio->opened) {
   471     if (audio->opened) {
   472         SDL_SetError ("Audio device is already opened");
   472         SDL_SetError("Audio device is already opened");
   473         return (-1);
   473         return (-1);
   474     }
   474     }
   475 
   475 
   476     /* Verify some parameters */
   476     /* Verify some parameters */
   477     if (desired->freq == 0) {
   477     if (desired->freq == 0) {
   478         env = SDL_getenv ("SDL_AUDIO_FREQUENCY");
   478         env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   479         if (env) {
   479         if (env) {
   480             desired->freq = SDL_atoi (env);
   480             desired->freq = SDL_atoi(env);
   481         }
   481         }
   482     }
   482     }
   483     if (desired->freq == 0) {
   483     if (desired->freq == 0) {
   484         /* Pick some default audio frequency */
   484         /* Pick some default audio frequency */
   485         desired->freq = 22050;
   485         desired->freq = 22050;
   486     }
   486     }
   487     if (desired->format == 0) {
   487     if (desired->format == 0) {
   488         env = SDL_getenv ("SDL_AUDIO_FORMAT");
   488         env = SDL_getenv("SDL_AUDIO_FORMAT");
   489         if (env) {
   489         if (env) {
   490             desired->format = SDL_ParseAudioFormat (env);
   490             desired->format = SDL_ParseAudioFormat(env);
   491         }
   491         }
   492     }
   492     }
   493     if (desired->format == 0) {
   493     if (desired->format == 0) {
   494         /* Pick some default audio format */
   494         /* Pick some default audio format */
   495         desired->format = AUDIO_S16;
   495         desired->format = AUDIO_S16;
   496     }
   496     }
   497     if (desired->channels == 0) {
   497     if (desired->channels == 0) {
   498         env = SDL_getenv ("SDL_AUDIO_CHANNELS");
   498         env = SDL_getenv("SDL_AUDIO_CHANNELS");
   499         if (env) {
   499         if (env) {
   500             desired->channels = SDL_atoi (env);
   500             desired->channels = SDL_atoi(env);
   501         }
   501         }
   502     }
   502     }
   503     if (desired->channels == 0) {
   503     if (desired->channels == 0) {
   504         /* Pick a default number of channels */
   504         /* Pick a default number of channels */
   505         desired->channels = 2;
   505         desired->channels = 2;
   509     case 2:                    /* Stereo */
   509     case 2:                    /* Stereo */
   510     case 4:                    /* surround */
   510     case 4:                    /* surround */
   511     case 6:                    /* surround with center and lfe */
   511     case 6:                    /* surround with center and lfe */
   512         break;
   512         break;
   513     default:
   513     default:
   514         SDL_SetError ("1 (mono) and 2 (stereo) channels supported");
   514         SDL_SetError("1 (mono) and 2 (stereo) channels supported");
   515         return (-1);
   515         return (-1);
   516     }
   516     }
   517     if (desired->samples == 0) {
   517     if (desired->samples == 0) {
   518         env = SDL_getenv ("SDL_AUDIO_SAMPLES");
   518         env = SDL_getenv("SDL_AUDIO_SAMPLES");
   519         if (env) {
   519         if (env) {
   520             desired->samples = SDL_atoi (env);
   520             desired->samples = SDL_atoi(env);
   521         }
   521         }
   522     }
   522     }
   523     if (desired->samples == 0) {
   523     if (desired->samples == 0) {
   524         /* Pick a default of ~46 ms at desired frequency */
   524         /* Pick a default of ~46 ms at desired frequency */
   525         int samples = (desired->freq / 1000) * 46;
   525         int samples = (desired->freq / 1000) * 46;
   528             power2 *= 2;
   528             power2 *= 2;
   529         }
   529         }
   530         desired->samples = power2;
   530         desired->samples = power2;
   531     }
   531     }
   532     if (desired->callback == NULL) {
   532     if (desired->callback == NULL) {
   533         SDL_SetError ("SDL_OpenAudio() passed a NULL callback");
   533         SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   534         return (-1);
   534         return (-1);
   535     }
   535     }
   536 #if defined(__MACOS__) || (defined(__RISCOS__) && SDL_THREADS_DISABLED)
   536 #if defined(__MACOS__) || (defined(__RISCOS__) && SDL_THREADS_DISABLED)
   537     /* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */
   537     /* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */
   538 #else
   538 #else
   539 #if defined(__MINT__) && SDL_THREADS_DISABLED
   539 #if defined(__MINT__) && SDL_THREADS_DISABLED
   540     /* Uses interrupt driven audio, without thread */
   540     /* Uses interrupt driven audio, without thread */
   541 #else
   541 #else
   542     /* Create a semaphore for locking the sound buffers */
   542     /* Create a semaphore for locking the sound buffers */
   543     audio->mixer_lock = SDL_CreateMutex ();
   543     audio->mixer_lock = SDL_CreateMutex();
   544     if (audio->mixer_lock == NULL) {
   544     if (audio->mixer_lock == NULL) {
   545         SDL_SetError ("Couldn't create mixer lock");
   545         SDL_SetError("Couldn't create mixer lock");
   546         SDL_CloseAudio ();
   546         SDL_CloseAudio();
   547         return (-1);
   547         return (-1);
   548     }
   548     }
   549 #endif /* __MINT__ */
   549 #endif /* __MINT__ */
   550 #endif /* __MACOS__ */
   550 #endif /* __MACOS__ */
   551 
   551 
   552     /* Calculate the silence and size of the audio specification */
   552     /* Calculate the silence and size of the audio specification */
   553     SDL_CalculateAudioSpec (desired);
   553     SDL_CalculateAudioSpec(desired);
   554 
   554 
   555     /* Open the audio subsystem */
   555     /* Open the audio subsystem */
   556     SDL_memcpy (&audio->spec, desired, sizeof (audio->spec));
   556     SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
   557     audio->convert.needed = 0;
   557     audio->convert.needed = 0;
   558     audio->enabled = 1;
   558     audio->enabled = 1;
   559     audio->paused = 1;
   559     audio->paused = 1;
   560 
   560 
   561 #if !SDL_AUDIO_DRIVER_AHI
   561 #if !SDL_AUDIO_DRIVER_AHI
   562 
   562 
   563 /* AmigaOS opens audio inside the main loop */
   563 /* AmigaOS opens audio inside the main loop */
   564     audio->opened = audio->OpenAudio (audio, &audio->spec) + 1;
   564     audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
   565 
   565 
   566     if (!audio->opened) {
   566     if (!audio->opened) {
   567         SDL_CloseAudio ();
   567         SDL_CloseAudio();
   568         return (-1);
   568         return (-1);
   569     }
   569     }
   570 #else
   570 #else
   571     D (bug ("Locking semaphore..."));
   571     D(bug("Locking semaphore..."));
   572     SDL_mutexP (audio->mixer_lock);
   572     SDL_mutexP(audio->mixer_lock);
   573 
   573 
   574 
   574 
   575     audio->thread = SDL_CreateThread (SDL_RunAudio, audio);
   575     audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   576     D (bug ("Created thread...\n"));
   576     D(bug("Created thread...\n"));
   577 
   577 
   578     if (audio->thread == NULL) {
   578     if (audio->thread == NULL) {
   579         SDL_mutexV (audio->mixer_lock);
   579         SDL_mutexV(audio->mixer_lock);
   580         SDL_CloseAudio ();
   580         SDL_CloseAudio();
   581         SDL_SetError ("Couldn't create audio thread");
   581         SDL_SetError("Couldn't create audio thread");
   582         return (-1);
   582         return (-1);
   583     }
   583     }
   584 
   584 
   585     while (!audio_configured)
   585     while (!audio_configured)
   586         SDL_Delay (100);
   586         SDL_Delay(100);
   587 #endif
   587 #endif
   588 
   588 
   589     /* If the audio driver changes the buffer size, accept it */
   589     /* If the audio driver changes the buffer size, accept it */
   590     if (audio->spec.samples != desired->samples) {
   590     if (audio->spec.samples != desired->samples) {
   591         desired->samples = audio->spec.samples;
   591         desired->samples = audio->spec.samples;
   592         SDL_CalculateAudioSpec (desired);
   592         SDL_CalculateAudioSpec(desired);
   593     }
   593     }
   594 
   594 
   595     /* Allocate a fake audio memory buffer */
   595     /* Allocate a fake audio memory buffer */
   596     audio->fake_stream = SDL_AllocAudioMem (audio->spec.size);
   596     audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
   597     if (audio->fake_stream == NULL) {
   597     if (audio->fake_stream == NULL) {
   598         SDL_CloseAudio ();
   598         SDL_CloseAudio();
   599         SDL_OutOfMemory ();
   599         SDL_OutOfMemory();
   600         return (-1);
   600         return (-1);
   601     }
   601     }
   602 
   602 
   603     /* See if we need to do any conversion */
   603     /* See if we need to do any conversion */
   604     if (obtained != NULL) {
   604     if (obtained != NULL) {
   605         SDL_memcpy (obtained, &audio->spec, sizeof (audio->spec));
   605         SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
   606     } else if (desired->freq != audio->spec.freq ||
   606     } else if (desired->freq != audio->spec.freq ||
   607                desired->format != audio->spec.format ||
   607                desired->format != audio->spec.format ||
   608                desired->channels != audio->spec.channels) {
   608                desired->channels != audio->spec.channels) {
   609         /* Build an audio conversion block */
   609         /* Build an audio conversion block */
   610         if (SDL_BuildAudioCVT (&audio->convert,
   610         if (SDL_BuildAudioCVT(&audio->convert,
   611                                desired->format, desired->channels,
   611                               desired->format, desired->channels,
   612                                desired->freq,
   612                               desired->freq,
   613                                audio->spec.format, audio->spec.channels,
   613                               audio->spec.format, audio->spec.channels,
   614                                audio->spec.freq) < 0) {
   614                               audio->spec.freq) < 0) {
   615             SDL_CloseAudio ();
   615             SDL_CloseAudio();
   616             return (-1);
   616             return (-1);
   617         }
   617         }
   618         if (audio->convert.needed) {
   618         if (audio->convert.needed) {
   619             audio->convert.len = desired->size;
   619             audio->convert.len = desired->size;
   620             audio->convert.buf =
   620             audio->convert.buf =
   621                 (Uint8 *) SDL_AllocAudioMem (audio->convert.len *
   621                 (Uint8 *) SDL_AllocAudioMem(audio->convert.len *
   622                                              audio->convert.len_mult);
   622                                             audio->convert.len_mult);
   623             if (audio->convert.buf == NULL) {
   623             if (audio->convert.buf == NULL) {
   624                 SDL_CloseAudio ();
   624                 SDL_CloseAudio();
   625                 SDL_OutOfMemory ();
   625                 SDL_OutOfMemory();
   626                 return (-1);
   626                 return (-1);
   627             }
   627             }
   628         }
   628         }
   629     }
   629     }
   630 #if !SDL_AUDIO_DRIVER_AHI
   630 #if !SDL_AUDIO_DRIVER_AHI
   632     switch (audio->opened) {
   632     switch (audio->opened) {
   633     case 1:
   633     case 1:
   634         /* Start the audio thread */
   634         /* Start the audio thread */
   635 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
   635 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
   636 #undef SDL_CreateThread
   636 #undef SDL_CreateThread
   637         audio->thread = SDL_CreateThread (SDL_RunAudio, audio, NULL, NULL);
   637         audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
   638 #else
   638 #else
   639         audio->thread = SDL_CreateThread (SDL_RunAudio, audio);
   639         audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   640 #endif
   640 #endif
   641         if (audio->thread == NULL) {
   641         if (audio->thread == NULL) {
   642             SDL_CloseAudio ();
   642             SDL_CloseAudio();
   643             SDL_SetError ("Couldn't create audio thread");
   643             SDL_SetError("Couldn't create audio thread");
   644             return (-1);
   644             return (-1);
   645         }
   645         }
   646         break;
   646         break;
   647 
   647 
   648     default:
   648     default:
   649         /* The audio is now playing */
   649         /* The audio is now playing */
   650         break;
   650         break;
   651     }
   651     }
   652 #else
   652 #else
   653     SDL_mutexV (audio->mixer_lock);
   653     SDL_mutexV(audio->mixer_lock);
   654     D (bug ("SDL_OpenAudio USCITA...\n"));
   654     D(bug("SDL_OpenAudio USCITA...\n"));
   655 
   655 
   656 #endif
   656 #endif
   657 
   657 
   658     return (0);
   658     return (0);
   659 }
   659 }
   660 
   660 
   661 SDL_audiostatus
   661 SDL_audiostatus
   662 SDL_GetAudioStatus (void)
   662 SDL_GetAudioStatus(void)
   663 {
   663 {
   664     SDL_AudioDevice *audio = current_audio;
   664     SDL_AudioDevice *audio = current_audio;
   665     SDL_audiostatus status;
   665     SDL_audiostatus status;
   666 
   666 
   667     status = SDL_AUDIO_STOPPED;
   667     status = SDL_AUDIO_STOPPED;
   674     }
   674     }
   675     return (status);
   675     return (status);
   676 }
   676 }
   677 
   677 
   678 void
   678 void
   679 SDL_PauseAudio (int pause_on)
   679 SDL_PauseAudio(int pause_on)
   680 {
   680 {
   681     SDL_AudioDevice *audio = current_audio;
   681     SDL_AudioDevice *audio = current_audio;
   682 
   682 
   683     if (audio) {
   683     if (audio) {
   684         audio->paused = pause_on;
   684         audio->paused = pause_on;
   685     }
   685     }
   686 }
   686 }
   687 
   687 
   688 void
   688 void
   689 SDL_LockAudio (void)
   689 SDL_LockAudio(void)
   690 {
   690 {
   691     SDL_AudioDevice *audio = current_audio;
   691     SDL_AudioDevice *audio = current_audio;
   692 
   692 
   693     /* Obtain a lock on the mixing buffers */
   693     /* Obtain a lock on the mixing buffers */
   694     if (audio && audio->LockAudio) {
   694     if (audio && audio->LockAudio) {
   695         audio->LockAudio (audio);
   695         audio->LockAudio(audio);
   696     }
   696     }
   697 }
   697 }
   698 
   698 
   699 void
   699 void
   700 SDL_UnlockAudio (void)
   700 SDL_UnlockAudio(void)
   701 {
   701 {
   702     SDL_AudioDevice *audio = current_audio;
   702     SDL_AudioDevice *audio = current_audio;
   703 
   703 
   704     /* Release lock on the mixing buffers */
   704     /* Release lock on the mixing buffers */
   705     if (audio && audio->UnlockAudio) {
   705     if (audio && audio->UnlockAudio) {
   706         audio->UnlockAudio (audio);
   706         audio->UnlockAudio(audio);
   707     }
   707     }
   708 }
   708 }
   709 
   709 
   710 void
   710 void
   711 SDL_CloseAudio (void)
   711 SDL_CloseAudio(void)
   712 {
   712 {
   713     SDL_QuitSubSystem (SDL_INIT_AUDIO);
   713     SDL_QuitSubSystem(SDL_INIT_AUDIO);
   714 }
   714 }
   715 
   715 
   716 void
   716 void
   717 SDL_AudioQuit (void)
   717 SDL_AudioQuit(void)
   718 {
   718 {
   719     SDL_AudioDevice *audio = current_audio;
   719     SDL_AudioDevice *audio = current_audio;
   720 
   720 
   721     if (audio) {
   721     if (audio) {
   722         audio->enabled = 0;
   722         audio->enabled = 0;
   723         if (audio->thread != NULL) {
   723         if (audio->thread != NULL) {
   724             SDL_WaitThread (audio->thread, NULL);
   724             SDL_WaitThread(audio->thread, NULL);
   725         }
   725         }
   726         if (audio->mixer_lock != NULL) {
   726         if (audio->mixer_lock != NULL) {
   727             SDL_DestroyMutex (audio->mixer_lock);
   727             SDL_DestroyMutex(audio->mixer_lock);
   728         }
   728         }
   729         if (audio->fake_stream != NULL) {
   729         if (audio->fake_stream != NULL) {
   730             SDL_FreeAudioMem (audio->fake_stream);
   730             SDL_FreeAudioMem(audio->fake_stream);
   731         }
   731         }
   732         if (audio->convert.needed) {
   732         if (audio->convert.needed) {
   733             SDL_FreeAudioMem (audio->convert.buf);
   733             SDL_FreeAudioMem(audio->convert.buf);
   734 
   734 
   735         }
   735         }
   736 #if !SDL_AUDIO_DRIVER_AHI
   736 #if !SDL_AUDIO_DRIVER_AHI
   737         if (audio->opened) {
   737         if (audio->opened) {
   738             audio->CloseAudio (audio);
   738             audio->CloseAudio(audio);
   739             audio->opened = 0;
   739             audio->opened = 0;
   740         }
   740         }
   741 #endif
   741 #endif
   742         /* Free the driver data */
   742         /* Free the driver data */
   743         audio->free (audio);
   743         audio->free(audio);
   744         current_audio = NULL;
   744         current_audio = NULL;
   745     }
   745     }
   746 }
   746 }
   747 
   747 
   748 #define NUM_FORMATS	6
   748 #define NUM_FORMATS	6
   762     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8,
   762     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8,
   763      AUDIO_S8},
   763      AUDIO_S8},
   764 };
   764 };
   765 
   765 
   766 Uint16
   766 Uint16
   767 SDL_FirstAudioFormat (Uint16 format)
   767 SDL_FirstAudioFormat(Uint16 format)
   768 {
   768 {
   769     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
   769     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
   770         if (format_list[format_idx][0] == format) {
   770         if (format_list[format_idx][0] == format) {
   771             break;
   771             break;
   772         }
   772         }
   773     }
   773     }
   774     format_idx_sub = 0;
   774     format_idx_sub = 0;
   775     return (SDL_NextAudioFormat ());
   775     return (SDL_NextAudioFormat());
   776 }
   776 }
   777 
   777 
   778 Uint16
   778 Uint16
   779 SDL_NextAudioFormat (void)
   779 SDL_NextAudioFormat(void)
   780 {
   780 {
   781     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
   781     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
   782         return (0);
   782         return (0);
   783     }
   783     }
   784     return (format_list[format_idx][format_idx_sub++]);
   784     return (format_list[format_idx][format_idx_sub++]);
   785 }
   785 }
   786 
   786 
   787 void
   787 void
   788 SDL_CalculateAudioSpec (SDL_AudioSpec * spec)
   788 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
   789 {
   789 {
   790     switch (spec->format) {
   790     switch (spec->format) {
   791     case AUDIO_U8:
   791     case AUDIO_U8:
   792         spec->silence = 0x80;
   792         spec->silence = 0x80;
   793         break;
   793         break;