From 6c1c1e738dd762fb388d6971c3edb7656e2185a2 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Fri, 25 Apr 2014 21:24:04 +0000 Subject: [PATCH] Better handling of write underruns. git-svn-id: https://svn.code.sf.net/p/freetel/code@1567 01035d8c-6547-0410-b346-abe4f91aad63 --- .../source/platform/linux/audio_in_alsa.cpp | 8 +++----- .../source/platform/linux/audio_out_alsa.cpp | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/freedv-server/source/platform/linux/audio_in_alsa.cpp b/freedv-server/source/platform/linux/audio_in_alsa.cpp index 6d95544a..0bd9174d 100644 --- a/freedv-server/source/platform/linux/audio_in_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_in_alsa.cpp @@ -117,10 +117,10 @@ namespace FreeDV { int result = snd_pcm_readi(handle, array, length); started = true; if ( result == -EPIPE ) { - snd_pcm_recover(handle, result, 1); + snd_pcm_drop(handle); snd_pcm_start(handle); std::cerr << "ALSA input \"" << parameters << "\": read underrun." << std::endl; - return 0; + return length; } if ( result >= 0 ) { return result; @@ -187,7 +187,7 @@ namespace FreeDV { } if ( error == -EPIPE ) { - snd_pcm_recover(handle, error, 1); + snd_pcm_drop(handle); snd_pcm_start(handle); std::cerr << "ALSA input \"" << parameters << "\": ready underrun." << std::endl; return 0; @@ -212,8 +212,6 @@ namespace FreeDV { AudioInALSA::stop() { snd_pcm_drop(handle); - snd_pcm_prepare(handle); - snd_pcm_pause(handle, 1); started = false; } diff --git a/freedv-server/source/platform/linux/audio_out_alsa.cpp b/freedv-server/source/platform/linux/audio_out_alsa.cpp index b00d59e1..a89e7ce1 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -130,6 +130,8 @@ namespace FreeDV { std::size_t AudioOutALSA::write16(const std::int16_t * array, std::size_t length) { + int16_t buf[AudioFrameSamples * FillFrames]; + if ( !started ) { // Preload the audio output queue with some silence. // This makes underruns less likely. @@ -143,7 +145,6 @@ namespace FreeDV { // to avoid this problem. // snd_pcm_prepare(handle); - int16_t buf[AudioFrameSamples * FillFrames]; memset(buf, 0, sizeof(buf)); snd_pcm_writei(handle, buf, sizeof(buf) / sizeof(*buf)); } @@ -152,12 +153,27 @@ namespace FreeDV { started = true; if ( error == -EPIPE ) { std::cerr << "ALSA output \"" << parameters << "\": write underrun." << std::endl; - snd_pcm_recover(handle, error, 1); + snd_pcm_drop(handle); + snd_pcm_prepare(handle); + memset(buf, 0, sizeof(buf)); + snd_pcm_writei(handle, buf, sizeof(buf) / sizeof(*buf)); error = snd_pcm_writei(handle, array, length); } if ( error >= 0 ) return error; + else if ( error == -EPIPE ) { + // This is an unlikely condition, but should not be allowed to abort + // the program. + // About the only reason this might happen would be a failure of + // real-time schduling, for example a system management interrupt + // outside of the control of the operating system, or a problem with + // the sound hardware or driver. Punt and hope it gets better the next + // time. + std::cerr << "ALSA output \"" << parameters + << "\": double write underrun." << std::endl; + return 0; + } else do_throw(error, "Write"); } -- 2.25.1