From ce0abd50d760975f1479a1d2f29af22016b9e0c3 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Tue, 18 Mar 2014 18:07:42 +0000 Subject: [PATCH] No more timer-based operation. git-svn-id: https://svn.code.sf.net/p/freetel/code@1447 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/source/drivers.h | 19 ++------ .../source/platform/linux/audio_in_alsa.cpp | 13 ++--- .../source/platform/linux/audio_out_alsa.cpp | 13 ++--- freedv-server/source/run.cpp | 48 +------------------ 4 files changed, 15 insertions(+), 78 deletions(-) diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index b2672c18..edd1b4b3 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -16,21 +16,10 @@ extern const char * program_name; /// drivers. const unsigned int SampleRate = 48000; -// The minimum frame duration in milliseconds. The audio interfaces will -// 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 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; +// The audio frame duration in milliseconds. The audio interfaces will +// use this as a period size. It should be 1/2 of the smallest codec frame +// size we expect to use. +const unsigned int AudioFrameDuration = 10; /// Allocate memory and copy a string into it, so that it is permanently /// stored. diff --git a/freedv-server/source/platform/linux/audio_in_alsa.cpp b/freedv-server/source/platform/linux/audio_in_alsa.cpp index 2e0ae798..e93b47c7 100644 --- a/freedv-server/source/platform/linux/audio_in_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_in_alsa.cpp @@ -15,7 +15,7 @@ namespace FreeDV { class AudioInALSA : public AudioInput { private: static const int overlong_delay = ((double)SampleRate / 1000.0) - * MaximumFrameDuration; + * AudioFrameDuration * 2; char * const parameters; snd_pcm_t * handle; @@ -67,8 +67,8 @@ namespace FreeDV { SND_PCM_ACCESS_RW_INTERLEAVED, 1, SampleRate, - (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration / 2), - (int)ceil(((double)SampleRate / 1000.0) * MaximumFrameDuration)); + (int)ceil((double)SampleRate / 1000.0) * AudioFrameDuration, + (int)ceil((double)SampleRate / 1000.0) * AudioFrameDuration); snd_pcm_start(handle); } @@ -129,16 +129,13 @@ namespace FreeDV { std::size_t AudioInALSA::ready() { - 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 ) { snd_pcm_start(handle); - return min_frame_size; + return ((double)SampleRate / 1000.0) * AudioFrameDuration; } error = snd_pcm_avail_delay(handle, &available, &delay); @@ -158,7 +155,7 @@ namespace FreeDV { std::cerr << "ALSA input \"" << parameters << "\": overlong delay, dropped " << seconds << " seconds of input." << std::endl; - return min_frame_size / 2; + return 0; } 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 dca77e80..cf371a41 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -17,7 +17,6 @@ namespace FreeDV { private: char * const parameters; snd_pcm_t * handle; - std::size_t min_frame_size; bool started; void @@ -57,8 +56,6 @@ namespace FreeDV { AudioOutALSA::AudioOutALSA(const char * p) : AudioOutput("alsa", p), parameters(strdup(p)), - min_frame_size( - (int)ceil(((double)SampleRate / 1000.0) * MinimumFrameDuration)), started(false) { handle = ALSASetup( @@ -69,8 +66,8 @@ namespace FreeDV { SND_PCM_ACCESS_RW_INTERLEAVED, 1, SampleRate, - min_frame_size / 2, - min_frame_size * 8); + (int)ceil((double)SampleRate / 1000.0) * AudioFrameDuration, + (int)ceil((double)SampleRate / 1000.0) * AudioFrameDuration); snd_pcm_pause(handle, 1); } @@ -134,10 +131,10 @@ namespace FreeDV { int error; if ( !started ) - return min_frame_size; + return ((double)SampleRate / 1000.0) * AudioFrameDuration; error = snd_pcm_avail_delay(handle, &available, &delay); - if ( delay > (((double)SampleRate / 1000.0) * MaximumFrameDuration) ) { + if ( delay > (((double)SampleRate / 1000.0) * AudioFrameDuration * 2) ) { const double seconds = (double)delay / (double)SampleRate; std::cerr << "ALSA output \"" << parameters @@ -154,7 +151,7 @@ namespace FreeDV { snd_pcm_recover(handle, error, 1); snd_pcm_pause(handle, 1); started = false; - return min_frame_size; + return 0; if ( error < 0 ) return 0; diff --git a/freedv-server/source/run.cpp b/freedv-server/source/run.cpp index 747a6ff0..f84ff747 100644 --- a/freedv-server/source/run.cpp +++ b/freedv-server/source/run.cpp @@ -34,8 +34,6 @@ namespace FreeDV { FIFO out_fifo; bool ptt_digital; bool ptt_ssb; - std::size_t min_frame_duration; - struct timespec next_frame_time; void key_down(); void key_up(); @@ -168,60 +166,16 @@ namespace FreeDV { if ( bytes_to_decode > 0 ) codec_fifo.get_done(bytes_to_decode); - if ( result > 0 ) { - // std::cerr << '.'; + if ( result > 0 ) out_fifo.put_done(result * 2); - - // Calculate a time one millisecond short of when the next frame - // should start. We can sleep until then. - const long duration = ((min_frame_duration - 1) * 1000000); - - next_frame_time.tv_sec = start_time.tv_sec; - next_frame_time.tv_nsec = start_time.tv_nsec + duration; - next_frame_time.tv_sec += next_frame_time.tv_nsec / 1000000000; - next_frame_time.tv_nsec %= 1000000000; - } - else { - - // std::cerr << '+'; - - // Go to sleep for a millisecond and try again. We could poll the - // I/O interfaces for ready instead. - next_frame_time = start_time; - next_frame_time.tv_nsec += 1000000; - next_frame_time.tv_sec += next_frame_time.tv_nsec / 1000000000; - next_frame_time.tv_nsec %= 1000000000; - } } } void Run::run() { - 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 << "The minimum frame duration is " - << min_frame_duration << " milliseconds." << 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," << std::endl; - str << "or MaximumFrameDuration must be increased."; - throw std::runtime_error(str.str().c_str()); - } - assert(min_frame_duration < 1000000); - while ( true ) { receive(); - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_frame_time, 0); } } -- 2.25.1