From 015427d9e74f34dc7d0f7fbad4ad1eaad6537cce Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Wed, 18 Sep 2019 11:49:11 +0200 Subject: EDI in: add audio levels metadata and source version --- lib/edi/STIDecoder.cpp | 35 +++++++++++++++++++++++++++++++++++ lib/edi/STIDecoder.hpp | 13 ++++++++++++- lib/edi/STIWriter.cpp | 13 +++++++++++++ lib/edi/STIWriter.hpp | 7 +++++++ lib/edi/common.cpp | 13 +++++++++++++ lib/edi/common.hpp | 8 ++++++++ 6 files changed, 88 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/edi/STIDecoder.cpp b/lib/edi/STIDecoder.cpp index aab93e0..1f5d45e 100644 --- a/lib/edi/STIDecoder.cpp +++ b/lib/edi/STIDecoder.cpp @@ -44,6 +44,10 @@ STIDecoder::STIDecoder(STIDataCollector& data_collector, bool verbose) : std::bind(&STIDecoder::decode_ssn, this, _1, _2)); m_dispatcher.register_tag("*dmy", std::bind(&STIDecoder::decode_stardmy, this, _1, _2)); + m_dispatcher.register_tag("ODRa", + std::bind(&STIDecoder::decode_odraudiolevel, this, _1, _2)); + m_dispatcher.register_tag("ODRv", + std::bind(&STIDecoder::decode_odrversion, this, _1, _2)); } void STIDecoder::push_bytes(const vector &buf) @@ -183,6 +187,37 @@ bool STIDecoder::decode_stardmy(const vector& /*value*/, uint16_t) return true; } +bool STIDecoder::decode_odraudiolevel(const vector& value, uint16_t) +{ + constexpr size_t expected_length = 2 * sizeof(int16_t); + + audio_level_data audio_level; + + if (value.size() == expected_length) { + audio_level.left = read_16b(value.begin()); + audio_level.right = read_16b(value.begin() + 2); + } + else { + audio_level.left = 0; + audio_level.right = 0; + etiLog.level(warn) << "EDI: ODR AudioLevel TAG has wrong length!"; + } + + m_data_collector.update_audio_levels(audio_level); + + // Not being able to decode the audio level is a soft-failure, it should + // not disrupt decoding the actual audio data. + return true; +} + +bool STIDecoder::decode_odrversion(const vector& value, uint16_t) +{ + const auto vd = parse_odr_version_data(value); + m_data_collector.update_odr_version(vd); + + return true; +} + void STIDecoder::packet_completed() { m_data_collector.assemble(); diff --git a/lib/edi/STIDecoder.hpp b/lib/edi/STIDecoder.hpp index 3f6f729..e2aa850 100644 --- a/lib/edi/STIDecoder.hpp +++ b/lib/edi/STIDecoder.hpp @@ -53,6 +53,12 @@ struct sti_payload_data { uint16_t stl(void) const { return istd.size(); } }; +struct audio_level_data { + int16_t left = 0; + int16_t right = 0; +}; + + /* A class that receives STI data must implement the interface described * in the STIDataCollector. This can be e.g. a converter to ETI, or something that * prepares data structures for a modulator. @@ -78,6 +84,9 @@ class STIDataCollector { virtual void add_payload(sti_payload_data&& payload) = 0; + virtual void update_audio_levels(const audio_level_data& data) = 0; + virtual void update_odr_version(const odr_version_data& data) = 0; + virtual void assemble() = 0; }; @@ -113,11 +122,13 @@ class STIDecoder { bool decode_ssn(const std::vector &value, uint16_t n); bool decode_stardmy(const std::vector &value, uint16_t); + bool decode_odraudiolevel(const std::vector &value, uint16_t); + bool decode_odrversion(const std::vector &value, uint16_t); + void packet_completed(); STIDataCollector& m_data_collector; TagDispatcher m_dispatcher; - }; } diff --git a/lib/edi/STIWriter.cpp b/lib/edi/STIWriter.cpp index 399922a..ea3bfe8 100644 --- a/lib/edi/STIWriter.cpp +++ b/lib/edi/STIWriter.cpp @@ -53,6 +53,7 @@ void STIWriter::reinit() m_stat_valid = false; m_time_valid = false; m_payload_valid = false; + m_audio_levels = audio_level_data(); m_stiFrame.frame.clear(); } @@ -84,6 +85,16 @@ void STIWriter::add_payload(sti_payload_data&& payload) m_payload_valid = true; } +void STIWriter::update_audio_levels(const audio_level_data& data) +{ + m_audio_levels = data; +} + +void STIWriter::update_odr_version(const odr_version_data& data) +{ + m_version_data = data; +} + void STIWriter::update_edi_time( uint32_t utco, uint32_t seconds) @@ -118,6 +129,8 @@ void STIWriter::assemble() // Do copies so as to preserve existing payload data m_stiFrame.frame = m_payload.istd; + m_stiFrame.audio_levels = m_audio_levels; + m_stiFrame.version_data = m_version_data; m_stiFrame.timestamp.seconds = m_seconds; m_stiFrame.timestamp.utco = m_utco; m_stiFrame.timestamp.tsta = m_management_data.tsta; diff --git a/lib/edi/STIWriter.hpp b/lib/edi/STIWriter.hpp index a75cb69..16cbfe8 100644 --- a/lib/edi/STIWriter.hpp +++ b/lib/edi/STIWriter.hpp @@ -32,6 +32,8 @@ namespace EdiDecoder { struct sti_frame_t { std::vector frame; frame_timestamp_t timestamp; + audio_level_data audio_levels; + odr_version_data version_data; }; class STIWriter : public STIDataCollector { @@ -53,6 +55,9 @@ class STIWriter : public STIDataCollector { virtual void update_sti_management(const sti_management_data& data); virtual void add_payload(sti_payload_data&& payload); + virtual void update_audio_levels(const audio_level_data& data); + virtual void update_odr_version(const odr_version_data& data); + virtual void assemble(void); // Return the assembled frame or an empty frame if not ready @@ -77,6 +82,8 @@ class STIWriter : public STIDataCollector { bool m_payload_valid = false; sti_payload_data m_payload; + audio_level_data m_audio_levels; + odr_version_data m_version_data; sti_frame_t m_stiFrame; }; diff --git a/lib/edi/common.cpp b/lib/edi/common.cpp index 4629b55..ac8ec0c 100644 --- a/lib/edi/common.cpp +++ b/lib/edi/common.cpp @@ -339,4 +339,17 @@ bool TagDispatcher::decode_tagpacket(const vector &payload) return success; } +odr_version_data parse_odr_version_data(const std::vector& data) +{ + if (data.size() < sizeof(uint32_t)) { + return {}; + } + + const size_t versionstr_length = data.size() - sizeof(uint32_t); + string version(data.begin(), data.begin() + versionstr_length); + uint32_t uptime_s = read_32b(data.begin() + versionstr_length); + + return {version, uptime_s}; +} + } diff --git a/lib/edi/common.hpp b/lib/edi/common.hpp index 1aa2cb6..5d15f8d 100644 --- a/lib/edi/common.hpp +++ b/lib/edi/common.hpp @@ -94,4 +94,12 @@ class TagDispatcher { std::function m_af_packet_completed; }; +// Data carried inside the ODRv EDI TAG +struct odr_version_data { + std::string version; + uint32_t uptime_s; +}; + +odr_version_data parse_odr_version_data(const std::vector& data); + } -- cgit v1.2.3