TinyModem
Header-only software audio modem library
Loading...
Searching...
No Matches
tinymodem::GGWaveDecoder Class Reference

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>

Inheritance diagram for tinymodem::GGWaveDecoder:
Collaboration diagram for tinymodem::GGWaveDecoder:

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

Detailed Description

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).

Constructor & Destructor Documentation

◆ GGWaveDecoder() [1/2]

tinymodem::GGWaveDecoder::GGWaveDecoder ( )
default

◆ GGWaveDecoder() [2/2]

tinymodem::GGWaveDecoder::GGWaveDecoder ( Print & out)
inline

Member Function Documentation

◆ accept()

void tinymodem::GGWaveDecoder::accept ( Candidate & c)
inlineprotected

◆ addSample()

void tinymodem::GGWaveDecoder::addSample ( float x,
bool add_noise )
inlineprotected

◆ audioInfo()

audio_tools::AudioInfo tinymodem::GGWaveDecoder::audioInfo ( )
inlineoverride

◆ begin() [1/2]

bool tinymodem::GGWaveDecoder::begin ( )
inlineoverride

◆ begin() [2/2]

bool tinymodem::GGWaveDecoder::begin ( GGWaveConfig config)
inline

Starts the processing with the indicated configuration.

◆ clearAccumulator()

void tinymodem::GGWaveDecoder::clearAccumulator ( Candidate & c)
inlineprotected

◆ clearCandidates()

void tinymodem::GGWaveDecoder::clearCandidates ( )
inlineprotected

◆ config()

GGWaveConfig & tinymodem::GGWaveDecoder::config ( )
inline

The configuration which was provided in begin().

◆ defaultConfig()

GGWaveConfig tinymodem::GGWaveDecoder::defaultConfig ( )
inline

Provides a default configuration: ggwave-fast.

◆ end()

void tinymodem::GGWaveDecoder::end ( )
inlineoverride

Processes the remaining samples.

◆ endBlock()

void tinymodem::GGWaveDecoder::endBlock ( )
inlineprotected

◆ endSymbol()

void tinymodem::GGWaveDecoder::endSymbol ( Candidate & c)
inlineprotected

◆ failed()

void tinymodem::GGWaveDecoder::failed ( )
inlineprotected

◆ flush()

void tinymodem::GGWaveDecoder::flush ( )
inlineoverridevirtual

Processes the remaining samples (e.g. at the end of the input).

Implements tinymodem::ModemDecoder.

◆ isCarrier()

bool tinymodem::GGWaveDecoder::isCarrier ( )
inlineoverridevirtual

true while a message is received

Implements tinymodem::ModemDecoder.

◆ isFinished()

bool tinymodem::GGWaveDecoder::isFinished ( )
inlineoverridevirtual

true if the decoding was stopped (rx_one)

Implements tinymodem::ModemDecoder.

◆ kill()

void tinymodem::GGWaveDecoder::kill ( Candidate & c)
inlineprotected

◆ markerScore()

float tinymodem::GGWaveDecoder::markerScore ( const float * power,
int n )
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.

◆ messageCount()

size_t tinymodem::GGWaveDecoder::messageCount ( )
inline

Number of received messages.

◆ noise()

float tinymodem::GGWaveDecoder::noise ( )
inlineprotected

uniform random value in the range -0.5 to 0.5

◆ operator bool()

tinymodem::GGWaveDecoder::operator bool ( )
inlineoverride

◆ processBlock()

void tinymodem::GGWaveDecoder::processBlock ( Candidate & c,
uint32_t t )
inlineprotected

◆ processCandidates()

void tinymodem::GGWaveDecoder::processCandidates ( uint32_t t)
inlineprotected

Provides the blocks up to t to all candidates.

◆ resetState()

void tinymodem::GGWaveDecoder::resetState ( )
inlineprotected

◆ ringIm()

float * tinymodem::GGWaveDecoder::ringIm ( uint32_t block)
inlineprotected

◆ ringPower()

float * tinymodem::GGWaveDecoder::ringPower ( uint32_t block)
inlineprotected

◆ ringRe()

float * tinymodem::GGWaveDecoder::ringRe ( uint32_t block)
inlineprotected

◆ setAudioInfo()

void tinymodem::GGWaveDecoder::setAudioInfo ( audio_tools::AudioInfo info)
inlineoverride

Defines the format of the input audio data.

◆ startCandidates()

void tinymodem::GGWaveDecoder::startCandidates ( uint32_t data_start)
inlineprotected

◆ trackStartMarker()

void tinymodem::GGWaveDecoder::trackStartMarker ( bool detected)
inlineprotected

◆ write()

size_t tinymodem::GGWaveDecoder::write ( const uint8_t * data,
size_t len )
inlineoverride

Provide PCM data to the decoder.

Member Data Documentation

◆ block_im

