From 9516092cb6d3d1514bddd39e6ac4cd8e554f1301 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Sun, 19 Jan 2014 23:56:16 +0000 Subject: [PATCH] Refactor to base AudioInput and AudioOutput on AudioDevice. Fix text formatting in drivers.h Add more tests. git-svn-id: https://svn.code.sf.net/p/freetel/code@1376 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/CMakeLists.txt | 1 + freedv-server/source/audio_input.cpp | 2 +- freedv-server/source/audio_output.cpp | 2 +- freedv-server/source/drivers.h | 560 +++++++++++++------------- freedv-server/source/test/tone.cpp | 60 ++- freedv-server/source/tone.cpp | 27 +- 6 files changed, 343 insertions(+), 309 deletions(-) diff --git a/freedv-server/CMakeLists.txt b/freedv-server/CMakeLists.txt index c2988381..7a337f18 100644 --- a/freedv-server/CMakeLists.txt +++ b/freedv-server/CMakeLists.txt @@ -87,6 +87,7 @@ message(STATUS "${Param.build-type} ${Version.major}.${Version.minor}.${Version. # Set cmake internal variables from parameters. # set(Compile.sources + source/audio_device.cpp source/audio_input.cpp source/audio_output.cpp source/audio_sink.cpp diff --git a/freedv-server/source/audio_input.cpp b/freedv-server/source/audio_input.cpp index 15cd142a..62ec9812 100644 --- a/freedv-server/source/audio_input.cpp +++ b/freedv-server/source/audio_input.cpp @@ -4,7 +4,7 @@ namespace FreeDV { AudioInput::AudioInput(const char * name, const char * parameters) - : Base(name, parameters) + : AudioDevice(name, parameters) { } diff --git a/freedv-server/source/audio_output.cpp b/freedv-server/source/audio_output.cpp index d7b0f44d..eaeb33fb 100644 --- a/freedv-server/source/audio_output.cpp +++ b/freedv-server/source/audio_output.cpp @@ -4,7 +4,7 @@ namespace FreeDV { AudioOutput::AudioOutput(const char * name, const char * parameters) - : Base(name, parameters) + : AudioDevice(name, parameters) { } diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 71e91b6f..43d1ba62 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -2,7 +2,6 @@ #include #include - /// Namespace used for all code in this program. namespace FreeDV { @@ -82,169 +81,177 @@ namespace FreeDV { return base.print(stream); } - /// Virtual base class for audio input drivers. - class AudioInput : public ::FreeDV::Base { + // Virtual base class for AudioInput and AudioOutput. + class AudioDevice : public ::FreeDV::Base { protected: - /// Create an AudioInput device instance. - /// \param name The name of the child driver. This is expected to be a - /// static string. - /// \param parameters Driver-specific configuration parameters. - AudioInput(const char * name, const char * parameters); + float master_amplitude; + + /// Create an AudioDevice instance. + /// \param name The name of the child driver. This is expected to be a + /// static string. + /// \param parameters Driver-specific configuration parameters. + AudioDevice(const char * name, const char * parameters); public: - /// Destroy an AudioInput device instance. - virtual ~AudioInput() = 0; + /// Destroy an AudioDevice instance. + virtual ~AudioDevice() = 0; + + /// Get the current audio level. + /// \return The current audio level. + /// The value is normalized to the range of 0.0 to 1.0. + virtual float amplitude(); + + /// Set the current audio level. + /// \param value The new value for the current audio level. + /// The value must be normalized within the range of 0.0 to 1.0. + virtual void amplitude(float value); + }; - /// Get the current audio level. - /// \return The current audio level. - /// The value is normalized to the range of 0.0 to 1.0. - virtual float amplitude() = 0; + /// Virtual base class for audio input drivers. + class AudioInput : public ::FreeDV::AudioDevice { + protected: + /// Create an AudioInput device instance. + /// \param name The name of the child driver. This is expected to be a + /// static string. + /// \param parameters Driver-specific configuration parameters. + AudioInput(const char * name, const char * parameters); - /// Set the current audio level. - /// \param value The new value for the current audio level. - /// The value must be normalized within the range of 0.0 to 1.0. - virtual void amplitude(float value) = 0; + public: + /// Destroy an AudioInput device instance. + virtual ~AudioInput() = 0; /// Read audio into an array of the signed 16-bit integer type. - virtual std::size_t - read16(int16_t * array, std::size_t length) = 0; + virtual std::size_t + read16(int16_t * array, std::size_t length) = 0; }; /// Virtual base class for audio output drivers. - class AudioOutput : public ::FreeDV::Base { + class AudioOutput : public ::FreeDV::AudioDevice { protected: - /// Create an AudioOutput device instance. - /// \param name The name of the child driver. This is expected to be a - /// static string. - /// \param parameters Driver-specific configuration parameters. + /// Create an AudioOutput device instance. + /// \param name The name of the child driver. This is expected to be a + /// static string. + /// \param parameters Driver-specific configuration parameters. AudioOutput(const char * name, const char * parameters); public: - /// Destroy an AudioOutput device instance. - virtual ~AudioOutput() = 0; - - /// Get the current audio level. - /// The value is normalized to the range of 0.0 to 1.0. - virtual float amplitude() = 0; - - /// Set the current audio level. - /// The value must be within the range of 0.0 to 1.0. - virtual void amplitude(float value) = 0; + /// Destroy an AudioOutput device instance. + virtual ~AudioOutput() = 0; /// Write audio from an array of the signed 16-bit integer type. - virtual std::size_t - write16(const int16_t * array, std::size_t length) = 0; + virtual std::size_t + write16(const int16_t * array, std::size_t length) = 0; }; /// Virtual base class for codecs. class Codec : public ::FreeDV::Base { protected: - /// Create a codec instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. - Codec(const char * name, const char * parameters); + /// Create a codec instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. + Codec(const char * name, const char * parameters); public: - /// Destroy a codec instance. - virtual ~Codec() = 0; - - /// Encode from an array of the signed 16-bit integer type to an - /// array of the unsigned 8-bit integer type (this is usually - /// implemented as unsigned char). - /// \param i The array of audio samples to be encoded, in an array - /// of signed 16-bit integers. - /// \param o The encoded data, in an array of unsigned 8-bit integers. - /// \param length The number of audio samples to be encoded. - /// \return The number of uint8_t elements in the encoded array. - virtual std::size_t - encode16(const int16_t * i, uint8_t * o, \ - std::size_t length) = 0; - - /// Return the size of uint8_t array necessary to encode the given - /// number of audio samples. Sample rate is 8K samples/second. - /// The result is invariant for a given input. - /// \param sample_count The number of audio samples to encode. - /// Must be a multiple of frame_size(). - /// \return The size of uint8_t array necessary to encode the given - /// number of audio samples. - virtual std::size_t const - encoded_buffer_size(std::size_t sample_count) const = 0; - - /// Return the duration of a frame in milliseconds. - /// \return The duration of a frame in milliseconds. - virtual int const - frame_duration() const = 0; - - /// Return the number of audio samples necessary to decode the given - /// encoded buffer size. Sample rate is 8K samples/second. - /// \param buffer_size is the size of the encoded buffer. It must - /// encode a multiple of frame_size() audio samples. - /// \return The number of audio samples necessary to decode the given - /// encoded buffer size. The result is invariant for a given input. - virtual std::size_t const - samples_per_buffer(std::size_t buffer_size) const = 0; - - /// Return the number of audio samples expected to create a codec - /// frame. Samples provided to encode_buffer_size must be a multiple - /// of this value. Sample rate is 8K samples/second. - /// The result for a particular input is invariant. - /// \return The number of audio samples expected to create a codec - /// frame. - virtual std::size_t const - samples_per_frame() const = 0; + /// Destroy a codec instance. + virtual ~Codec() = 0; + + /// Encode from an array of the signed 16-bit integer type to an + /// array of the unsigned 8-bit integer type (this is usually + /// implemented as unsigned char). + /// \param i The array of audio samples to be encoded, in an array + /// of signed 16-bit integers. + /// \param o The encoded data, in an array of unsigned 8-bit integers. + /// \param length The number of audio samples to be encoded. + /// \return The number of uint8_t elements in the encoded array. + virtual std::size_t + encode16(const int16_t * i, uint8_t * o, \ + std::size_t length) = 0; + + /// Return the size of uint8_t array necessary to encode the given + /// number of audio samples. Sample rate is 8K samples/second. + /// The result is invariant for a given input. + /// \param sample_count The number of audio samples to encode. + /// Must be a multiple of frame_size(). + /// \return The size of uint8_t array necessary to encode the given + /// number of audio samples. + virtual std::size_t const + encoded_buffer_size(std::size_t sample_count) const = 0; + + /// Return the duration of a frame in milliseconds. + /// \return The duration of a frame in milliseconds. + virtual int const + frame_duration() const = 0; + + /// Return the number of audio samples necessary to decode the given + /// encoded buffer size. Sample rate is 8K samples/second. + /// \param buffer_size is the size of the encoded buffer. It must + /// encode a multiple of frame_size() audio samples. + /// \return The number of audio samples necessary to decode the given + /// encoded buffer size. The result is invariant for a given input. + virtual std::size_t const + samples_per_buffer(std::size_t buffer_size) const = 0; + + /// Return the number of audio samples expected to create a codec + /// frame. Samples provided to encode_buffer_size must be a multiple + /// of this value. Sample rate is 8K samples/second. + /// The result for a particular input is invariant. + /// \return The number of audio samples expected to create a codec + /// frame. + virtual std::size_t const + samples_per_frame() const = 0; }; /// Event handler class, indirects the event handler of the particular GUI /// software or POSIX. class EventHandler : public ::FreeDV::Base { private: - bool do_exit; + bool do_exit; protected: - /// Bit field of status values for file descriptor events. - /// This is an argument to the coroutine called by monitor(). - /// This is a simplification on all of the values that POSIX - /// poll() can return. Events that aren't read or write are mapped - /// to one of those. - - /// File being monitored is readable or has read error. - const unsigned int Read = 1; - - /// File being monitored is writable or has write error. - const unsigned int Write = 2; - - /// Create an event handler instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. - EventHandler(const char * name, const char * parameters) - : Base(name, parameters), do_exit(false) - { - } - - /// If set_exit() has been called, return true once. - /// \return True if set_exit has been called. The next and subsequent - /// calls will return false until set_exit() is called again. - inline bool get_exit() { - if ( do_exit ) { - do_exit = false; - return true; - } - else - return false; - } - - /// Run one iteration of the event handler. - /// The default implementation throws std::runtime_error. - /// - /// If iterate() is not implemented in the child class, - /// the child class must implement loop(), and the child class - /// implementation of loop() must not call iterate(). - void iterate(); - - /// Cause get_exit() to return true the next time it is called. - inline void set_exit() { do_exit = true; } + /// Bit field of status values for file descriptor events. + /// This is an argument to the coroutine called by monitor(). + /// This is a simplification on all of the values that POSIX + /// poll() can return. Events that aren't read or write are mapped + /// to one of those. + + /// File being monitored is readable or has read error. + const unsigned int Read = 1; + + /// File being monitored is writable or has write error. + const unsigned int Write = 2; + + /// Create an event handler instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. + EventHandler(const char * name, const char * parameters) + : Base(name, parameters), do_exit(false) + { + } + + /// If set_exit() has been called, return true once. + /// \return True if set_exit has been called. The next and subsequent + /// calls will return false until set_exit() is called again. + inline bool get_exit() { + if ( do_exit ) { + do_exit = false; + return true; + } + else + return false; + } + + /// Run one iteration of the event handler. + /// The default implementation throws std::runtime_error. + /// + /// If iterate() is not implemented in the child class, + /// the child class must implement loop(), and the child class + /// implementation of loop() must not call iterate(). + void iterate(); + + /// Cause get_exit() to return true the next time it is called. + inline void set_exit() { do_exit = true; } public: virtual ~EventHandler() = 0; @@ -283,78 +290,76 @@ namespace FreeDV { /// Radio device keying driver. class Keying : public ::FreeDV::Base { protected: - /// Create an radio keying output device instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. + /// Create an radio keying output device instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. Keying(const char * name, const char * parameters); public: - /// Destroy the radio keying device instance. - virtual ~Keying() = 0; + /// Destroy the radio keying device instance. + virtual ~Keying() = 0; - /// Key or un-key the transmitter. - /// \param value If true, key the transmitter. If false, un-key. - virtual void key(bool value) = 0; + /// Key or un-key the transmitter. + /// \param value If true, key the transmitter. If false, un-key. + virtual void key(bool value) = 0; }; /// Softmodem driver. class Modem : public ::FreeDV::Base { protected: - /// Create a softmodem device instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. + /// Create a softmodem device instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. Modem(const char * name, const char * parameters); public: - virtual ~Modem() = 0; + virtual ~Modem() = 0; }; /// Push-to-talk input driver. class PTTInput : public ::FreeDV::Base { private: - /// Coroutine to be called when the sense of the push-to-talk switch - /// changes. - void (*callback)(bool); + /// Coroutine to be called when the sense of the push-to-talk switch + /// changes. + void (*callback)(bool); protected: - /// The driver calls this member to inform FreeDV that the PTT switch - /// sense has changed. The value is true for key-down, - /// false for key-up. - /// \param value True for key-down, false for key-up. - void changed(bool value); - - /// Create a push-to-talk switch instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. + /// The driver calls this member to inform FreeDV that the PTT switch + /// sense has changed. The value is true for key-down, + /// false for key-up. + /// \param value True for key-down, false for key-up. + void changed(bool value); + + /// Create a push-to-talk switch instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. PTTInput(const char * name, const char * parameters); - - public: - virtual ~PTTInput() = 0; + virtual ~PTTInput() = 0; - /// Set the function that will be called when the push-to-talk input - /// changes its value. - void set_callback(void (*value)(bool)); + /// Set the function that will be called when the push-to-talk input + /// changes its value. + void set_callback(void (*value)(bool)); }; /// Driver for the text message source function. class TextInput : public ::FreeDV::Base { protected: - /// The child class calls this member in its parent to set the text. - void set(const char * text); + /// The child class calls this member in its parent to set the text. + void set(const char * text); - /// Create a text source instance. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. + /// Create a text source instance. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. TextInput(const char * name, const char * parameters); public: - virtual ~TextInput() = 0; + virtual ~TextInput() = 0; }; class Interfaces; @@ -368,33 +373,30 @@ namespace FreeDV { /// loudspeaker, TextInput, both forms of PTT, and EventHandler. class UserInterface : public ::FreeDV::Base { protected: - /// The external Interfaces object. - Interfaces * - interfaces; - - /// Create an instance of the UserInterface object. - /// \param name Name of the driver. This is expected to be a single - /// constant static string per driver class. - /// \param parameters Driver-specific configuration parameters. - /// \param _interfaces An Interface object. The UserInterface object - /// may set various fields of Interface to be its own captive driver - /// objects, and they may change during operation if the user changes - /// device driver parameters. - UserInterface(const char * name, const char * parameters, Interfaces * _interfaces); + /// The external Interfaces object. + Interfaces * interfaces; + + /// Create an instance of the UserInterface object. + /// \param name Name of the driver. This is expected to be a single + /// constant static string per driver class. + /// \param parameters Driver-specific configuration parameters. + /// \param _interfaces An Interface object. The UserInterface object + /// may set various fields of Interface to be its own captive driver + /// objects, and they may change during operation if the user changes + /// device driver parameters. + UserInterface(const char * name, const char * parameters, Interfaces * _interfaces); public: - virtual ~UserInterface() = 0; + virtual ~UserInterface() = 0; }; /// Structure used to pass all of the drivers. Can be modified from - /// UserInterface while within the event loop, if a user changes a device - /// from the GUI. class Interfaces { public: - Interfaces() : codec(0), event_handler(0), + Interfaces() : codec(0), event_handler(0), keying_output(0), loudspeaker(0), microphone(0), modem(0), ptt_input_digital(0), ptt_input_ssb(0), - receiver(0), text_input(0), transmitter(0), + receiver(0), text_input(0), transmitter(0), user_interface(0) { } @@ -434,7 +436,7 @@ namespace FreeDV { /// \return A reference to the provided stream, meant for the /// usual successive call paradigm of ostream operator << . virtual std::ostream & - print(std::ostream & stream) const; + print(std::ostream & stream) const; }; /// Write the driver information from the Interfaces object onto a stream, /// for debugging and dumping the configuration information. @@ -472,92 +474,108 @@ namespace FreeDV { /// drivers. Instantiates device drivers on request. class DriverManager { private: - std::map audio_input_drivers; - std::map audio_output_drivers; - std::map codecs; - std::map keying_output_drivers; - std::map modems; - std::map ptt_input_drivers; - std::map text_input_drivers; - std::map user_interface_drivers; + std::map + audio_input_drivers; + + std::map + audio_output_drivers; + + std::map + codecs; + + std::map + keying_output_drivers; + + std::map + modems; + + std::map + ptt_input_drivers; + + std::map + text_input_drivers; + + std::map + user_interface_drivers; + public: - /// Initialize the driver manager. + /// Initialize the driver manager. DriverManager(); ~DriverManager(); - /// Print the available drivers to the argument stream. - /// \param stream A reference to an instance of ostream on which the - /// information is to be printed. + /// Print the available drivers to the argument stream. + /// \param stream A reference to an instance of ostream on which the + /// information is to be printed. std::ostream & print(std::ostream & stream) const; - /// Instantiate an AudioInput driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - AudioInput * audio_input(const char * driver, const char * parameters); - /// Instantiate an AudioOutput driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - AudioOutput * audio_output(const char * driver, const char * parameters); - /// Instantiate a Codec. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - Codec * codec(const char * driver, const char * parameters); - /// Instantiate a Keying driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - Keying * keying_output(const char * driver, const char * parameters); - /// Instantiate a softmodem. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - Modem * modem(const char * driver, const char * parameters); - /// Instantiate a PTT input driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - PTTInput * ptt_input(const char * driver, const char * parameters); - /// Instantiate a text input driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - TextInput * text_input(const char * driver, const char * parameters); - /// Instantiate a user interface driver. - /// \param driver The name of the driver. - /// \param parameters Driver-specific configuration parameters. - /// \param interfaces Interfaces object used to hold all of the - /// current device driver instances. - UserInterface * user_interface(const char * driver, const char * parameters, Interfaces * interfaces); - - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_audio_input(const char * driver, AudioInput * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_audio_output(const char * driver, AudioOutput * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_codec(const char * driver, Codec * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_keying_output(const char * driver, Keying * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_modem(const char * driver, Modem * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_ptt_input(const char * driver, PTTInput * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_text_input(const char * driver, TextInput * (*creator)(const char *)); - /// Register an audio input driver. - /// \param driver The name of the driver. - /// \param creator The coroutine that will instantiate the driver. - void register_user_interface(const char * driver, UserInterface * (*creator)(const char *, Interfaces *)); + /// Instantiate an AudioInput driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + AudioInput * audio_input(const char * driver, const char * parameters); + /// Instantiate an AudioOutput driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + AudioOutput * audio_output(const char * driver, const char * parameters); + /// Instantiate a Codec. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + Codec * codec(const char * driver, const char * parameters); + /// Instantiate a Keying driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + Keying * keying_output(const char * driver, const char * parameters); + /// Instantiate a softmodem. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + Modem * modem(const char * driver, const char * parameters); + /// Instantiate a PTT input driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + PTTInput * ptt_input(const char * driver, const char * parameters); + /// Instantiate a text input driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + TextInput * text_input(const char * driver, const char * parameters); + /// Instantiate a user interface driver. + /// \param driver The name of the driver. + /// \param parameters Driver-specific configuration parameters. + /// \param interfaces Interfaces object used to hold all of the + /// current device driver instances. + UserInterface * user_interface(const char * driver, const char * parameters, Interfaces * interfaces); + + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_audio_input(const char * driver, AudioInput * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_audio_output(const char * driver, AudioOutput * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_codec(const char * driver, Codec * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_keying_output(const char * driver, Keying * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_modem(const char * driver, Modem * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_ptt_input(const char * driver, PTTInput * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_text_input(const char * driver, TextInput * (*creator)(const char *)); + /// Register an audio input driver. + /// \param driver The name of the driver. + /// \param creator The coroutine that will instantiate the driver. + void register_user_interface(const char * driver, UserInterface * (*creator)(const char *, Interfaces *)); }; /// Write the driver information from the DriverManager object onto a stream, /// for debugging and dumping the configuration information. diff --git a/freedv-server/source/test/tone.cpp b/freedv-server/source/test/tone.cpp index 0089a967..36998df7 100644 --- a/freedv-server/source/test/tone.cpp +++ b/freedv-server/source/test/tone.cpp @@ -50,14 +50,30 @@ const int16_t MaxS16((1 << 15) - 1); // Half of the maximum positive value of a signed 16-bit integer. const int16_t HalfS16(1 << 14); -TEST(ToneTest1, AtNyquistLimit) { - int16_t buffer[4]; +class ToneTest2 : public ::testing::Test { +protected: + AudioInput * i; - std::stringstream stream; + ToneTest2() + : i(0) + { + } + + void SetUp() { + std::stringstream stream; + + stream << SampleRate / 2 << ",1"; + + i = Driver::Tone(stream.str().c_str()); + } - stream << SampleRate / 2 << ",1"; + void TearDown() { + delete i; + } +}; - AudioInput * i = Driver::Tone(stream.str().c_str()); +TEST_F(ToneTest2, AtNyquistLimit) { + int16_t buffer[4]; i->read16(buffer, sizeof(buffer) / sizeof(*buffer)); @@ -65,11 +81,33 @@ TEST(ToneTest1, AtNyquistLimit) { EXPECT_EQ(-MaxS16, buffer[1]); EXPECT_EQ(MaxS16, buffer[2]); EXPECT_EQ(-MaxS16, buffer[3]); +} - delete i; +TEST_F(ToneTest2, MasterAmplitudeIsZero) { + int16_t buffer[4]; + + i->amplitude(0); + i->read16(buffer, sizeof(buffer) / sizeof(*buffer)); + + EXPECT_EQ(0, buffer[0]); + EXPECT_EQ(0, buffer[1]); + EXPECT_EQ(0, buffer[2]); + EXPECT_EQ(0, buffer[3]); +} + +TEST_F(ToneTest2, MasterAmplitudeIsZeroPointFive) { + int16_t buffer[4]; + + i->amplitude(0.5); + i->read16(buffer, sizeof(buffer) / sizeof(*buffer)); + + EXPECT_EQ(HalfS16, buffer[0]); + EXPECT_EQ(-HalfS16, buffer[1]); + EXPECT_EQ(HalfS16, buffer[2]); + EXPECT_EQ(-HalfS16, buffer[3]); } -TEST(ToneTest1, AtHalfNyquistLimit) { +TEST(ToneTest3, AtHalfNyquistLimit) { int16_t buffer[8]; std::stringstream stream; @@ -92,7 +130,7 @@ TEST(ToneTest1, AtHalfNyquistLimit) { delete i; } -TEST(ToneTest1, FrequencyIsZero) { +TEST(ToneTest3, FrequencyIsZero) { int16_t buffer[4]; AudioInput * i = Driver::Tone("0,1"); @@ -107,7 +145,7 @@ TEST(ToneTest1, FrequencyIsZero) { delete i; } -TEST(ToneTest1, AmplitudeIsZero) { +TEST(ToneTest3, ToneAmplitudeIsZero) { int16_t buffer[4]; AudioInput * i = Driver::Tone("1000,0"); @@ -122,7 +160,7 @@ TEST(ToneTest1, AmplitudeIsZero) { delete i; } -TEST(ToneTest1, WavesSumCorrectly) { +TEST(ToneTest3, WavesSumCorrectly) { int16_t buffer[8]; std::stringstream stream; @@ -146,7 +184,7 @@ TEST(ToneTest1, WavesSumCorrectly) { delete i; } -TEST(ToneTest1, SumOfAmplitudesIsNormalizedCorrectly) { +TEST(ToneTest3, SumOfAmplitudesIsNormalizedCorrectly) { int16_t buffer[8]; std::stringstream stream; diff --git a/freedv-server/source/tone.cpp b/freedv-server/source/tone.cpp index 66f4e853..dd4a37c1 100644 --- a/freedv-server/source/tone.cpp +++ b/freedv-server/source/tone.cpp @@ -1,7 +1,6 @@ /// The tone audio input driver, for testing. #include "drivers.h" -#include #include #define _USE_MATH_DEFINES #include @@ -10,7 +9,6 @@ namespace FreeDV { /// This is a test driver that provides tones. class Tone : public AudioInput { private: - float master_amplitude; unsigned int clock; struct tone_info { @@ -48,19 +46,13 @@ namespace FreeDV { Tone(const char * parameter); virtual ~Tone(); - // Get the current audio amplitude, normalized to the range of 0.0 to 1.0. - virtual float amplitude(); - - // Set the current audio amplitude within the range of 0.0 to 1.0. - virtual void amplitude(float value); - // 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), master_amplitude(1.0) + : AudioInput("tone", parameters), clock(0) { unsigned int index = 0; unsigned int input = 0; @@ -119,21 +111,6 @@ namespace FreeDV { { } - float - Tone::amplitude() - { - return master_amplitude; - } - - void - Tone::amplitude(float value) - { - if ( value < 0.0 || value > 1.0 ) - throw std::runtime_error( - "Amplitude set to value outside of the range 0.0..1.0"); - master_amplitude = value; - } - std::size_t Tone::read16(int16_t * array, std::size_t length) { @@ -153,7 +130,7 @@ namespace FreeDV { // sum of amplitudes is 1.0. if ( sumOfAmplitudes > 1.0 ) value /= sumOfAmplitudes; - array[i] = (int16_t)rint((value * ((1 << 15) - 1))); + array[i] = (int16_t)rint(value * master_amplitude * ((1 << 15) - 1)); } clock = (clock + length) % SampleRate; } -- 2.25.1