|
TinyModem
Header-only software audio modem library
|
ggwave compatible demodulator: the PCM audio data is written to the decoder and the payload of the received messages is written to the output. The input can be 8, 16 or 32 bit signed samples with any number of channels (only GGWaveConfig::channel is evaluated). More...
#include <GGWaveDecoder.h>


Classes | |
| struct | Candidate |
| decoder for one protocol and timing offset More... | |
Public Member Functions | |
| GGWaveDecoder ()=default | |
| GGWaveDecoder (Print &out) | |
| GGWaveConfig | defaultConfig () |
| Provides a default configuration: ggwave-fast. | |
| void | setAudioInfo (audio_tools::AudioInfo info) override |
| Defines the format of the input audio data. | |
| audio_tools::AudioInfo | audioInfo () override |
| bool | begin (GGWaveConfig config) |
| Starts the processing with the indicated configuration. | |
| bool | begin () override |
| void | end () override |
| Processes the remaining samples. | |
| void | flush () override |
| Processes the remaining samples (e.g. at the end of the input). | |
| size_t | write (const uint8_t *data, size_t len) override |
| Provide PCM data to the decoder. | |
| bool | isCarrier () override |
| true while a message is received | |
| bool | isFinished () override |
| true if the decoding was stopped (rx_one) | |
| size_t | messageCount () |
| Number of received messages. | |
| GGWaveConfig & | config () |
| The configuration which was provided in begin(). | |
| operator bool () override | |
| Public Member Functions inherited from tinymodem::ModemDecoder | |
| void | setStatusOutput (Print &out) |
| Defines the output for the ### CARRIER / ### NOCARRIER messages. | |
| void | setQuiet (bool quiet) |
| Suppresses the status messages. | |
| const char * | mime () override |
Protected Member Functions | |
| void | resetState () |
| void | clearCandidates () |
| float | noise () |
| uniform random value in the range -0.5 to 0.5 | |
| void | addSample (float x, bool add_noise) |
| float * | ringRe (uint32_t block) |
| float * | ringIm (uint32_t block) |
| float * | ringPower (uint32_t block) |
| void | endBlock () |
| float | markerScore (const float *power, int n) |
| void | trackStartMarker (bool detected) |
| void | startCandidates (uint32_t data_start) |
| void | clearAccumulator (Candidate &c) |
| void | processCandidates (uint32_t t) |
| Provides the blocks up to t to all candidates. | |
| void | processBlock (Candidate &c, uint32_t t) |
| void | endSymbol (Candidate &c) |
| void | kill (Candidate &c) |
| void | failed () |
| void | accept (Candidate &c) |
| Protected Member Functions inherited from tinymodem::ModemDecoder | |
| void | status (const char *fmt,...) |
Protected Attributes | |
| GGWaveConfig | cfg |
| bool | is_active = false |
| bool | is_finished = false |
| PcmInput | input |
| OFDMTable | table |
| uint32_t | noise_seed = 1 |
| size_t | messages = 0 |
| int | frame_size = 1024 |
| int | block_size = 256 |
| int | freq_start = 40 |
| int | data_bins = 96 |
| int | nbins = 96 |
| GGWaveProtocol | rx_protocols [3] |
| int | nprotocols = 0 |
| audio_tools::Vector< int > | table_idx |
| audio_tools::Vector< float > | block_re |
| audio_tools::Vector< float > | block_im |
| int | sample_pos = 0 |
| audio_tools::Vector< float > | ring_re |
| audio_tools::Vector< float > | ring_im |
| audio_tools::Vector< float > | ring_power |
| float | scores [SCORE_RING] |
| float | detect_score = 8 |
| uint32_t | block_no = 0 |
| bool | run_active = false |
| uint32_t | run_first = 0 |
| int | run_detections = 0 |
| int | run_misses = 0 |
| audio_tools::Vector< Candidate > | candidates |
| int | nalive = 0 |
| Protected Attributes inherited from tinymodem::ModemDecoder | |
| Print * | p_status = nullptr |
| bool | is_quiet = false |
Static Protected Attributes | |
| static constexpr int | RING = 24 |
| number of blocks of the history of the window power | |
| static constexpr int | SCORE_RING = 128 |
| number of blocks of the history of the marker score | |
| static constexpr int | WINDOW = 4 |
| number of blocks of the marker detection window (one frame) | |
| static constexpr int | BLOCKS = 4 |
| blocks per frame | |
| static constexpr int | NOFFSETS = 3 |
| timing offsets of the candidates: -1, 0, +1 block | |
| static constexpr int | MAX_MISSES = 8 |
| the marker is lost after this number of blocks without detection | |
| static constexpr int | MIN_DETECTIONS = 24 |
| a marker must be detected in this number of blocks (of 64) | |
| static constexpr int | MARKER_WINDOWS |
| number of windows which are completely inside a marker | |
| static constexpr int | MAX_ENCODED |
ggwave compatible demodulator: the PCM audio data is written to the decoder and the payload of the received messages is written to the output. The input can be 8, 16 or 32 bit signed samples with any number of channels (only GGWaveConfig::channel is evaluated).
All ggwave tones are multiples of the frame rate, so they are periodic in a frame. The decoder calculates a DFT of the used bins for each quarter frame (block) and adds the blocks coherently. For each window of one frame a marker score is calculated: the sum of (on - off) / (on + off) of the 16 tone pairs of the marker, which is +16 for the start marker, -16 for the end marker and about 0 for noise and data. When the start marker was detected, the position with the highest sum of the scores over the length of the marker provides the start of the data. Then each symbol is decoded by adding the power of the windows inside the symbol (without the first and last block). The power is not added coherently over the whole symbol (like ggwave), so a different clock of the sender is tolerated. This is done in parallel for the normal, fast and fastest variant (rx_any_speed) and for the timing offsets -1, 0 and +1 block. The first candidate with a valid Reed-Solomon code and the end marker at the expected position wins.
Unlike ggwave, which records the audio of a whole message, the memory needed is small: about 27 KB for the audible protocols at 48000 Hz (23 KB at 24000 Hz).
|
default |
|
inline |
|
inlineprotected |
|
inlineprotected |
|
inlineoverride |
|
inlineoverride |
|
inline |
Starts the processing with the indicated configuration.
|
inlineprotected |
|
inlineprotected |
|
inline |
The configuration which was provided in begin().
|
inline |
Provides a default configuration: ggwave-fast.
|
inlineoverride |
Processes the remaining samples.
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
|
inlineoverridevirtual |
Processes the remaining samples (e.g. at the end of the input).
Implements tinymodem::ModemDecoder.
|
inlineoverridevirtual |
true while a message is received
Implements tinymodem::ModemDecoder.
|
inlineoverridevirtual |
true if the decoding was stopped (rx_one)
Implements tinymodem::ModemDecoder.
|
inlineprotected |
|
inlineprotected |
Score of the start marker (-score for the end marker): the start marker tone i uses bin 2i + i % 2, the end marker tone bin 2i + 1 - i % 2. Pairs which are 40 dB below the strongest bin are ignored: e.g. rounding errors next to the loud data tones.
|
inline |
Number of received messages.
|
inlineprotected |
uniform random value in the range -0.5 to 0.5
|
inlineoverride |
|
inlineprotected |
|
inlineprotected |
Provides the blocks up to t to all candidates.
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
|
inlineoverride |
Defines the format of the input audio data.
|
inlineprotected |
|
inlineprotected |
|
inlineoverride |
Provide PCM data to the decoder.
|
protected |
|
protected |
|
protected |
|
protected |
|
staticconstexprprotected |
blocks per frame
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
staticconstexprprotected |
number of windows which are completely inside a marker
|
staticconstexprprotected |
|
staticconstexprprotected |
the marker is lost after this number of blocks without detection
|
protected |
|
staticconstexprprotected |
a marker must be detected in this number of blocks (of 64)
|
protected |
|
protected |
|
staticconstexprprotected |
timing offsets of the candidates: -1, 0, +1 block
|
protected |
|
protected |
|
staticconstexprprotected |
number of blocks of the history of the window power
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
staticconstexprprotected |
number of blocks of the history of the marker score
|
protected |
|
protected |
|
protected |
|
staticconstexprprotected |
number of blocks of the marker detection window (one frame)