From d1c01e10bbc13d207952f935272899535a5196e0 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Thu, 13 Mar 2014 20:01:55 +0000 Subject: [PATCH] More coding to handle frame duration periods in the audio interfaces and the scheduler. git-svn-id: https://svn.code.sf.net/p/freetel/code@1436 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/source/drivers.h | 16 ++++++++------ .../source/platform/linux/audio_in_alsa.cpp | 2 +- .../source/platform/linux/audio_out_alsa.cpp | 2 +- freedv-server/source/run.cpp | 21 +++++++++++++------ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 548537c7..0ab42bb8 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -14,15 +14,19 @@ namespace FreeDV { const unsigned int SampleRate = 48000; // The minimum frame duration in milliseconds. The audio interfaces will - // use this as a period size. It should be the smallest frame we expect - // a modem/protocol/codec combination to use. If it's too large, latency - // will be overlong. + // use one half of this as a period size. It should be the smallest frame + // we expect a modem/protocol/codec combination to use. If it's too large, + // latency will be overlong. const unsigned int MinimumFrameDuration = 10; // The maximum frame duration in milliseconds. The audio interfaces will - // use 3 times this as a buffer size. It should be the largest frame we - // expect a modem/protocol/codec combination to use. If it's too large, - // ALSA bugs surface and cause long delays. + // use 2 times this as a buffer size. It must be an integer multiple of + // MinimumFrameDuration, or ALSA will complain. It should be the largest + // frame we expect a modem/protocol/codec combination to use. + // If a modem/framer/codec combination specify a frame duration larger than + // this, it's an error. + // If it's too large, ALSA bugs surface (Or is it my lack of + // understanding?) and cause long delays. const unsigned int MaximumFrameDuration = 100; /// Allocate memory and copy a string into it, so that it is permanently diff --git a/freedv-server/source/platform/linux/audio_in_alsa.cpp b/freedv-server/source/platform/linux/audio_in_alsa.cpp index 50ba740e..6d084110 100644 --- a/freedv-server/source/platform/linux/audio_in_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_in_alsa.cpp @@ -59,7 +59,7 @@ namespace FreeDV { SND_PCM_ACCESS_RW_INTERLEAVED, 1, SampleRate, - (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration), + (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration / 2), (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration * 2)); snd_pcm_start(handle); diff --git a/freedv-server/source/platform/linux/audio_out_alsa.cpp b/freedv-server/source/platform/linux/audio_out_alsa.cpp index 763ee0bd..5931e11d 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -61,7 +61,7 @@ namespace FreeDV { SND_PCM_ACCESS_RW_INTERLEAVED, 1, SampleRate, - period_size, + period_size / 2, (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration)); } diff --git a/freedv-server/source/run.cpp b/freedv-server/source/run.cpp index dd762f01..35272e8e 100644 --- a/freedv-server/source/run.cpp +++ b/freedv-server/source/run.cpp @@ -1,9 +1,10 @@ /// The main loop of the program. #include "drivers.h" -#include #include -#include +#include +#include +#include #include #include @@ -22,7 +23,6 @@ /// namespace FreeDV { - class Run { private: const std::size_t TempSize = 10240; @@ -197,14 +197,23 @@ namespace FreeDV { void Run::run() { - // The no-op codec, modem, and framer may have very small durations. - // So we set a minimum here. - min_frame_duration = 10; + min_frame_duration = MinimumFrameDuration; min_frame_duration = max(min_frame_duration, i->modem->min_frame_duration()); min_frame_duration = max(min_frame_duration, i->codec->min_frame_duration()); min_frame_duration = max(min_frame_duration, i->framer->min_frame_duration()); std::cerr << "minimum frame duration is " << min_frame_duration << std::endl; + if ( min_frame_duration > MaximumFrameDuration ) { + std::ostringstream str; + + str << "At " << __FILE__ << ":" << __LINE__ << std::endl; + str << "min_frame_duration of " << min_frame_duration; + str << " is larger than MaximumFrameDuration of "; + str << MaximumFrameDuration << '.' << std::endl; + str << "A Modem, Framer, or Codec returned min_frame_duration() that"; + str << " was too large, or MaximumFrameDuration must be increased."; + throw std::runtime_error(str.str().c_str()); + } assert(min_frame_duration < 1000000); while ( true ) { -- 2.25.1