Mercurial > sdl-ios-xcode
comparison src/audio/alsa/SDL_alsa_audio.c @ 4333:55717a755897 SDL-1.2
Switched from setting the period size and count to setting the buffer size directly, based on feedback from the ALSA development list:
http://mailman.alsa-project.org/pipermail/alsa-devel/2009-October/022267.html
This has the nice side effect of reducing latency on my SBLive! card.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 13 Oct 2009 09:56:15 +0000 |
parents | 67e799ffcadf |
children | afadcd7d2319 |
comparison
equal
deleted
inserted
replaced
4332:67e799ffcadf | 4333:55717a755897 |
---|---|
43 /* The tag name used by ALSA audio */ | 43 /* The tag name used by ALSA audio */ |
44 #define DRIVER_NAME "alsa" | 44 #define DRIVER_NAME "alsa" |
45 | 45 |
46 /* The default ALSA audio driver */ | 46 /* The default ALSA audio driver */ |
47 #define DEFAULT_DEVICE "default" | 47 #define DEFAULT_DEVICE "default" |
48 | |
49 /* Whether we should set the buffer size or the period size */ | |
50 /*#define SET_PERIOD_SIZE*/ | |
51 /*#define DEBUG_PERIOD_SIZE*/ | |
48 | 52 |
49 /* Audio driver functions */ | 53 /* Audio driver functions */ |
50 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec); | 54 static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec); |
51 static void ALSA_WaitAudio(_THIS); | 55 static void ALSA_WaitAudio(_THIS); |
52 static void ALSA_PlayAudio(_THIS); | 56 static void ALSA_PlayAudio(_THIS); |
76 static 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); | 80 static 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); |
77 static int (*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); | 81 static int (*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); |
78 static int (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir); | 82 static int (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir); |
79 static 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); | 83 static 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_get_periods))(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); | 84 static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); |
85 static int (*SDL_NAME(snd_pcm_hw_params_set_buffer_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); | |
81 static int (*SDL_NAME(snd_pcm_hw_params_get_buffer_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); | 86 static int (*SDL_NAME(snd_pcm_hw_params_get_buffer_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); |
82 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); | 87 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); |
83 /* | 88 /* |
84 */ | 89 */ |
85 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); | 90 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); |
86 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); | 91 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); |
87 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); | |
88 static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); | 92 static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); |
89 static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); | 93 static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); |
90 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) | 94 #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) |
91 #define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) | 95 #define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) |
92 | 96 |
112 { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, | 116 { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, |
113 { "snd_pcm_hw_params_set_period_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_period_size_near) }, | 117 { "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_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, | 118 { "snd_pcm_hw_params_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, |
115 { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, | 119 { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, |
116 { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, | 120 { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, |
121 { "snd_pcm_hw_params_set_buffer_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_buffer_size_near) }, | |
117 { "snd_pcm_hw_params_get_buffer_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_buffer_size) }, | 122 { "snd_pcm_hw_params_get_buffer_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_buffer_size) }, |
118 { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, | 123 { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, |
119 { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, | 124 { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, |
120 { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, | 125 { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, |
121 { "snd_pcm_sw_params_set_avail_min", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min) }, | |
122 { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, | 126 { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, |
123 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, | 127 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, |
124 }; | 128 }; |
125 | 129 |
126 static void UnloadALSALibrary(void) { | 130 static void UnloadALSALibrary(void) { |
366 snd_pcm_hw_params_t *hwparams; | 370 snd_pcm_hw_params_t *hwparams; |
367 snd_pcm_sw_params_t *swparams; | 371 snd_pcm_sw_params_t *swparams; |
368 snd_pcm_format_t format; | 372 snd_pcm_format_t format; |
369 snd_pcm_uframes_t frames; | 373 snd_pcm_uframes_t frames; |
370 unsigned int rate; | 374 unsigned int rate; |
375 #ifdef SET_PERIOD_SIZE | |
371 unsigned int periods; | 376 unsigned int periods; |
372 unsigned int channels; | 377 #endif |
378 unsigned int channels; | |
373 Uint16 test_format; | 379 Uint16 test_format; |
374 | 380 |
375 /* Open the audio device */ | 381 /* Open the audio device */ |
376 /* Name of device should depend on # channels in spec */ | 382 /* Name of device should depend on # channels in spec */ |
377 status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); | 383 status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); |
462 return(-1); | 468 return(-1); |
463 } | 469 } |
464 spec->freq = rate; | 470 spec->freq = rate; |
465 | 471 |
466 /* Set the buffer size, in samples */ | 472 /* Set the buffer size, in samples */ |
473 #ifdef SET_PERIOD_SIZE | |
467 frames = spec->samples; | 474 frames = spec->samples; |
468 status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL); | 475 status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL); |
469 if ( status < 0 ) { | 476 if ( status < 0 ) { |
470 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); | 477 SDL_SetError("Couldn't set period size: %s", SDL_NAME(snd_strerror)(status)); |
471 ALSA_CloseAudio(this); | 478 ALSA_CloseAudio(this); |
472 return(-1); | 479 return(-1); |
473 } | 480 } |
474 | 481 |
475 spec->samples = frames; | 482 spec->samples = frames; |
476 | 483 |
477 periods = 2; | 484 periods = 2; |
478 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL); | 485 status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL); |
486 if ( status < 0 ) { | |
487 SDL_SetError("Couldn't set period count: %s", SDL_NAME(snd_strerror)(status)); | |
488 ALSA_CloseAudio(this); | |
489 return(-1); | |
490 } | |
491 #else | |
492 frames = spec->samples * 2; | |
493 status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames); | |
494 #endif | |
479 | 495 |
480 /* "set" the hardware with the desired parameters */ | 496 /* "set" the hardware with the desired parameters */ |
481 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); | 497 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); |
482 if ( status < 0 ) { | 498 if ( status < 0 ) { |
483 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); | 499 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); |
484 ALSA_CloseAudio(this); | 500 ALSA_CloseAudio(this); |
485 return(-1); | 501 return(-1); |
486 } | 502 } |
487 | 503 |
488 /* This is useful for debugging... */ | 504 /* This is useful for debugging... */ |
489 #if 0 | 505 #ifdef DEBUG_PERIOD_SIZE |
490 { snd_pcm_uframes_t bufsize; snd_pcm_sframes_t persize; unsigned int periods; int dir; | 506 { snd_pcm_uframes_t bufsize; snd_pcm_sframes_t persize; unsigned int periods; int dir; |
491 SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &bufsize); | 507 SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &bufsize); |
492 SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, &dir); | 508 SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, &dir); |
493 SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, &dir); | 509 SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, &dir); |
494 | 510 |
508 if ( status < 0 ) { | 524 if ( status < 0 ) { |
509 SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status)); | 525 SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status)); |
510 ALSA_CloseAudio(this); | 526 ALSA_CloseAudio(this); |
511 return(-1); | 527 return(-1); |
512 } | 528 } |
513 status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames); | |
514 if ( status < 0 ) { | |
515 SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status)); | |
516 ALSA_CloseAudio(this); | |
517 return(-1); | |
518 } | |
519 status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); | 529 status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); |
520 if ( status < 0 ) { | 530 if ( status < 0 ) { |
521 SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status)); | 531 SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status)); |
522 ALSA_CloseAudio(this); | 532 ALSA_CloseAudio(this); |
523 return(-1); | 533 return(-1); |