simpleaudio-alsa: loop in the sa_ routine; fix xruns

This commit is contained in:
Kamal Mostafa 2012-08-08 16:24:44 -07:00
parent 95d7a87ce1
commit deed39904d
1 changed files with 36 additions and 12 deletions

View File

@ -45,11 +45,12 @@ sa_alsa_read( simpleaudio *sa, float *buf, size_t nframes )
snd_pcm_t *pcm = (snd_pcm_t *)sa->backend_handle;
while ( frames_read < nframes ) {
ssize_t r;
r = snd_pcm_readi(pcm, buf, nframes-frames_read);
r = snd_pcm_readi(pcm, buf+frames_read*sa->backend_framesize, nframes-frames_read);
if (r < 0) {
/* silently recover from e.g. overruns, and try once more */
fprintf(stderr, "snd_pcm_readi: reset for %s\n", snd_strerror(r));
snd_pcm_prepare(pcm);
r = snd_pcm_readi(pcm, buf, nframes-frames_read);
r = snd_pcm_readi(pcm, buf+frames_read*sa->backend_framesize, nframes-frames_read);
}
if (r < 0) {
fprintf(stderr, "snd_pcm_readi: %s\n", snd_strerror(r));
@ -66,18 +67,23 @@ sa_alsa_read( simpleaudio *sa, float *buf, size_t nframes )
static ssize_t
sa_alsa_write( simpleaudio *sa, float *buf, size_t nframes )
{
ssize_t frames_written;
ssize_t frames_written = 0;
snd_pcm_t *pcm = (snd_pcm_t *)sa->backend_handle;
frames_written = snd_pcm_writei(pcm, buf, nframes);
if (frames_written < 0) {
/* silently recover from e.g. underruns, and try once more */
snd_pcm_recover(pcm, frames_written, 1 /*silent*/);
frames_written = snd_pcm_writei(pcm, buf, nframes);
}
if (frames_written < 0) {
fprintf(stderr, "E: %s\n", snd_strerror(frames_written));
return -1;
while ( frames_written < nframes ) {
ssize_t r;
r = snd_pcm_writei(pcm, buf+frames_written*sa->backend_framesize, nframes-frames_written);
if (r < 0) {
/* silently recover from e.g. underruns, and try once more */
snd_pcm_recover(pcm, r, 0 /*silent*/);
r = snd_pcm_writei(pcm, buf+frames_written*sa->backend_framesize, nframes-frames_written);
}
if (r < 0) {
fprintf(stderr, "E: %s\n", snd_strerror(frames_written));
return -1;
}
frames_written += r;
}
assert (frames_written == nframes);
return frames_written;
}
@ -117,6 +123,7 @@ simpleaudio_open_stream_alsa(
return NULL;
}
/* set up ALSA hardware params */
error = snd_pcm_set_params(pcm,
SND_PCM_FORMAT_FLOAT,
SND_PCM_ACCESS_RW_INTERLEAVED,
@ -130,6 +137,23 @@ simpleaudio_open_stream_alsa(
return NULL;
}
/* set ALSA's "stop threshold" to 0.1 sec (rate/10) to avoid underruns */
snd_pcm_sw_params_t *swparams;
snd_pcm_sw_params_alloca(&swparams);
error = snd_pcm_sw_params_current(pcm, swparams);
if (error) {
fprintf(stderr, "E: %s\n", snd_strerror(error));
snd_pcm_close(pcm);
return NULL;
}
snd_pcm_sw_params_set_stop_threshold(pcm, swparams, rate/10);
error = snd_pcm_sw_params(pcm, swparams);
if (error) {
fprintf(stderr, "E: %s\n", snd_strerror(error));
snd_pcm_close(pcm);
return NULL;
}
simpleaudio *sa = malloc(sizeof(simpleaudio));
if ( !sa ) {
perror("malloc");