SDL_audio.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:15k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_audio.c,v 1.4 2002/04/22 21:38:01 wmay Exp $";
  21. #endif
  22. /* Allow access to a raw mixing buffer */
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "SDL.h"
  27. #include "SDL_audio.h"
  28. #include "SDL_timer.h"
  29. #include "SDL_error.h"
  30. #include "SDL_audio_c.h"
  31. #include "SDL_audiomem.h"
  32. #include "SDL_sysaudio.h"
  33. /* Available audio drivers */
  34. static AudioBootStrap *bootstrap[] = {
  35. #ifdef OPENBSD_AUDIO_SUPPORT
  36. &OPENBSD_AUDIO_bootstrap,
  37. #endif
  38. #ifdef OSS_SUPPORT
  39. &DSP_bootstrap,
  40. &DMA_bootstrap,
  41. #endif
  42. #ifdef ALSA_SUPPORT
  43. &ALSA_bootstrap,
  44. #endif
  45. #ifdef SUNAUDIO_SUPPORT
  46. &SUNAUDIO_bootstrap,
  47. #endif
  48. #ifdef DMEDIA_SUPPORT
  49. &DMEDIA_bootstrap,
  50. #endif
  51. #ifdef ARTSC_SUPPORT
  52. &ARTSC_bootstrap,
  53. #endif
  54. #ifdef ESD_SUPPORT
  55. &ESD_bootstrap,
  56. #endif
  57. #ifdef NAS_SUPPORT
  58. &NAS_bootstrap,
  59. #endif
  60. #ifdef ENABLE_DIRECTX
  61. &DSOUND_bootstrap,
  62. #endif
  63. #ifdef ENABLE_WINDIB
  64. &WAVEOUT_bootstrap,
  65. #endif
  66. #ifdef __BEOS__
  67. &BAUDIO_bootstrap,
  68. #endif
  69. #if defined(macintosh) || TARGET_API_MAC_CARBON
  70. &SNDMGR_bootstrap,
  71. #endif
  72. #ifdef _AIX
  73. &Paud_bootstrap,
  74. #endif
  75. #ifdef ENABLE_AHI
  76. &AHI_bootstrap,
  77. #endif
  78. #ifdef DISKAUD_SUPPORT
  79. &DISKAUD_bootstrap,
  80. #endif
  81. NULL
  82. };
  83. SDL_AudioDevice *current_audio = NULL;
  84. /* Various local functions */
  85. int SDL_AudioInit(const char *driver_name);
  86. void SDL_AudioQuit(void);
  87. #ifdef ENABLE_AHI
  88. static int audio_configured = 0;
  89. #endif
  90. /* The general mixing thread function */
  91. int SDL_RunAudio(void *audiop)
  92. {
  93. SDL_AudioDevice *audio = (SDL_AudioDevice *)audiop;
  94. Uint8 *stream;
  95. int    stream_len;
  96. void  *udata;
  97. void (*fill)(void *userdata,Uint8 *stream, int len);
  98. int    silence;
  99. #ifdef ENABLE_AHI
  100. int started = 0;
  101. /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
  102. D(bug("Task audio started audio struct:<%lx>...n",audiop));
  103. D(bug("Before Openaudio..."));
  104. if(audio->OpenAudio(audio, &audio->spec)==-1)
  105. {
  106. D(bug("Open audio failed...n"));
  107. return(-1);
  108. }
  109. D(bug("OpenAudio...OKn"));
  110. #endif
  111. /* Perform any thread setup */
  112. if ( audio->ThreadInit ) {
  113. audio->ThreadInit(audio);
  114. }
  115. audio->threadid = SDL_ThreadID();
  116. /* Set up the mixing function */
  117. fill  = audio->spec.callback;
  118. udata = audio->spec.userdata;
  119. #ifdef ENABLE_AHI
  120. audio_configured = 1;
  121. D(bug("Audio configured... Checking for conversionn"));
  122. SDL_mutexP(audio->mixer_lock);
  123. D(bug("Semaphore obtained...n"));
  124. #endif
  125. if ( audio->convert.needed ) {
  126. if ( audio->convert.src_format == AUDIO_U8 ) {
  127. silence = 0x80;
  128. } else {
  129. silence = 0;
  130. }
  131. stream_len = audio->convert.len;
  132. } else {
  133. silence = audio->spec.silence;
  134. stream_len = audio->spec.size;
  135. }
  136. stream = audio->fake_stream;
  137. #ifdef ENABLE_AHI
  138. SDL_mutexV(audio->mixer_lock);
  139. D(bug("Entering audio loop...n"));
  140. #endif
  141. /* Loop, filling the audio buffers */
  142. while ( audio->enabled ) {
  143. /* Wait for new current buffer to finish playing */
  144. if ( stream == audio->fake_stream ) {
  145. SDL_Delay((audio->spec.samples*1000)/audio->spec.freq);
  146. } else {
  147. #ifdef ENABLE_AHI
  148. if ( started > 1 )
  149. #endif
  150. audio->WaitAudio(audio);
  151. }
  152. /* Fill the current buffer with sound */
  153. if ( audio->convert.needed ) {
  154. if ( audio->convert.buf ) {
  155. stream = audio->convert.buf;
  156. } else {
  157. continue;
  158. }
  159. } else {
  160. stream = audio->GetAudioBuf(audio);
  161. if ( stream == NULL ) {
  162. stream = audio->fake_stream;
  163. }
  164. }
  165. memset(stream, silence, stream_len);
  166. if ( ! audio->paused ) {
  167. SDL_mutexP(audio->mixer_lock);
  168. (*fill)(udata, stream, stream_len);
  169. SDL_mutexV(audio->mixer_lock);
  170. }
  171. /* Convert the audio if necessary */
  172. if ( audio->convert.needed ) {
  173. SDL_ConvertAudio(&audio->convert);
  174. stream = audio->GetAudioBuf(audio);
  175. if ( stream == NULL ) {
  176. stream = audio->fake_stream;
  177. }
  178. memcpy(stream, audio->convert.buf,
  179.                audio->convert.len_cvt);
  180. }
  181. /* Ready current buffer for play and change current buffer */
  182. if ( stream != audio->fake_stream ) {
  183. audio->PlayAudio(audio);
  184. #ifdef ENABLE_AHI
  185. /* AmigaOS don't have to wait the first time audio is played! */
  186. started++;
  187. #endif
  188. }
  189. }
  190. /* Wait for the audio to drain.. */
  191. if ( audio->WaitDone ) {
  192. audio->WaitDone(audio);
  193. }
  194. #ifdef ENABLE_AHI
  195. D(bug("WaitAudio...Donen"));
  196. audio->CloseAudio(audio);
  197. D(bug("CloseAudio..Done, subtask exiting...n"));
  198. audio_configured = 0;
  199. #endif
  200. return(0);
  201. }
  202. static void SDL_LockAudio_Default(SDL_AudioDevice *audio)
  203. {
  204. if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
  205. return;
  206. }
  207. SDL_mutexP(audio->mixer_lock);
  208. }
  209. static void SDL_UnlockAudio_Default(SDL_AudioDevice *audio)
  210. {
  211. if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) {
  212. return;
  213. }
  214. SDL_mutexV(audio->mixer_lock);
  215. }
  216. int SDL_AudioInit(const char *driver_name)
  217. {
  218. SDL_AudioDevice *audio;
  219. int i = 0, idx;
  220. /* Check to make sure we don't overwrite 'current_audio' */
  221. if ( current_audio != NULL ) {
  222. SDL_AudioQuit();
  223. }
  224. /* Select the proper audio driver */
  225. audio = NULL;
  226. idx = 0;
  227. #ifdef unix
  228. if ( (driver_name == NULL) && (getenv("ESPEAKER") != NULL) ) {
  229. /* Ahem, we know that if ESPEAKER is set, user probably wants
  230.    to use ESD, but don't start it if it's not already running.
  231.    This probably isn't the place to do this, but... Shh! :)
  232.  */
  233. for ( i=0; bootstrap[i]; ++i ) {
  234. if ( strcmp(bootstrap[i]->name, "esd") == 0 ) {
  235. const char *esd_no_spawn;
  236. /* Don't start ESD if it's not running */
  237. esd_no_spawn = getenv("ESD_NO_SPAWN");
  238. if ( esd_no_spawn == NULL ) {
  239. putenv("ESD_NO_SPAWN=1");
  240. }
  241. if ( bootstrap[i]->available() ) {
  242. audio = bootstrap[i]->create(0);
  243. break;
  244. }
  245. #ifdef linux /* No unsetenv() on most platforms */
  246. if ( esd_no_spawn == NULL ) {
  247. unsetenv("ESD_NO_SPAWN");
  248. }
  249. #endif
  250. }
  251. }
  252. }
  253. #endif /* unix */
  254. if ( audio == NULL ) {
  255. if ( driver_name != NULL ) {
  256. #if 0 /* This will be replaced with a better driver selection API */
  257. if ( strrchr(driver_name, ':') != NULL ) {
  258. idx = atoi(strrchr(driver_name, ':')+1);
  259. }
  260. #endif
  261. for ( i=0; bootstrap[i]; ++i ) {
  262. if (strncmp(bootstrap[i]->name, driver_name,
  263.             strlen(bootstrap[i]->name)) == 0) {
  264. if ( bootstrap[i]->available() ) {
  265. audio=bootstrap[i]->create(idx);
  266. break;
  267. }
  268. }
  269. }
  270. } else {
  271. for ( i=0; bootstrap[i]; ++i ) {
  272. if ( bootstrap[i]->available() ) {
  273. audio = bootstrap[i]->create(idx);
  274. if ( audio != NULL ) {
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. if ( audio == NULL ) {
  281. SDL_SetError("No available audio device");
  282. #if 0 /* Don't fail SDL_Init() if audio isn't available.
  283.          SDL_OpenAudio() will handle it at that point.  *sigh*
  284.        */
  285. return(-1);
  286. #endif
  287. }
  288. }
  289. current_audio = audio;
  290. if ( current_audio ) {
  291. current_audio->name = bootstrap[i]->name;
  292. if ( !current_audio->LockAudio && !current_audio->UnlockAudio ) {
  293. current_audio->LockAudio = SDL_LockAudio_Default;
  294. current_audio->UnlockAudio = SDL_UnlockAudio_Default;
  295. }
  296. }
  297. return(0);
  298. }
  299. char *SDL_AudioDriverName(char *namebuf, int maxlen)
  300. {
  301. if ( current_audio != NULL ) {
  302. strncpy(namebuf, current_audio->name, maxlen-1);
  303. namebuf[maxlen-1] = '';
  304. return(namebuf);
  305. }
  306. return(NULL);
  307. }
  308. int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
  309. {
  310. SDL_AudioDevice *audio;
  311. /* Start up the audio driver, if necessary */
  312. if ( ! current_audio ) {
  313. if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
  314.      (current_audio == NULL) ) {
  315. return(-1);
  316. }
  317. }
  318. audio = current_audio;
  319. if (audio->opened) {
  320. SDL_SetError("Audio device is already opened");
  321. return(-1);
  322. }
  323. /* Verify some parameters */
  324. if ( desired->callback == NULL ) {
  325. SDL_SetError("SDL_OpenAudio() passed a NULL callback");
  326. return(-1);
  327. }
  328. switch ( desired->channels ) {
  329.     case 1: /* Mono */
  330.     case 2: /* Stereo */
  331. break;
  332.     default:
  333. SDL_SetError("1 (mono) and 2 (stereo) channels supported");
  334. return(-1);
  335. }
  336. #ifdef macintosh
  337. /* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */
  338. #else
  339. /* Create a semaphore for locking the sound buffers */
  340. audio->mixer_lock = SDL_CreateMutex();
  341. if ( audio->mixer_lock == NULL ) {
  342. SDL_SetError("Couldn't create mixer lock");
  343. SDL_CloseAudio();
  344. return(-1);
  345. }
  346. #endif
  347. /* Calculate the silence and size of the audio specification */
  348. SDL_CalculateAudioSpec(desired);
  349. /* Open the audio subsystem */
  350. memcpy(&audio->spec, desired, sizeof(audio->spec));
  351. audio->convert.needed = 0;
  352. audio->enabled = 1;
  353. audio->paused  = 1;
  354. #ifndef ENABLE_AHI
  355. /* AmigaOS opens audio inside the main loop */
  356. audio->opened = audio->OpenAudio(audio, &audio->spec)+1;
  357. if ( ! audio->opened ) {
  358. SDL_CloseAudio();
  359. return(-1);
  360. }
  361. #else
  362. D(bug("Locking semaphore..."));
  363. SDL_mutexP(audio->mixer_lock);
  364. audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
  365. D(bug("Created thread...n"));
  366. if ( audio->thread == NULL ) {
  367. SDL_mutexV(audio->mixer_lock);
  368. SDL_CloseAudio();
  369. SDL_SetError("Couldn't create audio thread");
  370. return(-1);
  371. }
  372. while(!audio_configured)
  373. SDL_Delay(100);
  374. #endif
  375. /* If the audio driver changes the buffer size, accept it */
  376. if ( audio->spec.samples != desired->samples ) {
  377. desired->samples = audio->spec.samples;
  378. SDL_CalculateAudioSpec(desired);
  379. }
  380. /* Allocate a fake audio memory buffer */
  381. audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
  382. if ( audio->fake_stream == NULL ) {
  383. SDL_CloseAudio();
  384. SDL_OutOfMemory();
  385. return(-1);
  386. }
  387. /* See if we need to do any conversion */
  388. if ( memcmp(desired, &audio->spec, sizeof(audio->spec)) == 0 ) {
  389. /* Just copy over the desired audio specification */
  390. if ( obtained != NULL ) {
  391. memcpy(obtained, &audio->spec, sizeof(audio->spec));
  392. }
  393. } else {
  394. /* Copy over the audio specification if possible */
  395. if ( obtained != NULL ) {
  396. memcpy(obtained, &audio->spec, sizeof(audio->spec));
  397. } else {
  398. /* Build an audio conversion block */
  399. if ( SDL_BuildAudioCVT(&audio->convert,
  400. desired->format, desired->channels,
  401. desired->freq,
  402. audio->spec.format, audio->spec.channels,
  403. audio->spec.freq) < 0 ) {
  404. SDL_CloseAudio();
  405. return(-1);
  406. }
  407. if ( audio->convert.needed ) {
  408. audio->convert.len = desired->size;
  409. audio->convert.buf =(Uint8 *)SDL_AllocAudioMem(
  410.    audio->convert.len*audio->convert.len_mult);
  411. if ( audio->convert.buf == NULL ) {
  412. SDL_CloseAudio();
  413. SDL_OutOfMemory();
  414. return(-1);
  415. }
  416. }
  417. }
  418. }
  419. #ifndef ENABLE_AHI
  420. /* Start the audio thread if necessary */
  421. switch (audio->opened) {
  422. case  1:
  423. /* Start the audio thread */
  424. audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
  425. if ( audio->thread == NULL ) {
  426. SDL_CloseAudio();
  427. SDL_SetError("Couldn't create audio thread");
  428. return(-1);
  429. }
  430. break;
  431. default:
  432. /* The audio is now playing */
  433. break;
  434. }
  435. #else
  436. SDL_mutexV(audio->mixer_lock);
  437. D(bug("SDL_OpenAudio USCITA...n"));
  438. #endif
  439. return(0);
  440. }
  441. SDL_audiostatus SDL_GetAudioStatus(void)
  442. {
  443. SDL_AudioDevice *audio = current_audio;
  444. SDL_audiostatus status;
  445. status = SDL_AUDIO_STOPPED;
  446. if ( audio && audio->enabled ) {
  447. if ( audio->paused ) {
  448. status = SDL_AUDIO_PAUSED;
  449. } else {
  450. status = SDL_AUDIO_PLAYING;
  451. }
  452. }
  453. return(status);
  454. }
  455. void SDL_PauseAudio (int pause_on)
  456. {
  457. SDL_AudioDevice *audio = current_audio;
  458. if ( audio ) {
  459. audio->paused = pause_on;
  460. }
  461. }
  462. void SDL_LockAudio (void)
  463. {
  464. SDL_AudioDevice *audio = current_audio;
  465. /* Obtain a lock on the mixing buffers */
  466. if ( audio && audio->LockAudio ) {
  467. audio->LockAudio(audio);
  468. }
  469. }
  470. void SDL_UnlockAudio (void)
  471. {
  472. SDL_AudioDevice *audio = current_audio;
  473. /* Release lock on the mixing buffers */
  474. if ( audio && audio->UnlockAudio ) {
  475. audio->UnlockAudio(audio);
  476. }
  477. }
  478. void SDL_CloseAudio (void)
  479. {
  480. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  481. }
  482. int SDL_HasAudioDelayMsec (void)
  483. {
  484.   SDL_AudioDevice *audio = current_audio;
  485.   if (audio && audio->AudioDelayMsec != NULL) {
  486.     return 1;
  487.   }
  488.   return 0;
  489. }
  490. int SDL_AudioDelayMsec (void)
  491. {
  492.   SDL_AudioDevice *audio = current_audio;
  493.   if (audio && audio->AudioDelayMsec != NULL) {
  494.     return (audio->AudioDelayMsec(audio));
  495.   } else {
  496.     return (-1);
  497.    }
  498. }
  499. void SDL_AudioQuit(void)
  500. {
  501. SDL_AudioDevice *audio = current_audio;
  502. if ( audio ) {
  503. audio->enabled = 0;
  504. if ( audio->thread != NULL ) {
  505. SDL_WaitThread(audio->thread, NULL);
  506. }
  507. if ( audio->mixer_lock != NULL ) {
  508. SDL_DestroyMutex(audio->mixer_lock);
  509. }
  510. if ( audio->fake_stream != NULL ) {
  511. SDL_FreeAudioMem(audio->fake_stream);
  512. }
  513. if ( audio->convert.needed ) {
  514. SDL_FreeAudioMem(audio->convert.buf);
  515. }
  516. #ifndef ENABLE_AHI
  517. if ( audio->opened ) {
  518. audio->CloseAudio(audio);
  519. audio->opened = 0;
  520. }
  521. #endif
  522. /* Free the driver data */
  523. audio->free(audio);
  524. current_audio = NULL;
  525. }
  526. }
  527. #define NUM_FORMATS 6
  528. static int format_idx;
  529. static int format_idx_sub;
  530. static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = {
  531.  { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
  532.  { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB },
  533.  { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
  534.  { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
  535.  { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
  536.  { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
  537. };
  538. Uint16 SDL_FirstAudioFormat(Uint16 format)
  539. {
  540. for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) {
  541. if ( format_list[format_idx][0] == format ) {
  542. break;
  543. }
  544. }
  545. format_idx_sub = 0;
  546. return(SDL_NextAudioFormat());
  547. }
  548. Uint16 SDL_NextAudioFormat(void)
  549. {
  550. if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) {
  551. return(0);
  552. }
  553. return(format_list[format_idx][format_idx_sub++]);
  554. }
  555. void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
  556. {
  557. switch (spec->format) {
  558. case AUDIO_U8:
  559. spec->silence = 0x80;
  560. break;
  561. default:
  562. spec->silence = 0x00;
  563. break;
  564. }
  565. spec->size = (spec->format&0xFF)/8;
  566. spec->size *= spec->channels;
  567. spec->size *= spec->samples;
  568. }