ggwave : big refactoring / renaming

This commit is contained in:
Georgi Gerganov
2022-06-05 11:05:34 +03:00
parent 05f1b4750b
commit 7c5b614c16
26 changed files with 1097 additions and 834 deletions

View File

@@ -45,41 +45,39 @@ void mainUpdate(void *) {
extern "C" {
EMSCRIPTEN_KEEPALIVE
int sendData(int textLength, const char * text, int protocolId, int volume) {
g_ggWave->init(textLength, text, g_ggWave->getTxProtocol(protocolId), volume);
g_ggWave->init(textLength, text, GGWave::TxProtocolId(protocolId), volume);
return 0;
}
EMSCRIPTEN_KEEPALIVE
int getText(char * text) {
std::copy(g_ggWave->getRxData().begin(), g_ggWave->getRxData().end(), text);
std::copy(g_ggWave->rxData().begin(), g_ggWave->rxData().end(), text);
return 0;
}
EMSCRIPTEN_KEEPALIVE
float getSampleRate() { return g_ggWave->getSampleRateInp(); }
float sampleRate() { return g_ggWave->sampleRateInp(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToRecord() { return g_ggWave->getFramesToRecord(); }
int framesToRecord() { return g_ggWave->rxFramesToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToRecord() { return g_ggWave->getFramesLeftToRecord(); }
int framesLeftToRecord() { return g_ggWave->rxFramesLeftToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToAnalyze() { return g_ggWave->getFramesToAnalyze(); }
int framesToAnalyze() { return g_ggWave->rxFramesToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToAnalyze() { return g_ggWave->getFramesLeftToAnalyze(); }
int framesLeftToAnalyze() { return g_ggWave->rxFramesLeftToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int hasDeviceOutput() { return g_devIdOut; }
int hasDeviceOutput() { return g_devIdOut; }
EMSCRIPTEN_KEEPALIVE
int hasDeviceCapture() { return g_devIdInp; }
int hasDeviceCapture() { return g_devIdInp; }
EMSCRIPTEN_KEEPALIVE
int doInit() {
return g_doInit();
}
int doInit() { return g_doInit(); }
}
void GGWave_setDefaultCaptureDeviceName(std::string name) {
@@ -253,16 +251,16 @@ bool GGWave_mainLoop() {
return false;
}
if (g_ggWave->hasTxData() == false) {
if (g_ggWave->txHasData() == false) {
SDL_PauseAudioDevice(g_devIdOut, SDL_FALSE);
static auto tLastNoData = std::chrono::high_resolution_clock::now();
auto tNow = std::chrono::high_resolution_clock::now();
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesOut()) {
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeOut()) {
SDL_PauseAudioDevice(g_devIdInp, SDL_FALSE);
const int nHave = (int) SDL_GetQueuedAudioSize(g_devIdInp);
const int nNeed = g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesInp();
const int nNeed = g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeInp();
if (::getTime_ms(tLastNoData, tNow) > 500.0f && nHave >= nNeed) {
static std::vector<uint8_t> dataInp(nNeed);
SDL_DequeueAudio(g_devIdInp, dataInp.data(), nNeed);
@@ -271,7 +269,7 @@ bool GGWave_mainLoop() {
fprintf(stderr, "Warning: failed to decode input data!\n");
} else {
GGWave::TxRxData rxData;
int n = g_ggWave->takeRxData(rxData);
int n = g_ggWave->rxTakeData(rxData);
if (n > 0) {
std::time_t timestamp = std::time(nullptr);
std::string tstr = std::asctime(std::localtime(&timestamp));
@@ -335,7 +333,8 @@ int main(int argc, char** argv) {
printf("\n");
#endif
const GGWave::TxProtocols protocols = {
auto & protocols = GGWave::Protocols::rx();
protocols = {
{ "[R2T2] Normal", 64, 9, 1, 2, true, },
{ "[R2T2] Fast", 64, 6, 1, 2, true, },
{ "[R2T2] Fastest", 64, 3, 1, 2, true, },
@@ -356,8 +355,6 @@ int main(int argc, char** argv) {
return false;
}
g_ggWave->setRxProtocols(protocols);
isInitialized = true;
printf("Listening for payload with length = %d bytes ..\n", payloadLength);

View File

@@ -101,6 +101,7 @@
parameters.samplesPerFrame = 512;
parameters.sampleRateInp = context.sampleRate;
parameters.sampleRateOut = context.sampleRate;
parameters.operatingMode = GGWAVE_OPERATING_MODE_RX_AND_TX | GGWAVE_OPERATING_MODE_USE_DSS;
instance = ggwave.init(parameters);
}
}
@@ -122,7 +123,7 @@
}
// generate audio waveform
var waveform = ggwave.encode(instance, payload, ggwave.TxProtocolId.GGWAVE_TX_PROTOCOL_MT_FASTEST, 25)
var waveform = ggwave.encode(instance, payload, ggwave.TxProtocolId.GGWAVE_PROTOCOL_MT_FASTEST, 25)
// play audio
var buf = convertTypedArray(waveform, Float32Array);

View File

@@ -48,29 +48,20 @@ void loop() {
Serial.println("trying to create ggwave instance");
auto p = GGWave::getDefaultParameters();
p.sampleRateInp = frequency;
p.sampleRateOut = frequency;
p.sampleRate = frequency;
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
p.payloadLength = 16;
p.sampleRateInp = frequency;
p.sampleRateOut = frequency;
p.sampleRate = frequency;
p.samplesPerFrame = 128;
p.payloadLength = 16;
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I16;
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
{
auto & protocols = GGWave::getTxProtocols();
for (auto & p : protocols) {
p.enabled = false;
}
protocols[GGWAVE_TX_PROTOCOL_MT_FASTEST].enabled = true;
protocols[GGWAVE_TX_PROTOCOL_DT_FASTEST].enabled = true;
}
GGWave::Protocols::tx().only({GGWAVE_PROTOCOL_MT_FASTEST, GGWAVE_PROTOCOL_DT_FASTEST});
GGWave::Protocols::rx().only({GGWAVE_PROTOCOL_MT_FASTEST, GGWAVE_PROTOCOL_DT_FASTEST});
GGWave ggwave(p);
ggwave.setLogFile(nullptr);
ggwave.setRxProtocols({
ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_MT_FASTEST),
ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_DT_FASTEST),
});
Serial.println("Instance initialized");
@@ -103,14 +94,14 @@ void loop() {
Serial.println(tEnd - tStart);
}
nr = ggwave.takeRxData(result);
nr = ggwave.rxTakeData(result);
if (nr > 0) {
Serial.println(tEnd - tStart);
Serial.println(nr);
Serial.println((char *)result.data());
if (strcmp((char *)result.data(), "test") == 0) {
ggwave.init("hello", ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_MT_FASTEST));
ggwave.init("hello", GGWave::TxProtocolId(GGWAVE_PROTOCOL_MT_FASTEST));
ggwave.encode();
const auto & tones = ggwave.txTones();

View File

@@ -1,5 +1,6 @@
ggwave
ggwave.cpp
fft.h
resampler.h
resampler.cpp
reed-solomon

View File

@@ -1,9 +1,10 @@
#
# arduino-tx
configure_file(${CMAKE_SOURCE_DIR}/include/ggwave/ggwave.h ${CMAKE_CURRENT_SOURCE_DIR}/ggwave/ggwave.h COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/ggwave.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ggwave.cpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/gf.hpp ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/gf.hpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/rs.hpp ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/rs.hpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/include/ggwave/ggwave.h ${CMAKE_CURRENT_SOURCE_DIR}/ggwave/ggwave.h COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/ggwave.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ggwave.cpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/fft.h ${CMAKE_CURRENT_SOURCE_DIR}/fft.h COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/gf.hpp ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/gf.hpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/rs.hpp ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/rs.hpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/poly.hpp ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/poly.hpp COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/LICENSE COPYONLY)
configure_file(${CMAKE_SOURCE_DIR}/src/reed-solomon/LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/reed-solomon/LICENSE COPYONLY)

View File

@@ -1,4 +1,4 @@
#include <ArduinoSTL.h>
#include "Arduino_AVRSTL.h"
#include "ggwave/ggwave.h"
@@ -9,6 +9,7 @@ const int kPinButton1 = 4;
void setup() {
Serial.begin(57600);
display_freeram();
//pinMode(kPinLed0, OUTPUT);
//pinMode(kPinSpeaker, OUTPUT);
@@ -61,17 +62,42 @@ char txt[16];
int pressed = 0;
bool isDown = false;
void display_freeram() {
Serial.print(F("- SRAM left: "));
Serial.println(freeRam());
}
int freeRam() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
}
void loop() {
Serial.println("hello");
auto p = GGWave::getDefaultParameters();
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
p.payloadLength = 4;
p.sampleRateInp = 6000;
p.sampleRateOut = 6000;
p.sampleRate = 6000;
p.samplesPerFrame = 128;
p.payloadLength = 4;
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
p.sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8;
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
GGWave::getTxProtocols() = GGWave::TxProtocols({{ "[MT] Fastest", 24, 3, 1, 2, true, }});
delay(1000);
GGWave::Protocols::kDefault() = {};
Serial.println("aaaaaaaaaaaa");
GGWave::Protocols::tx() = { { "[MT] Fastest", 24, 3, 1, 2, true, } };
delay(1000);
display_freeram();
Serial.println("xxxxxxxxxxx");
delay(1000);
Serial.println("yyyyyyyyyyyy");
GGWave ggwave(p);
display_freeram();
while (true) {
delay(1000);

View File

@@ -40,17 +40,17 @@
<script type="text/javascript" src="ggwave.js"></script>
<script type='text/javascript'>
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
var context = null;
var context = null;
var recorder = null;
// the ggwave module instance
var ggwave = null;
var ggwave = null;
var ggwave_FluentPet = null;
var parameters = null;
var instance = null;
var parameters = null;
var instance = null;
const kPayloadLength = 3;
@@ -65,10 +65,10 @@
ggwave_FluentPet = obj;
});
var txData = document.getElementById("txData");
var rxData = document.getElementById("rxData");
var txData = document.getElementById("txData");
var rxData = document.getElementById("rxData");
var captureStart = document.getElementById("captureStart");
var captureStop = document.getElementById("captureStop");
var captureStop = document.getElementById("captureStop");
// helper function
function convertTypedArray(src, type) {
@@ -113,9 +113,9 @@
// generate audio waveform
var waveform = null;
if (document.getElementById("checkbox-fp").checked) {
waveform = ggwave_FluentPet.encode(instance, payload, ggwave_FluentPet.TxProtocolId.GGWAVE_TX_PROTOCOL_DT_FAST, 25)
waveform = ggwave_FluentPet.encode(instance, payload, ggwave_FluentPet.TxProtocolId.GGWAVE_PROTOCOL_DT_FAST, 25)
} else {
waveform = ggwave.encode(instance, payload, ggwave.TxProtocolId.GGWAVE_TX_PROTOCOL_DT_FAST, 25)
waveform = ggwave.encode(instance, payload, ggwave.TxProtocolId.GGWAVE_PROTOCOL_DT_FAST, 25)
}
// play audio

View File

@@ -22,13 +22,13 @@ int main(int argc, char** argv) {
printf(" -v - print generated tones on resend\n");
printf("\n");
const auto argm = parseCmdArguments(argc, argv);
const int captureId = argm.count("c") == 0 ? 0 : std::stoi(argm.at("c"));
const int playbackId = argm.count("p") == 0 ? 0 : std::stoi(argm.at("p"));
const int txProtocolId = argm.count("t") == 0 ? 1 : std::stoi(argm.at("t"));
const auto argm = parseCmdArguments(argc, argv);
const int captureId = argm.count("c") == 0 ? 0 : std::stoi(argm.at("c"));
const int playbackId = argm.count("p") == 0 ? 0 : std::stoi(argm.at("p"));
const int txProtocolId = argm.count("t") == 0 ? 1 : std::stoi(argm.at("t"));
const int payloadLength = argm.count("l") == 0 ? -1 : std::stoi(argm.at("l"));
const bool useDSS = argm.count("s") > 0;
const bool printTones = argm.count("v") > 0;
const bool useDSS = argm.count("s") > 0;
const bool printTones = argm.count("v") > 0;
if (GGWave_init(playbackId, captureId, payloadLength, 0.0f, useDSS) == false) {
fprintf(stderr, "Failed to initialize GGWave\n");
@@ -38,7 +38,7 @@ int main(int argc, char** argv) {
auto ggWave = GGWave_instance();
printf("Available Tx protocols:\n");
const auto & protocols = GGWave::getTxProtocols();
const auto & protocols = GGWave::Protocols::kDefault();
for (int i = 0; i < (int) protocols.size(); ++i) {
const auto & protocol = protocols[i];
if (protocol.enabled == false) {
@@ -82,7 +82,7 @@ int main(int argc, char** argv) {
}
{
std::lock_guard<std::mutex> lock(mutex);
ggWave->init(input.size(), input.data(), ggWave->getTxProtocol(txProtocolId), 10);
ggWave->init(input.size(), input.data(), GGWave::TxProtocolId(txProtocolId), 10);
}
inputOld = input;
}

View File

@@ -34,41 +34,39 @@ std::shared_ptr<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->getTxProtocol(protocolId), volume);
g_ggWave->init(textLength, text, GGWave::TxProtocolId(protocolId), volume);
return 0;
}
EMSCRIPTEN_KEEPALIVE
int getText(char * text) {
std::copy(g_ggWave->getRxData().begin(), g_ggWave->getRxData().end(), text);
std::copy(g_ggWave->rxData().begin(), g_ggWave->rxData().end(), text);
return 0;
}
EMSCRIPTEN_KEEPALIVE
float getSampleRate() { return g_ggWave->getSampleRateInp(); }
float sampleRate() { return g_ggWave->sampleRateInp(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToRecord() { return g_ggWave->getFramesToRecord(); }
int framesToRecord() { return g_ggWave->rxFramesToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToRecord() { return g_ggWave->getFramesLeftToRecord(); }
int framesLeftToRecord() { return g_ggWave->rxFramesLeftToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToAnalyze() { return g_ggWave->getFramesToAnalyze(); }
int framesToAnalyze() { return g_ggWave->rxFramesToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToAnalyze() { return g_ggWave->getFramesLeftToAnalyze(); }
int framesLeftToAnalyze() { return g_ggWave->rxFramesLeftToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int hasDeviceOutput() { return g_devIdOut; }
int hasDeviceOutput() { return g_devIdOut; }
EMSCRIPTEN_KEEPALIVE
int hasDeviceCapture() { return g_devIdInp; }
int hasDeviceCapture() { return g_devIdInp; }
EMSCRIPTEN_KEEPALIVE
int doInit() {
return GGWave_init(-1, -1);
}
int doInit() { return GGWave_init(-1, -1); }
}
void GGWave_setDefaultCaptureDeviceName(std::string name) {
@@ -244,16 +242,16 @@ bool GGWave_mainLoop() {
return false;
}
if (g_ggWave->hasTxData() == false) {
if (g_ggWave->txHasData() == false) {
SDL_PauseAudioDevice(g_devIdOut, SDL_FALSE);
static auto tLastNoData = std::chrono::high_resolution_clock::now();
auto tNow = std::chrono::high_resolution_clock::now();
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesOut()) {
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeOut()) {
SDL_PauseAudioDevice(g_devIdInp, SDL_FALSE);
const int nHave = (int) SDL_GetQueuedAudioSize(g_devIdInp);
const int nNeed = g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesInp();
const int nNeed = g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeInp();
if (::getTime_ms(tLastNoData, tNow) > 500.0f && nHave >= nNeed) {
static std::vector<uint8_t> dataInp(nNeed);
SDL_DequeueAudio(g_devIdInp, dataInp.data(), nNeed);

View File

@@ -4,7 +4,7 @@ import pyaudio
p = pyaudio.PyAudio()
# generate audio waveform for string "hello python"
waveform = ggwave.encode("hello python", txProtocolId = 1, volume = 20)
waveform = ggwave.encode("hello python", protocolId = 1, volume = 20)
print("Transmitting text 'hello python' ...")
stream = p.open(format=pyaudio.paFloat32, channels=1, rate=48000, output=True, frames_per_buffer=4096)

View File

@@ -12,13 +12,14 @@
int main(int argc, char** argv) {
fprintf(stderr, "Usage: %s [-vN] [-sN] [-pN] [-lN]\n", argv[0]);
fprintf(stderr, " -vN - output volume, N in (0, 100], (default: 50)\n");
fprintf(stderr, " -sN - output sample rate, N in [%d, %d], (default: %d)\n", (int) GGWave::kSampleRateMin, (int) GGWave::kSampleRateMax, (int) GGWave::kDefaultSampleRate);
fprintf(stderr, " -SN - output sample rate, N in [%d, %d], (default: %d)\n", (int) GGWave::kSampleRateMin, (int) GGWave::kSampleRateMax, (int) GGWave::kDefaultSampleRate);
fprintf(stderr, " -pN - select the transmission protocol id (default: 1)\n");
fprintf(stderr, " -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed);
fprintf(stderr, " -s - use Direct Sequence Spread (DSS)\n");
fprintf(stderr, "\n");
fprintf(stderr, " Available protocols:\n");
const auto & protocols = GGWave::getTxProtocols();
const auto & protocols = GGWave::Protocols::kDefault();
for (int i = 0; i < (int) protocols.size(); ++i) {
const auto & protocol = protocols[i];
fprintf(stderr, " %d - %s\n", i, protocol.name);
@@ -29,16 +30,17 @@ int main(int argc, char** argv) {
return -1;
}
auto argm = parseCmdArguments(argc, argv);
const auto argm = parseCmdArguments(argc, argv);
if (argm.find("h") != argm.end()) {
if (argm.count("h") > 0) {
return 0;
}
int volume = argm["v"].empty() ? 50 : std::stoi(argm["v"]);
float sampleRateOut = argm["s"].empty() ? GGWave::kDefaultSampleRate : std::stof(argm["s"]);
int protocolId = argm["p"].empty() ? 1 : std::stoi(argm["p"]);
int payloadLength = argm["l"].empty() ? -1 : std::stoi(argm["l"]);
const int volume = argm.count("v") == 0 ? 50 : std::stoi(argm.at("v"));
const float sampleRateOut = argm.count("S") == 0 ? GGWave::kDefaultSampleRate : std::stof(argm.at("S"));
const int protocolId = argm.count("p") == 0 ? 1 : std::stoi(argm.at("p"));
const int payloadLength = argm.count("l") == 0 ? -1 : std::stoi(argm.at("l"));
const bool useDSS = argm.count("s") > 0;
if (volume <= 0 || volume > 100) {
fprintf(stderr, "Invalid volume\n");
@@ -50,11 +52,16 @@ int main(int argc, char** argv) {
return -1;
}
if (protocolId < 0 || protocolId >= (int) GGWave::getTxProtocols().size()) {
if (protocolId < 0 || protocolId >= (int) protocols.size()) {
fprintf(stderr, "Invalid transmission protocol id\n");
return -1;
}
if (protocols[protocolId].enabled == false) {
fprintf(stderr, "Protocol %d is not enabled\n", protocolId);
return -1;
}
fprintf(stderr, "Enter a text message:\n");
std::string message;
@@ -72,6 +79,9 @@ int main(int argc, char** argv) {
fprintf(stderr, "Generating waveform for message '%s' ...\n", message.c_str());
ggwave_OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
if (useDSS) mode = ggwave_OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
GGWave ggWave({
payloadLength,
GGWave::kDefaultSampleRate,
@@ -81,9 +91,9 @@ int main(int argc, char** argv) {
GGWave::kDefaultSoundMarkerThreshold,
GGWAVE_SAMPLE_FORMAT_F32,
GGWAVE_SAMPLE_FORMAT_I16,
GGWAVE_OPERATING_MODE_RX_AND_TX,
mode,
});
ggWave.init(message.size(), message.data(), ggWave.getTxProtocol(protocolId), volume);
ggWave.init(message.size(), message.data(), GGWave::TxProtocolId(protocolId), volume);
const auto nBytes = ggWave.encode();
if (nBytes == 0) {

View File

@@ -48,11 +48,13 @@ int main(int argc, char** argv) {
printf(" -p - print tones, no playback\n");
printf(" -A - print Arduino code\n");
printf(" -b - use 'beep' command\n");
printf(" -s - use Direct Sequence Spread (DSS)\n");
printf(" -tN - transmission protocol\n");
printf(" -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed);
printf("\n");
const GGWave::TxProtocols protocols = {
auto & protocols = GGWave::Protocols::tx();
protocols = {
{ "[R2T2] Normal", 64, 9, 1, 2, true, },
{ "[R2T2] Fast", 64, 6, 1, 2, true, },
{ "[R2T2] Fastest", 64, 3, 1, 2, true, },
@@ -61,13 +63,17 @@ int main(int argc, char** argv) {
{ "[R2T2] Low Fastest", 16, 3, 1, 2, true, },
};
const auto argm = parseCmdArguments(argc, argv);
const bool printTones = argm.count("p") > 0;
const auto argm = parseCmdArguments(argc, argv);
const bool printTones = argm.count("p") > 0;
const bool printArduino = argm.count("A") > 0;
const bool useBeep = argm.count("b") > 0;
const int txProtocolId = argm.count("t") == 0 ? GGWAVE_TX_PROTOCOL_CUSTOM_0 : std::stoi(argm.at("t"));
const bool useBeep = argm.count("b") > 0;
const bool useDSS = argm.count("s") > 0;
const int txProtocolId = argm.count("t") == 0 ? 0 : std::stoi(argm.at("t"));
const int payloadLength = argm.count("l") == 0 ? 16 : std::stoi(argm.at("l"));
ggwave_OperatingMode mode = ggwave_OperatingMode(GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
if (useDSS) mode = ggwave_OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
GGWave ggWave({
payloadLength,
GGWave::kDefaultSampleRate,
@@ -77,7 +83,7 @@ int main(int argc, char** argv) {
GGWave::kDefaultSoundMarkerThreshold,
GGWAVE_SAMPLE_FORMAT_F32,
GGWAVE_SAMPLE_FORMAT_F32,
(ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES),
mode,
});
printf("Available Tx protocols:\n");
@@ -123,7 +129,7 @@ int main(int argc, char** argv) {
return -3;
}
ggWave.init(message.size(), message.data(), protocols.at(GGWave::TxProtocolId(txProtocolId)), 10);
ggWave.init(message.size(), message.data(), GGWave::TxProtocolId(txProtocolId), 10);
ggWave.encode();
int nFrames = 0;

View File

@@ -44,41 +44,39 @@ void mainUpdate(void *) {
extern "C" {
EMSCRIPTEN_KEEPALIVE
int sendData(int textLength, const char * text, int protocolId, int volume) {
g_ggWave->init(textLength, text, g_ggWave->getTxProtocol(protocolId), volume);
g_ggWave->init(textLength, text, GGWave::TxProtocolId(protocolId), volume);
return 0;
}
EMSCRIPTEN_KEEPALIVE
int getText(char * text) {
std::copy(g_ggWave->getRxData().begin(), g_ggWave->getRxData().end(), text);
std::copy(g_ggWave->rxData().begin(), g_ggWave->rxData().end(), text);
return 0;
}
EMSCRIPTEN_KEEPALIVE
float getSampleRate() { return g_ggWave->getSampleRateInp(); }
float sampleRate() { return g_ggWave->sampleRateInp(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToRecord() { return g_ggWave->getFramesToRecord(); }
int framesToRecord() { return g_ggWave->rxFramesToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToRecord() { return g_ggWave->getFramesLeftToRecord(); }
int framesLeftToRecord() { return g_ggWave->rxFramesLeftToRecord(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToAnalyze() { return g_ggWave->getFramesToAnalyze(); }
int framesToAnalyze() { return g_ggWave->rxFramesToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int getFramesLeftToAnalyze() { return g_ggWave->getFramesLeftToAnalyze(); }
int framesLeftToAnalyze() { return g_ggWave->rxFramesLeftToAnalyze(); }
EMSCRIPTEN_KEEPALIVE
int hasDeviceOutput() { return g_devIdOut; }
int hasDeviceOutput() { return g_devIdOut; }
EMSCRIPTEN_KEEPALIVE
int hasDeviceCapture() { return g_devIdInp; }
int hasDeviceCapture() { return g_devIdInp; }
EMSCRIPTEN_KEEPALIVE
int doInit() {
return g_doInit();
}
int doInit() { return g_doInit(); }
}
void GGWave_setDefaultCaptureDeviceName(std::string name) {
@@ -89,7 +87,8 @@ bool GGWave_init(
const int playbackId,
const int captureId,
const int payloadLength,
const float sampleRateOffset) {
const float sampleRateOffset,
const bool useDSS) {
if (g_devIdInp && g_devIdOut) {
return false;
@@ -225,6 +224,9 @@ bool GGWave_init(
if (reinit) {
if (g_ggWave) delete g_ggWave;
ggwave_OperatingMode mode = GGWAVE_OPERATING_MODE_RX;
if (useDSS) mode = ggwave_OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
g_ggWave = new GGWave({
payloadLength,
(float) g_obtainedSpecInp.freq,
@@ -234,7 +236,7 @@ bool GGWave_init(
GGWave::kDefaultSoundMarkerThreshold,
sampleFormatInp,
sampleFormatOut,
GGWAVE_OPERATING_MODE_RX,
mode,
});
}
@@ -248,16 +250,16 @@ bool GGWave_mainLoop() {
return false;
}
if (g_ggWave->hasTxData() == false) {
if (g_ggWave->txHasData() == false) {
SDL_PauseAudioDevice(g_devIdOut, SDL_FALSE);
static auto tLastNoData = std::chrono::high_resolution_clock::now();
auto tNow = std::chrono::high_resolution_clock::now();
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesOut()) {
if ((int) SDL_GetQueuedAudioSize(g_devIdOut) < g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeOut()) {
SDL_PauseAudioDevice(g_devIdInp, SDL_FALSE);
const int nHave = (int) SDL_GetQueuedAudioSize(g_devIdInp);
const int nNeed = g_ggWave->getSamplesPerFrame()*g_ggWave->getSampleSizeBytesInp();
const int nNeed = g_ggWave->samplesPerFrame()*g_ggWave->sampleSizeInp();
if (::getTime_ms(tLastNoData, tNow) > 500.0f && nHave >= nNeed) {
static std::vector<uint8_t> dataInp(nNeed);
SDL_DequeueAudio(g_devIdInp, dataInp.data(), nNeed);
@@ -318,10 +320,12 @@ int main(int argc, char** argv) {
printf("Usage: %s [-cN] [-lN]\n", argv[0]);
printf(" -cN - select capture device N\n");
printf(" -lN - fixed payload length of size N, N in [1, %d]\n", GGWave::kMaxLengthFixed);
printf(" -s - use Direct Sequence Spread (DSS)\n");
printf("\n");
#endif
const GGWave::TxProtocols protocols = {
auto & protocols = GGWave::Protocols::rx();
protocols = {
{ "[R2T2] Normal", 64, 9, 1, 2, true, },
{ "[R2T2] Fast", 64, 6, 1, 2, true, },
{ "[R2T2] Fastest", 64, 3, 1, 2, true, },
@@ -330,20 +334,19 @@ int main(int argc, char** argv) {
{ "[R2T2] Low Fastest", 16, 3, 1, 2, true, },
};
const auto argm = parseCmdArguments(argc, argv);
const int captureId = argm.count("c") == 0 ? 0 : std::stoi(argm.at("c"));
const auto argm = parseCmdArguments(argc, argv);
const int captureId = argm.count("c") == 0 ? 0 : std::stoi(argm.at("c"));
const int payloadLength = argm.count("l") == 0 ? 16 : std::stoi(argm.at("l"));
const bool useDSS = argm.count("s") > 0;
bool isInitialized = false;
g_doInit = [&]() {
if (GGWave_init(0, captureId, payloadLength, 0) == false) {
if (GGWave_init(0, captureId, payloadLength, 0, useDSS) == false) {
fprintf(stderr, "Failed to initialize GGWave\n");
return false;
}
g_ggWave->setRxProtocols(protocols);
isInitialized = true;
printf("Listening for payload with length = %d bytes ..\n", payloadLength);

View File

@@ -136,8 +136,8 @@ struct Message {
};
struct GGWaveStats {
bool isReceiving;
bool isAnalyzing;
bool receiving;
bool analyzing;
int framesToRecord;
int framesLeftToRecord;
int framesToAnalyze;
@@ -146,8 +146,8 @@ struct GGWaveStats {
float sampleRateInp;
float sampleRateOut;
float sampleRate;
int sampleSizeBytesInp;
int sampleSizeBytesOut;
int sampleSizeInp;
int sampleSizeOut;
};
struct State {
@@ -201,9 +201,11 @@ struct State {
}
Message message;
GGWave::SpectrumData rxSpectrum;
GGWave::AmplitudeData rxAmplitude;
GGWave::AmplitudeDataI16 txAmplitude;
GGWave::Spectrum rxSpectrum;
GGWave::Amplitude rxAmplitude;
GGWave::AmplitudeI16 txAmplitude;
GGWaveStats stats;
GGWave::TxProtocols txProtocols;
};
@@ -302,7 +304,7 @@ GGSock::FileServer g_fileServer;
// file received data
struct FileInfoExtended {
bool isReceiving = false;
bool receiving = false;
bool readyToShare = false;
bool requestToShare = false;
int nReceivedChunks = 0;
@@ -614,16 +616,16 @@ void updateCore() {
ggWave->init(
n, inputCurrent.message.data.data(),
ggWave->getTxProtocol(inputCurrent.message.protocolId),
GGWave::TxProtocolId(inputCurrent.message.protocolId),
100*inputCurrent.message.volume);
}
if (inputCurrent.flags.needReinit) {
static auto sampleRateInpOld = ggWave->getSampleRateInp();
static auto sampleRateOutOld = ggWave->getSampleRateOut();
GGWave::SampleFormat sampleFormatInpOld = ggWave->getSampleFormatInp();
GGWave::SampleFormat sampleFormatOutOld = ggWave->getSampleFormatOut();
auto rxProtocolsOld = ggWave->getRxProtocols();
static auto sampleRateInpOld = ggWave->sampleRateInp();
static auto sampleRateOutOld = ggWave->sampleRateOut();
GGWave::SampleFormat sampleFormatInpOld = ggWave->sampleFormatInp();
GGWave::SampleFormat sampleFormatOutOld = ggWave->sampleFormatOut();
auto rxProtocolsOld = ggWave->rxProtocols();
GGWave::OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
if (inputCurrent.directSequenceSpread) mode = GGWave::OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
@@ -643,7 +645,7 @@ void updateCore() {
GGWave_reset(&parameters);
ggWave = GGWave_instance();
ggWave->setRxProtocols(rxProtocolsOld);
ggWave->rxProtocols() = rxProtocolsOld;
}
if (inputCurrent.flags.changeNeedSpectrum) {
@@ -651,11 +653,11 @@ void updateCore() {
}
if (inputCurrent.flags.stopReceiving) {
ggWave->stopReceiving();
ggWave->rxStopReceiving();
}
if (inputCurrent.flags.changeRxProtocols) {
ggWave->setRxProtocols(inputCurrent.rxProtocols);
ggWave->rxProtocols() = inputCurrent.rxProtocols;
}
inputCurrent.flags.clear();
@@ -664,7 +666,7 @@ void updateCore() {
GGWave_mainLoop();
rxDataLengthLast = ggWave->takeRxData(rxDataLast);
rxDataLengthLast = ggWave->rxTakeData(rxDataLast);
if (rxDataLengthLast == -1) {
g_buffer.stateCore.update = true;
g_buffer.stateCore.flags.newMessage = true;
@@ -672,7 +674,7 @@ void updateCore() {
true,
std::chrono::system_clock::now(),
"",
ggWave->getRxProtocolId(),
ggWave->rxProtocolId(),
ggWave->isDSSEnabled(),
0,
Message::Error,
@@ -687,7 +689,7 @@ void updateCore() {
true,
std::chrono::system_clock::now(),
std::move(message),
ggWave->getRxProtocolId(),
ggWave->rxProtocolId(),
ggWave->isDSSEnabled(),
0,
type,
@@ -697,11 +699,11 @@ void updateCore() {
}
if (needSpectrum) {
if (ggWave->takeRxAmplitude(g_buffer.stateCore.rxAmplitude)) {
if (ggWave->rxTakeAmplitude(g_buffer.stateCore.rxAmplitude)) {
static const int NMax = GGWave::kMaxSamplesPerFrame;
static float tmp[2*NMax];
int N = ggWave->getSamplesPerFrame();
int N = ggWave->samplesPerFrame();
ggWave->computeFFTR(g_buffer.stateCore.rxAmplitude.data(), tmp, N);
g_buffer.stateCore.rxSpectrum.resize(N);
@@ -717,7 +719,7 @@ void updateCore() {
}
}
if (ggWave->takeTxAmplitudeI16(g_buffer.stateCore.txAmplitude)) {
if (ggWave->txTakeAmplitudeI16(g_buffer.stateCore.txAmplitude)) {
g_buffer.stateCore.update = true;
g_buffer.stateCore.flags.newTxAmplitude = true;
}
@@ -725,24 +727,24 @@ void updateCore() {
if (true) {
g_buffer.stateCore.update = true;
g_buffer.stateCore.flags.newStats = true;
g_buffer.stateCore.stats.isReceiving = ggWave->isReceiving();
g_buffer.stateCore.stats.isAnalyzing = ggWave->isAnalyzing();
g_buffer.stateCore.stats.framesToRecord = ggWave->getFramesToRecord();
g_buffer.stateCore.stats.framesLeftToRecord = ggWave->getFramesLeftToRecord();
g_buffer.stateCore.stats.framesToAnalyze = ggWave->getFramesToAnalyze();
g_buffer.stateCore.stats.framesLeftToAnalyze = ggWave->getFramesLeftToAnalyze();
g_buffer.stateCore.stats.samplesPerFrame = ggWave->getSamplesPerFrame();
g_buffer.stateCore.stats.sampleRateInp = ggWave->getSampleRateInp();
g_buffer.stateCore.stats.sampleRateOut = ggWave->getSampleRateOut();
g_buffer.stateCore.stats.sampleRate = GGWave::kDefaultSampleRate;
g_buffer.stateCore.stats.sampleSizeBytesInp = ggWave->getSampleSizeBytesInp();
g_buffer.stateCore.stats.sampleSizeBytesOut = ggWave->getSampleSizeBytesOut();
g_buffer.stateCore.stats.receiving = ggWave->rxReceiving();
g_buffer.stateCore.stats.analyzing = ggWave->rxAnalyzing();
g_buffer.stateCore.stats.framesToRecord = ggWave->rxFramesToRecord();
g_buffer.stateCore.stats.framesLeftToRecord = ggWave->rxFramesLeftToRecord();
g_buffer.stateCore.stats.framesToAnalyze = ggWave->rxFramesToAnalyze();
g_buffer.stateCore.stats.framesLeftToAnalyze = ggWave->rxFramesLeftToAnalyze();
g_buffer.stateCore.stats.samplesPerFrame = ggWave->samplesPerFrame();
g_buffer.stateCore.stats.sampleRateInp = ggWave->sampleRateInp();
g_buffer.stateCore.stats.sampleRateOut = ggWave->sampleRateOut();
g_buffer.stateCore.stats.sampleRate = GGWave::kDefaultSampleRate;
g_buffer.stateCore.stats.sampleSizeInp = ggWave->sampleSizeInp();
g_buffer.stateCore.stats.sampleSizeOut = ggWave->sampleSizeOut();
}
if (isFirstCall) {
g_buffer.stateCore.update = true;
g_buffer.stateCore.flags.newTxProtocols = true;
g_buffer.stateCore.txProtocols = ggWave->getTxProtocols();
g_buffer.stateCore.txProtocols = GGWave::Protocols::tx();
isFirstCall = false;
}
@@ -773,7 +775,7 @@ void renderMain() {
const auto & uri = fileInfo.second.uri;
auto & fileInfoExtended = g_receivedFileInfosExtended[uri];
if (fileInfoExtended.isReceiving == false) {
if (fileInfoExtended.receiving == false) {
continue;
}
@@ -835,7 +837,7 @@ void renderMain() {
};
struct Settings {
int protocolId = GGWAVE_TX_PROTOCOL_AUDIBLE_FAST;
int protocolId = GGWAVE_PROTOCOL_AUDIBLE_FAST;
bool isSampleRateOffset = false;
float sampleRateOffset = -512.0f;
bool isFixedLength = false;
@@ -882,8 +884,8 @@ void renderMain() {
static double tLengthTx = 0.0f;
static GGWaveStats statsCurrent;
static GGWave::SpectrumData spectrumCurrent;
static GGWave::AmplitudeDataI16 txAmplitudeDataCurrent;
static GGWave::Spectrum spectrumCurrent;
static GGWave::AmplitudeI16 txAmplitudeCurrent;
static std::vector<Message> messageHistory;
static std::string inputLast = "";
@@ -912,12 +914,12 @@ void renderMain() {
hasAudioCaptureData = !spectrumCurrent.empty();
}
if (stateCurrent.flags.newTxAmplitude) {
txAmplitudeDataCurrent = std::move(stateCurrent.txAmplitude);
txAmplitudeCurrent = std::move(stateCurrent.txAmplitude);
tStartTx = ImGui::GetTime() + (16.0f*1024.0f)/statsCurrent.sampleRateOut;
tLengthTx = txAmplitudeDataCurrent.size()/statsCurrent.sampleRateOut;
tLengthTx = txAmplitudeCurrent.size()/statsCurrent.sampleRateOut;
{
auto & ampl = txAmplitudeDataCurrent;
auto & ampl = txAmplitudeCurrent;
int nBins = 512;
int nspb = (int) ampl.size()/nBins;
for (int i = 0; i < nBins; ++i) {
@@ -1043,8 +1045,8 @@ void renderMain() {
ImGui::Separator();
ImGui::Text("%s", "");
ImGui::Text("Sample rate (capture): %g, %d B/sample", statsCurrent.sampleRateInp, statsCurrent.sampleSizeBytesInp);
ImGui::Text("Sample rate (playback): %g, %d B/sample", statsCurrent.sampleRateOut, statsCurrent.sampleSizeBytesOut);
ImGui::Text("Sample rate (capture): %g, %d B/sample", statsCurrent.sampleRateInp, statsCurrent.sampleSizeInp);
ImGui::Text("Sample rate (playback): %g, %d B/sample", statsCurrent.sampleRateOut, statsCurrent.sampleSizeOut);
const float kLabelWidth = ImGui::CalcTextSize("Inp. SR Offset: ").x;
@@ -1501,8 +1503,8 @@ void renderMain() {
}
ImGui::EndChild();
if (statsCurrent.isReceiving) {
if (statsCurrent.isAnalyzing) {
if (statsCurrent.receiving) {
if (statsCurrent.analyzing) {
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Analyzing ...");
ImGui::SameLine();
ImGui::ProgressBar(1.0f - float(statsCurrent.framesLeftToAnalyze)/statsCurrent.framesToAnalyze,
@@ -1525,7 +1527,7 @@ void renderMain() {
amax = 0.0f;
frac = (ImGui::GetTime() - tStartTx)/tLengthTx;
if (txAmplitudeDataCurrent.size() && frac <= 1.0f) {
if (txAmplitudeCurrent.size() && frac <= 1.0f) {
struct Funcs {
static float Sample(void * data, int i) {
auto res = std::fabs(((int16_t *)(data))[i]) ;
@@ -1534,7 +1536,7 @@ void renderMain() {
}
static float SampleFrac(void * data, int i) {
if (i > frac*txAmplitudeDataCurrent.size()) {
if (i > frac*txAmplitudeCurrent.size()) {
return 0.0f;
}
return std::fabs(((int16_t *)(data))[i]);
@@ -1550,8 +1552,8 @@ void renderMain() {
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled));
ImGui::PlotHistogram("##plotSpectrumCurrent",
Funcs::Sample,
txAmplitudeDataCurrent.data(),
(int) txAmplitudeDataCurrent.size(), 0,
txAmplitudeCurrent.data(),
(int) txAmplitudeCurrent.size(), 0,
(std::string("")).c_str(),
0.0f, FLT_MAX, wSize);
ImGui::PopStyleColor(2);
@@ -1562,8 +1564,8 @@ void renderMain() {
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, { 0.0f, 1.0f, 0.0f, 1.0f });
ImGui::PlotHistogram("##plotSpectrumCurrent",
Funcs::SampleFrac,
txAmplitudeDataCurrent.data(),
(int) txAmplitudeDataCurrent.size(), 0,
txAmplitudeCurrent.data(),
(int) txAmplitudeCurrent.size(), 0,
(std::string("")).c_str(),
0.0f, amax, wSize);
ImGui::PopStyleColor(2);
@@ -1835,14 +1837,14 @@ void renderMain() {
if (fileInfoExtended.readyToShare) {
ImGui::TextColored({ 0.0f, 1.0f, 0.0f, 1.0f }, "Ready to share!");
}
} else if (g_fileClient.isConnected() && (fileInfoExtended.isReceiving || fileInfoExtended.nReceivedChunks > 0)) {
if (fileInfoExtended.isReceiving) {
} else if (g_fileClient.isConnected() && (fileInfoExtended.receiving || fileInfoExtended.nReceivedChunks > 0)) {
if (fileInfoExtended.receiving) {
if (ImGui::Button(ICON_FA_PAUSE " Pause")) {
fileInfoExtended.isReceiving = false;
fileInfoExtended.receiving = false;
}
} else {
if (ImGui::Button(ICON_FA_PLAY " Resume")) {
fileInfoExtended.isReceiving = true;
fileInfoExtended.receiving = true;
}
}
@@ -1850,7 +1852,7 @@ void renderMain() {
ImGui::ProgressBar(float(fileInfoExtended.nReceivedChunks)/fileInfo.second.nChunks);
} else if (g_fileClient.isConnected()) {
if (ImGui::Button(ICON_FA_DOWNLOAD " Receive")) {
fileInfoExtended.isReceiving = true;
fileInfoExtended.receiving = true;
fileInfoExtended.isChunkReceived.resize(fileInfo.second.nChunks);
fileInfoExtended.isChunkRequested.resize(fileInfo.second.nChunks);
}
@@ -1858,7 +1860,7 @@ void renderMain() {
ImGui::Text("%s", "");
}
if ((fileInfoExtended.isReceiving == false || isReceived) && fileInfoExtended.requestToShare == false) {
if ((fileInfoExtended.receiving == false || isReceived) && fileInfoExtended.requestToShare == false) {
ImGui::SameLine();
if (ImGui::Button(ICON_FA_TRASH " Clear")) {
toErase = fileInfo.first;
@@ -2034,7 +2036,7 @@ void renderMain() {
}
auto wSize = ImGui::GetContentRegionAvail();
ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0.3f, 0.3f, 0.3f, 0.3f });
if (statsCurrent.isReceiving) {
if (statsCurrent.receiving) {
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, { 1.0f, 0.0f, 0.0f, 1.0f });
} else {
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, { 0.0f, 1.0f, 0.0f, 1.0f });