From 195ea5920975dd6136add9bf2b5e2e1151fa517e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 26 Aug 2015 12:30:46 -0700 Subject: [PATCH] ALSA: fix playback on raw device --- README.md | 1 - example/sio_sine.c | 5 +++++ src/alsa.cpp | 29 ++++++++++++++++++----------- src/alsa.hpp | 1 + 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 23d58f7..857d1c6 100644 --- a/README.md +++ b/README.md @@ -274,7 +274,6 @@ Then look at `html/index.html` in a browser. ## Roadmap - 0. test sio_sine with ALSA raw device 0. Make sure PulseAudio can handle refresh devices crashing before block_until_have_devices 0. Integrate into libgroove and test with Groove Basin diff --git a/example/sio_sine.c b/example/sio_sine.c index b75bfb5..04a56a6 100644 --- a/example/sio_sine.c +++ b/example/sio_sine.c @@ -188,6 +188,11 @@ int main(int argc, char **argv) { fprintf(stderr, "Output device: %s\n", device->name); + if (device->probe_error) { + fprintf(stderr, "Cannot probe device: %s\n", soundio_strerror(device->probe_error)); + return 1; + } + struct SoundIoOutStream *outstream = soundio_outstream_create(device); outstream->write_callback = write_callback; outstream->underflow_callback = underflow_callback; diff --git a/src/alsa.cpp b/src/alsa.cpp index cdc6c6b..a0d0389 100644 --- a/src/alsa.cpp +++ b/src/alsa.cpp @@ -970,6 +970,17 @@ void outstream_thread_run(void *arg) { } case SND_PCM_STATE_PREPARED: { + snd_pcm_sframes_t avail = snd_pcm_avail_update(osa->handle); + if (avail < 0) { + outstream->error_callback(outstream, SoundIoErrorStreaming); + return; + } + + if ((snd_pcm_uframes_t)avail == osa->buffer_size_frames) { + outstream->write_callback(outstream, 0, avail); + continue; + } + if ((err = snd_pcm_start(osa->handle)) < 0) { outstream->error_callback(outstream, SoundIoErrorStreaming); return; @@ -1155,6 +1166,13 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) return SoundIoErrorOpeningDevice; } + osa->buffer_size_frames = ceil(outstream->software_latency * (double)outstream->sample_rate); + + if ((err = snd_pcm_hw_params_set_buffer_size_near(osa->handle, hwparams, &osa->buffer_size_frames)) < 0) { + outstream_destroy_alsa(si, os); + return SoundIoErrorOpeningDevice; + } + outstream->software_latency = ((double)osa->buffer_size_frames) / (double)outstream->sample_rate; if (device->is_raw) { unsigned int microseconds; @@ -1172,17 +1190,6 @@ static int outstream_open_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) } } - - snd_pcm_uframes_t buffer_size_frames = ceil(outstream->software_latency * (double)outstream->sample_rate); - - if ((err = snd_pcm_hw_params_set_buffer_size_near(osa->handle, hwparams, &buffer_size_frames)) < 0) { - outstream_destroy_alsa(si, os); - return SoundIoErrorOpeningDevice; - } - outstream->software_latency = ((double)buffer_size_frames) / (double)outstream->sample_rate; - - - snd_pcm_uframes_t period_size; if ((snd_pcm_hw_params_get_period_size(hwparams, &period_size, nullptr)) < 0) { outstream_destroy_alsa(si, os); diff --git a/src/alsa.hpp b/src/alsa.hpp index bac9ea8..de7f874 100644 --- a/src/alsa.hpp +++ b/src/alsa.hpp @@ -42,6 +42,7 @@ struct SoundIoOutStreamAlsa { int chmap_size; snd_pcm_uframes_t offset; snd_pcm_access_t access; + snd_pcm_uframes_t buffer_size_frames; int sample_buffer_size; char *sample_buffer; int poll_fd_count;