From 2daa7aacebf3d969bed570490d00fbb5d89d1855 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Wed, 28 May 2014 22:02:30 +0000 Subject: [PATCH] Get the wait-for-output software working correctly. git-svn-id: https://svn.code.sf.net/p/freetel/code@1606 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/source/drivers.h | 7 +- freedv-server/source/platform/linux/alsa.cpp | 2 - .../source/platform/linux/audio_in_alsa.cpp | 4 +- .../source/platform/linux/audio_out_alsa.cpp | 6 +- freedv-server/source/run.cpp | 78 +++++++------------ 5 files changed, 36 insertions(+), 61 deletions(-) diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 0682e5b8..6d262583 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -60,10 +60,9 @@ const unsigned int SampleRate = 48000; const unsigned int SamplesPerMillisecond = ((double)SampleRate / 1000.0); -/// The number of audio samples in an audio frame. Audio frames must be a -/// power of two (this is a common hardware requirement) and must be shorter -/// than any codec/modem frame in the program. -const unsigned int AudioFrameSamples = 512; +/// The number of audio samples in an audio frame. Some systems will require +/// this to be a power of two (this is a common hardware requirement). +const unsigned int AudioFrameSamples = SampleRate / 20; /// The audio frame duration in milliseconds. The audio interfaces will /// use this as a period size. diff --git a/freedv-server/source/platform/linux/alsa.cpp b/freedv-server/source/platform/linux/alsa.cpp index e38c46a8..738a6ffe 100644 --- a/freedv-server/source/platform/linux/alsa.cpp +++ b/freedv-server/source/platform/linux/alsa.cpp @@ -303,13 +303,11 @@ namespace FreeDV { if ((error = snd_pcm_sw_params(handle, sw_params)) < 0) do_throw(error, name, stream, "ALSA set software parameters"); -#if 0 // Dump sound parameters, for debugging. snd_output_t * output = 0; snd_output_stdio_attach(&output, stderr, 0); fprintf(stderr, "%s\n", name); snd_pcm_dump_setup(handle, output); -#endif snd_pcm_sw_params_free(sw_params); diff --git a/freedv-server/source/platform/linux/audio_in_alsa.cpp b/freedv-server/source/platform/linux/audio_in_alsa.cpp index e5a194f6..becad0d5 100644 --- a/freedv-server/source/platform/linux/audio_in_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_in_alsa.cpp @@ -23,7 +23,7 @@ namespace FreeDV { /// class AudioInALSA : public AudioInput { private: - static const int overlong_delay = AudioFrameSamples * 8; + static const int overlong_delay = AudioFrameSamples * 4; snd_pcm_t * handle; char * const parameters; @@ -83,7 +83,7 @@ namespace FreeDV { 1, SampleRate, AudioFrameSamples, - AudioFrameSamples * 2); + AudioFrameSamples * 3); if ( handle == 0 ) do_throw(-ENODEV); diff --git a/freedv-server/source/platform/linux/audio_out_alsa.cpp b/freedv-server/source/platform/linux/audio_out_alsa.cpp index d20d983c..9d914462 100644 --- a/freedv-server/source/platform/linux/audio_out_alsa.cpp +++ b/freedv-server/source/platform/linux/audio_out_alsa.cpp @@ -22,7 +22,7 @@ namespace FreeDV { // If more than this number of frames are queued for audio output, the // latency is too high. Flush the output and print an overlong-delay message. - const unsigned int MaximumDelayFrames = 8; + const unsigned int MaximumDelayFrames = 4; // At the start of playback, preload the audio output with this many // frames of zero data. This delays the output enough to avoid later @@ -95,7 +95,7 @@ namespace FreeDV { 1, SampleRate, AudioFrameSamples, - AudioFrameSamples * 2); + AudioFrameSamples * 3); if ( handle == 0 ) do_throw(-ENODEV); @@ -206,7 +206,7 @@ namespace FreeDV { // If we've not started, allow the first write to be large, but // not so large that we'll active the overlong-delay code. if ( !started ) - return AudioFrameSamples * MaximumDelayFrames - FillFrames - 1; + return AudioFrameSamples * min(1, (MaximumDelayFrames - FillFrames - 1)); else return available; } diff --git a/freedv-server/source/run.cpp b/freedv-server/source/run.cpp index bba6642b..5834b488 100644 --- a/freedv-server/source/run.cpp +++ b/freedv-server/source/run.cpp @@ -63,6 +63,9 @@ namespace FreeDV { /// Run the main loop of FreeDV in half-duplex mode. /// void half_duplex(); + + /// Wake when there is room in the output device. + void wake_output(AudioDevice *); }; Run::Run(Interfaces * interfaces) @@ -214,22 +217,7 @@ namespace FreeDV { else if ( result < 0 ) std::cerr << "Transmitter I/O error: " << strerror(errno) << std::endl; } - if ( out_fifo.get_available() > 0 ) { - // There are samples queued for the transmitter. Wake when there is room - // in its buffer. - if ( output_fd_base < 0 ) { - output_fd_base = poll_fd_count; - add_poll_device(i->transmitter); - } - } - else { - // There are no samples queued for the transmitter. Don't wake upon its - // buffer availability. - if ( output_fd_base > 0 ) { - poll_fd_count = output_fd_base; - output_fd_base = -1; - } - } + wake_output(i->transmitter); if ( final ) { if ( in_fifo.get_available() == 0 @@ -267,22 +255,7 @@ namespace FreeDV { else if ( result < 0 ) std::cerr << "Transmitter I/O error: " << strerror(errno) << std::endl; } - if ( out_fifo.get_available() > 0 ) { - // There are samples queued for the transmitter. Wake when there is room - // in its buffer. - if ( output_fd_base < 0 ) { - output_fd_base = poll_fd_count; - add_poll_device(i->transmitter); - } - } - else { - // There are no samples queued for the transmitter. Don't wake upon its - // buffer availability. - if ( output_fd_base > 0 ) { - poll_fd_count = output_fd_base; - output_fd_base = -1; - } - } + wake_output(i->transmitter); if ( final ) { if ( in_fifo.get_available() == 0 @@ -367,24 +340,7 @@ namespace FreeDV { else if ( result < 0 ) std::cerr << "Loudspeaker I/O error: " << strerror(errno) << std::endl; } - - if ( out_fifo.get_available() > 0 ) { - // std::cerr << out_fifo.get_available() / 2 << ' '; - // There are samples queued for the loudspeaker. Wake when there is room - // in its buffer. - if ( output_fd_base < 0 ) { - output_fd_base = poll_fd_count; - add_poll_device(i->transmitter); - } - } - else { - // There are no samples queued for the loudspeaker. Don't wake upon its - // buffer availability. - if ( output_fd_base > 0 ) { - poll_fd_count = output_fd_base; - output_fd_base = -1; - } - } + wake_output(i->loudspeaker); } // FIX: Once everything else has been tested, make this program work with @@ -616,6 +572,28 @@ namespace FreeDV { drain_ssb(false); } + void + Run::wake_output(AudioDevice * device) + { + if ( out_fifo.get_available() / 2 > 0 ) { + // There are samples queued for the loudspeaker/transmitter. + // Wake when there is room + // in its buffer. + if ( output_fd_base < 0 ) { + output_fd_base = poll_fd_count; + add_poll_device(device); + } + } + else { + // There are no samples queued for the loudspeaker/transmitter. + // Don't wake upon its buffer availability. + if ( output_fd_base > 0 ) { + poll_fd_count = output_fd_base; + output_fd_base = -1; + } + } + } + int run(Interfaces * i) { -- 2.25.1