From cd332b5919109c6130ffab3168610b0348f0bed3 Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sun, 17 Jan 2021 21:19:33 +0200 Subject: [PATCH] ggwave : refactoring + comments --- bindings/python/.gitignore | 4 + bindings/python/cggwave.pxd | 4 +- bindings/python/ggwave.pyx | 4 +- examples/ggwave-cli/main.cpp | 7 +- examples/ggwave-common-sdl2.cpp | 8 +- examples/ggwave-py/send.py | 2 +- examples/ggwave-to-file/main.cpp | 10 +-- examples/waver/common.cpp | 8 +- include/ggwave/ggwave.h | 126 ++++++++++++++++++++++--------- src/ggwave.cpp | 45 ++++++----- 10 files changed, 143 insertions(+), 75 deletions(-) diff --git a/bindings/python/.gitignore b/bindings/python/.gitignore index 90c8b6f..4ae7f59 100644 --- a/bindings/python/.gitignore +++ b/bindings/python/.gitignore @@ -1 +1,5 @@ ggwave.so +README.rst +ggwave.bycython.cpp +ggwave.cpython-36m-x86_64-linux-gnu.so +ggwave/ diff --git a/bindings/python/cggwave.pxd b/bindings/python/cggwave.pxd index 10cd127..6a8bec7 100644 --- a/bindings/python/cggwave.pxd +++ b/bindings/python/cggwave.pxd @@ -4,7 +4,7 @@ cdef extern from "ggwave.h" nogil: GGWAVE_SAMPLE_FORMAT_I16, GGWAVE_SAMPLE_FORMAT_F32 - ctypedef enum ggwave_TxProtocol: + ctypedef enum ggwave_TxProtocolId: GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, @@ -31,7 +31,7 @@ cdef extern from "ggwave.h" nogil: ggwave_Instance instance, const char * dataBuffer, int dataSize, - ggwave_TxProtocol txProtocol, + ggwave_TxProtocolId txProtocolId, int volume, char * outputBuffer); diff --git a/bindings/python/ggwave.pyx b/bindings/python/ggwave.pyx index 589ffba..192769d 100644 --- a/bindings/python/ggwave.pyx +++ b/bindings/python/ggwave.pyx @@ -18,7 +18,7 @@ def init(parameters = None): def free(instance): return cggwave.ggwave_free(instance) -def encode(payload, txProtocol = 1, volume = 10, instance = None): +def encode(payload, txProtocolId = 1, volume = 10, instance = None): """ Encode payload into an audio waveform. @param {string} payload, the data to be encoded @return Generated audio waveform bytes representing 16-bit signed integer samples. @@ -35,7 +35,7 @@ def encode(payload, txProtocol = 1, volume = 10, instance = None): own = True instance = init(defaultParameters()) - n = cggwave.ggwave_encode(instance, cdata, len(data_bytes), txProtocol, volume, coutput) + n = cggwave.ggwave_encode(instance, cdata, len(data_bytes), txProtocolId, volume, coutput) if (own): free(instance) diff --git a/examples/ggwave-cli/main.cpp b/examples/ggwave-cli/main.cpp index 004c9f8..6f8c7ad 100644 --- a/examples/ggwave-cli/main.cpp +++ b/examples/ggwave-cli/main.cpp @@ -30,8 +30,9 @@ int main(int argc, char** argv) { auto ggWave = GGWave_instance(); printf("Available Tx protocols:\n"); - for (int i = 0; i < (int) ggWave->getTxProtocols().size(); ++i) { - printf(" -t%d : %s\n", i, ggWave->getTxProtocols()[i].name); + const auto & protocols = GGWave::getTxProtocols(); + for (const auto & protocol : protocols) { + printf(" -t%d : %s\n", protocol.first, protocol.second.name); } if (txProtocol < 0 || txProtocol > (int) ggWave->getTxProtocols().size()) { @@ -56,7 +57,7 @@ int main(int argc, char** argv) { } { std::lock_guard lock(mutex); - ggWave->init(input.size(), input.data(), ggWave->getTxProtocols()[txProtocol], 10); + ggWave->init(input.size(), input.data(), ggWave->getTxProtocol(txProtocol), 10); } inputOld = input; } diff --git a/examples/ggwave-common-sdl2.cpp b/examples/ggwave-common-sdl2.cpp index ba85651..90d9f3b 100644 --- a/examples/ggwave-common-sdl2.cpp +++ b/examples/ggwave-common-sdl2.cpp @@ -34,7 +34,7 @@ GGWave *g_ggWave = nullptr; extern "C" { EMSCRIPTEN_KEEPALIVE int sendData(int textLength, const char * text, int protocolId, int volume) { - g_ggWave->init(textLength, text, g_ggWave->getTxProtocols()[protocolId], volume); + g_ggWave->init(textLength, text, g_ggWave->getTxProtocol(protocolId), volume); return 0; } @@ -242,7 +242,7 @@ bool GGWave_mainLoop() { return false; } - static GGWave::CBQueueAudio cbQueueAudio = [&](const void * data, uint32_t nBytes) { + static GGWave::CBEnqueueAudio cbQueueAudio = [&](const void * data, uint32_t nBytes) { SDL_QueueAudio(g_devIdOut, data, nBytes); }; @@ -259,7 +259,7 @@ bool GGWave_mainLoop() { if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesOut()) { SDL_PauseAudioDevice(g_devIdIn, SDL_FALSE); if (::getTime_ms(tLastNoData, tNow) > 500.0f) { - g_ggWave->receive(CBDequeueAudio); + g_ggWave->decode(CBDequeueAudio); if ((int) SDL_GetQueuedAudioSize(g_devIdIn) > 32*g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesIn()) { SDL_ClearQueuedAudio(g_devIdIn); } @@ -273,7 +273,7 @@ bool GGWave_mainLoop() { SDL_PauseAudioDevice(g_devIdOut, SDL_TRUE); SDL_PauseAudioDevice(g_devIdIn, SDL_TRUE); - g_ggWave->send(cbQueueAudio); + g_ggWave->encode(cbQueueAudio); } return true; diff --git a/examples/ggwave-py/send.py b/examples/ggwave-py/send.py index 00fcc90..613e9cb 100644 --- a/examples/ggwave-py/send.py +++ b/examples/ggwave-py/send.py @@ -5,7 +5,7 @@ import numpy as np p = pyaudio.PyAudio() # generate audio waveform for string "hello python" -waveform = ggwave.encode("hello python", txProtocol = 1, volume = 20) +waveform = ggwave.encode("hello python", txProtocolId = 1, volume = 20) print("Transmitting text 'hello python' ...") stream = p.open(format=pyaudio.paInt16, channels=1, rate=48000, output=True, frames_per_buffer=4096) diff --git a/examples/ggwave-to-file/main.cpp b/examples/ggwave-to-file/main.cpp index 34cfc70..beba159 100644 --- a/examples/ggwave-to-file/main.cpp +++ b/examples/ggwave-to-file/main.cpp @@ -18,8 +18,8 @@ int main(int argc, char** argv) { fprintf(stderr, " Available protocols:\n"); const auto & protocols = GGWave::getTxProtocols(); - for (int i = 0; i < (int) protocols.size(); ++i) { - fprintf(stderr, " %d - %s\n", i, protocols[i].name); + for (const auto & protocol : protocols) { + fprintf(stderr, " %d - %s\n", protocol.first, protocol.second.name); } fprintf(stderr, "\n"); @@ -71,15 +71,15 @@ int main(int argc, char** argv) { fprintf(stderr, "Generating waveform for message '%s' ...\n", message.c_str()); GGWave ggWave(GGWave::kBaseSampleRate, sampleRateOut, 1024, 4, 2); - ggWave.init(message.size(), message.data(), ggWave.getTxProtocols()[protocolId], volume); + ggWave.init(message.size(), message.data(), ggWave.getTxProtocol(protocolId), volume); std::vector bufferPCM; - GGWave::CBQueueAudio cbQueueAudio = [&](const void * data, uint32_t nBytes) { + GGWave::CBEnqueueAudio cbEnqueueAudio = [&](const void * data, uint32_t nBytes) { bufferPCM.resize(nBytes); std::memcpy(bufferPCM.data(), data, nBytes); }; - if (ggWave.send(cbQueueAudio) == false) { + if (ggWave.encode(cbEnqueueAudio) == false) { fprintf(stderr, "Failed to generate waveform!\n"); return -4; } diff --git a/examples/waver/common.cpp b/examples/waver/common.cpp index 765342d..191da83 100644 --- a/examples/waver/common.cpp +++ b/examples/waver/common.cpp @@ -523,7 +523,7 @@ void updateCore() { g_ggWave->init( (int) inputCurrent.message.data.size(), inputCurrent.message.data.data(), - g_ggWave->getTxProtocols()[inputCurrent.message.protocolId], + g_ggWave->getTxProtocol(inputCurrent.message.protocolId), 100*inputCurrent.message.volume); inputCurrent.update = false; @@ -892,10 +892,10 @@ void renderMain() { ImGui::Text("Tx Protocol: "); ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y }); } - if (ImGui::BeginCombo("##protocol", g_ggWave->getTxProtocols()[settings.protocolId].name)) { + if (ImGui::BeginCombo("##protocol", g_ggWave->getTxProtocol(settings.protocolId).name)) { for (int i = 0; i < (int) g_ggWave->getTxProtocols().size(); ++i) { const bool isSelected = (settings.protocolId == i); - if (ImGui::Selectable(g_ggWave->getTxProtocols()[i].name, isSelected)) { + if (ImGui::Selectable(g_ggWave->getTxProtocol(i).name, isSelected)) { settings.protocolId = i; } @@ -966,7 +966,7 @@ void renderMain() { const auto msgStatus = message.received ? "Recv" : "Send"; const auto msgColor = message.received ? ImVec4 { 0.0f, 1.0f, 0.0f, interp } : ImVec4 { 1.0f, 1.0f, 0.0f, interp }; - ImGui::TextColored(msgColor, "[%s] %s (%s):", ::toTimeString(message.timestamp), msgStatus, g_ggWave->getTxProtocols()[message.protocolId].name); + ImGui::TextColored(msgColor, "[%s] %s (%s):", ::toTimeString(message.timestamp), msgStatus, g_ggWave->getTxProtocol(message.protocolId).name); { auto p0 = ImGui::GetCursorScreenPos(); diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 661c5c6..8099795 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -1,7 +1,6 @@ #ifndef GGWAVE_H #define GGWAVE_H -// Define GGWAVE_API macro to properly export symbols #ifdef GGWAVE_SHARED # ifdef _WIN32 # ifdef GGWAVE_BUILD @@ -20,11 +19,17 @@ extern "C" { #endif + // + // C interface + // + + // Data format of the audio samples typedef enum { GGWAVE_SAMPLE_FORMAT_I16, GGWAVE_SAMPLE_FORMAT_F32, } ggwave_SampleFormat; + // TxProtocol ids typedef enum { GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, @@ -32,32 +37,72 @@ extern "C" { GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, - } ggwave_TxProtocol; + } ggwave_TxProtocolId; + // GGWave instance parameters typedef struct { - int sampleRateIn; - int sampleRateOut; - int samplesPerFrame; - ggwave_SampleFormat formatIn; - ggwave_SampleFormat formatOut; + int sampleRateIn; // capture sample rate + int sampleRateOut; // playback sample rate + int samplesPerFrame; // number of samples per audio frame + ggwave_SampleFormat formatIn; // format of the captured audio samples + ggwave_SampleFormat formatOut; // format of the playback audio samples } ggwave_Parameters; + // GGWave instances are identified with an integer and are stored + // in a private map container. Using void * caused some issues with + // the python module and unfortunately had to do it this way typedef int ggwave_Instance; + // Helper method to get default instance parameters GGWAVE_API ggwave_Parameters ggwave_defaultParameters(void); + // Create a new GGWave instance with the specified parameters GGWAVE_API ggwave_Instance ggwave_init(const ggwave_Parameters parameters); + // Free a GGWave instance GGWAVE_API void ggwave_free(ggwave_Instance instance); + // Encode data into audio waveform + // instance - the GGWave instance to use + // dataBuffer - the data to encode + // dataSize - number of bytes in the input dataBuffer + // txProtocolId - the protocol to use for encoding + // volume - the volume of the generated waveform [0, 100] + // outputBuffer - the generated audio waveform. must be big enough to fit the generated data + // + // returns the number of generated samples + // + // returns -1 if there was an error + // + // todo : implement api to query the size of the generated waveform before generating it + // so that the user can allocate enough memory for the outputBuffer + // GGWAVE_API int ggwave_encode( ggwave_Instance instance, const char * dataBuffer, int dataSize, - ggwave_TxProtocol txProtocol, + ggwave_TxProtocolId txProtocolId, int volume, char * outputBuffer); + // Decode an audio waveform into data + // instance - the GGWave instance to use + // dataBuffer - the audio waveform + // dataSize - number of bytes in the input dataBuffer + // outputBuffer - stores the decoded data on success + // + // returns the number of decoded bytes + // + // Use this function to continuously provide audio samples to a GGWave instance. + // On each call, GGWave will analyze the provided data and if it detects a payload, + // it will return a non-zero result. + // + // If the return value is -1 then there was an error during the decoding process. + // Usually can occur if there is a lot of background noise in the audio. + // + // If the return value is greater than 0, then there will be that number of bytes + // decoded in the outputBuffer + // GGWAVE_API int ggwave_decode( ggwave_Instance instance, const char * dataBuffer, @@ -67,9 +112,14 @@ extern "C" { #ifdef __cplusplus } +// +// C++ interface +// + #include #include #include +#include class GGWave { public: @@ -82,26 +132,28 @@ public: static constexpr auto kMaxSpectrumHistory = 4; static constexpr auto kMaxRecordedFrames = 1024; - struct TxProtocol { - const char * name; + using TxProtocolId = ggwave_TxProtocolId; - int freqStart; - int framesPerTx; - int bytesPerTx; + struct TxProtocol { + const char * name; // string identifier of the protocol + + int freqStart; // FFT bin index of the lowest frequency + int framesPerTx; // number of frames to transmit a single chunk of data + int bytesPerTx; // number of bytes in a chunk of data int nDataBitsPerTx() const { return 8*bytesPerTx; } }; - using TxProtocols = std::vector; + using TxProtocols = std::map; static const TxProtocols & getTxProtocols() { - static TxProtocols kTxProtocols { - { "Normal", 40, 9, 3, }, - { "Fast", 40, 6, 3, }, - { "Fastest", 40, 3, 3, }, - { "[U] Normal", 320, 9, 3, }, - { "[U] Fast", 320, 6, 3, }, - { "[U] Fastest", 320, 3, 3, }, + static const TxProtocols kTxProtocols { + { GGWAVE_TX_PROTOCOL_AUDIBLE_NORMAL, { "Normal", 40, 9, 3, } }, + { GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, { "Fast", 40, 6, 3, } }, + { GGWAVE_TX_PROTOCOL_AUDIBLE_FASTEST, { "Fastest", 40, 3, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_NORMAL, { "[U] Normal", 320, 9, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_FAST, { "[U] Fast", 320, 6, 3, } }, + { GGWAVE_TX_PROTOCOL_ULTRASOUND_FASTEST, { "[U] Fastest", 320, 3, 3, } }, }; return kTxProtocols; @@ -113,8 +165,7 @@ public: using RecordedData = std::vector; using TxRxData = std::vector; - // todo : rename to CBEnqueueAudio - using CBQueueAudio = std::function; + using CBEnqueueAudio = std::function; using CBDequeueAudio = std::function; GGWave( @@ -128,13 +179,12 @@ public: bool init(int textLength, const char * stext, const TxProtocol & aProtocol, const int volume); - // todo : rename to "encode" / "decode" - bool send(const CBQueueAudio & cbQueueAudio); - void receive(const CBDequeueAudio & CBDequeueAudio); + bool encode(const CBEnqueueAudio & cbEnqueueAudio); + void decode(const CBDequeueAudio & cbDequeueAudio); - const bool & hasTxData() const { return m_hasNewTxData; } - const bool & isReceiving() const { return m_receivingData; } - const bool & isAnalyzing() const { return m_analyzingData; } + const bool & hasTxData() const { return m_hasNewTxData; } + const bool & isReceiving() const { return m_receivingData; } + const bool & isAnalyzing() const { return m_analyzingData; } const int & getFramesToRecord() const { return m_framesToRecord; } const int & getFramesLeftToRecord() const { return m_framesLeftToRecord; } @@ -144,15 +194,17 @@ public: const int & getSampleSizeBytesIn() const { return m_sampleSizeBytesIn; } const int & getSampleSizeBytesOut() const { return m_sampleSizeBytesOut; } - const float & getSampleRateIn() const { return m_sampleRateIn; } - const float & getSampleRateOut() const { return m_sampleRateOut; } + const float & getSampleRateIn() const { return m_sampleRateIn; } + const float & getSampleRateOut() const { return m_sampleRateOut; } - static int getDefultTxProtocolId() { return 1; } - static const TxProtocol & getDefultTxProtocol() { return getTxProtocols()[getDefultTxProtocolId()]; } + static TxProtocolId getDefaultTxProtocolId() { return GGWAVE_TX_PROTOCOL_AUDIBLE_FAST; } + static const TxProtocol & getDefaultTxProtocol() { return getTxProtocols().at(getDefaultTxProtocolId()); } + static const TxProtocol & getTxProtocol(int id) { return getTxProtocols().at(TxProtocolId(id)); } + static const TxProtocol & getTxProtocol(TxProtocolId id) { return getTxProtocols().at(id); } - const TxRxData & getRxData() const { return m_rxData; } - const TxProtocol & getRxProtocol() const { return m_rxProtocol; } - const int & getRxProtocolId() const { return m_rxProtocolId; } + const TxRxData & getRxData() const { return m_rxData; } + const TxProtocol & getRxProtocol() const { return m_rxProtocol; } + const TxProtocolId & getRxProtocolId() const { return m_rxProtocolId; } int takeRxData(TxRxData & dst); int takeTxAmplitudeData16(AmplitudeData16 & dst); @@ -207,7 +259,7 @@ private: int m_lastRxDataLength; TxRxData m_rxData; TxProtocol m_rxProtocol; - int m_rxProtocolId; + TxProtocolId m_rxProtocolId; int m_historyId = 0; AmplitudeData m_sampleAmplitudeAverage; diff --git a/src/ggwave.cpp b/src/ggwave.cpp index 0e20225..c7576ef 100644 --- a/src/ggwave.cpp +++ b/src/ggwave.cpp @@ -53,16 +53,24 @@ int ggwave_encode( ggwave_Instance instance, const char * dataBuffer, int dataSize, - ggwave_TxProtocol txProtocol, + ggwave_TxProtocolId txProtocolId, int volume, char * outputBuffer) { GGWave * ggWave = (GGWave *) g_instances[instance]; - ggWave->init(dataSize, dataBuffer, ggWave->getTxProtocols()[txProtocol], volume); + if (ggWave == nullptr) { + fprintf(stderr, "Invalid GGWave instance %d\n", instance); + return -1; + } + + if (ggWave->init(dataSize, dataBuffer, ggWave->getTxProtocol(txProtocolId), volume) == false) { + fprintf(stderr, "Failed to initialize GGWave instance %d\n", instance); + return -1; + } int nSamples = 0; - GGWave::CBQueueAudio cbQueueAudio = [&](const void * data, uint32_t nBytes) { + GGWave::CBEnqueueAudio cbEnqueueAudio = [&](const void * data, uint32_t nBytes) { char * p = (char *) data; std::copy(p, p + nBytes, outputBuffer); @@ -70,7 +78,10 @@ int ggwave_encode( nSamples = nBytes/2; }; - ggWave->send(cbQueueAudio); + if (ggWave->encode(cbEnqueueAudio) == false) { + fprintf(stderr, "Failed to encode data - GGWave instance %d\n", instance); + return -1; + } return nSamples; } @@ -92,7 +103,7 @@ int ggwave_decode( return nCopied; }; - ggWave->receive(cbDequeueAudio); + ggWave->decode(cbDequeueAudio); // todo : avoid allocation GGWave::TxRxData rxData; @@ -273,7 +284,7 @@ GGWave::GGWave( throw std::runtime_error("Invalid samples per frame"); } - init(0, "", getDefultTxProtocol(), 0); + init(0, "", getDefaultTxProtocol(), 0); } GGWave::~GGWave() { @@ -328,7 +339,7 @@ bool GGWave::init(int textLength, const char * stext, const TxProtocol & aProtoc return true; } -bool GGWave::send(const CBQueueAudio & cbQueueAudio) { +bool GGWave::encode(const CBEnqueueAudio & cbEnqueueAudio) { int samplesPerFrameOut = (m_sampleRateOut/m_sampleRateIn)*m_samplesPerFrame; if (m_sampleRateOut > m_sampleRateIn) { fprintf(stderr, "Error: capture sample rate (%d Hz) must be <= playback sample rate (%d Hz)\n", (int) m_sampleRateIn, (int) m_sampleRateOut); @@ -490,7 +501,7 @@ bool GGWave::send(const CBQueueAudio & cbQueueAudio) { ++frameId; } - cbQueueAudio(m_outputBlock16.data(), frameId*samplesPerFrameOut*m_sampleSizeBytesOut); + cbEnqueueAudio(m_outputBlock16.data(), frameId*samplesPerFrameOut*m_sampleSizeBytesOut); m_txAmplitudeData16.resize(frameId*samplesPerFrameOut); for (int i = 0; i < frameId*samplesPerFrameOut; ++i) { @@ -500,7 +511,7 @@ bool GGWave::send(const CBQueueAudio & cbQueueAudio) { return true; } -void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { +void GGWave::decode(const CBDequeueAudio & cbDequeueAudio) { while (m_hasNewTxData == false) { // read capture data // @@ -561,7 +572,7 @@ void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { bool isValid = false; for (int rxProtocolId = 0; rxProtocolId < (int) getTxProtocols().size(); ++rxProtocolId) { - const auto & rxProtocol = getTxProtocols()[rxProtocolId]; + const auto & rxProtocol = getTxProtocol(rxProtocolId); // skip Rx protocol if start frequency is different from detected one if (rxProtocol.freqStart != m_markerFreqStart) { @@ -654,7 +665,7 @@ void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { m_hasNewRxData = true; m_lastRxDataLength = decodedLength; m_rxProtocol = rxProtocol; - m_rxProtocolId = rxProtocolId; + m_rxProtocolId = TxProtocolId(rxProtocolId); } } } @@ -696,7 +707,7 @@ void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { int nDetectedMarkerBits = m_nBitsInMarker; for (int i = 0; i < m_nBitsInMarker; ++i) { - double freq = bitFreq(rxProtocol, i); + double freq = bitFreq(rxProtocol.second, i); int bin = std::round(freq*m_ihzPerSample); if (i%2 == 0) { @@ -707,7 +718,7 @@ void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { } if (nDetectedMarkerBits == m_nBitsInMarker) { - m_markerFreqStart = rxProtocol.freqStart; + m_markerFreqStart = rxProtocol.second.freqStart; isReceiving = true; break; } @@ -735,7 +746,7 @@ void GGWave::receive(const CBDequeueAudio & cbDequeueAudio) { int nDetectedMarkerBits = m_nBitsInMarker; for (int i = 0; i < m_nBitsInMarker; ++i) { - double freq = bitFreq(rxProtocol, i); + double freq = bitFreq(rxProtocol.second, i); int bin = std::round(freq*m_ihzPerSample); if (i%2 == 0) { @@ -798,15 +809,15 @@ bool GGWave::takeSpectrum(SpectrumData & dst) { int GGWave::maxFramesPerTx() const { int res = 0; for (const auto & protocol : getTxProtocols()) { - res = std::max(res, protocol.framesPerTx); + res = std::max(res, protocol.second.framesPerTx); } return res; } int GGWave::minBytesPerTx() const { - int res = getTxProtocols().front().framesPerTx; + int res = getTxProtocols().begin()->second.bytesPerTx; for (const auto & protocol : getTxProtocols()) { - res = std::min(res, protocol.bytesPerTx); + res = std::min(res, protocol.second.bytesPerTx); } return res; }