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)
{
}
- 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 *
/// 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;
/// 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.
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.
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
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
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)
{
}
+ 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)
{
#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[] =
#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);
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