Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -rupN SDL.orig/src/audio/alsa/SDL_alsa_audio.c SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.c
- --- SDL.orig/src/audio/alsa/SDL_alsa_audio.c 2013-02-27 08:25:35.000000000 -0500
- +++ SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.c 2013-02-27 10:50:04.000000000 -0500
- @@ -43,6 +43,13 @@
- /* The tag name used by ALSA audio */
- #define DRIVER_NAME "alsa"
- +#if 1
- +/* Both aplay and mpg123 seem to go for a 0.5s buffer */
- +static int BUFFER_LENGTH = 1000; /* in millisecs */
- +static int PLAY_START_THRESH = (1000/2); /* in millisecs */
- +static int PERIOD_LENGTH = 1024; /* in frames */
- +#endif
- +
- /* Audio driver functions */
- static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec);
- static void ALSA_WaitAudio(_THIS);
- @@ -308,6 +315,7 @@ static void ALSA_PlayAudio(_THIS)
- snd_pcm_uframes_t frames_left;
- const Uint8 *sample_buf = (const Uint8 *) mixbuf;
- const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) * this->spec.channels;
- + int frames;
- swizzle_alsa_channels(this);
- @@ -317,22 +325,35 @@ static void ALSA_PlayAudio(_THIS)
- /* This works, but needs more testing before going live */
- /*SDL_NAME(snd_pcm_wait)(pcm_handle, -1);*/
- - status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, frames_left);
- + frames = frames_left;
- + status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, frames);
- if ( status < 0 ) {
- if ( status == -EAGAIN ) {
- /* Apparently snd_pcm_recover() doesn't handle this case - does it assume snd_pcm_wait() above? */
- SDL_Delay(1);
- continue;
- }
- +#if 0
- + if ( status == -EPIPE ) {
- + /* EPIPE means underrun */
- + PRINTF("SDL_DBG %s Underrun.\n", __FUNCTION__);
- + }
- + else
- + PRINTF("SDL_DBG %s pcm_recover(%d).\n", __FUNCTION__, status);
- +#endif
- status = SDL_NAME(snd_pcm_recover)(pcm_handle, status, 0);
- if ( status < 0 ) {
- /* Hmm, not much we can do - abort */
- fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", SDL_NAME(snd_strerror)(status));
- - this->enabled = 0;
- + this->enabled = 0;
- return;
- }
- continue;
- }
- +#if 0
- + else if (status != frames)
- + PRINTF("SDL_DBG %s short write %d frames.\n", __FUNCTION__, status);
- +#endif
- sample_buf += status * frame_size;
- frames_left -= status;
- }
- @@ -360,6 +381,8 @@ static int ALSA_finalize_hardware(_THIS,
- {
- int status;
- snd_pcm_uframes_t bufsize;
- + snd_pcm_uframes_t persize = 0;
- + unsigned int periods = 0;
- /* "set" the hardware with the desired parameters */
- status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
- @@ -372,23 +395,39 @@ static int ALSA_finalize_hardware(_THIS,
- if ( status < 0 ) {
- return(-1);
- }
- - if ( !override && bufsize != spec->samples * 2 ) {
- +#if 0
- + if ( !override && bufsize != spec->samples * 2 ) {
- return(-1);
- }
- /* FIXME: Is this safe to do? */
- spec->samples = bufsize / 2;
- +#else
- + /* For ZIPIT test 16k buffer with various period sizes */
- + status = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, NULL);
- + if ( status < 0 ) {
- + return(-1);
- + }
- + if ( !override && persize != spec->samples ) {
- + return(-1);
- + }
- + spec->samples = persize;
- + periodsize = 32; /* Loop write size. Try smaller than persize; */
- +#endif
- /* This is useful for debugging */
- if ( getenv("SDL_AUDIO_ALSA_DEBUG") ) {
- - snd_pcm_uframes_t persize = 0;
- - unsigned int periods = 0;
- -
- SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, NULL);
- SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, NULL);
- + periodsize = persize;
- fprintf(stderr, "ALSA: period size = %ld, periods = %u, buffer size = %lu\n", persize, periods, bufsize);
- }
- + else { /* ZIPIT */
- + SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, NULL);
- + /* PRINTF("SDL_DBG: period size = %ld, periods = %u, buffer size = %lu\n", persize, periods, bufsize); */
- + }
- +
- return(0);
- }
- @@ -415,6 +454,7 @@ static int ALSA_set_period_size(_THIS, S
- }
- frames = spec->samples;
- +#if 0
- status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
- if ( status < 0 ) {
- return(-1);
- @@ -425,6 +465,26 @@ static int ALSA_set_period_size(_THIS, S
- if ( status < 0 ) {
- return(-1);
- }
- +#else
- + /* For ZIPIT test 16k buffer with various period sizes */
- + /* Lets try 1024 instead of spec->samples from SDL. */
- + frames = 1024;
- +
- + if (frames > (16384 / 2))
- + periods = 2;
- + else
- + periods = 16384 / frames;
- +
- + status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
- + if ( status < 0 ) {
- + return(-1);
- + }
- +
- + status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL);
- + if ( status < 0 ) {
- + return(-1);
- + }
- +#endif
- return ALSA_finalize_hardware(this, spec, hwparams, override);
- }
- @@ -449,8 +509,12 @@ static int ALSA_set_buffer_size(_THIS, S
- }
- }
- }
- -
- +#if 0
- frames = spec->samples * 2;
- +#else
- + /* For ZIPIT test 16k buffer with various period sizes */
- + frames = 16384;
- +#endif
- status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames);
- if ( status < 0 ) {
- return(-1);
- @@ -467,6 +531,11 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
- snd_pcm_format_t format;
- unsigned int rate;
- unsigned int channels;
- + const char * env;
- + snd_pcm_uframes_t buffer_size;
- + snd_pcm_uframes_t period_size;
- + snd_pcm_uframes_t start_thresh = 1;
- + snd_pcm_uframes_t frames;
- Uint16 test_format;
- /* Open the audio device */
- @@ -560,6 +629,7 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
- }
- spec->freq = rate;
- +#if 0
- /* Set the buffer size, in samples */
- if ( ALSA_set_period_size(this, spec, hwparams, 0) < 0 &&
- ALSA_set_buffer_size(this, spec, hwparams, 0) < 0 ) {
- @@ -570,6 +640,85 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
- return(-1);
- }
- }
- +#else
- + frames = spec->samples * 2;
- +
- + /* On ZIPIT IZ2S just go for 1 sec buffer and 1024 periods. */
- + env = getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE");
- + if ( env ) {
- + status = SDL_atoi(env);
- + if ( status > 1 )
- + BUFFER_LENGTH = status;
- + }
- + frames = buffer_size = rate * BUFFER_LENGTH / 1000;
- + status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames);
- + if ( status < 0 ) {
- + SDL_SetError("Couldn't set buffer size: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return(-1);
- + }
- +
- + /* Since we can override in env, lets start with the SDL period_size. */
- + PERIOD_LENGTH = spec->samples;
- +
- + env = getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE");
- + if ( env ) {
- + status = SDL_atoi(env);
- + if ( status > 1 )
- + PERIOD_LENGTH = status;
- + }
- + frames = period_size = PERIOD_LENGTH;
- + if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &frames, NULL) < 0) {
- + SDL_SetError("Couldn't set period size: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return(-1);
- + }
- +
- + /* "set" the hardware with the desired parameters */
- + status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
- + if ( status < 0 ) {
- + SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return(-1);
- + }
- +
- + env = getenv("SDL_AUDIO_ALSA_SET_START_THRESH");
- + if ( env ) {
- + status = SDL_atoi(env);
- + if ( status >= 0 )
- + PLAY_START_THRESH = status;
- + }
- + start_thresh = rate * PLAY_START_THRESH / 1000;
- +
- + /* Get samples for the actual buffer size */
- + status = SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &buffer_size);
- + if ( status < 0 ) {
- + SDL_SetError("Couldn't set buffer size: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return(-1);
- + }
- + status = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &period_size, NULL);
- + if ( status < 0 ) {
- + SDL_SetError("Couldn't get period size: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return(-1);
- + }
- +
- + if (PLAY_START_THRESH <= 1)
- + start_thresh = 1; /* start playing after the first write */
- + else /* start playing after a few periods to calm down rockbox outta the gate */
- + {
- + if (start_thresh > buffer_size)
- + frames = buffer_size;
- + else for (frames = 0; frames < start_thresh; frames+=period_size);
- + if (frames < 1)
- + frames = period_size*2;
- + start_thresh = frames;
- + }
- +
- + /* Tell the SDL client what we really got for period_size. */
- + spec->samples = period_size;
- +#endif
- /* Set the software parameters */
- snd_pcm_sw_params_alloca(&swparams);
- @@ -579,12 +728,22 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
- ALSA_CloseAudio(this);
- return(-1);
- }
- - status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 1);
- +
- + /* Start playing after so many frames. */
- + frames = start_thresh;
- + status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, frames);
- if ( status < 0 ) {
- SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status));
- ALSA_CloseAudio(this);
- return(-1);
- }
- + /* wake up on every interrupt */
- + status = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, 1);
- + if ( status < 0 ) {
- + SDL_SetError("Couldn't set min available: %s", SDL_NAME(snd_strerror)(status));
- + ALSA_CloseAudio(this);
- + return -1;
- + }
- status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams);
- if ( status < 0 ) {
- SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status));
- diff -rupN SDL.orig/src/audio/alsa/SDL_alsa_audio.h SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.h
- --- SDL.orig/src/audio/alsa/SDL_alsa_audio.h 2013-02-27 08:25:35.000000000 -0500
- +++ SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.h 2013-02-27 09:48:14.000000000 -0500
- @@ -35,6 +35,9 @@ struct SDL_PrivateAudioData {
- /* The audio device handle */
- snd_pcm_t *pcm_handle;
- + /* periods */
- + snd_pcm_uframes_t periodsize;
- +
- /* Raw mixing buffer */
- Uint8 *mixbuf;
- int mixlen;
- @@ -44,5 +47,6 @@ struct SDL_PrivateAudioData {
- #define pcm_handle (this->hidden->pcm_handle)
- #define mixbuf (this->hidden->mixbuf)
- #define mixlen (this->hidden->mixlen)
- +#define periodsize (this->hidden->periodsize)
- #endif /* _ALSA_PCM_audio_h */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement