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

流媒体/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_artsaudio.c,v 1.4 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* Allow access to a raw mixing buffer */
  23. #include <sys/types.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include <unistd.h>
  30. #include "SDL_audio.h"
  31. #include "SDL_error.h"
  32. #include "SDL_audiomem.h"
  33. #include "SDL_audio_c.h"
  34. #include "SDL_timer.h"
  35. #include "SDL_audiodev_c.h"
  36. #include "SDL_artsaudio.h"
  37. #ifdef ARTSC_DYNAMIC
  38. #include "SDL_name.h"
  39. #include "SDL_loadso.h"
  40. #else
  41. #define SDL_NAME(X) X
  42. #endif
  43. /* The tag name used by artsc audio */
  44. #define ARTSC_DRIVER_NAME         "artsc"
  45. /* Audio driver functions */
  46. static int ARTSC_OpenAudio(_THIS, SDL_AudioSpec *spec);
  47. static void ARTSC_WaitAudio(_THIS);
  48. static void ARTSC_PlayAudio(_THIS);
  49. static Uint8 *ARTSC_GetAudioBuf(_THIS);
  50. static void ARTSC_CloseAudio(_THIS);
  51. #ifdef ARTSC_DYNAMIC
  52. static const char *arts_library = ARTSC_DYNAMIC;
  53. static void *arts_handle = NULL;
  54. static int arts_loaded = 0;
  55. static int (*SDL_NAME(arts_init))(void);
  56. static void (*SDL_NAME(arts_free))(void);
  57. static arts_stream_t (*SDL_NAME(arts_play_stream))(int rate, int bits, int channels, const char *name);
  58. static int (*SDL_NAME(arts_stream_set))(arts_stream_t s, arts_parameter_t param, int value);
  59. static int (*SDL_NAME(arts_stream_get))(arts_stream_t s, arts_parameter_t param);
  60. static int (*SDL_NAME(arts_write))(arts_stream_t s, const void *buffer, int count);
  61. static void (*SDL_NAME(arts_close_stream))(arts_stream_t s);
  62. static struct {
  63. const char *name;
  64. void **func;
  65. } arts_functions[] = {
  66. { "arts_init", (void **)&SDL_NAME(arts_init) },
  67. { "arts_free", (void **)&SDL_NAME(arts_free) },
  68. { "arts_play_stream", (void **)&SDL_NAME(arts_play_stream) },
  69. { "arts_stream_set", (void **)&SDL_NAME(arts_stream_set) },
  70. { "arts_stream_get", (void **)&SDL_NAME(arts_stream_get) },
  71. { "arts_write", (void **)&SDL_NAME(arts_write) },
  72. { "arts_close_stream", (void **)&SDL_NAME(arts_close_stream) },
  73. };
  74. static void UnloadARTSLibrary()
  75. {
  76. if ( arts_loaded ) {
  77. SDL_UnloadObject(arts_handle);
  78. arts_handle = NULL;
  79. arts_loaded = 0;
  80. }
  81. }
  82. static int LoadARTSLibrary(void)
  83. {
  84. int i, retval = -1;
  85. arts_handle = SDL_LoadObject(arts_library);
  86. if ( arts_handle ) {
  87. arts_loaded = 1;
  88. retval = 0;
  89. for ( i=0; i<SDL_TABLESIZE(arts_functions); ++i ) {
  90. *arts_functions[i].func = SDL_LoadFunction(arts_handle, arts_functions[i].name);
  91. if ( ! arts_functions[i].func ) {
  92. retval = -1;
  93. UnloadARTSLibrary();
  94. break;
  95. }
  96. }
  97. }
  98. return retval;
  99. }
  100. #else
  101. static void UnloadARTSLibrary()
  102. {
  103. return;
  104. }
  105. static int LoadARTSLibrary(void)
  106. {
  107. return 0;
  108. }
  109. #endif /* ARTSC_DYNAMIC */
  110. /* Audio driver bootstrap functions */
  111. static int Audio_Available(void)
  112. {
  113. int available = 0;
  114. if ( LoadARTSLibrary() < 0 ) {
  115. return available;
  116. }
  117. if ( SDL_NAME(arts_init)() == 0 ) {
  118. available = 1;
  119. SDL_NAME(arts_free)();
  120. }
  121. UnloadARTSLibrary();
  122. }
  123. static void Audio_DeleteDevice(SDL_AudioDevice *device)
  124. {
  125. free(device->hidden);
  126. free(device);
  127. UnloadARTSLibrary();
  128. }
  129. static SDL_AudioDevice *Audio_CreateDevice(int devindex)
  130. {
  131. SDL_AudioDevice *this;
  132. /* Initialize all variables that we clean on shutdown */
  133. LoadARTSLibrary();
  134. this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
  135. if ( this ) {
  136. memset(this, 0, (sizeof *this));
  137. this->hidden = (struct SDL_PrivateAudioData *)
  138. malloc((sizeof *this->hidden));
  139. }
  140. if ( (this == NULL) || (this->hidden == NULL) ) {
  141. SDL_OutOfMemory();
  142. if ( this ) {
  143. free(this);
  144. }
  145. return(0);
  146. }
  147. memset(this->hidden, 0, (sizeof *this->hidden));
  148. stream = 0;
  149. /* Set the function pointers */
  150. this->OpenAudio = ARTSC_OpenAudio;
  151. this->WaitAudio = ARTSC_WaitAudio;
  152. this->PlayAudio = ARTSC_PlayAudio;
  153. this->GetAudioBuf = ARTSC_GetAudioBuf;
  154. this->CloseAudio = ARTSC_CloseAudio;
  155. this->free = Audio_DeleteDevice;
  156. return this;
  157. }
  158. AudioBootStrap ARTSC_bootstrap = {
  159. ARTSC_DRIVER_NAME, "Analog Realtime Synthesizer",
  160. Audio_Available, Audio_CreateDevice
  161. };
  162. /* This function waits until it is possible to write a full sound buffer */
  163. static void ARTSC_WaitAudio(_THIS)
  164. {
  165. Sint32 ticks;
  166. /* Check to see if the thread-parent process is still alive */
  167. { static int cnt = 0;
  168. /* Note that this only works with thread implementations 
  169.    that use a different process id for each thread.
  170. */
  171. if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */
  172. if ( kill(parent, 0) < 0 ) {
  173. this->enabled = 0;
  174. }
  175. }
  176. }
  177. /* Use timer for general audio synchronization */
  178. ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS;
  179. if ( ticks > 0 ) {
  180. SDL_Delay(ticks);
  181. }
  182. }
  183. static void ARTSC_PlayAudio(_THIS)
  184. {
  185. int written;
  186. /* Write the audio data */
  187. written = SDL_NAME(arts_write)(stream, mixbuf, mixlen);
  188. /* If timer synchronization is enabled, set the next write frame */
  189. if ( frame_ticks ) {
  190. next_frame += frame_ticks;
  191. }
  192. /* If we couldn't write, assume fatal error for now */
  193. if ( written < 0 ) {
  194. this->enabled = 0;
  195. }
  196. #ifdef DEBUG_AUDIO
  197. fprintf(stderr, "Wrote %d bytes of audio datan", written);
  198. #endif
  199. }
  200. static Uint8 *ARTSC_GetAudioBuf(_THIS)
  201. {
  202. return(mixbuf);
  203. }
  204. static void ARTSC_CloseAudio(_THIS)
  205. {
  206. if ( mixbuf != NULL ) {
  207. SDL_FreeAudioMem(mixbuf);
  208. mixbuf = NULL;
  209. }
  210. if ( stream ) {
  211. SDL_NAME(arts_close_stream)(stream);
  212. stream = 0;
  213. }
  214. SDL_NAME(arts_free)();
  215. }
  216. static int ARTSC_OpenAudio(_THIS, SDL_AudioSpec *spec)
  217. {
  218. int bits, frag_spec;
  219. Uint16 test_format, format;
  220. /* Reset the timer synchronization flag */
  221. frame_ticks = 0.0;
  222. mixbuf = NULL;
  223. /* Try for a closest match on audio format */
  224. format = 0;
  225. bits = 0;
  226. for ( test_format = SDL_FirstAudioFormat(spec->format);
  227. ! format && test_format; ) {
  228. #ifdef DEBUG_AUDIO
  229. fprintf(stderr, "Trying format 0x%4.4xn", test_format);
  230. #endif
  231. switch ( test_format ) {
  232. case AUDIO_U8:
  233. bits = 8;
  234. format = 1;
  235. break;
  236. case AUDIO_S16LSB:
  237. bits = 16;
  238. format = 1;
  239. break;
  240. default:
  241. format = 0;
  242. break;
  243. }
  244. if ( ! format ) {
  245. test_format = SDL_NextAudioFormat();
  246. }
  247. }
  248. if ( format == 0 ) {
  249. SDL_SetError("Couldn't find any hardware audio formats");
  250. return(-1);
  251. }
  252. spec->format = test_format;
  253. if ( SDL_NAME(arts_init)() != 0 ) {
  254. SDL_SetError("Unable to initialize ARTS");
  255. return(-1);
  256. }
  257. stream = SDL_NAME(arts_play_stream)(spec->freq, bits, spec->channels, "SDL");
  258. /* Calculate the final parameters for this audio specification */
  259. SDL_CalculateAudioSpec(spec);
  260. /* Determine the power of two of the fragment size */
  261. for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec );
  262. if ( (0x01<<frag_spec) != spec->size ) {
  263. SDL_SetError("Fragment size must be a power of two");
  264. return(-1);
  265. }
  266. frag_spec |= 0x00020000; /* two fragments, for low latency */
  267. #ifdef ARTS_P_PACKET_SETTINGS
  268. SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SETTINGS, frag_spec);
  269. #else
  270. SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff);
  271. SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_COUNT, frag_spec>>16);
  272. #endif
  273. spec->size = SDL_NAME(arts_stream_get)(stream, ARTS_P_PACKET_SIZE);
  274. /* Allocate mixing buffer */
  275. mixlen = spec->size;
  276. mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
  277. if ( mixbuf == NULL ) {
  278. return(-1);
  279. }
  280. memset(mixbuf, spec->silence, spec->size);
  281. /* Get the parent process id (we're the parent of the audio thread) */
  282. parent = getpid();
  283. /* We're ready to rock and roll. :-) */
  284. return(0);
  285. }