flatudp: vector rows as channels or as a waveform, a re-openable source, probes for both

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-02 01:18:43 +01:00
1 parent a523bc2bd9
commit e3bc1f72f3
10 files changed
+446 -100

No files matched your search

+17 -1
View File
@@ -15,12 +15,16 @@ enum class Type : std::uint8_t { U8 = 0, I8, U16, I16, U32, I32, U64, I64, F32,
constexpr std::uint32_t kMaxCount = 4096;
constexpr std::size_t kMaxDatagram = 65507; ///< the largest UDP payload over IPv4
constexpr int kMaxChannels = 256; ///< the most channels one list may make
/// One signal of the sender's datagram: `count` consecutive values of `type`.
struct Row {
std::string name;
Type type = Type::F32;
std::uint32_t count = 1;
/// A vector row (count > 1) only: true is ONE channel of `count` consecutive samples per
/// datagram (a waveform); false is `count` channels `name[0]`.. of one sample each.
bool wave = false;
bool operator==(const Row&) const = default;
};
@@ -33,7 +37,13 @@ std::size_t datagram_size(const std::vector<Row>& rows);
/// True when no row is a vector. Such a list can be batched, several datagrams to a frame.
bool all_scalar(const std::vector<Row>& rows);
/// `name:type[,name:type[count]...]`; a count of 1 is written without brackets.
/// True when some row is a waveform (`wave`).
bool any_wave(const std::vector<Row>& rows);
/// The channels the list makes: a scalar 1, a non-wave vector `count`, a waveform 1.
int channel_count(const std::vector<Row>& rows);
/// `name:type[,name:type[count][w]...]`; a count of 1 is written without brackets, and the `w`
/// of a waveform row follows its count.
std::string format(const std::vector<Row>& rows);
/// The inverse of `format`. Whitespace around names, types and counts is ignored. An empty text
/// is an empty list (and not an error: `problem` reports it). Returns an error in words, empty
@@ -43,6 +53,12 @@ std::string parse(const std::string& text, std::vector<Row>& rows);
/// The first reason this list cannot describe a datagram, in words for the user; empty when valid.
std::string problem(const std::vector<Row>& rows);
/// Decodes one datagram of `datagram_size(rows)` bytes to one column per *channel* (see
/// `channel_count`): a non-wave vector row feeds `count` columns of one value each, a waveform row
/// one column of `count` values. Appends; the caller clears the columns between uses.
void decode_channels(const std::vector<Row>& rows, const std::uint8_t* data, bool big_endian,
std::vector<std::vector<double>>& cols);
/// Decodes one datagram of `datagram_size(rows)` bytes to doubles, row by row, byte-swapping when
/// `big_endian` differs from the host. Appends to `cols[s]`; the caller clears them between uses.
void decode_datagram(const std::vector<Row>& rows, const std::uint8_t* data, bool big_endian,