Mercurial > sdl-ios-xcode
comparison src/audio/dsp/SDL_dspaudio.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | 97d0966f4bf7 |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
24 */ | 24 */ |
25 #include "SDL_config.h" | 25 #include "SDL_config.h" |
26 | 26 |
27 /* Allow access to a raw mixing buffer */ | 27 /* Allow access to a raw mixing buffer */ |
28 | 28 |
29 #include <stdio.h> /* For perror() */ | 29 #include <stdio.h> /* For perror() */ |
30 #include <string.h> /* For strerror() */ | 30 #include <string.h> /* For strerror() */ |
31 #include <errno.h> | 31 #include <errno.h> |
32 #include <unistd.h> | 32 #include <unistd.h> |
33 #include <fcntl.h> | 33 #include <fcntl.h> |
34 #include <signal.h> | 34 #include <signal.h> |
35 #include <sys/time.h> | 35 #include <sys/time.h> |
56 | 56 |
57 /* Open the audio device for playback, and don't block if busy */ | 57 /* Open the audio device for playback, and don't block if busy */ |
58 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) | 58 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) |
59 | 59 |
60 /* Audio driver functions */ | 60 /* Audio driver functions */ |
61 static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec); | 61 static int DSP_OpenAudio (_THIS, SDL_AudioSpec * spec); |
62 static void DSP_WaitAudio(_THIS); | 62 static void DSP_WaitAudio (_THIS); |
63 static void DSP_PlayAudio(_THIS); | 63 static void DSP_PlayAudio (_THIS); |
64 static Uint8 *DSP_GetAudioBuf(_THIS); | 64 static Uint8 *DSP_GetAudioBuf (_THIS); |
65 static void DSP_CloseAudio(_THIS); | 65 static void DSP_CloseAudio (_THIS); |
66 | 66 |
67 /* Audio driver bootstrap functions */ | 67 /* Audio driver bootstrap functions */ |
68 | 68 |
69 static int Audio_Available(void) | 69 static int |
70 { | 70 Audio_Available (void) |
71 int fd; | 71 { |
72 int available; | 72 int fd; |
73 | 73 int available; |
74 available = 0; | 74 |
75 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | 75 available = 0; |
76 if ( fd >= 0 ) { | 76 fd = SDL_OpenAudioPath (NULL, 0, OPEN_FLAGS, 0); |
77 available = 1; | 77 if (fd >= 0) { |
78 close(fd); | 78 available = 1; |
79 } | 79 close (fd); |
80 return(available); | 80 } |
81 } | 81 return (available); |
82 | 82 } |
83 static void Audio_DeleteDevice(SDL_AudioDevice *device) | 83 |
84 { | 84 static void |
85 SDL_free(device->hidden); | 85 Audio_DeleteDevice (SDL_AudioDevice * device) |
86 SDL_free(device); | 86 { |
87 } | 87 SDL_free (device->hidden); |
88 | 88 SDL_free (device); |
89 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | 89 } |
90 { | 90 |
91 SDL_AudioDevice *this; | 91 static SDL_AudioDevice * |
92 | 92 Audio_CreateDevice (int devindex) |
93 /* Initialize all variables that we clean on shutdown */ | 93 { |
94 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 94 SDL_AudioDevice *this; |
95 if ( this ) { | 95 |
96 SDL_memset(this, 0, (sizeof *this)); | 96 /* Initialize all variables that we clean on shutdown */ |
97 this->hidden = (struct SDL_PrivateAudioData *) | 97 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); |
98 SDL_malloc((sizeof *this->hidden)); | 98 if (this) { |
99 } | 99 SDL_memset (this, 0, (sizeof *this)); |
100 if ( (this == NULL) || (this->hidden == NULL) ) { | 100 this->hidden = (struct SDL_PrivateAudioData *) |
101 SDL_OutOfMemory(); | 101 SDL_malloc ((sizeof *this->hidden)); |
102 if ( this ) { | 102 } |
103 SDL_free(this); | 103 if ((this == NULL) || (this->hidden == NULL)) { |
104 } | 104 SDL_OutOfMemory (); |
105 return(0); | 105 if (this) { |
106 } | 106 SDL_free (this); |
107 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 107 } |
108 audio_fd = -1; | 108 return (0); |
109 | 109 } |
110 /* Set the function pointers */ | 110 SDL_memset (this->hidden, 0, (sizeof *this->hidden)); |
111 this->OpenAudio = DSP_OpenAudio; | 111 audio_fd = -1; |
112 this->WaitAudio = DSP_WaitAudio; | 112 |
113 this->PlayAudio = DSP_PlayAudio; | 113 /* Set the function pointers */ |
114 this->GetAudioBuf = DSP_GetAudioBuf; | 114 this->OpenAudio = DSP_OpenAudio; |
115 this->CloseAudio = DSP_CloseAudio; | 115 this->WaitAudio = DSP_WaitAudio; |
116 | 116 this->PlayAudio = DSP_PlayAudio; |
117 this->free = Audio_DeleteDevice; | 117 this->GetAudioBuf = DSP_GetAudioBuf; |
118 | 118 this->CloseAudio = DSP_CloseAudio; |
119 return this; | 119 |
120 this->free = Audio_DeleteDevice; | |
121 | |
122 return this; | |
120 } | 123 } |
121 | 124 |
122 AudioBootStrap DSP_bootstrap = { | 125 AudioBootStrap DSP_bootstrap = { |
123 DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", | 126 DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", |
124 Audio_Available, Audio_CreateDevice | 127 Audio_Available, Audio_CreateDevice |
125 }; | 128 }; |
126 | 129 |
127 /* This function waits until it is possible to write a full sound buffer */ | 130 /* This function waits until it is possible to write a full sound buffer */ |
128 static void DSP_WaitAudio(_THIS) | 131 static void |
129 { | 132 DSP_WaitAudio (_THIS) |
130 /* Not needed at all since OSS handles waiting automagically */ | 133 { |
131 } | 134 /* Not needed at all since OSS handles waiting automagically */ |
132 | 135 } |
133 static void DSP_PlayAudio(_THIS) | 136 |
134 { | 137 static void |
135 if (write(audio_fd, mixbuf, mixlen)==-1) | 138 DSP_PlayAudio (_THIS) |
136 { | 139 { |
137 perror("Audio write"); | 140 if (write (audio_fd, mixbuf, mixlen) == -1) { |
138 this->enabled = 0; | 141 perror ("Audio write"); |
139 } | 142 this->enabled = 0; |
140 | 143 } |
141 #ifdef DEBUG_AUDIO | 144 #ifdef DEBUG_AUDIO |
142 fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); | 145 fprintf (stderr, "Wrote %d bytes of audio data\n", mixlen); |
143 #endif | 146 #endif |
144 } | 147 } |
145 | 148 |
146 static Uint8 *DSP_GetAudioBuf(_THIS) | 149 static Uint8 * |
147 { | 150 DSP_GetAudioBuf (_THIS) |
148 return(mixbuf); | 151 { |
149 } | 152 return (mixbuf); |
150 | 153 } |
151 static void DSP_CloseAudio(_THIS) | 154 |
152 { | 155 static void |
153 if ( mixbuf != NULL ) { | 156 DSP_CloseAudio (_THIS) |
154 SDL_FreeAudioMem(mixbuf); | 157 { |
155 mixbuf = NULL; | 158 if (mixbuf != NULL) { |
156 } | 159 SDL_FreeAudioMem (mixbuf); |
157 if ( audio_fd >= 0 ) { | 160 mixbuf = NULL; |
158 close(audio_fd); | 161 } |
159 audio_fd = -1; | 162 if (audio_fd >= 0) { |
160 } | 163 close (audio_fd); |
161 } | 164 audio_fd = -1; |
162 | 165 } |
163 static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec) | 166 } |
164 { | 167 |
165 char audiodev[1024]; | 168 static int |
166 int format; | 169 DSP_OpenAudio (_THIS, SDL_AudioSpec * spec) |
167 int value; | 170 { |
168 int frag_spec; | 171 char audiodev[1024]; |
169 Uint16 test_format; | 172 int format; |
170 | 173 int value; |
171 /* Open the audio device */ | 174 int frag_spec; |
172 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | 175 Uint16 test_format; |
173 if ( audio_fd < 0 ) { | 176 |
174 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | 177 /* Open the audio device */ |
175 return(-1); | 178 audio_fd = SDL_OpenAudioPath (audiodev, sizeof (audiodev), OPEN_FLAGS, 0); |
176 } | 179 if (audio_fd < 0) { |
177 mixbuf = NULL; | 180 SDL_SetError ("Couldn't open %s: %s", audiodev, strerror (errno)); |
178 | 181 return (-1); |
179 /* Make the file descriptor use blocking writes with fcntl() */ | 182 } |
180 { long flags; | 183 mixbuf = NULL; |
181 flags = fcntl(audio_fd, F_GETFL); | 184 |
182 flags &= ~O_NONBLOCK; | 185 /* Make the file descriptor use blocking writes with fcntl() */ |
183 if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) { | 186 { |
184 SDL_SetError("Couldn't set audio blocking mode"); | 187 long flags; |
185 DSP_CloseAudio(this); | 188 flags = fcntl (audio_fd, F_GETFL); |
186 return(-1); | 189 flags &= ~O_NONBLOCK; |
187 } | 190 if (fcntl (audio_fd, F_SETFL, flags) < 0) { |
188 } | 191 SDL_SetError ("Couldn't set audio blocking mode"); |
189 | 192 DSP_CloseAudio (this); |
190 /* Get a list of supported hardware formats */ | 193 return (-1); |
191 if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { | 194 } |
192 perror("SNDCTL_DSP_GETFMTS"); | 195 } |
193 SDL_SetError("Couldn't get audio format list"); | 196 |
194 DSP_CloseAudio(this); | 197 /* Get a list of supported hardware formats */ |
195 return(-1); | 198 if (ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) { |
196 } | 199 perror ("SNDCTL_DSP_GETFMTS"); |
197 | 200 SDL_SetError ("Couldn't get audio format list"); |
198 /* Try for a closest match on audio format */ | 201 DSP_CloseAudio (this); |
199 format = 0; | 202 return (-1); |
200 for ( test_format = SDL_FirstAudioFormat(spec->format); | 203 } |
201 ! format && test_format; ) { | 204 |
205 /* Try for a closest match on audio format */ | |
206 format = 0; | |
207 for (test_format = SDL_FirstAudioFormat (spec->format); | |
208 !format && test_format;) { | |
202 #ifdef DEBUG_AUDIO | 209 #ifdef DEBUG_AUDIO |
203 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); | 210 fprintf (stderr, "Trying format 0x%4.4x\n", test_format); |
204 #endif | 211 #endif |
205 switch ( test_format ) { | 212 switch (test_format) { |
206 case AUDIO_U8: | 213 case AUDIO_U8: |
207 if ( value & AFMT_U8 ) { | 214 if (value & AFMT_U8) { |
208 format = AFMT_U8; | 215 format = AFMT_U8; |
209 } | 216 } |
210 break; | 217 break; |
211 case AUDIO_S16LSB: | 218 case AUDIO_S16LSB: |
212 if ( value & AFMT_S16_LE ) { | 219 if (value & AFMT_S16_LE) { |
213 format = AFMT_S16_LE; | 220 format = AFMT_S16_LE; |
214 } | 221 } |
215 break; | 222 break; |
216 case AUDIO_S16MSB: | 223 case AUDIO_S16MSB: |
217 if ( value & AFMT_S16_BE ) { | 224 if (value & AFMT_S16_BE) { |
218 format = AFMT_S16_BE; | 225 format = AFMT_S16_BE; |
219 } | 226 } |
220 break; | 227 break; |
221 #if 0 | 228 #if 0 |
222 /* | 229 /* |
223 * These formats are not used by any real life systems so they are not | 230 * These formats are not used by any real life systems so they are not |
224 * needed here. | 231 * needed here. |
225 */ | 232 */ |
226 case AUDIO_S8: | 233 case AUDIO_S8: |
227 if ( value & AFMT_S8 ) { | 234 if (value & AFMT_S8) { |
228 format = AFMT_S8; | 235 format = AFMT_S8; |
229 } | 236 } |
230 break; | 237 break; |
231 case AUDIO_U16LSB: | 238 case AUDIO_U16LSB: |
232 if ( value & AFMT_U16_LE ) { | 239 if (value & AFMT_U16_LE) { |
233 format = AFMT_U16_LE; | 240 format = AFMT_U16_LE; |
234 } | 241 } |
235 break; | 242 break; |
236 case AUDIO_U16MSB: | 243 case AUDIO_U16MSB: |
237 if ( value & AFMT_U16_BE ) { | 244 if (value & AFMT_U16_BE) { |
238 format = AFMT_U16_BE; | 245 format = AFMT_U16_BE; |
239 } | 246 } |
240 break; | 247 break; |
241 #endif | 248 #endif |
242 default: | 249 default: |
243 format = 0; | 250 format = 0; |
244 break; | 251 break; |
245 } | 252 } |
246 if ( ! format ) { | 253 if (!format) { |
247 test_format = SDL_NextAudioFormat(); | 254 test_format = SDL_NextAudioFormat (); |
248 } | 255 } |
249 } | 256 } |
250 if ( format == 0 ) { | 257 if (format == 0) { |
251 SDL_SetError("Couldn't find any hardware audio formats"); | 258 SDL_SetError ("Couldn't find any hardware audio formats"); |
252 DSP_CloseAudio(this); | 259 DSP_CloseAudio (this); |
253 return(-1); | 260 return (-1); |
254 } | 261 } |
255 spec->format = test_format; | 262 spec->format = test_format; |
256 | 263 |
257 /* Set the audio format */ | 264 /* Set the audio format */ |
258 value = format; | 265 value = format; |
259 if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || | 266 if ((ioctl (audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || |
260 (value != format) ) { | 267 (value != format)) { |
261 perror("SNDCTL_DSP_SETFMT"); | 268 perror ("SNDCTL_DSP_SETFMT"); |
262 SDL_SetError("Couldn't set audio format"); | 269 SDL_SetError ("Couldn't set audio format"); |
263 DSP_CloseAudio(this); | 270 DSP_CloseAudio (this); |
264 return(-1); | 271 return (-1); |
265 } | 272 } |
266 | 273 |
267 /* Set the number of channels of output */ | 274 /* Set the number of channels of output */ |
268 value = spec->channels; | 275 value = spec->channels; |
269 if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) { | 276 if (ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) { |
270 perror("SNDCTL_DSP_CHANNELS"); | 277 perror ("SNDCTL_DSP_CHANNELS"); |
271 SDL_SetError("Cannot set the number of channels"); | 278 SDL_SetError ("Cannot set the number of channels"); |
272 DSP_CloseAudio(this); | 279 DSP_CloseAudio (this); |
273 return(-1); | 280 return (-1); |
274 } | 281 } |
275 spec->channels = value; | 282 spec->channels = value; |
276 | 283 |
277 /* Set the DSP frequency */ | 284 /* Set the DSP frequency */ |
278 value = spec->freq; | 285 value = spec->freq; |
279 if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) { | 286 if (ioctl (audio_fd, SNDCTL_DSP_SPEED, &value) < 0) { |
280 perror("SNDCTL_DSP_SPEED"); | 287 perror ("SNDCTL_DSP_SPEED"); |
281 SDL_SetError("Couldn't set audio frequency"); | 288 SDL_SetError ("Couldn't set audio frequency"); |
282 DSP_CloseAudio(this); | 289 DSP_CloseAudio (this); |
283 return(-1); | 290 return (-1); |
284 } | 291 } |
285 spec->freq = value; | 292 spec->freq = value; |
286 | 293 |
287 /* Calculate the final parameters for this audio specification */ | 294 /* Calculate the final parameters for this audio specification */ |
288 SDL_CalculateAudioSpec(spec); | 295 SDL_CalculateAudioSpec (spec); |
289 | 296 |
290 /* Determine the power of two of the fragment size */ | 297 /* Determine the power of two of the fragment size */ |
291 for ( frag_spec = 0; (0x01U<<frag_spec) < spec->size; ++frag_spec ); | 298 for (frag_spec = 0; (0x01U << frag_spec) < spec->size; ++frag_spec); |
292 if ( (0x01U<<frag_spec) != spec->size ) { | 299 if ((0x01U << frag_spec) != spec->size) { |
293 SDL_SetError("Fragment size must be a power of two"); | 300 SDL_SetError ("Fragment size must be a power of two"); |
294 DSP_CloseAudio(this); | 301 DSP_CloseAudio (this); |
295 return(-1); | 302 return (-1); |
296 } | 303 } |
297 frag_spec |= 0x00020000; /* two fragments, for low latency */ | 304 frag_spec |= 0x00020000; /* two fragments, for low latency */ |
298 | 305 |
299 /* Set the audio buffering parameters */ | 306 /* Set the audio buffering parameters */ |
300 #ifdef DEBUG_AUDIO | 307 #ifdef DEBUG_AUDIO |
301 fprintf(stderr, "Requesting %d fragments of size %d\n", | 308 fprintf (stderr, "Requesting %d fragments of size %d\n", |
302 (frag_spec >> 16), 1<<(frag_spec&0xFFFF)); | 309 (frag_spec >> 16), 1 << (frag_spec & 0xFFFF)); |
303 #endif | 310 #endif |
304 if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { | 311 if (ioctl (audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) { |
305 perror("SNDCTL_DSP_SETFRAGMENT"); | 312 perror ("SNDCTL_DSP_SETFRAGMENT"); |
306 } | 313 } |
307 #ifdef DEBUG_AUDIO | 314 #ifdef DEBUG_AUDIO |
308 { audio_buf_info info; | 315 { |
309 ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info); | 316 audio_buf_info info; |
310 fprintf(stderr, "fragments = %d\n", info.fragments); | 317 ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &info); |
311 fprintf(stderr, "fragstotal = %d\n", info.fragstotal); | 318 fprintf (stderr, "fragments = %d\n", info.fragments); |
312 fprintf(stderr, "fragsize = %d\n", info.fragsize); | 319 fprintf (stderr, "fragstotal = %d\n", info.fragstotal); |
313 fprintf(stderr, "bytes = %d\n", info.bytes); | 320 fprintf (stderr, "fragsize = %d\n", info.fragsize); |
314 } | 321 fprintf (stderr, "bytes = %d\n", info.bytes); |
315 #endif | 322 } |
316 | 323 #endif |
317 /* Allocate mixing buffer */ | 324 |
318 mixlen = spec->size; | 325 /* Allocate mixing buffer */ |
319 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | 326 mixlen = spec->size; |
320 if ( mixbuf == NULL ) { | 327 mixbuf = (Uint8 *) SDL_AllocAudioMem (mixlen); |
321 DSP_CloseAudio(this); | 328 if (mixbuf == NULL) { |
322 return(-1); | 329 DSP_CloseAudio (this); |
323 } | 330 return (-1); |
324 SDL_memset(mixbuf, spec->silence, spec->size); | 331 } |
325 | 332 SDL_memset (mixbuf, spec->silence, spec->size); |
326 /* Get the parent process id (we're the parent of the audio thread) */ | 333 |
327 parent = getpid(); | 334 /* Get the parent process id (we're the parent of the audio thread) */ |
328 | 335 parent = getpid (); |
329 /* We're ready to rock and roll. :-) */ | 336 |
330 return(0); | 337 /* We're ready to rock and roll. :-) */ |
331 } | 338 return (0); |
339 } | |
340 | |
341 /* vi: set ts=4 sw=4 expandtab: */ |