SDL-1.2.14
[sdl_omap.git] / src / audio / SDL_audio.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 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     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* Allow access to a raw mixing buffer */
25
26 #include "SDL.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_audiomem.h"
29 #include "SDL_sysaudio.h"
30
31 #ifdef __OS2__
32 /* We'll need the DosSetPriority() API! */
33 #define INCL_DOSPROCESS
34 #include <os2.h>
35 #endif
36
37 /* Available audio drivers */
38 static AudioBootStrap *bootstrap[] = {
39 #if SDL_AUDIO_DRIVER_BSD
40         &BSD_AUDIO_bootstrap,
41 #endif
42 #if SDL_AUDIO_DRIVER_PULSE
43         &PULSE_bootstrap,
44 #endif
45 #if SDL_AUDIO_DRIVER_ALSA
46         &ALSA_bootstrap,
47 #endif
48 #if SDL_AUDIO_DRIVER_OSS
49         &DSP_bootstrap,
50         &DMA_bootstrap,
51 #endif
52 #if SDL_AUDIO_DRIVER_QNXNTO
53         &QNXNTOAUDIO_bootstrap,
54 #endif
55 #if SDL_AUDIO_DRIVER_SUNAUDIO
56         &SUNAUDIO_bootstrap,
57 #endif
58 #if SDL_AUDIO_DRIVER_DMEDIA
59         &DMEDIA_bootstrap,
60 #endif
61 #if SDL_AUDIO_DRIVER_ARTS
62         &ARTS_bootstrap,
63 #endif
64 #if SDL_AUDIO_DRIVER_ESD
65         &ESD_bootstrap,
66 #endif
67 #if SDL_AUDIO_DRIVER_NAS
68         &NAS_bootstrap,
69 #endif
70 #if SDL_AUDIO_DRIVER_DSOUND
71         &DSOUND_bootstrap,
72 #endif
73 #if SDL_AUDIO_DRIVER_WAVEOUT
74         &WAVEOUT_bootstrap,
75 #endif
76 #if SDL_AUDIO_DRIVER_PAUD
77         &Paud_bootstrap,
78 #endif
79 #if SDL_AUDIO_DRIVER_BAUDIO
80         &BAUDIO_bootstrap,
81 #endif
82 #if SDL_AUDIO_DRIVER_COREAUDIO
83         &COREAUDIO_bootstrap,
84 #endif
85 #if SDL_AUDIO_DRIVER_SNDMGR
86         &SNDMGR_bootstrap,
87 #endif
88 #if SDL_AUDIO_DRIVER_MINT
89         &MINTAUDIO_GSXB_bootstrap,
90         &MINTAUDIO_MCSN_bootstrap,
91         &MINTAUDIO_STFA_bootstrap,
92         &MINTAUDIO_XBIOS_bootstrap,
93         &MINTAUDIO_DMA8_bootstrap,
94 #endif
95 #if SDL_AUDIO_DRIVER_DISK
96         &DISKAUD_bootstrap,
97 #endif
98 #if SDL_AUDIO_DRIVER_DUMMY
99         &DUMMYAUD_bootstrap,
100 #endif
101 #if SDL_AUDIO_DRIVER_DC
102         &DCAUD_bootstrap,
103 #endif
104 #if SDL_AUDIO_DRIVER_NDS
105         &NDSAUD_bootstrap,
106 #endif
107 #if SDL_AUDIO_DRIVER_MMEAUDIO
108         &MMEAUDIO_bootstrap,
109 #endif
110 #if SDL_AUDIO_DRIVER_DART
111         &DART_bootstrap,
112 #endif
113 #if SDL_AUDIO_DRIVER_EPOCAUDIO
114         &EPOCAudio_bootstrap,
115 #endif
116         NULL
117 };
118 SDL_AudioDevice *current_audio = NULL;
119
120 /* Various local functions */
121 int SDL_AudioInit(const char *driver_name);
122 void SDL_AudioQuit(void);
123
124 /* The general mixing thread function */
125 int SDLCALL SDL_RunAudio(void *audiop)
126 {
127         SDL_AudioDevice *audio = (SDL_AudioDevice *)audiop;
128         Uint8 *stream;
129         int    stream_len;
130         void  *udata;
131         void (SDLCALL *fill)(void *userdata,Uint8 *stream, int len);
132         int    silence;
133
134         /* Perform any thread setup */
135         if ( audio->ThreadInit ) {
136                 audio->ThreadInit(audio);
137         }
138         audio->threadid = SDL_ThreadID();
139
140         /* Set up the mixing function */
141         fill  = audio->spec.callback;
142         udata = audio->spec.userdata;
143
144         if ( audio->convert.needed ) {
145                 if ( audio->convert.src_format == AUDIO_U8 ) {
146                         silence = 0x80;
147                 } else {
148                         silence = 0;
149                 }
150                 stream_len = audio->convert.len;
151         } else {
152                 silence = audio->spec.silence;
153                 stream_len = audio->spec.size;
154         }
155
156 #ifdef __OS2__
157         /* Increase the priority of this thread to make sure that
158            the audio will be continuous all the time! */
159 #ifdef USE_DOSSETPRIORITY
160         if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO"))
161         {
162 #ifdef DEBUG_BUILD
163           printf("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", SDL_ThreadID());
164 #endif
165           DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
166         }
167         else
168         {
169 #ifdef DEBUG_BUILD
170           printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID());
171 #endif
172           DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
173         }
174 #endif
175 #endif
176
177         /* Loop, filling the audio buffers */
178         while ( audio->enabled ) {
179
180                 /* Fill the current buffer with sound */
181                 if ( audio->convert.needed ) {
182                         if ( audio->convert.buf ) {
183                                 stream = audio->convert.buf;
184                         } else {
185                                 continue;
186                         }
187                 } else {
188                         stream = audio->GetAudioBuf(audio);
189                         if ( stream == NULL ) {
190                                 stream = audio->fake_stream;
191                         }
192                 }
193
194                 SDL_memset(stream, silence, stream_len);
195
196                 if ( ! audio->paused ) {
197                         SDL_mutexP(audio->mixer_lock);
198                         (*fill)(udata, stream, stream_len);
199                         SDL_mutexV(audio->mixer_lock);
200                 }
201
202                 /* Convert the audio if necessary */
203                 if ( audio->convert.needed ) {
204                         SDL_ConvertAudio(&audio->convert);
205                         stream = audio->GetAudioBuf(audio);
206                         if ( stream == NULL ) {
207                                 stream = audio->fake_stream;
208                         }
209                         SDL_memcpy(stream, audio->convert.buf,
210                                        audio->convert.len_cvt);
211                 }
212
213                 /* Ready current buffer for play and change current buffer */
214                 if ( stream != audio->fake_stream ) {
215                         audio->PlayAudio(audio);
216                 }
217
218                 /* Wait for an audio buffer to become available */
219                 if ( stream == audio->fake_stream ) {
220                         SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
221                 } else {
222                         audio->WaitAudio(audio);
223                 }
224         }
225
226         /* Wait for the audio to drain.. */
227         if ( audio->WaitDone ) {
228                 audio->WaitDone(audio);
229         }
230
231 #ifdef __OS2__
232 #ifdef DEBUG_BUILD
233         printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
234 #endif
235 #endif
236         return(0);
237 }
238
239 static void SDL_LockAudio_Default(SDL_AudioDevice *audio)
240 {
241         if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
242                 return;
243         }
244         SDL_mutexP(audio->mixer_lock);
245 }
246
247 static void SDL_UnlockAudio_Default(SDL_AudioDevice *audio)
248 {
249         if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
250                 return;
251         }
252         SDL_mutexV(audio->mixer_lock);
253 }
254
255 static Uint16 SDL_ParseAudioFormat(const char *string)
256 {
257         Uint16 format = 0;
258
259         switch (*string) {
260             case 'U':
261                 ++string;
262                 format |= 0x0000;
263                 break;
264             case 'S':
265                 ++string;
266                 format |= 0x8000;
267                 break;
268             default:
269                 return 0;
270         }
271         switch (SDL_atoi(string)) {
272             case 8:
273                 string += 1;
274                 format |= 8;
275                 break;
276             case 16:
277                 string += 2;
278                 format |= 16;
279                 if ( SDL_strcmp(string, "LSB") == 0
280 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
281                      || SDL_strcmp(string, "SYS") == 0
282 #endif
283                     ) {
284                         format |= 0x0000;
285                 }
286                 if ( SDL_strcmp(string, "MSB") == 0
287 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
288                      || SDL_strcmp(string, "SYS") == 0
289 #endif
290                     ) {
291                         format |= 0x1000;
292                 }
293                 break;
294             default:
295                 return 0;
296         }
297         return format;
298 }
299
300 int SDL_AudioInit(const char *driver_name)
301 {
302         SDL_AudioDevice *audio;
303         int i = 0, idx;
304
305         /* Check to make sure we don't overwrite 'current_audio' */
306         if ( current_audio != NULL ) {
307                 SDL_AudioQuit();
308         }
309
310         /* Select the proper audio driver */
311         audio = NULL;
312         idx = 0;
313 #if SDL_AUDIO_DRIVER_ESD
314         if ( (driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL) ) {
315                 /* Ahem, we know that if ESPEAKER is set, user probably wants
316                    to use ESD, but don't start it if it's not already running.
317                    This probably isn't the place to do this, but... Shh! :)
318                  */
319                 for ( i=0; bootstrap[i]; ++i ) {
320                         if ( SDL_strcasecmp(bootstrap[i]->name, "esd") == 0 ) {
321 #ifdef HAVE_PUTENV
322                                 const char *esd_no_spawn;
323
324                                 /* Don't start ESD if it's not running */
325                                 esd_no_spawn = getenv("ESD_NO_SPAWN");
326                                 if ( esd_no_spawn == NULL ) {
327                                         putenv("ESD_NO_SPAWN=1");
328                                 }
329 #endif
330                                 if ( bootstrap[i]->available() ) {
331                                         audio = bootstrap[i]->create(0);
332                                         break;
333                                 }
334 #ifdef HAVE_UNSETENV
335                                 if ( esd_no_spawn == NULL ) {
336                                         unsetenv("ESD_NO_SPAWN");
337                                 }
338 #endif
339                         }
340                 }
341         }
342 #endif /* SDL_AUDIO_DRIVER_ESD */
343         if ( audio == NULL ) {
344                 if ( driver_name != NULL ) {
345 #if 0   /* This will be replaced with a better driver selection API */
346                         if ( SDL_strrchr(driver_name, ':') != NULL ) {
347                                 idx = atoi(SDL_strrchr(driver_name, ':')+1);
348                         }
349 #endif
350                         for ( i=0; bootstrap[i]; ++i ) {
351                                 if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
352                                         if ( bootstrap[i]->available() ) {
353                                                 audio=bootstrap[i]->create(idx);
354                                                 break;
355                                         }
356                                 }
357                         }
358                 } else {
359                         for ( i=0; bootstrap[i]; ++i ) {
360                                 if ( bootstrap[i]->available() ) {
361                                         audio = bootstrap[i]->create(idx);
362                                         if ( audio != NULL ) {
363                                                 break;
364                                         }
365                                 }
366                         }
367                 }
368                 if ( audio == NULL ) {
369                         SDL_SetError("No available audio device");
370 #if 0 /* Don't fail SDL_Init() if audio isn't available.
371          SDL_OpenAudio() will handle it at that point.  *sigh*
372        */
373                         return(-1);
374 #endif
375                 }
376         }
377         current_audio = audio;
378         if ( current_audio ) {
379                 current_audio->name = bootstrap[i]->name;
380                 if ( !current_audio->LockAudio && !current_audio->UnlockAudio ) {
381                         current_audio->LockAudio = SDL_LockAudio_Default;
382                         current_audio->UnlockAudio = SDL_UnlockAudio_Default;
383                 }
384         }
385         return(0);
386 }
387
388 char *SDL_AudioDriverName(char *namebuf, int maxlen)
389 {
390         if ( current_audio != NULL ) {
391                 SDL_strlcpy(namebuf, current_audio->name, maxlen);
392                 return(namebuf);
393         }
394         return(NULL);
395 }
396
397 int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
398 {
399         SDL_AudioDevice *audio;
400         const char *env;
401
402         /* Start up the audio driver, if necessary */
403         if ( ! current_audio ) {
404                 if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
405                      (current_audio == NULL) ) {
406                         return(-1);
407                 }
408         }
409         audio = current_audio;
410
411         if (audio->opened) {
412                 SDL_SetError("Audio device is already opened");
413                 return(-1);
414         }
415
416         /* Verify some parameters */
417         if ( desired->freq == 0 ) {
418                 env = SDL_getenv("SDL_AUDIO_FREQUENCY");
419                 if ( env ) {
420                         desired->freq = SDL_atoi(env);
421                 }
422         }
423         if ( desired->freq == 0 ) {
424                 /* Pick some default audio frequency */
425                 desired->freq = 22050;
426         }
427         if ( desired->format == 0 ) {
428                 env = SDL_getenv("SDL_AUDIO_FORMAT");
429                 if ( env ) {
430                         desired->format = SDL_ParseAudioFormat(env);
431                 }
432         }
433         if ( desired->format == 0 ) {
434                 /* Pick some default audio format */
435                 desired->format = AUDIO_S16;
436         }
437         if ( desired->channels == 0 ) {
438                 env = SDL_getenv("SDL_AUDIO_CHANNELS");
439                 if ( env ) {
440                         desired->channels = (Uint8)SDL_atoi(env);
441                 }
442         }
443         if ( desired->channels == 0 ) {
444                 /* Pick a default number of channels */
445                 desired->channels = 2;
446         }
447         switch ( desired->channels ) {
448             case 1:     /* Mono */
449             case 2:     /* Stereo */
450             case 4:     /* surround */
451             case 6:     /* surround with center and lfe */
452                 break;
453             default:
454                 SDL_SetError("1 (mono) and 2 (stereo) channels supported");
455                 return(-1);
456         }
457         if ( desired->samples == 0 ) {
458                 env = SDL_getenv("SDL_AUDIO_SAMPLES");
459                 if ( env ) {
460                         desired->samples = (Uint16)SDL_atoi(env);
461                 }
462         }
463         if ( desired->samples == 0 ) {
464                 /* Pick a default of ~46 ms at desired frequency */
465                 int samples = (desired->freq / 1000) * 46;
466                 int power2 = 1;
467                 while ( power2 < samples ) {
468                         power2 *= 2;
469                 }
470                 desired->samples = power2;
471         }
472         if ( desired->callback == NULL ) {
473                 SDL_SetError("SDL_OpenAudio() passed a NULL callback");
474                 return(-1);
475         }
476
477 #if SDL_THREADS_DISABLED
478         /* Uses interrupt driven audio, without thread */
479 #else
480         /* Create a semaphore for locking the sound buffers */
481         audio->mixer_lock = SDL_CreateMutex();
482         if ( audio->mixer_lock == NULL ) {
483                 SDL_SetError("Couldn't create mixer lock");
484                 SDL_CloseAudio();
485                 return(-1);
486         }
487 #endif /* SDL_THREADS_DISABLED */
488
489         /* Calculate the silence and size of the audio specification */
490         SDL_CalculateAudioSpec(desired);
491
492         /* Open the audio subsystem */
493         SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
494         audio->convert.needed = 0;
495         audio->enabled = 1;
496         audio->paused  = 1;
497
498         audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
499
500         if ( ! audio->opened ) {
501                 SDL_CloseAudio();
502                 return(-1);
503         }
504
505         /* If the audio driver changes the buffer size, accept it */
506         if ( audio->spec.samples != desired->samples ) {
507                 desired->samples = audio->spec.samples;
508                 SDL_CalculateAudioSpec(desired);
509         }
510
511         /* Allocate a fake audio memory buffer */
512         audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
513         if ( audio->fake_stream == NULL ) {
514                 SDL_CloseAudio();
515                 SDL_OutOfMemory();
516                 return(-1);
517         }
518
519         /* See if we need to do any conversion */
520         if ( obtained != NULL ) {
521                 SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
522         } else if ( desired->freq != audio->spec.freq ||
523                     desired->format != audio->spec.format ||
524                     desired->channels != audio->spec.channels ) {
525                 /* Build an audio conversion block */
526                 if ( SDL_BuildAudioCVT(&audio->convert,
527                         desired->format, desired->channels,
528                                         desired->freq,
529                         audio->spec.format, audio->spec.channels,
530                                         audio->spec.freq) < 0 ) {
531                         SDL_CloseAudio();
532                         return(-1);
533                 }
534                 if ( audio->convert.needed ) {
535                         audio->convert.len = (int) ( ((double) audio->spec.size) /
536                                           audio->convert.len_ratio );
537                         audio->convert.buf =(Uint8 *)SDL_AllocAudioMem(
538                            audio->convert.len*audio->convert.len_mult);
539                         if ( audio->convert.buf == NULL ) {
540                                 SDL_CloseAudio();
541                                 SDL_OutOfMemory();
542                                 return(-1);
543                         }
544                 }
545         }
546
547         /* Start the audio thread if necessary */
548         switch (audio->opened) {
549                 case  1:
550                         /* Start the audio thread */
551 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__)
552 #undef SDL_CreateThread
553                         audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
554 #else
555                         audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
556 #endif
557                         if ( audio->thread == NULL ) {
558                                 SDL_CloseAudio();
559                                 SDL_SetError("Couldn't create audio thread");
560                                 return(-1);
561                         }
562                         break;
563
564                 default:
565                         /* The audio is now playing */
566                         break;
567         }
568
569         return(0);
570 }
571
572 SDL_audiostatus SDL_GetAudioStatus(void)
573 {
574         SDL_AudioDevice *audio = current_audio;
575         SDL_audiostatus status;
576
577         status = SDL_AUDIO_STOPPED;
578         if ( audio && audio->enabled ) {
579                 if ( audio->paused ) {
580                         status = SDL_AUDIO_PAUSED;
581                 } else {
582                         status = SDL_AUDIO_PLAYING;
583                 }
584         }
585         return(status);
586 }
587
588 void SDL_PauseAudio (int pause_on)
589 {
590         SDL_AudioDevice *audio = current_audio;
591
592         if ( audio ) {
593                 audio->paused = pause_on;
594         }
595 }
596
597 void SDL_LockAudio (void)
598 {
599         SDL_AudioDevice *audio = current_audio;
600
601         /* Obtain a lock on the mixing buffers */
602         if ( audio && audio->LockAudio ) {
603                 audio->LockAudio(audio);
604         }
605 }
606
607 void SDL_UnlockAudio (void)
608 {
609         SDL_AudioDevice *audio = current_audio;
610
611         /* Release lock on the mixing buffers */
612         if ( audio && audio->UnlockAudio ) {
613                 audio->UnlockAudio(audio);
614         }
615 }
616
617 void SDL_CloseAudio (void)
618 {
619         SDL_QuitSubSystem(SDL_INIT_AUDIO);
620 }
621
622 void SDL_AudioQuit(void)
623 {
624         SDL_AudioDevice *audio = current_audio;
625
626         if ( audio ) {
627                 audio->enabled = 0;
628                 if ( audio->thread != NULL ) {
629                         SDL_WaitThread(audio->thread, NULL);
630                 }
631                 if ( audio->mixer_lock != NULL ) {
632                         SDL_DestroyMutex(audio->mixer_lock);
633                 }
634                 if ( audio->fake_stream != NULL ) {
635                         SDL_FreeAudioMem(audio->fake_stream);
636                 }
637                 if ( audio->convert.needed ) {
638                         SDL_FreeAudioMem(audio->convert.buf);
639
640                 }
641                 if ( audio->opened ) {
642                         audio->CloseAudio(audio);
643                         audio->opened = 0;
644                 }
645                 /* Free the driver data */
646                 audio->free(audio);
647                 current_audio = NULL;
648         }
649 }
650
651 #define NUM_FORMATS     6
652 static int format_idx;
653 static int format_idx_sub;
654 static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
655  { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
656  { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
657  { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
658  { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
659  { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
660  { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
661 };
662
663 Uint16 SDL_FirstAudioFormat(Uint16 format)
664 {
665         for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) {
666                 if ( format_list[format_idx][0] == format ) {
667                         break;
668                 }
669         }
670         format_idx_sub = 0;
671         return(SDL_NextAudioFormat());
672 }
673
674 Uint16 SDL_NextAudioFormat(void)
675 {
676         if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) {
677                 return(0);
678         }
679         return(format_list[format_idx][format_idx_sub++]);
680 }
681
682 void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
683 {
684         switch (spec->format) {
685                 case AUDIO_U8:
686                         spec->silence = 0x80;
687                         break;
688                 default:
689                         spec->silence = 0x00;
690                         break;
691         }
692         spec->size = (spec->format&0xFF)/8;
693         spec->size *= spec->channels;
694         spec->size *= spec->samples;
695 }