Refine the codec and modem API.
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 22 Jan 2014 02:16:58 +0000 (02:16 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 22 Jan 2014 02:16:58 +0000 (02:16 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1386 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/codec_noop.cpp
freedv-server/source/drivers.h
freedv-server/source/modem_noop.cpp
freedv-server/source/platform/linux/scheduler.cpp
freedv-server/source/run.cpp

index 99c8a5526ded629d347171eb101ee4f027b29963..30a05d65690fe2e416b2ac49dcd35fc8d2fe0754 100644 (file)
@@ -7,56 +7,51 @@ namespace FreeDV {
   class CodecNoOp : public Codec {
   public:
 
-       /// Instantiate the no-op codec.
-               CodecNoOp(const char *);
-               ~CodecNoOp();
-
-       /// 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.
-       ///  This  must be a multiple of frame_size().
-       /// \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);
-
-       /// 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;
-
-       /// Return the duration of a frame in milliseconds.
-       /// \return The duration of a frame in milliseconds.
-       virtual int const
-                       frame_duration() const;
-
-       /// 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;
-
-       /// 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;
-
+    /// Instantiate the no-op codec.
+                       CodecNoOp(const char *);
+                       ~CodecNoOp();
+
+    /// Return the number of data bytes that store a single codec frame.
+    /// Data Bytes provided to decode16 and encode16 must be a multiple
+    /// of this value. The result is invariant.
+    /// \return The number of data bytes necessary to store a codec frame.
+    virtual std::size_t const
+                       bytes_per_frame() const;
+
+    /// Decode from data bytes to audio samples.
+    /// \param i The encoded data, in an array of unsigned 8-bit integers.
+    /// \param o The array of audio samples after decoding, in an array
+    /// of signed 16-bit integers.
+    /// \param length The number of bytes of data to be decoded.
+    /// \return The number of int16_t elements in the decoded array.
+    virtual std::size_t
+                       decode16(const uint8_t * i, int16_t * o, \
+                        std::size_t length);
+
+
+    /// Encode from audio samples to data bytes.
+    /// \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);
+
+    /// Return the duration of a frame in milliseconds.
+    /// \return The duration of a frame in milliseconds.
+    virtual int const
+                       frame_duration() const;
+
+    /// Return the number of audio samples expected to create a codec
+    /// frame at SampleRate. Samples provided to encode16 and decode16
+    /// must be a multiple of this value. The result is invariant for
+    /// a given SampleRate.
+    /// \return The number of audio samples expected to create a codec
+    /// frame.
+    virtual std::size_t const
+                       samples_per_frame() const;
   };
 
   CodecNoOp::CodecNoOp(const char * parameters)
@@ -68,35 +63,34 @@ namespace FreeDV {
   {
   }
 
-  std::size_t
-  CodecNoOp::encode16(const int16_t * i, uint8_t * o, std::size_t length)
+  std::size_t const
+  CodecNoOp::bytes_per_frame() const
   {
-    return 0;
+    return sizeof(int16_t);
   }
 
-  std::size_t const    
-  CodecNoOp::encoded_buffer_size(std::size_t sample_count) const
+  std::size_t
+  CodecNoOp::decode16(const uint8_t * i, int16_t * o, std::size_t length)
   {
-    return 0;
+    return length;
   }
 
-  int const
-  CodecNoOp::frame_duration() const
+  std::size_t
+  CodecNoOp::encode16(const int16_t * i, uint8_t * o, std::size_t length)
   {
-    return 0;
+    return length;
   }
 
-  std::size_t const    
-  CodecNoOp::samples_per_buffer(std::size_t buffer_size) const
+  int const
+  CodecNoOp::frame_duration() const
   {
     return 0;
   }
 
   std::size_t const
   CodecNoOp::samples_per_frame() const
   {
-    return 0;
+    return 1;
   }
 
   Codec *
index 407258767b0a346827db191ed679719a27128af6..35d6495d588e4cdfc2c517b143cbcd9845d68d33 100644 (file)
@@ -59,7 +59,7 @@ namespace FreeDV {
 
        /// Return true if the object is owned by a UserInterface object and
        /// should not be destroyed separately.
-       /// The return value is invariant for a particular object (or possibly
+       /// The result is invariant for a particular object (or possibly
        /// class).
        virtual bool const
                        captive() const;
@@ -187,8 +187,14 @@ namespace FreeDV {
     /// Destroy a codec instance.
     virtual            ~Codec() = 0;
 
-    /// Decode from an array of the unsigned 8-bit integer type to an
-    /// array of the signed 16-bit integer type.
+    /// Return the number of data bytes that store a single codec frame.
+    /// Data Bytes provided to decode16 and encode16 must be a multiple
+    /// of this value. The result is invariant.
+    /// \return The number of data bytes necessary to store a codec frame.
+    virtual std::size_t const
+                       bytes_per_frame() const = 0;
+
+    /// Decode from data bytes to audio samples.
     /// \param i The encoded data, in an array of unsigned 8-bit integers.
     /// \param o The array of audio samples after decoding, in an array
     /// of signed 16-bit integers.
@@ -198,8 +204,8 @@ namespace FreeDV {
                        decode16(const uint8_t * i, int16_t * o, \
                         std::size_t length) = 0;
 
-    /// Encode from an array of the signed 16-bit integer type to an
-    /// array of the unsigned 8-bit integer type.
+
+    /// Encode from audio samples to data bytes.
     /// \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.
@@ -209,34 +215,15 @@ namespace FreeDV {
                        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 at SampleRate.
-    /// 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 at SampleRate.
-    /// \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 at SampleRate. Samples provided to encode_buffer_size
-    /// must be a multiple of this value.
-    /// The result for a particular input is invariant.
+    /// frame at SampleRate. Samples provided to encode16 and decode16
+    /// must be a multiple of this value. The result is invariant for
+    /// a given SampleRate.
     /// \return The number of audio samples expected to create a codec
     /// frame.
     virtual std::size_t const
@@ -361,56 +348,42 @@ namespace FreeDV {
   public:
     virtual            ~Modem() = 0;
 
-    /// Decode from an array of the signed 16-bit integer type to an
-    /// array of the unsigned 8-bit integer type.
-    /// \param i The array of audio samples to be decoded, in an array
+    /// Return the number of data bytes output in a single modem frame.
+    /// The data buffer provided to demodulate16 must be a multiple of
+    /// this value. The result is invariant.
+    /// \return The number of data bytes necessary to store a modem frame.
+    virtual std::size_t const
+                       bytes_per_frame() const = 0;
+
+    /// Demodulate from audio samples to data.
+    /// \param i The array of audio samples to be demodulated, in an array
     /// of signed 16-bit integers.
-    /// \param o The decoded data, in an array of unsigned 8-bit integers.
-    /// \param length The number of audio samples to be decoded.
-    /// \return The number of uint8_t elements in the decoded array.
+    /// \param o The demodulated data, in an array of unsigned 8-bit integers.
+    /// \param length The number of audio samples to be demodulated.
+    /// \return The number of uint8_t elements in the demodulated array.
     virtual std::size_t
-                       decode16(const int16_t * i, uint8_t * o, \
+                       demodulate16(const int16_t * i, uint8_t * o, \
                         std::size_t length) = 0;
 
-    /// Encode from an array of the unsigned 8-bit integer type to an
-    /// array of the signed 16-bit integer type.
+    /// Modulate from data to audio samples.
     /// \param i The data, in an array of unsigned 8-bit integers.
-    /// \param o The array of audio samples after encoding, in an array
+    /// \param o The array of audio samples after modulation, in an array
     /// of signed 16-bit integers.
-    /// \param length The number of bytes of data to be encoded.
-    /// \return The number of int16_t elements in the encoded array.
+    /// \param length The number of bytes of data to be modulated.
+    /// \return The number of int16_t elements in the modulated array.
     virtual std::size_t
-                       encode16(const uint8_t * i, int16_t * o, \
+                       modulate16(const uint8_t * i, int16_t * o, \
                         std::size_t length) = 0;
 
-    /// Return the size of uint8_t array necessary to encode the given
-    /// number of audio samples at SampleRate.
-    /// 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 at SampleRate.
-    /// \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 at SampleRate. Samples provided to encode_buffer_size
-    /// must be a multiple of this value.
-    /// The result for a particular input is invariant.
+    /// frame at SampleRate. Samples provided to modulate16 and
+    /// demodulate16 must be a multiple of this value. The result is
+    /// invariant for a given SampleRate.
     /// \return The number of audio samples expected to create a codec
     /// frame.
     virtual std::size_t const
index 7f019657d65ca260ef5ef326c58e8e333c8031d2..c90b9a55b121707ea2c7f944a00abf71326be3fd 100644 (file)
@@ -9,8 +9,50 @@ namespace FreeDV {
   public:
 
        /// Instantiate the no-op modem.
-               ModemNoOp(const char *);
-       virtual ~ModemNoOp();
+                       ModemNoOp(const char *);
+
+       virtual         ~ModemNoOp();
+
+    /// Return the number of data bytes output in a single modem frame.
+    /// The data buffer provided to demodulate16 must be a multiple of
+    /// this value. The result is invariant.
+    /// \return The number of data bytes necessary to store a modem frame.
+    virtual std::size_t const
+                       bytes_per_frame() const;
+
+    /// Demodulate from audio samples to data.
+    /// \param i The array of audio samples to be demodulated, in an array
+    /// of signed 16-bit integers.
+    /// \param o The demodulated data, in an array of unsigned 8-bit integers.
+    /// \param length The number of audio samples to be demodulated.
+    /// \return The number of uint8_t elements in the demodulated array.
+    virtual std::size_t
+                       demodulate16(const int16_t * i, uint8_t * o, \
+                        std::size_t length);
+
+    /// Modulate from data to audio samples.
+    /// \param i The data, in an array of unsigned 8-bit integers.
+    /// \param o The array of audio samples after modulation, in an array
+    /// of signed 16-bit integers.
+    /// \param length The number of bytes of data to be modulated.
+    /// \return The number of int16_t elements in the modulated array.
+    virtual std::size_t
+                       modulate16(const uint8_t * i, int16_t * o, \
+                        std::size_t length);
+
+    /// Return the duration of a frame in milliseconds.
+    /// \return The duration of a frame in milliseconds.
+    virtual int const
+                       frame_duration() const;
+
+    /// Return the number of audio samples expected to create a codec
+    /// frame at SampleRate. Samples provided to modulate16 and
+    /// demodulate16 must be a multiple of this value. The result is
+    /// invariant for a given SampleRate.
+    /// \return The number of audio samples expected to create a codec
+    /// frame.
+    virtual std::size_t const
+                       samples_per_frame() const;
   };
 
   ModemNoOp::ModemNoOp(const char * parameters)
@@ -22,6 +64,36 @@ namespace FreeDV {
   {
   }
 
+  std::size_t const
+  ModemNoOp::bytes_per_frame() const
+  {
+    return sizeof(int16_t);
+  }
+
+  std::size_t
+  ModemNoOp::demodulate16(const int16_t * i, uint8_t * o, std::size_t length)
+  {
+    return length;
+  }
+
+  std::size_t
+  ModemNoOp::modulate16(const uint8_t * i, int16_t * o, std::size_t length)
+  {
+    return length;
+  }
+
+  int const
+  ModemNoOp::frame_duration() const
+  {
+    return 1;
+  }
+
+  std::size_t const
+  ModemNoOp::samples_per_frame() const
+  {
+    return 1;
+  }
+
   Modem *
   Driver::ModemNoOp(const char * parameter)
   {
index 023c7b291b746bbf54af1cc8d7074ee0f3b5ae43..cc1bc13aa09027ad579c06d4272b84226c01af71 100644 (file)
@@ -8,14 +8,14 @@
 #include "drivers.h"
 
 static const char insufficient_privilege_message[] =
-"Warning: Insufficient privilege to set real-time priority.\n"
-"This could cause audio to be interrupted as other programs run.\n" 
+"Warning: Insufficient privilege to set a real-time scheduling priority.\n"
+"This could cause audio to be interrupted while other programs use the CPU.\n" 
 "To fix: As root, run\n"
 "\n"
 "\tsetcap cap_sys_nice+ep filename\n"
 "\n"
 "where filename is the executable file for this program. That will\n"
-"allow you to use real-time priority while running as any user.\n"
+"allow you to use a real-time scheduling priority while running as any user.\n"
 "Alternatively, you can execute this program as root.\n\n";
 
 static const char old_kernel_message[] =
index 48de7bfb276510a6e6aba58438efab99e161eda3..10dbfa8d3f0f6c51ed9bb2dc0f148e4a6e0011b5 100644 (file)
@@ -4,15 +4,24 @@
 #include <unistd.h>
 #include <iostream>
 
-/// FIX: Make the delay at start of transmit and end of transmit adjustable.
+/// FIX:
+///
+/// Start of Transmit:
+/// Make the delay at start of transmit and end of transmit adjustable.
 /// The radio in general takes some time to begin transmitting, and thus we
 /// should not send audio until that's done.
 ///
+/// End of Transmit:
 /// There is a lot to fill in for end-of-transmit.
 /// On PTT-up, we should be sending the remaining audio in the microphone
 /// device queue first, waiting for completion of its transmission, and then
 /// un-keying the transmitter.
 ///
+/// Codec to Modem connection:
+/// We need a circular buffer between the codec and the modem. It's perfectly
+/// possible for the modem to demodulate nothing, given an array of audio
+/// samples. We can't invoke the codec until we have an entire frame for it
+/// to work upon.
 
 namespace FreeDV {
   static void key_down(Interfaces * i);
@@ -100,8 +109,7 @@ namespace FreeDV {
   receive(Interfaces * i)
   {
     const size_t       samples_to_decode = i->receiver->ready()
-                        % i->codec_frame_size();
-    const size_t       
+                        % i->modem->samples_per_frame();
   }
   
   static void