Mercurial > sdl-ios-xcode
comparison src/audio/alsa/SDL_alsa_audio.c @ 1552:b2462b772cce
Fixed bug #79
Implemented snd_pcm_sw_params_set_start_threshold() and snd_pcm_sw_params_set_avail_min() in the ALSA 0.9 driver.
This doesn't actually change any latency for me, but it's the right thing to do...
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 19 Mar 2006 10:41:49 +0000 |
parents | d910939febfa |
children | 63fa37538842 |
comparison
equal
deleted
inserted
replaced
1551:02e19471a694 | 1552:b2462b772cce |
---|---|
67 static int (*SDL_NAME(snd_pcm_resume))(snd_pcm_t *pcm); | 67 static int (*SDL_NAME(snd_pcm_resume))(snd_pcm_t *pcm); |
68 static int (*SDL_NAME(snd_pcm_prepare))(snd_pcm_t *pcm); | 68 static int (*SDL_NAME(snd_pcm_prepare))(snd_pcm_t *pcm); |
69 static int (*SDL_NAME(snd_pcm_drain))(snd_pcm_t *pcm); | 69 static int (*SDL_NAME(snd_pcm_drain))(snd_pcm_t *pcm); |
70 static const char *(*SDL_NAME(snd_strerror))(int errnum); | 70 static const char *(*SDL_NAME(snd_strerror))(int errnum); |
71 static size_t (*SDL_NAME(snd_pcm_hw_params_sizeof))(void); | 71 static size_t (*SDL_NAME(snd_pcm_hw_params_sizeof))(void); |
72 static size_t (*SDL_NAME(snd_pcm_sw_params_sizeof))(void); | |
72 static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | 73 static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); |
73 static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); | 74 static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); |
74 static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); | 75 static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); |
75 static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); | 76 static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); |
76 static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params); | 77 static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params); |
77 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); | 78 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); |
78 static snd_pcm_uframes_t (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int *dir); | 79 static snd_pcm_uframes_t (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int *dir); |
79 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); | 80 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); |
80 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | 81 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); |
81 static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); | 82 static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); |
83 /* | |
84 static unsigned int (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params); | |
85 static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(snd_pcm_hw_params_t *params); | |
86 */ | |
87 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); | |
88 static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); | |
89 static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); | |
90 static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | |
82 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) | 91 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) |
92 #define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) | |
83 | 93 |
84 /* cast funcs to char* first, to please GCC's strict aliasing rules. */ | 94 /* cast funcs to char* first, to please GCC's strict aliasing rules. */ |
85 static struct { | 95 static struct { |
86 const char *name; | 96 const char *name; |
87 void **func; | 97 void **func; |
92 { "snd_pcm_resume", (void**)(char*)&SDL_NAME(snd_pcm_resume) }, | 102 { "snd_pcm_resume", (void**)(char*)&SDL_NAME(snd_pcm_resume) }, |
93 { "snd_pcm_prepare", (void**)(char*)&SDL_NAME(snd_pcm_prepare) }, | 103 { "snd_pcm_prepare", (void**)(char*)&SDL_NAME(snd_pcm_prepare) }, |
94 { "snd_pcm_drain", (void**)(char*)&SDL_NAME(snd_pcm_drain) }, | 104 { "snd_pcm_drain", (void**)(char*)&SDL_NAME(snd_pcm_drain) }, |
95 { "snd_strerror", (void**)(char*)&SDL_NAME(snd_strerror) }, | 105 { "snd_strerror", (void**)(char*)&SDL_NAME(snd_strerror) }, |
96 { "snd_pcm_hw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_sizeof) }, | 106 { "snd_pcm_hw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_sizeof) }, |
107 { "snd_pcm_sw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_sizeof) }, | |
97 { "snd_pcm_hw_params_any", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_any) }, | 108 { "snd_pcm_hw_params_any", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_any) }, |
98 { "snd_pcm_hw_params_set_access", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_access) }, | 109 { "snd_pcm_hw_params_set_access", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_access) }, |
99 { "snd_pcm_hw_params_set_format", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_format) }, | 110 { "snd_pcm_hw_params_set_format", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_format) }, |
100 { "snd_pcm_hw_params_set_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_channels) }, | 111 { "snd_pcm_hw_params_set_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_channels) }, |
101 { "snd_pcm_hw_params_get_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_channels) }, | 112 { "snd_pcm_hw_params_get_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_channels) }, |
102 { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, | 113 { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, |
103 { "snd_pcm_hw_params_set_period_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_period_size_near) }, | 114 { "snd_pcm_hw_params_set_period_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_period_size_near) }, |
104 { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, | 115 { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, |
105 { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, | 116 { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, |
106 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, | 117 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, |
118 /* | |
119 { "snd_pcm_hw_params_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, | |
120 { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, | |
121 */ | |
122 { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, | |
123 { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, | |
124 { "snd_pcm_sw_params_set_avail_min", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min) }, | |
125 { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, | |
107 }; | 126 }; |
108 | 127 |
109 static void UnloadALSALibrary(void) { | 128 static void UnloadALSALibrary(void) { |
110 if (alsa_loaded) { | 129 if (alsa_loaded) { |
111 /* SDL_UnloadObject(alsa_handle);*/ | 130 /* SDL_UnloadObject(alsa_handle);*/ |
302 } | 321 } |
303 | 322 |
304 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) | 323 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) |
305 { | 324 { |
306 int status; | 325 int status; |
307 snd_pcm_hw_params_t *params; | 326 snd_pcm_hw_params_t *hwparams; |
327 snd_pcm_sw_params_t *swparams; | |
308 snd_pcm_format_t format; | 328 snd_pcm_format_t format; |
309 snd_pcm_uframes_t frames; | 329 snd_pcm_uframes_t frames; |
310 Uint16 test_format; | 330 Uint16 test_format; |
311 | 331 |
312 /* Open the audio device */ | 332 /* Open the audio device */ |
317 SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status)); | 337 SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status)); |
318 return(-1); | 338 return(-1); |
319 } | 339 } |
320 | 340 |
321 /* Figure out what the hardware is capable of */ | 341 /* Figure out what the hardware is capable of */ |
322 snd_pcm_hw_params_alloca(¶ms); | 342 snd_pcm_hw_params_alloca(&hwparams); |
323 status = SDL_NAME(snd_pcm_hw_params_any)(pcm_handle, params); | 343 status = SDL_NAME(snd_pcm_hw_params_any)(pcm_handle, hwparams); |
324 if ( status < 0 ) { | 344 if ( status < 0 ) { |
325 SDL_SetError("Couldn't get hardware config: %s", SDL_NAME(snd_strerror)(status)); | 345 SDL_SetError("Couldn't get hardware config: %s", SDL_NAME(snd_strerror)(status)); |
326 ALSA_CloseAudio(this); | 346 ALSA_CloseAudio(this); |
327 return(-1); | 347 return(-1); |
328 } | 348 } |
329 | 349 |
330 /* SDL only uses interleaved sample output */ | 350 /* SDL only uses interleaved sample output */ |
331 status = SDL_NAME(snd_pcm_hw_params_set_access)(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); | 351 status = SDL_NAME(snd_pcm_hw_params_set_access)(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); |
332 if ( status < 0 ) { | 352 if ( status < 0 ) { |
333 SDL_SetError("Couldn't set interleaved access: %s", SDL_NAME(snd_strerror)(status)); | 353 SDL_SetError("Couldn't set interleaved access: %s", SDL_NAME(snd_strerror)(status)); |
334 ALSA_CloseAudio(this); | 354 ALSA_CloseAudio(this); |
335 return(-1); | 355 return(-1); |
336 } | 356 } |
361 default: | 381 default: |
362 format = 0; | 382 format = 0; |
363 break; | 383 break; |
364 } | 384 } |
365 if ( format != 0 ) { | 385 if ( format != 0 ) { |
366 status = SDL_NAME(snd_pcm_hw_params_set_format)(pcm_handle, params, format); | 386 status = SDL_NAME(snd_pcm_hw_params_set_format)(pcm_handle, hwparams, format); |
367 } | 387 } |
368 if ( status < 0 ) { | 388 if ( status < 0 ) { |
369 test_format = SDL_NextAudioFormat(); | 389 test_format = SDL_NextAudioFormat(); |
370 } | 390 } |
371 } | 391 } |
375 return(-1); | 395 return(-1); |
376 } | 396 } |
377 spec->format = test_format; | 397 spec->format = test_format; |
378 | 398 |
379 /* Set the number of channels */ | 399 /* Set the number of channels */ |
380 status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, params, spec->channels); | 400 status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels); |
381 if ( status < 0 ) { | 401 if ( status < 0 ) { |
382 status = SDL_NAME(snd_pcm_hw_params_get_channels)(params); | 402 status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams); |
383 if ( (status <= 0) || (status > 2) ) { | 403 if ( (status <= 0) || (status > 2) ) { |
384 SDL_SetError("Couldn't set audio channels"); | 404 SDL_SetError("Couldn't set audio channels"); |
385 ALSA_CloseAudio(this); | 405 ALSA_CloseAudio(this); |
386 return(-1); | 406 return(-1); |
387 } | 407 } |
388 spec->channels = status; | 408 spec->channels = status; |
389 } | 409 } |
390 | 410 |
391 /* Set the audio rate */ | 411 /* Set the audio rate */ |
392 status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, params, spec->freq, NULL); | 412 status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, spec->freq, NULL); |
393 if ( status < 0 ) { | 413 if ( status < 0 ) { |
394 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); | 414 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); |
395 ALSA_CloseAudio(this); | 415 ALSA_CloseAudio(this); |
396 return(-1); | 416 return(-1); |
397 } | 417 } |
398 spec->freq = status; | 418 spec->freq = status; |
399 | 419 |
400 /* Set the buffer size, in samples */ | 420 /* Set the buffer size, in samples */ |
401 frames = spec->samples; | 421 frames = spec->samples; |
402 frames = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, params, frames, NULL); | 422 frames = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, frames, NULL); |
403 spec->samples = frames; | 423 spec->samples = frames; |
404 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, params, 2, NULL); | 424 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, 2, NULL); |
405 | 425 |
406 /* "set" the hardware with the desired parameters */ | 426 /* "set" the hardware with the desired parameters */ |
407 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, params); | 427 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); |
408 if ( status < 0 ) { | 428 if ( status < 0 ) { |
409 SDL_SetError("Couldn't set audio parameters: %s", SDL_NAME(snd_strerror)(status)); | 429 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); |
430 ALSA_CloseAudio(this); | |
431 return(-1); | |
432 } | |
433 | |
434 /* | |
435 { unsigned int bufsize; int fragments; | |
436 bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams); | |
437 fragments = SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams); | |
438 | |
439 fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments); | |
440 } | |
441 */ | |
442 | |
443 /* Set the software parameters */ | |
444 snd_pcm_sw_params_alloca(&swparams); | |
445 status = SDL_NAME(snd_pcm_sw_params_current)(pcm_handle, swparams); | |
446 if ( status < 0 ) { | |
447 SDL_SetError("Couldn't get software config: %s", SDL_NAME(snd_strerror)(status)); | |
448 ALSA_CloseAudio(this); | |
449 return(-1); | |
450 } | |
451 status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 0); | |
452 if ( status < 0 ) { | |
453 SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status)); | |
454 ALSA_CloseAudio(this); | |
455 return(-1); | |
456 } | |
457 status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames); | |
458 if ( status < 0 ) { | |
459 SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status)); | |
460 ALSA_CloseAudio(this); | |
461 return(-1); | |
462 } | |
463 status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); | |
464 if ( status < 0 ) { | |
465 SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status)); | |
410 ALSA_CloseAudio(this); | 466 ALSA_CloseAudio(this); |
411 return(-1); | 467 return(-1); |
412 } | 468 } |
413 | 469 |
414 /* Calculate the final parameters for this audio specification */ | 470 /* Calculate the final parameters for this audio specification */ |