From 0d79a71c67021845e4d61ac86e1c6779193fc3f2 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Tue, 21 Jan 2014 03:34:02 +0000 Subject: [PATCH] Add I/O ready indication. New tests for blank_panel. git-svn-id: https://svn.code.sf.net/p/freetel/code@1379 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/CMakeLists.txt | 2 + freedv-server/source/audio_sink.cpp | 12 +++++ freedv-server/source/blank_panel.cpp | 9 ++++ freedv-server/source/drivers.h | 31 ++++++++++-- freedv-server/source/io_device.cpp | 14 ++++++ freedv-server/source/ptt_constant.cpp | 8 +++ freedv-server/source/ptt_input.cpp | 2 +- freedv-server/source/test/audio_sink.cpp | 5 ++ freedv-server/source/test/blank_panel.cpp | 31 ++++++++++++ freedv-server/source/test/tone.cpp | 5 ++ freedv-server/source/text_constant.cpp | 9 ++++ freedv-server/source/text_input.cpp | 2 +- freedv-server/source/tone.cpp | 59 ++++++++++++++--------- freedv-server/source/user_interface.cpp | 2 +- 14 files changed, 160 insertions(+), 31 deletions(-) create mode 100644 freedv-server/source/io_device.cpp create mode 100644 freedv-server/source/test/blank_panel.cpp diff --git a/freedv-server/CMakeLists.txt b/freedv-server/CMakeLists.txt index e8ec3251..b70ca163 100644 --- a/freedv-server/CMakeLists.txt +++ b/freedv-server/CMakeLists.txt @@ -98,6 +98,7 @@ set(Compile.sources source/driver_manager.cpp source/event_handler.cpp source/interfaces.cpp + source/io_device.cpp source/keying.cpp source/keying_sink.cpp source/libevent.cpp @@ -126,6 +127,7 @@ set(Optional.sources set(Test.sources source/test/audio_sink.cpp source/test/base.cpp + source/test/blank_panel.cpp source/test/keying_sink.cpp source/test/tone.cpp ) diff --git a/freedv-server/source/audio_sink.cpp b/freedv-server/source/audio_sink.cpp index e0b41f10..560db6b0 100644 --- a/freedv-server/source/audio_sink.cpp +++ b/freedv-server/source/audio_sink.cpp @@ -1,6 +1,7 @@ /// The AudioSink driver, called as "sink", discards the audio, for testing. #include "drivers.h" +#include namespace FreeDV { /// Audio output "sink", discards the audio, for testing. @@ -11,6 +12,11 @@ namespace FreeDV { AudioSink(const char * parameters); ~AudioSink(); + /// Return the number of audio samples the device can handle in + /// a write without blocking. This version always returns SIZE_MAX. + virtual size_t + ready(); + /// Write audio into the "short" type. virtual std::size_t write16(const int16_t * array, std::size_t length); @@ -38,6 +44,12 @@ namespace FreeDV { return new ::FreeDV::AudioSink(parameter); } + size_t + AudioSink::ready() + { + return SIZE_MAX; + } + #ifndef NO_INITIALIZERS static bool diff --git a/freedv-server/source/blank_panel.cpp b/freedv-server/source/blank_panel.cpp index a9444fdf..9127a181 100644 --- a/freedv-server/source/blank_panel.cpp +++ b/freedv-server/source/blank_panel.cpp @@ -11,6 +11,9 @@ namespace FreeDV { BlankPanel(const char * parameter, Interfaces * interfaces); virtual ~BlankPanel(); + /// Return the amount of bytes ready for read. In this case, it always + /// returns 0. + size_t ready(); }; BlankPanel::BlankPanel(const char * parameter, Interfaces * interfaces) @@ -22,6 +25,12 @@ namespace FreeDV { { } + size_t + BlankPanel::ready() + { + return 0; + } + UserInterface * Driver::BlankPanel(const char * parameter, Interfaces * interfaces) { diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 61473626..e7e09f66 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -81,8 +81,31 @@ namespace FreeDV { return base.print(stream); } + /// Virtual base class for all drivers that perform non-blocking I/O. + /// These are AudioInput and AudioOutput, PTTInput, TextInput, and + /// UserInterface. + /// Keying is assumed to never need to block. + class IODevice : public ::FreeDV::Base { + protected: + IODevice(const char * name, const char * parameters); + + public: + /// Return the number of audio samples, or bytes for devices other than + /// audio interfaces, that can be read or written. Return zero if there + /// is not enough readable or writable data to do some work, for example + /// if the device is a PTT input and the internal driver detects less + /// readable data than necessary to read the HID status. + /// + /// All drivers present a unidirectional interface. + /// If the underlying device is bidirectional that detail is hidden and + /// we present one or more separate read and write drivers. + virtual size_t ready() = 0; + + virtual ~IODevice() = 0; + }; + /// Virtual base class for AudioInput and AudioOutput. - class AudioDevice : public ::FreeDV::Base { + class AudioDevice : public ::FreeDV::IODevice { protected: /// The master volume control for the device. float master_amplitude; @@ -320,7 +343,7 @@ namespace FreeDV { }; /// Push-to-talk input driver. - class PTTInput : public ::FreeDV::Base { + class PTTInput : public ::FreeDV::IODevice { private: /// Coroutine to be called when the sense of the push-to-talk switch /// changes. @@ -347,7 +370,7 @@ namespace FreeDV { }; /// Driver for the text message source function. - class TextInput : public ::FreeDV::Base { + class TextInput : public ::FreeDV::IODevice { protected: /// The child class calls this member in its parent to set the text. void set(const char * text); @@ -372,7 +395,7 @@ namespace FreeDV { /// There must be inputs and callbacks for many things here. /// UserInterfaces may provide their own drivers for microphone, /// loudspeaker, TextInput, both forms of PTT, and EventHandler. - class UserInterface : public ::FreeDV::Base { + class UserInterface : public ::FreeDV::IODevice { protected: /// The external Interfaces object. Interfaces * interfaces; diff --git a/freedv-server/source/io_device.cpp b/freedv-server/source/io_device.cpp new file mode 100644 index 00000000..146312f3 --- /dev/null +++ b/freedv-server/source/io_device.cpp @@ -0,0 +1,14 @@ +/// The I/O Device class. + +#include "drivers.h" + +namespace FreeDV { + IODevice::IODevice(const char * name, const char * parameters) + : Base(name, parameters) + { + } + + IODevice::~IODevice() + { + } +} diff --git a/freedv-server/source/ptt_constant.cpp b/freedv-server/source/ptt_constant.cpp index 474d376b..d15c6181 100644 --- a/freedv-server/source/ptt_constant.cpp +++ b/freedv-server/source/ptt_constant.cpp @@ -10,6 +10,8 @@ namespace FreeDV { PTTConstant(const char * parameters); virtual ~PTTConstant(); + /// Return the amount of bytes ready for read. + size_t ready(); }; PTTConstant::PTTConstant(const char * parameters) @@ -21,6 +23,12 @@ namespace FreeDV { { } + size_t + PTTConstant::ready() + { + return SIZE_MAX; + } + PTTInput * Driver::PTTConstant(const char * parameter) { diff --git a/freedv-server/source/ptt_input.cpp b/freedv-server/source/ptt_input.cpp index 3f79a717..447790ba 100644 --- a/freedv-server/source/ptt_input.cpp +++ b/freedv-server/source/ptt_input.cpp @@ -4,7 +4,7 @@ namespace FreeDV { PTTInput::PTTInput(const char * name, const char * parameters) - : Base(name, parameters) + : IODevice(name, parameters) { } diff --git a/freedv-server/source/test/audio_sink.cpp b/freedv-server/source/test/audio_sink.cpp index 8d1943f9..4f86a1c3 100644 --- a/freedv-server/source/test/audio_sink.cpp +++ b/freedv-server/source/test/audio_sink.cpp @@ -1,6 +1,7 @@ // Tests for the AudioSink class. #include #include +#include using namespace FreeDV; @@ -22,6 +23,10 @@ protected: } }; +TEST_F(AudioSinkTest, AlwaysReady) { + EXPECT_EQ(SIZE_MAX, o->ready()); +} + TEST_F(AudioSinkTest, WriteReturnsSize) { int16_t buffer[8]; diff --git a/freedv-server/source/test/blank_panel.cpp b/freedv-server/source/test/blank_panel.cpp new file mode 100644 index 00000000..751016fb --- /dev/null +++ b/freedv-server/source/test/blank_panel.cpp @@ -0,0 +1,31 @@ +/// Tests for the BlankPanel class. +#include +#include +#include + +using namespace FreeDV; + +class BlankPanelTest : public ::testing::Test { +protected: + UserInterface * u; + Interfaces * i; + + BlankPanelTest() + : u(0) + { + } + + void SetUp() { + i = new Interfaces(); + u = Driver::BlankPanel("", i); + } + + void TearDown() { + delete u; + delete i; + } +}; + +TEST_F(BlankPanelTest, NeverReady) { + EXPECT_EQ(0, u->ready()); +} diff --git a/freedv-server/source/test/tone.cpp b/freedv-server/source/test/tone.cpp index 36998df7..a64cc7f7 100644 --- a/freedv-server/source/test/tone.cpp +++ b/freedv-server/source/test/tone.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace FreeDV; @@ -45,6 +46,10 @@ TEST_F(ToneTest, EnforcesNormalization) { EXPECT_NO_THROW(i->amplitude(1.0)); } +TEST_F(ToneTest, AlwaysReady) { + EXPECT_EQ(SIZE_MAX, i->ready()); +} + // Maximum positive value of a signed 16-bit integer. const int16_t MaxS16((1 << 15) - 1); // Half of the maximum positive value of a signed 16-bit integer. diff --git a/freedv-server/source/text_constant.cpp b/freedv-server/source/text_constant.cpp index adee5063..5923c9c4 100644 --- a/freedv-server/source/text_constant.cpp +++ b/freedv-server/source/text_constant.cpp @@ -10,6 +10,9 @@ namespace FreeDV { TextConstant(const char * parameter); virtual ~TextConstant(); + /// Return the amount of bytes ready for read. In this case, it always + /// returns SIZE_MAX. + size_t ready(); }; TextConstant::TextConstant(const char * parameters) @@ -21,6 +24,12 @@ namespace FreeDV { { } + size_t + TextConstant::ready() + { + return SIZE_MAX; + } + TextInput * Driver::TextConstant(const char * parameter) { diff --git a/freedv-server/source/text_input.cpp b/freedv-server/source/text_input.cpp index 740bebd1..54c979f7 100644 --- a/freedv-server/source/text_input.cpp +++ b/freedv-server/source/text_input.cpp @@ -4,7 +4,7 @@ namespace FreeDV { TextInput::TextInput(const char * name, const char * parameters) - : Base(name, parameters) + : IODevice(name, parameters) { } diff --git a/freedv-server/source/tone.cpp b/freedv-server/source/tone.cpp index dd4a37c1..a8bb3305 100644 --- a/freedv-server/source/tone.cpp +++ b/freedv-server/source/tone.cpp @@ -18,39 +18,22 @@ namespace FreeDV { tone_info tones[101]; - /// Generate a sine wave. - float - sine_wave(float frequency, unsigned int step) - { - // The number of samples per cycle for the given frequency and sample - // rate. - const float samplesPerCycle = SampleRate / frequency; - - // Add 1/4 turn to the step so that at the Nyquist frequency we - // render the peaks rather than the zero crossings. - const float bias = step + (samplesPerCycle / 4); - - // Angular measure where 1.0 = 360 degrees. - const float portionOfCycle = fmod(bias, samplesPerCycle) / samplesPerCycle; - - // Convert to radians. - const float radians = portionOfCycle * M_PI * 2; - - const float sine = sin(radians); - - return sine; - } + /// Return the amount of audio samples for read. In this case, it always + /// returns SIZE_MAX. + size_t ready(); + /// Generate a sine wave. + float sine_wave(float frequency, unsigned int step); public: /// Instantiate the tone driver. - Tone(const char * parameter); + Tone(const char * parameters); + virtual ~Tone(); // Read audio into the "short" type. virtual std::size_t read16(int16_t * array, std::size_t length); }; - Tone::Tone(const char * parameters) : AudioInput("tone", parameters), clock(0) { @@ -135,6 +118,34 @@ namespace FreeDV { clock = (clock + length) % SampleRate; } + size_t + Tone::ready() + { + return SIZE_MAX; + } + + float + Tone::sine_wave(float frequency, unsigned int step) + { + // The number of samples per cycle for the given frequency and sample + // rate. + const float samplesPerCycle = SampleRate / frequency; + + // Add 1/4 turn to the step so that at the Nyquist frequency we + // render the peaks rather than the zero crossings. + const float bias = step + (samplesPerCycle / 4); + + // Angular measure where 1.0 = 360 degrees. + const float portionOfCycle = fmod(bias, samplesPerCycle) / samplesPerCycle; + + // Convert to radians. + const float radians = portionOfCycle * M_PI * 2; + + const float sine = sin(radians); + + return sine; + } + AudioInput * Driver::Tone(const char * parameter) { diff --git a/freedv-server/source/user_interface.cpp b/freedv-server/source/user_interface.cpp index 119d7295..5a74388e 100644 --- a/freedv-server/source/user_interface.cpp +++ b/freedv-server/source/user_interface.cpp @@ -4,7 +4,7 @@ namespace FreeDV { UserInterface::UserInterface(const char * name, const char * parameters, Interfaces * interfaces) - : Base(name, parameters) + : IODevice(name, parameters) { } -- 2.25.1