From: bruceperens Date: Thu, 13 Mar 2014 22:45:48 +0000 (+0000) Subject: Still confused about ALSA buffer sizes and their effect upon latency. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=95d600807842945fd8599bafc54d4c8fe4c897e6;p=freetel-svn-tracking.git Still confused about ALSA buffer sizes and their effect upon latency. git-svn-id: https://svn.code.sf.net/p/freetel/code@1440 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-server/source/platform/linux/audio_in_alsa.cpp b/freedv-server/source/platform/linux/audio_in_alsa.cpp index 9c7741b4..1bc555a9 100644 --- a/freedv-server/source/platform/linux/audio_in_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_in_alsa.cpp @@ -60,7 +60,7 @@ namespace FreeDV { 1, SampleRate, (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration / 2), - (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration * 2)); + (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration)); snd_pcm_start(handle); } @@ -80,10 +80,9 @@ namespace FreeDV { started = true; if ( result == -EPIPE ) { snd_pcm_recover(handle, result, 1); - result = snd_pcm_readi(handle, array, length); + snd_pcm_start(handle); std::cerr << "ALSA input \"" << parameters << "\": read underrun." << std::endl; - if ( result == -EPIPE ) - return 0; + return 0; } if ( result >= 0 ) { return result; @@ -109,15 +108,17 @@ namespace FreeDV { std::size_t AudioInALSA::ready() { - static const int period_size = (int)ceil( + static const int min_frame_size = (int)ceil( ((double)SampleRate * 1000.0) * MinimumFrameDuration); snd_pcm_sframes_t available = 0; snd_pcm_sframes_t delay = 0; int error; - if ( !started ) - return period_size; + if ( !started ) { + snd_pcm_start(handle); + return min_frame_size; + } error = snd_pcm_avail_delay(handle, &available, &delay); @@ -127,16 +128,16 @@ namespace FreeDV { if ( delay >= overlong_delay && available > 0 ) { snd_pcm_drop(handle); snd_pcm_prepare(handle); - started = false; + snd_pcm_start(handle); const double seconds = (double)delay / (double)SampleRate; error = snd_pcm_avail_delay(handle, &available, &delay); std::cerr << "ALSA input \"" << parameters << "\": overlong delay, dropped " - << seconds << " seconds of queued audio samples." << std::endl; + << seconds << " seconds of input." << std::endl; - return 0; + return min_frame_size / 2; } if ( error == -EPIPE ) { diff --git a/freedv-server/source/platform/linux/audio_out_alsa.cpp b/freedv-server/source/platform/linux/audio_out_alsa.cpp index 3cf78946..8600c544 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -17,7 +17,7 @@ namespace FreeDV { private: char * const parameters; snd_pcm_t * handle; - std::size_t period_size; + std::size_t min_frame_size; bool started; void @@ -49,7 +49,7 @@ namespace FreeDV { AudioOutALSA::AudioOutALSA(const char * p) : AudioOutput("alsa", p), parameters(strdup(p)), - period_size( + min_frame_size( (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration)), started(false) { @@ -61,8 +61,9 @@ namespace FreeDV { SND_PCM_ACCESS_RW_INTERLEAVED, 1, SampleRate, - period_size / 2, - (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration)); + min_frame_size / 2, + min_frame_size * 8); + snd_pcm_pause(handle, 1); } AudioOutALSA::~AudioOutALSA() @@ -112,16 +113,27 @@ namespace FreeDV { int error; if ( !started ) - return period_size * 2; + return min_frame_size; error = snd_pcm_avail_delay(handle, &available, &delay); + if ( delay > (((double)SampleRate / 1000.0) * MaximumFrameDuration) ) { + const double seconds = (double)delay / (double)SampleRate; + + std::cerr << "ALSA output \"" << parameters + << "\": overlong delay, dropped " + << seconds << " seconds of output." << std::endl; + snd_pcm_drop(handle); + snd_pcm_prepare(handle); + started = false; + return 0; + } if ( error == -EPIPE ) { std::cerr << "ALSA output \"" << parameters << "\": ready underrun." << std::endl; snd_pcm_recover(handle, error, 1); snd_pcm_pause(handle, 1); started = false; - return (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration); + return min_frame_size; if ( error < 0 ) return 0;