audio_tools::Vector<float> tinymodem::GGWaveDecoder::block_im
protected

◆ block_no

uint32_t tinymodem::GGWaveDecoder::block_no = 0
protected

◆ block_re

audio_tools::Vector<float> tinymodem::GGWaveDecoder::block_re
protected

◆ block_size

int tinymodem::GGWaveDecoder::block_size = 256
protected

◆ BLOCKS

int tinymodem::GGWaveDecoder::BLOCKS = 4
staticconstexprprotected

blocks per frame

◆ candidates

audio_tools::Vector<Candidate> tinymodem::GGWaveDecoder::candidates
protected

◆ cfg

GGWaveConfig tinymodem::GGWaveDecoder::cfg
protected

◆ data_bins

int tinymodem::GGWaveDecoder::data_bins = 96
protected

◆ detect_score

float tinymodem::GGWaveDecoder::detect_score = 8
protected

◆ frame_size

int tinymodem::GGWaveDecoder::frame_size = 1024
protected

◆ freq_start

int tinymodem::GGWaveDecoder::freq_start = 40
protected

◆ input

PcmInput tinymodem::GGWaveDecoder::input
protected

◆ is_active

bool tinymodem::GGWaveDecoder::is_active = false
protected

◆ is_finished

bool tinymodem::GGWaveDecoder::is_finished = false
protected

◆ MARKER_WINDOWS

int tinymodem::GGWaveDecoder::MARKER_WINDOWS
staticconstexprprotected
Initial value:
=
static constexpr int BLOCKS
blocks per frame
Definition GGWaveDecoder.h:163
static constexpr int WINDOW
number of blocks of the marker detection window (one frame)
Definition GGWaveDecoder.h:161
static constexpr int MARKER_FRAMES
number of frames of the start and end marker
Definition GGWave.h:87

number of windows which are completely inside a marker

◆ MAX_ENCODED

int tinymodem::GGWaveDecoder::MAX_ENCODED
staticconstexprprotected
Initial value:
static constexpr int LENGTH_BYTES
bytes of the Reed-Solomon coded length at the start of a message
Definition GGWave.h:91
static constexpr int MAX_PAYLOAD
max payload of a message (variable length format)
Definition GGWave.h:85

◆ MAX_MISSES

int tinymodem::GGWaveDecoder::MAX_MISSES = 8
staticconstexprprotected

the marker is lost after this number of blocks without detection

◆ messages

size_t tinymodem::GGWaveDecoder::messages = 0
protected

◆ MIN_DETECTIONS

int tinymodem::GGWaveDecoder::MIN_DETECTIONS = 24
staticconstexprprotected

a marker must be detected in this number of blocks (of 64)

◆ nalive

int tinymodem::GGWaveDecoder::nalive = 0
protected

◆ nbins

int tinymodem::GGWaveDecoder::nbins = 96
protected

◆ NOFFSETS

int tinymodem::GGWaveDecoder::NOFFSETS = 3
staticconstexprprotected

timing offsets of the candidates: -1, 0, +1 block

◆ noise_seed

uint32_t tinymodem::GGWaveDecoder::noise_seed = 1
protected

◆ nprotocols

int tinymodem::GGWaveDecoder::nprotocols = 0
protected

◆ RING

int tinymodem::GGWaveDecoder::RING = 24
staticconstexprprotected

number of blocks of the history of the window power

◆ ring_im

audio_tools::Vector<float> tinymodem::GGWaveDecoder::ring_im
protected

◆ ring_power

audio_tools::Vector<float> tinymodem::GGWaveDecoder::ring_power
protected

◆ ring_re

audio_tools::Vector<float> tinymodem::GGWaveDecoder::ring_re
protected

◆ run_active

bool tinymodem::GGWaveDecoder::run_active = false
protected

◆ run_detections

int tinymodem::GGWaveDecoder::run_detections = 0
protected

◆ run_first

uint32_t tinymodem::GGWaveDecoder::run_first = 0
protected

◆ run_misses

int tinymodem::GGWaveDecoder::run_misses = 0
protected

◆ rx_protocols

GGWaveProtocol tinymodem::GGWaveDecoder::rx_protocols[3]
protected

◆ sample_pos

int tinymodem::GGWaveDecoder::sample_pos = 0
protected

◆ SCORE_RING

int tinymodem::GGWaveDecoder::SCORE_RING = 128
staticconstexprprotected

number of blocks of the history of the marker score

◆ scores

float tinymodem::GGWaveDecoder::scores[SCORE_RING]
protected

◆ table

OFDMTable tinymodem::GGWaveDecoder::table
protected

◆ table_idx

audio_tools::Vector<int> tinymodem::GGWaveDecoder::table_idx
protected

◆ WINDOW

int tinymodem::GGWaveDecoder::WINDOW = 4
staticconstexprprotected

number of blocks of the marker detection window (one frame)


The documentation for this class was generated from the following file: