comparison src/audio/paudio/SDL_paudio.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 d910939febfa
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
53 /* Open the audio device for playback, and don't block if busy */ 53 /* Open the audio device for playback, and don't block if busy */
54 /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ 54 /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */
55 #define OPEN_FLAGS O_WRONLY 55 #define OPEN_FLAGS O_WRONLY
56 56
57 /* Audio driver functions */ 57 /* Audio driver functions */
58 static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec); 58 static int Paud_OpenAudio (_THIS, SDL_AudioSpec * spec);
59 static void Paud_WaitAudio(_THIS); 59 static void Paud_WaitAudio (_THIS);
60 static void Paud_PlayAudio(_THIS); 60 static void Paud_PlayAudio (_THIS);
61 static Uint8 *Paud_GetAudioBuf(_THIS); 61 static Uint8 *Paud_GetAudioBuf (_THIS);
62 static void Paud_CloseAudio(_THIS); 62 static void Paud_CloseAudio (_THIS);
63 63
64 /* Audio driver bootstrap functions */ 64 /* Audio driver bootstrap functions */
65 65
66 static int Audio_Available(void) 66 static int
67 { 67 Audio_Available (void)
68 int fd; 68 {
69 int available; 69 int fd;
70 70 int available;
71 available = 0; 71
72 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); 72 available = 0;
73 if ( fd >= 0 ) { 73 fd = SDL_OpenAudioPath (NULL, 0, OPEN_FLAGS, 0);
74 available = 1; 74 if (fd >= 0) {
75 close(fd); 75 available = 1;
76 } 76 close (fd);
77 return(available); 77 }
78 } 78 return (available);
79 79 }
80 static void Audio_DeleteDevice(SDL_AudioDevice *device) 80
81 { 81 static void
82 SDL_free(device->hidden); 82 Audio_DeleteDevice (SDL_AudioDevice * device)
83 SDL_free(device); 83 {
84 } 84 SDL_free (device->hidden);
85 85 SDL_free (device);
86 static SDL_AudioDevice *Audio_CreateDevice(int devindex) 86 }
87 { 87
88 SDL_AudioDevice *this; 88 static SDL_AudioDevice *
89 89 Audio_CreateDevice (int devindex)
90 /* Initialize all variables that we clean on shutdown */ 90 {
91 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 91 SDL_AudioDevice *this;
92 if ( this ) { 92
93 SDL_memset(this, 0, (sizeof *this)); 93 /* Initialize all variables that we clean on shutdown */
94 this->hidden = (struct SDL_PrivateAudioData *) 94 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice));
95 SDL_malloc((sizeof *this->hidden)); 95 if (this) {
96 } 96 SDL_memset (this, 0, (sizeof *this));
97 if ( (this == NULL) || (this->hidden == NULL) ) { 97 this->hidden = (struct SDL_PrivateAudioData *)
98 SDL_OutOfMemory(); 98 SDL_malloc ((sizeof *this->hidden));
99 if ( this ) { 99 }
100 SDL_free(this); 100 if ((this == NULL) || (this->hidden == NULL)) {
101 } 101 SDL_OutOfMemory ();
102 return(0); 102 if (this) {
103 } 103 SDL_free (this);
104 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 104 }
105 audio_fd = -1; 105 return (0);
106 106 }
107 /* Set the function pointers */ 107 SDL_memset (this->hidden, 0, (sizeof *this->hidden));
108 this->OpenAudio = Paud_OpenAudio; 108 audio_fd = -1;
109 this->WaitAudio = Paud_WaitAudio; 109
110 this->PlayAudio = Paud_PlayAudio; 110 /* Set the function pointers */
111 this->GetAudioBuf = Paud_GetAudioBuf; 111 this->OpenAudio = Paud_OpenAudio;
112 this->CloseAudio = Paud_CloseAudio; 112 this->WaitAudio = Paud_WaitAudio;
113 113 this->PlayAudio = Paud_PlayAudio;
114 this->free = Audio_DeleteDevice; 114 this->GetAudioBuf = Paud_GetAudioBuf;
115 115 this->CloseAudio = Paud_CloseAudio;
116 return this; 116
117 this->free = Audio_DeleteDevice;
118
119 return this;
117 } 120 }
118 121
119 AudioBootStrap Paud_bootstrap = { 122 AudioBootStrap Paud_bootstrap = {
120 Paud_DRIVER_NAME, "AIX Paudio", 123 Paud_DRIVER_NAME, "AIX Paudio",
121 Audio_Available, Audio_CreateDevice 124 Audio_Available, Audio_CreateDevice
122 }; 125 };
123 126
124 /* This function waits until it is possible to write a full sound buffer */ 127 /* This function waits until it is possible to write a full sound buffer */
125 static void Paud_WaitAudio(_THIS) 128 static void
129 Paud_WaitAudio (_THIS)
126 { 130 {
127 fd_set fdset; 131 fd_set fdset;
128 132
129 /* See if we need to use timed audio synchronization */ 133 /* See if we need to use timed audio synchronization */
130 if ( frame_ticks ) { 134 if (frame_ticks) {
131 /* Use timer for general audio synchronization */ 135 /* Use timer for general audio synchronization */
132 Sint32 ticks; 136 Sint32 ticks;
133 137
134 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; 138 ticks = ((Sint32) (next_frame - SDL_GetTicks ())) - FUDGE_TICKS;
135 if ( ticks > 0 ) { 139 if (ticks > 0) {
136 SDL_Delay(ticks); 140 SDL_Delay (ticks);
137 } 141 }
138 } else { 142 } else {
139 audio_buffer paud_bufinfo; 143 audio_buffer paud_bufinfo;
140 144
141 /* Use select() for audio synchronization */ 145 /* Use select() for audio synchronization */
142 struct timeval timeout; 146 struct timeval timeout;
143 FD_ZERO(&fdset); 147 FD_ZERO (&fdset);
144 FD_SET(audio_fd, &fdset); 148 FD_SET (audio_fd, &fdset);
145 149
146 if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { 150 if (ioctl (audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
147 #ifdef DEBUG_AUDIO 151 #ifdef DEBUG_AUDIO
148 fprintf(stderr, "Couldn't get audio buffer information\n"); 152 fprintf (stderr, "Couldn't get audio buffer information\n");
149 #endif 153 #endif
150 timeout.tv_sec = 10; 154 timeout.tv_sec = 10;
151 timeout.tv_usec = 0; 155 timeout.tv_usec = 0;
152 } else { 156 } else {
153 long ms_in_buf = paud_bufinfo.write_buf_time; 157 long ms_in_buf = paud_bufinfo.write_buf_time;
154 timeout.tv_sec = ms_in_buf/1000; 158 timeout.tv_sec = ms_in_buf / 1000;
155 ms_in_buf = ms_in_buf - timeout.tv_sec*1000; 159 ms_in_buf = ms_in_buf - timeout.tv_sec * 1000;
156 timeout.tv_usec = ms_in_buf*1000; 160 timeout.tv_usec = ms_in_buf * 1000;
157 #ifdef DEBUG_AUDIO 161 #ifdef DEBUG_AUDIO
158 fprintf( stderr, 162 fprintf (stderr,
159 "Waiting for write_buf_time=%ld,%ld\n", 163 "Waiting for write_buf_time=%ld,%ld\n",
160 timeout.tv_sec, 164 timeout.tv_sec, timeout.tv_usec);
161 timeout.tv_usec ); 165 #endif
162 #endif 166 }
163 } 167
164 168 #ifdef DEBUG_AUDIO
165 #ifdef DEBUG_AUDIO 169 fprintf (stderr, "Waiting for audio to get ready\n");
166 fprintf(stderr, "Waiting for audio to get ready\n"); 170 #endif
167 #endif 171 if (select (audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
168 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { 172 const char *message =
169 const char *message = "Audio timeout - buggy audio driver? (disabled)"; 173 "Audio timeout - buggy audio driver? (disabled)";
170 /* 174 /*
171 * In general we should never print to the screen, 175 * In general we should never print to the screen,
172 * but in this case we have no other way of letting 176 * but in this case we have no other way of letting
173 * the user know what happened. 177 * the user know what happened.
174 */ 178 */
175 fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); 179 fprintf (stderr, "SDL: %s - %s\n", strerror (errno), message);
176 this->enabled = 0; 180 this->enabled = 0;
177 /* Don't try to close - may hang */ 181 /* Don't try to close - may hang */
178 audio_fd = -1; 182 audio_fd = -1;
179 #ifdef DEBUG_AUDIO 183 #ifdef DEBUG_AUDIO
180 fprintf(stderr, "Done disabling audio\n"); 184 fprintf (stderr, "Done disabling audio\n");
181 #endif 185 #endif
182 } 186 }
183 #ifdef DEBUG_AUDIO 187 #ifdef DEBUG_AUDIO
184 fprintf(stderr, "Ready!\n"); 188 fprintf (stderr, "Ready!\n");
185 #endif 189 #endif
186 } 190 }
187 } 191 }
188 192
189 static void Paud_PlayAudio(_THIS) 193 static void
190 { 194 Paud_PlayAudio (_THIS)
191 int written; 195 {
192 196 int written;
193 /* Write the audio data, checking for EAGAIN on broken audio drivers */ 197
194 do { 198 /* Write the audio data, checking for EAGAIN on broken audio drivers */
195 written = write(audio_fd, mixbuf, mixlen); 199 do {
196 if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { 200 written = write (audio_fd, mixbuf, mixlen);
197 SDL_Delay(1); /* Let a little CPU time go by */ 201 if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
198 } 202 SDL_Delay (1); /* Let a little CPU time go by */
199 } while ( (written < 0) && 203 }
200 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); 204 }
201 205 while ((written < 0) &&
202 /* If timer synchronization is enabled, set the next write frame */ 206 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
203 if ( frame_ticks ) { 207
204 next_frame += frame_ticks; 208 /* If timer synchronization is enabled, set the next write frame */
205 } 209 if (frame_ticks) {
206 210 next_frame += frame_ticks;
207 /* If we couldn't write, assume fatal error for now */ 211 }
208 if ( written < 0 ) { 212
209 this->enabled = 0; 213 /* If we couldn't write, assume fatal error for now */
210 } 214 if (written < 0) {
211 #ifdef DEBUG_AUDIO 215 this->enabled = 0;
212 fprintf(stderr, "Wrote %d bytes of audio data\n", written); 216 }
213 #endif 217 #ifdef DEBUG_AUDIO
214 } 218 fprintf (stderr, "Wrote %d bytes of audio data\n", written);
215 219 #endif
216 static Uint8 *Paud_GetAudioBuf(_THIS) 220 }
217 { 221
218 return mixbuf; 222 static Uint8 *
219 } 223 Paud_GetAudioBuf (_THIS)
220 224 {
221 static void Paud_CloseAudio(_THIS) 225 return mixbuf;
222 { 226 }
223 if ( mixbuf != NULL ) { 227
224 SDL_FreeAudioMem(mixbuf); 228 static void
225 mixbuf = NULL; 229 Paud_CloseAudio (_THIS)
226 } 230 {
227 if ( audio_fd >= 0 ) { 231 if (mixbuf != NULL) {
228 close(audio_fd); 232 SDL_FreeAudioMem (mixbuf);
229 audio_fd = -1; 233 mixbuf = NULL;
230 } 234 }
231 } 235 if (audio_fd >= 0) {
232 236 close (audio_fd);
233 static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec) 237 audio_fd = -1;
234 { 238 }
235 char audiodev[1024]; 239 }
236 int format; 240
237 int bytes_per_sample; 241 static int
238 Uint16 test_format; 242 Paud_OpenAudio (_THIS, SDL_AudioSpec * spec)
239 audio_init paud_init; 243 {
240 audio_buffer paud_bufinfo; 244 char audiodev[1024];
241 audio_status paud_status; 245 int format;
242 audio_control paud_control; 246 int bytes_per_sample;
243 audio_change paud_change; 247 Uint16 test_format;
244 248 audio_init paud_init;
245 /* Reset the timer synchronization flag */ 249 audio_buffer paud_bufinfo;
246 frame_ticks = 0.0; 250 audio_status paud_status;
247 251 audio_control paud_control;
248 /* Open the audio device */ 252 audio_change paud_change;
249 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); 253
250 if ( audio_fd < 0 ) { 254 /* Reset the timer synchronization flag */
251 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 255 frame_ticks = 0.0;
252 return -1; 256
253 } 257 /* Open the audio device */
254 258 audio_fd = SDL_OpenAudioPath (audiodev, sizeof (audiodev), OPEN_FLAGS, 0);
255 /* 259 if (audio_fd < 0) {
256 * We can't set the buffer size - just ask the device for the maximum 260 SDL_SetError ("Couldn't open %s: %s", audiodev, strerror (errno));
257 * that we can have. 261 return -1;
258 */ 262 }
259 if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { 263
260 SDL_SetError("Couldn't get audio buffer information"); 264 /*
261 return -1; 265 * We can't set the buffer size - just ask the device for the maximum
262 } 266 * that we can have.
263 267 */
264 mixbuf = NULL; 268 if (ioctl (audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
265 269 SDL_SetError ("Couldn't get audio buffer information");
266 if ( spec->channels > 1 ) 270 return -1;
267 spec->channels = 2; 271 }
268 else 272
269 spec->channels = 1; 273 mixbuf = NULL;
270 274
271 /* 275 if (spec->channels > 1)
272 * Fields in the audio_init structure: 276 spec->channels = 2;
273 * 277 else
274 * Ignored by us: 278 spec->channels = 1;
275 * 279
276 * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only? 280 /*
277 * paud.slot_number; * slot number of the adapter 281 * Fields in the audio_init structure:
278 * paud.device_id; * adapter identification number 282 *
279 * 283 * Ignored by us:
280 * Input: 284 *
281 * 285 * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only?
282 * paud.srate; * the sampling rate in Hz 286 * paud.slot_number; * slot number of the adapter
283 * paud.bits_per_sample; * 8, 16, 32, ... 287 * paud.device_id; * adapter identification number
284 * paud.bsize; * block size for this rate 288 *
285 * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX 289 * Input:
286 * paud.channels; * 1=mono, 2=stereo 290 *
287 * paud.flags; * FIXED - fixed length data 291 * paud.srate; * the sampling rate in Hz
288 * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only) 292 * paud.bits_per_sample; * 8, 16, 32, ...
289 * * TWOS_COMPLEMENT - 2's complement data 293 * paud.bsize; * block size for this rate
290 * * SIGNED - signed? comment seems wrong in sys/audio.h 294 * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX
291 * * BIG_ENDIAN 295 * paud.channels; * 1=mono, 2=stereo
292 * paud.operation; * PLAY, RECORD 296 * paud.flags; * FIXED - fixed length data
293 * 297 * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only)
294 * Output: 298 * * TWOS_COMPLEMENT - 2's complement data
295 * 299 * * SIGNED - signed? comment seems wrong in sys/audio.h
296 * paud.flags; * PITCH - pitch is supported 300 * * BIG_ENDIAN
297 * * INPUT - input is supported 301 * paud.operation; * PLAY, RECORD
298 * * OUTPUT - output is supported 302 *
299 * * MONITOR - monitor is supported 303 * Output:
300 * * VOLUME - volume is supported 304 *
301 * * VOLUME_DELAY - volume delay is supported 305 * paud.flags; * PITCH - pitch is supported
302 * * BALANCE - balance is supported 306 * * INPUT - input is supported
303 * * BALANCE_DELAY - balance delay is supported 307 * * OUTPUT - output is supported
304 * * TREBLE - treble control is supported 308 * * MONITOR - monitor is supported
305 * * BASS - bass control is supported 309 * * VOLUME - volume is supported
306 * * BESTFIT_PROVIDED - best fit returned 310 * * VOLUME_DELAY - volume delay is supported
307 * * LOAD_CODE - DSP load needed 311 * * BALANCE - balance is supported
308 * paud.rc; * NO_PLAY - DSP code can't do play requests 312 * * BALANCE_DELAY - balance delay is supported
309 * * NO_RECORD - DSP code can't do record requests 313 * * TREBLE - treble control is supported
310 * * INVALID_REQUEST - request was invalid 314 * * BASS - bass control is supported
311 * * CONFLICT - conflict with open's flags 315 * * BESTFIT_PROVIDED - best fit returned
312 * * OVERLOADED - out of DSP MIPS or memory 316 * * LOAD_CODE - DSP load needed
313 * paud.position_resolution; * smallest increment for position 317 * paud.rc; * NO_PLAY - DSP code can't do play requests
314 */ 318 * * NO_RECORD - DSP code can't do record requests
315 319 * * INVALID_REQUEST - request was invalid
316 paud_init.srate = spec->freq; 320 * * CONFLICT - conflict with open's flags
317 paud_init.mode = PCM; 321 * * OVERLOADED - out of DSP MIPS or memory
318 paud_init.operation = PLAY; 322 * paud.position_resolution; * smallest increment for position
319 paud_init.channels = spec->channels; 323 */
320 324
321 /* Try for a closest match on audio format */ 325 paud_init.srate = spec->freq;
322 format = 0; 326 paud_init.mode = PCM;
323 for ( test_format = SDL_FirstAudioFormat(spec->format); 327 paud_init.operation = PLAY;
324 ! format && test_format; ) { 328 paud_init.channels = spec->channels;
325 #ifdef DEBUG_AUDIO 329
326 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); 330 /* Try for a closest match on audio format */
327 #endif 331 format = 0;
328 switch ( test_format ) { 332 for (test_format = SDL_FirstAudioFormat (spec->format);
329 case AUDIO_U8: 333 !format && test_format;) {
330 bytes_per_sample = 1; 334 #ifdef DEBUG_AUDIO
331 paud_init.bits_per_sample = 8; 335 fprintf (stderr, "Trying format 0x%4.4x\n", test_format);
332 paud_init.flags = TWOS_COMPLEMENT | FIXED; 336 #endif
333 format = 1; 337 switch (test_format) {
334 break; 338 case AUDIO_U8:
335 case AUDIO_S8: 339 bytes_per_sample = 1;
336 bytes_per_sample = 1; 340 paud_init.bits_per_sample = 8;
337 paud_init.bits_per_sample = 8; 341 paud_init.flags = TWOS_COMPLEMENT | FIXED;
338 paud_init.flags = SIGNED | 342 format = 1;
339 TWOS_COMPLEMENT | FIXED; 343 break;
340 format = 1; 344 case AUDIO_S8:
341 break; 345 bytes_per_sample = 1;
342 case AUDIO_S16LSB: 346 paud_init.bits_per_sample = 8;
343 bytes_per_sample = 2; 347 paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
344 paud_init.bits_per_sample = 16; 348 format = 1;
345 paud_init.flags = SIGNED | 349 break;
346 TWOS_COMPLEMENT | FIXED; 350 case AUDIO_S16LSB:
347 format = 1; 351 bytes_per_sample = 2;
348 break; 352 paud_init.bits_per_sample = 16;
349 case AUDIO_S16MSB: 353 paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
350 bytes_per_sample = 2; 354 format = 1;
351 paud_init.bits_per_sample = 16; 355 break;
352 paud_init.flags = BIG_ENDIAN | 356 case AUDIO_S16MSB:
353 SIGNED | 357 bytes_per_sample = 2;
354 TWOS_COMPLEMENT | FIXED; 358 paud_init.bits_per_sample = 16;
355 format = 1; 359 paud_init.flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
356 break; 360 format = 1;
357 case AUDIO_U16LSB: 361 break;
358 bytes_per_sample = 2; 362 case AUDIO_U16LSB:
359 paud_init.bits_per_sample = 16; 363 bytes_per_sample = 2;
360 paud_init.flags = TWOS_COMPLEMENT | FIXED; 364 paud_init.bits_per_sample = 16;
361 format = 1; 365 paud_init.flags = TWOS_COMPLEMENT | FIXED;
362 break; 366 format = 1;
363 case AUDIO_U16MSB: 367 break;
364 bytes_per_sample = 2; 368 case AUDIO_U16MSB:
365 paud_init.bits_per_sample = 16; 369 bytes_per_sample = 2;
366 paud_init.flags = BIG_ENDIAN | 370 paud_init.bits_per_sample = 16;
367 TWOS_COMPLEMENT | FIXED; 371 paud_init.flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
368 format = 1; 372 format = 1;
369 break; 373 break;
370 default: 374 default:
371 break; 375 break;
372 } 376 }
373 if ( ! format ) { 377 if (!format) {
374 test_format = SDL_NextAudioFormat(); 378 test_format = SDL_NextAudioFormat ();
375 } 379 }
376 } 380 }
377 if ( format == 0 ) { 381 if (format == 0) {
378 #ifdef DEBUG_AUDIO 382 #ifdef DEBUG_AUDIO
379 fprintf(stderr, "Couldn't find any hardware audio formats\n"); 383 fprintf (stderr, "Couldn't find any hardware audio formats\n");
380 #endif 384 #endif
381 SDL_SetError("Couldn't find any hardware audio formats"); 385 SDL_SetError ("Couldn't find any hardware audio formats");
382 return -1; 386 return -1;
383 } 387 }
384 spec->format = test_format; 388 spec->format = test_format;
385 389
386 /* 390 /*
387 * We know the buffer size and the max number of subsequent writes 391 * We know the buffer size and the max number of subsequent writes
388 * that can be pending. If more than one can pend, allow the application 392 * that can be pending. If more than one can pend, allow the application
389 * to do something like double buffering between our write buffer and 393 * to do something like double buffering between our write buffer and
390 * the device's own buffer that we are filling with write() anyway. 394 * the device's own buffer that we are filling with write() anyway.
391 * 395 *
392 * We calculate spec->samples like this because SDL_CalculateAudioSpec() 396 * We calculate spec->samples like this because SDL_CalculateAudioSpec()
393 * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) 397 * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2)
394 * into spec->size in return. 398 * into spec->size in return.
395 */ 399 */
396 if ( paud_bufinfo.request_buf_cap == 1 ) 400 if (paud_bufinfo.request_buf_cap == 1) {
397 { 401 spec->samples = paud_bufinfo.write_buf_cap
398 spec->samples = paud_bufinfo.write_buf_cap 402 / bytes_per_sample / spec->channels;
399 / bytes_per_sample 403 } else {
400 / spec->channels; 404 spec->samples = paud_bufinfo.write_buf_cap
401 } 405 / bytes_per_sample / spec->channels / 2;
402 else 406 }
403 { 407 paud_init.bsize = bytes_per_sample * spec->channels;
404 spec->samples = paud_bufinfo.write_buf_cap 408
405 / bytes_per_sample 409 SDL_CalculateAudioSpec (spec);
406 / spec->channels 410
407 / 2; 411 /*
408 } 412 * The AIX paud device init can't modify the values of the audio_init
409 paud_init.bsize = bytes_per_sample * spec->channels; 413 * structure that we pass to it. So we don't need any recalculation
410 414 * of this stuff and no reinit call as in linux dsp and dma code.
411 SDL_CalculateAudioSpec(spec); 415 *
412 416 * /dev/paud supports all of the encoding formats, so we don't need
413 /* 417 * to do anything like reopening the device, either.
414 * The AIX paud device init can't modify the values of the audio_init 418 */
415 * structure that we pass to it. So we don't need any recalculation 419 if (ioctl (audio_fd, AUDIO_INIT, &paud_init) < 0) {
416 * of this stuff and no reinit call as in linux dsp and dma code. 420 switch (paud_init.rc) {
417 * 421 case 1:
418 * /dev/paud supports all of the encoding formats, so we don't need 422 SDL_SetError
419 * to do anything like reopening the device, either. 423 ("Couldn't set audio format: DSP can't do play requests");
420 */ 424 return -1;
421 if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 ) { 425 break;
422 switch ( paud_init.rc ) 426 case 2:
423 { 427 SDL_SetError
424 case 1 : 428 ("Couldn't set audio format: DSP can't do record requests");
425 SDL_SetError("Couldn't set audio format: DSP can't do play requests"); 429 return -1;
426 return -1; 430 break;
427 break; 431 case 4:
428 case 2 : 432 SDL_SetError ("Couldn't set audio format: request was invalid");
429 SDL_SetError("Couldn't set audio format: DSP can't do record requests"); 433 return -1;
430 return -1; 434 break;
431 break; 435 case 5:
432 case 4 : 436 SDL_SetError
433 SDL_SetError("Couldn't set audio format: request was invalid"); 437 ("Couldn't set audio format: conflict with open's flags");
434 return -1; 438 return -1;
435 break; 439 break;
436 case 5 : 440 case 6:
437 SDL_SetError("Couldn't set audio format: conflict with open's flags"); 441 SDL_SetError
438 return -1; 442 ("Couldn't set audio format: out of DSP MIPS or memory");
439 break; 443 return -1;
440 case 6 : 444 break;
441 SDL_SetError("Couldn't set audio format: out of DSP MIPS or memory"); 445 default:
442 return -1; 446 SDL_SetError
443 break; 447 ("Couldn't set audio format: not documented in sys/audio.h");
444 default : 448 return -1;
445 SDL_SetError("Couldn't set audio format: not documented in sys/audio.h"); 449 break;
446 return -1; 450 }
447 break; 451 }
448 } 452
449 } 453 /* Allocate mixing buffer */
450 454 mixlen = spec->size;
451 /* Allocate mixing buffer */ 455 mixbuf = (Uint8 *) SDL_AllocAudioMem (mixlen);
452 mixlen = spec->size; 456 if (mixbuf == NULL) {
453 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); 457 return -1;
454 if ( mixbuf == NULL ) { 458 }
455 return -1; 459 SDL_memset (mixbuf, spec->silence, spec->size);
456 } 460
457 SDL_memset(mixbuf, spec->silence, spec->size); 461 /*
458 462 * Set some paramters: full volume, first speaker that we can find.
459 /* 463 * Ignore the other settings for now.
460 * Set some paramters: full volume, first speaker that we can find. 464 */
461 * Ignore the other settings for now. 465 paud_change.input = AUDIO_IGNORE; /* the new input source */
462 */ 466 paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */
463 paud_change.input = AUDIO_IGNORE; /* the new input source */ 467 paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
464 paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */ 468 paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */
465 paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ 469 paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
466 paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */ 470 paud_change.balance = 0x3fffffff; /* the new balance */
467 paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ 471 paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
468 paud_change.balance = 0x3fffffff; /* the new balance */ 472 paud_change.treble = AUDIO_IGNORE; /* the new treble state */
469 paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ 473 paud_change.bass = AUDIO_IGNORE; /* the new bass state */
470 paud_change.treble = AUDIO_IGNORE; /* the new treble state */ 474 paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
471 paud_change.bass = AUDIO_IGNORE; /* the new bass state */ 475
472 paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ 476 paud_control.ioctl_request = AUDIO_CHANGE;
473 477 paud_control.request_info = (char *) &paud_change;
474 paud_control.ioctl_request = AUDIO_CHANGE; 478 if (ioctl (audio_fd, AUDIO_CONTROL, &paud_control) < 0) {
475 paud_control.request_info = (char*)&paud_change; 479 #ifdef DEBUG_AUDIO
476 if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { 480 fprintf (stderr, "Can't change audio display settings\n");
477 #ifdef DEBUG_AUDIO 481 #endif
478 fprintf(stderr, "Can't change audio display settings\n" ); 482 }
479 #endif 483
480 } 484 /*
481 485 * Tell the device to expect data. Actual start will wait for
482 /* 486 * the first write() call.
483 * Tell the device to expect data. Actual start will wait for 487 */
484 * the first write() call. 488 paud_control.ioctl_request = AUDIO_START;
485 */ 489 paud_control.position = 0;
486 paud_control.ioctl_request = AUDIO_START; 490 if (ioctl (audio_fd, AUDIO_CONTROL, &paud_control) < 0) {
487 paud_control.position = 0; 491 #ifdef DEBUG_AUDIO
488 if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { 492 fprintf (stderr, "Can't start audio play\n");
489 #ifdef DEBUG_AUDIO 493 #endif
490 fprintf(stderr, "Can't start audio play\n" ); 494 SDL_SetError ("Can't start audio play");
491 #endif 495 return -1;
492 SDL_SetError("Can't start audio play"); 496 }
493 return -1; 497
494 } 498 /* Check to see if we need to use select() workaround */
495 499 {
496 /* Check to see if we need to use select() workaround */ 500 char *workaround;
497 { char *workaround; 501 workaround = SDL_getenv ("SDL_DSP_NOSELECT");
498 workaround = SDL_getenv("SDL_DSP_NOSELECT"); 502 if (workaround) {
499 if ( workaround ) { 503 frame_ticks = (float) (spec->samples * 1000) / spec->freq;
500 frame_ticks = (float)(spec->samples*1000)/spec->freq; 504 next_frame = SDL_GetTicks () + frame_ticks;
501 next_frame = SDL_GetTicks()+frame_ticks; 505 }
502 } 506 }
503 } 507
504 508 /* Get the parent process id (we're the parent of the audio thread) */
505 /* Get the parent process id (we're the parent of the audio thread) */ 509 parent = getpid ();
506 parent = getpid(); 510
507 511 /* We're ready to rock and roll. :-) */
508 /* We're ready to rock and roll. :-) */ 512 return 0;
509 return 0; 513 }
510 } 514
511 515 /* vi: set ts=4 sw=4 expandtab: */