From: bruceperens Date: Wed, 22 Jan 2014 02:16:58 +0000 (+0000) Subject: Refine the codec and modem API. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=13901bd9610c68964d99bd33e07f62de1f3a3028;p=freetel-svn-tracking.git Refine the codec and modem API. git-svn-id: https://svn.code.sf.net/p/freetel/code@1386 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-server/source/codec_noop.cpp b/freedv-server/source/codec_noop.cpp index 99c8a552..30a05d65 100644 --- a/freedv-server/source/codec_noop.cpp +++ b/freedv-server/source/codec_noop.cpp @@ -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 * diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 40725876..35d6495d 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -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 diff --git a/freedv-server/source/modem_noop.cpp b/freedv-server/source/modem_noop.cpp index 7f019657..c90b9a55 100644 --- a/freedv-server/source/modem_noop.cpp +++ b/freedv-server/source/modem_noop.cpp @@ -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) { diff --git a/freedv-server/source/platform/linux/scheduler.cpp b/freedv-server/source/platform/linux/scheduler.cpp index 023c7b29..cc1bc13a 100644 --- a/freedv-server/source/platform/linux/scheduler.cpp +++ b/freedv-server/source/platform/linux/scheduler.cpp @@ -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[] = diff --git a/freedv-server/source/run.cpp b/freedv-server/source/run.cpp index 48de7bfb..10dbfa8d 100644 --- a/freedv-server/source/run.cpp +++ b/freedv-server/source/run.cpp @@ -4,15 +4,24 @@ #include #include -/// 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