mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-04-01 10:46:53 +08:00
ggwave : various improvements
- faster FFT implementation - built-in Direct Sequence Spread option - remove <map> dependency from implementation - update arduino-rx example
This commit is contained in:
@@ -20,15 +20,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Direct-sequence spread magic numbers
|
||||
// Used to xor the actual payload
|
||||
const std::array<uint8_t, 64> kDSSMagic = {
|
||||
0x96, 0x9f, 0xb4, 0xaf, 0x1b, 0x91, 0xde, 0xc5, 0x45, 0x75, 0xe8, 0x2e, 0x0f, 0x32, 0x4a, 0x5f,
|
||||
0xb4, 0x56, 0x95, 0xcb, 0x7f, 0x6a, 0x54, 0x6a, 0x48, 0xf2, 0x0b, 0x7b, 0xcd, 0xfb, 0x93, 0x6d,
|
||||
0x3c, 0x77, 0x5e, 0xc3, 0x33, 0x47, 0xc0, 0xf1, 0x71, 0x32, 0x33, 0x27, 0x35, 0x68, 0x47, 0x1f,
|
||||
0x4e, 0xac, 0x23, 0x42, 0x5f, 0x00, 0x37, 0xa4, 0x50, 0x6d, 0x48, 0x24, 0x91, 0x7c, 0xa1, 0x4e,
|
||||
};
|
||||
|
||||
std::string g_defaultCaptureDeviceName = "";
|
||||
|
||||
SDL_AudioDeviceID g_devIdInp = 0;
|
||||
@@ -99,7 +90,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;
|
||||
@@ -235,6 +227,9 @@ bool GGWave_init(
|
||||
if (reinit) {
|
||||
if (g_ggWave) delete g_ggWave;
|
||||
|
||||
ggwave_OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
|
||||
if (useDSS) mode = ggwave_OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
|
||||
|
||||
g_ggWave = new GGWave({
|
||||
payloadLength,
|
||||
(float) g_obtainedSpecInp.freq,
|
||||
@@ -244,7 +239,7 @@ bool GGWave_init(
|
||||
GGWave::kDefaultSoundMarkerThreshold,
|
||||
sampleFormatInp,
|
||||
sampleFormatOut,
|
||||
GGWAVE_OPERATING_MODE_RX_AND_TX,
|
||||
mode,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -278,9 +273,6 @@ bool GGWave_mainLoop() {
|
||||
GGWave::TxRxData rxData;
|
||||
int n = g_ggWave->takeRxData(rxData);
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
rxData[i] ^= kDSSMagic[i%kDSSMagic.size()];
|
||||
}
|
||||
std::time_t timestamp = std::time(nullptr);
|
||||
std::string tstr = std::asctime(std::localtime(×tamp));
|
||||
tstr.back() = 0;
|
||||
@@ -359,7 +351,7 @@ int main(int argc, char** argv) {
|
||||
bool isInitialized = false;
|
||||
|
||||
g_doInit = [&]() {
|
||||
if (GGWave_init(0, captureId, payloadLength, 0) == false) {
|
||||
if (GGWave_init(0, captureId, payloadLength, 0, true) == false) {
|
||||
fprintf(stderr, "Failed to initialize GGWave\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -73,13 +73,6 @@
|
||||
|
||||
const kPayloadLength = 16;
|
||||
|
||||
var kDSSMagic = [
|
||||
0x96, 0x9f, 0xb4, 0xaf, 0x1b, 0x91, 0xde, 0xc5, 0x45, 0x75, 0xe8, 0x2e, 0x0f, 0x32, 0x4a, 0x5f,
|
||||
0xb4, 0x56, 0x95, 0xcb, 0x7f, 0x6a, 0x54, 0x6a, 0x48, 0xf2, 0x0b, 0x7b, 0xcd, 0xfb, 0x93, 0x6d,
|
||||
0x3c, 0x77, 0x5e, 0xc3, 0x33, 0x47, 0xc0, 0xf1, 0x71, 0x32, 0x33, 0x27, 0x35, 0x68, 0x47, 0x1f,
|
||||
0x4e, 0xac, 0x23, 0x42, 0x5f, 0x00, 0x37, 0xa4, 0x50, 0x6d, 0x48, 0x24, 0x91, 0x7c, 0xa1, 0x4e,
|
||||
];
|
||||
|
||||
// instantiate the ggwave instance
|
||||
// ggwave_factory comes from the ggwave.js module
|
||||
ggwave_factory().then(function(obj) {
|
||||
@@ -127,9 +120,6 @@
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
payload[i] = text.charCodeAt(i);
|
||||
}
|
||||
for (var i = 0; i < kPayloadLength; i++) {
|
||||
payload[i] = payload[i] ^ kDSSMagic[i];
|
||||
}
|
||||
|
||||
// generate audio waveform
|
||||
var waveform = ggwave.encode(instance, payload, ggwave.TxProtocolId.GGWAVE_TX_PROTOCOL_MT_FASTEST, 25)
|
||||
@@ -187,7 +177,6 @@
|
||||
var payload = "";
|
||||
res8 = convertTypedArray(res, Uint8Array);
|
||||
for (var i = 0; i < kPayloadLength; i++) {
|
||||
res8[i] = res8[i] ^ kDSSMagic[i];
|
||||
payload += String.fromCharCode(res8[i]);
|
||||
if (res8[i] == 0) {
|
||||
break;
|
||||
|
||||
1
examples/arduino-rx/.gitignore
vendored
1
examples/arduino-rx/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
ggwave
|
||||
ggwave.cpp
|
||||
fft.h
|
||||
resampler.h
|
||||
resampler.cpp
|
||||
reed-solomon
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#
|
||||
# arduino-rx
|
||||
|
||||
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)
|
||||
|
||||
@@ -49,51 +49,53 @@ void loop() {
|
||||
|
||||
auto p = GGWave::getDefaultParameters();
|
||||
p.sampleRateInp = frequency;
|
||||
p.sampleRateOut = frequency;
|
||||
p.sampleRate = frequency;
|
||||
p.sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16;
|
||||
p.samplesPerFrame = 128;
|
||||
p.payloadLength = 16;
|
||||
p.operatingMode = (ggwave_OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_TX_ONLY_TONES);
|
||||
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 ggwave(p);
|
||||
ggwave.setRxProtocols({
|
||||
//{ GGWAVE_TX_PROTOCOL_MT_FASTEST, ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_MT_FASTEST) },
|
||||
{ GGWAVE_TX_PROTOCOL_DT_FASTEST, ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_DT_FASTEST) },
|
||||
//ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_MT_FASTEST),
|
||||
ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_DT_FASTEST),
|
||||
});
|
||||
|
||||
Serial.println("Instance initialized");
|
||||
|
||||
static GGWave::CBWaveformInp cbWaveformInp = [&](void * data, uint32_t nMaxBytes) {
|
||||
const int nSamples = nMaxBytes/kSampleSize_bytes;
|
||||
if (qsize < nSamples) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
qsize -= nSamples;
|
||||
|
||||
TSample * pDst = (TSample *)(data);
|
||||
TSample * pSrc = (TSample *)(sampleBuffer + qhead);
|
||||
|
||||
if (qhead + nSamples > qmax) {
|
||||
// should never happen but just in case
|
||||
memcpy(pDst, pSrc, (qmax - qhead)*kSampleSize_bytes);
|
||||
memcpy(pDst + (qmax - qhead), sampleBuffer, (nSamples - (qmax - qhead))*kSampleSize_bytes);
|
||||
qhead += nSamples - qmax;
|
||||
} else {
|
||||
memcpy(pDst, pSrc, nSamples*kSampleSize_bytes);
|
||||
qhead += nSamples;
|
||||
}
|
||||
|
||||
return nSamples*kSampleSize_bytes;
|
||||
};
|
||||
|
||||
int nr = 0;
|
||||
int niter = 0;
|
||||
|
||||
GGWave::TxRxData result;
|
||||
while (true) {
|
||||
if (qsize >= 128) {
|
||||
while (qsize >= p.samplesPerFrame) {
|
||||
auto tStart = millis();
|
||||
|
||||
ggwave.decode(cbWaveformInp);
|
||||
//Serial.print(qhead);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(qtail);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(qsize);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(ggwave.getSamplesNeeded());
|
||||
//Serial.println("");
|
||||
|
||||
ggwave.decode(sampleBuffer + qhead, p.samplesPerFrame*kSampleSize_bytes);
|
||||
qsize -= p.samplesPerFrame;
|
||||
qhead += p.samplesPerFrame;
|
||||
if (qhead >= qmax) {
|
||||
qhead = 0;
|
||||
}
|
||||
|
||||
auto tEnd = millis();
|
||||
if (++niter % 10 == 0) {
|
||||
@@ -108,17 +110,17 @@ void loop() {
|
||||
|
||||
if (strcmp((char *)result.data(), "test") == 0) {
|
||||
ggwave.init("hello", ggwave.getTxProtocol(GGWAVE_TX_PROTOCOL_MT_FASTEST));
|
||||
ggwave.encode(nullptr);
|
||||
ggwave.encode();
|
||||
|
||||
const auto & waveformTones = ggwave.getWaveformTones();
|
||||
for (int i = 0; i < (int) waveformTones.size(); ++i) {
|
||||
const auto & tones = ggwave.txTones();
|
||||
for (int i = 0; i < (int) tones.size(); ++i) {
|
||||
Serial.print(" - frame ");
|
||||
Serial.print(i);
|
||||
Serial.print(", ");
|
||||
Serial.print(waveformTones[i].size());
|
||||
Serial.print(tones[i].size());
|
||||
Serial.print(": ");
|
||||
for (int j = 0; j < (int) waveformTones[i].size(); ++j) {
|
||||
Serial.print((int)(waveformTones[i][j].freq_hz));
|
||||
for (int j = 0; j < (int) tones[i].size(); ++j) {
|
||||
Serial.print((int)(tones[i][j].freq_hz));
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
@@ -54,13 +54,6 @@
|
||||
|
||||
const kPayloadLength = 3;
|
||||
|
||||
var kDSSMagic = [
|
||||
0x96, 0x9f, 0xb4, 0xaf, 0x1b, 0x91, 0xde, 0xc5, 0x45, 0x75, 0xe8, 0x2e, 0x0f, 0x32, 0x4a, 0x5f,
|
||||
0xb4, 0x56, 0x95, 0xcb, 0x7f, 0x6a, 0x54, 0x6a, 0x48, 0xf2, 0x0b, 0x7b, 0xcd, 0xfb, 0x93, 0x6d,
|
||||
0x3c, 0x77, 0x5e, 0xc3, 0x33, 0x47, 0xc0, 0xf1, 0x71, 0x32, 0x33, 0x27, 0x35, 0x68, 0x47, 0x1f,
|
||||
0x4e, 0xac, 0x23, 0x42, 0x5f, 0x00, 0x37, 0xa4, 0x50, 0x6d, 0x48, 0x24, 0x91, 0x7c, 0xa1, 0x4e,
|
||||
];
|
||||
|
||||
// instantiate the ggwave instance
|
||||
// ggwave_factory comes from the ggwave.js module
|
||||
ggwave_factory().then(function(obj) {
|
||||
@@ -93,12 +86,14 @@
|
||||
parameters.payloadLength = kPayloadLength;
|
||||
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);
|
||||
|
||||
parameters = ggwave_FluentPet.getDefaultParameters();
|
||||
parameters.payloadLength = kPayloadLength;
|
||||
parameters.sampleRateInp = context.sampleRate;
|
||||
parameters.sampleRateOut = context.sampleRate - 512;
|
||||
parameters.operatingMode = GGWAVE_OPERATING_MODE_RX_AND_TX | GGWAVE_OPERATING_MODE_USE_DSS;
|
||||
instance = ggwave_FluentPet.init(parameters);
|
||||
}
|
||||
}
|
||||
@@ -110,10 +105,9 @@
|
||||
function onSend(text) {
|
||||
init();
|
||||
|
||||
// DSS : xor the text with the magic numbers
|
||||
var payload = new Uint8Array(text.length);
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
payload[i] = text.charCodeAt(i) ^ kDSSMagic[i];
|
||||
payload[i] = text.charCodeAt(i);
|
||||
}
|
||||
|
||||
// generate audio waveform
|
||||
@@ -177,7 +171,7 @@
|
||||
var payload = "";
|
||||
res8 = convertTypedArray(res, Uint8Array);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
payload += String.fromCharCode(res8[i] ^ kDSSMagic[i]);
|
||||
payload += String.fromCharCode(res8[i]);
|
||||
}
|
||||
|
||||
if (payload == 'RRR' || payload == 'GGG' || payload == 'BBB') {
|
||||
|
||||
@@ -18,17 +18,19 @@ int main(int argc, char** argv) {
|
||||
printf(" -pN - select playback device N\n");
|
||||
printf(" -tN - transmission protocol\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(" -v - print generated tones on resend\n");
|
||||
printf("\n");
|
||||
|
||||
auto argm = parseCmdArguments(argc, argv);
|
||||
int captureId = argm["c"].empty() ? 0 : std::stoi(argm["c"]);
|
||||
int playbackId = argm["p"].empty() ? 0 : std::stoi(argm["p"]);
|
||||
int txProtocolId = argm["t"].empty() ? 1 : std::stoi(argm["t"]);
|
||||
int payloadLength = argm["l"].empty() ? -1 : std::stoi(argm["l"]);
|
||||
bool printTones = argm.find("v") == argm.end() ? false : true;
|
||||
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;
|
||||
|
||||
if (GGWave_init(playbackId, captureId, payloadLength) == false) {
|
||||
if (GGWave_init(playbackId, captureId, payloadLength, 0.0f, useDSS) == false) {
|
||||
fprintf(stderr, "Failed to initialize GGWave\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -39,6 +41,9 @@ int main(int argc, char** argv) {
|
||||
const auto & protocols = GGWave::getTxProtocols();
|
||||
for (int i = 0; i < (int) protocols.size(); ++i) {
|
||||
const auto & protocol = protocols[i];
|
||||
if (protocol.enabled == false) {
|
||||
continue;
|
||||
}
|
||||
printf(" %d - %s\n", i, protocol.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,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;
|
||||
@@ -213,6 +214,9 @@ bool GGWave_init(
|
||||
}
|
||||
|
||||
if (reinit) {
|
||||
ggwave_OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
|
||||
if (useDSS) mode = ggwave_OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
|
||||
|
||||
g_ggWave = std::make_shared<GGWave>(GGWave::Parameters {
|
||||
payloadLength,
|
||||
(float) g_obtainedSpecInp.freq,
|
||||
@@ -222,7 +226,7 @@ bool GGWave_init(
|
||||
GGWave::kDefaultSoundMarkerThreshold,
|
||||
sampleFormatInp,
|
||||
sampleFormatOut,
|
||||
(GGWave::OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX),
|
||||
mode,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class GGWave;
|
||||
// GGWave helpers
|
||||
|
||||
void GGWave_setDefaultCaptureDeviceName(std::string name);
|
||||
bool GGWave_init(const int playbackId, const int captureId, const int payloadLength = -1, const float sampleRateOffset = 0);
|
||||
bool GGWave_init(const int playbackId, const int captureId, const int payloadLength = -1, const float sampleRateOffset = 0, const bool useDSS = false);
|
||||
std::shared_ptr<GGWave> GGWave_instance();
|
||||
void GGWave_reset(void * parameters);
|
||||
bool GGWave_mainLoop();
|
||||
|
||||
@@ -36,15 +36,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Direct-sequence spread magic numbers
|
||||
// Used to xor the actual payload
|
||||
const std::array<uint8_t, 64> kDSSMagic = {
|
||||
0x96, 0x9f, 0xb4, 0xaf, 0x1b, 0x91, 0xde, 0xc5, 0x45, 0x75, 0xe8, 0x2e, 0x0f, 0x32, 0x4a, 0x5f,
|
||||
0xb4, 0x56, 0x95, 0xcb, 0x7f, 0x6a, 0x54, 0x6a, 0x48, 0xf2, 0x0b, 0x7b, 0xcd, 0xfb, 0x93, 0x6d,
|
||||
0x3c, 0x77, 0x5e, 0xc3, 0x33, 0x47, 0xc0, 0xf1, 0x71, 0x32, 0x33, 0x27, 0x35, 0x68, 0x47, 0x1f,
|
||||
0x4e, 0xac, 0x23, 0x42, 0x5f, 0x00, 0x37, 0xa4, 0x50, 0x6d, 0x48, 0x24, 0x91, 0x7c, 0xa1, 0x4e,
|
||||
};
|
||||
|
||||
std::mutex g_mutex;
|
||||
char * toTimeString(const std::chrono::system_clock::time_point & tp) {
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
@@ -139,6 +130,7 @@ struct Message {
|
||||
std::chrono::system_clock::time_point timestamp;
|
||||
std::string data;
|
||||
int protocolId;
|
||||
bool dss;
|
||||
float volume;
|
||||
Type type;
|
||||
};
|
||||
@@ -225,7 +217,6 @@ struct Input {
|
||||
bool changeNeedSpectrum = false;
|
||||
bool stopReceiving = false;
|
||||
bool changeRxProtocols = false;
|
||||
bool changeDSS = false;
|
||||
|
||||
void clear() { memset(this, 0, sizeof(Flags)); }
|
||||
} flags;
|
||||
@@ -244,6 +235,7 @@ struct Input {
|
||||
dst.flags.needReinit = true;
|
||||
dst.sampleRateOffset = std::move(this->sampleRateOffset);
|
||||
dst.payloadLength = std::move(this->payloadLength);
|
||||
dst.directSequenceSpread = std::move(this->directSequenceSpread);
|
||||
}
|
||||
|
||||
if (this->flags.changeNeedSpectrum) {
|
||||
@@ -263,12 +255,6 @@ struct Input {
|
||||
dst.rxProtocols = std::move(this->rxProtocols);
|
||||
}
|
||||
|
||||
if (this->flags.changeDSS) {
|
||||
dst.update = true;
|
||||
dst.flags.changeDSS = true;
|
||||
dst.directSequenceSpread = std::move(this->directSequenceSpread);
|
||||
}
|
||||
|
||||
flags.clear();
|
||||
update = false;
|
||||
}
|
||||
@@ -608,7 +594,6 @@ void updateCore() {
|
||||
|
||||
static bool isFirstCall = true;
|
||||
static bool needSpectrum = false;
|
||||
static bool directSequenceSpread = false;
|
||||
static int rxDataLengthLast = 0;
|
||||
static float rxTimestampLast = 0.0f;
|
||||
static GGWave::TxRxData rxDataLast;
|
||||
@@ -627,12 +612,6 @@ void updateCore() {
|
||||
if (inputCurrent.flags.newMessage) {
|
||||
int n = (int) inputCurrent.message.data.size();
|
||||
|
||||
if (directSequenceSpread) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
inputCurrent.message.data[i] ^= kDSSMagic[i%kDSSMagic.size()];
|
||||
}
|
||||
}
|
||||
|
||||
ggWave->init(
|
||||
n, inputCurrent.message.data.data(),
|
||||
ggWave->getTxProtocol(inputCurrent.message.protocolId),
|
||||
@@ -646,6 +625,9 @@ void updateCore() {
|
||||
GGWave::SampleFormat sampleFormatOutOld = ggWave->getSampleFormatOut();
|
||||
auto rxProtocolsOld = ggWave->getRxProtocols();
|
||||
|
||||
GGWave::OperatingMode mode = GGWAVE_OPERATING_MODE_RX_AND_TX;
|
||||
if (inputCurrent.directSequenceSpread) mode = GGWave::OperatingMode(mode | GGWAVE_OPERATING_MODE_USE_DSS);
|
||||
|
||||
GGWave::Parameters parameters {
|
||||
inputCurrent.payloadLength,
|
||||
sampleRateInpOld,
|
||||
@@ -655,7 +637,7 @@ void updateCore() {
|
||||
GGWave::kDefaultSoundMarkerThreshold,
|
||||
sampleFormatInpOld,
|
||||
sampleFormatOutOld,
|
||||
(GGWave::OperatingMode) (GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_TX),
|
||||
mode,
|
||||
};
|
||||
|
||||
GGWave_reset(¶meters);
|
||||
@@ -676,10 +658,6 @@ void updateCore() {
|
||||
ggWave->setRxProtocols(inputCurrent.rxProtocols);
|
||||
}
|
||||
|
||||
if (inputCurrent.flags.changeDSS) {
|
||||
directSequenceSpread = inputCurrent.directSequenceSpread;
|
||||
}
|
||||
|
||||
inputCurrent.flags.clear();
|
||||
inputCurrent.update = false;
|
||||
}
|
||||
@@ -695,18 +673,13 @@ void updateCore() {
|
||||
std::chrono::system_clock::now(),
|
||||
"",
|
||||
ggWave->getRxProtocolId(),
|
||||
ggWave->isDSSEnabled(),
|
||||
0,
|
||||
Message::Error,
|
||||
};
|
||||
} else if (rxDataLengthLast > 0 && ImGui::GetTime() - rxTimestampLast > 0.5f) {
|
||||
auto message = std::string((char *) rxDataLast.data(), rxDataLengthLast);
|
||||
|
||||
if (directSequenceSpread) {
|
||||
for (int i = 0; i < rxDataLengthLast; ++i) {
|
||||
message[i] ^= kDSSMagic[i%kDSSMagic.size()];
|
||||
}
|
||||
}
|
||||
|
||||
const Message::Type type = isFileBroadcastMessage(message) ? Message::FileBroadcast : Message::Text;
|
||||
g_buffer.stateCore.update = true;
|
||||
g_buffer.stateCore.flags.newMessage = true;
|
||||
@@ -715,6 +688,7 @@ void updateCore() {
|
||||
std::chrono::system_clock::now(),
|
||||
std::move(message),
|
||||
ggWave->getRxProtocolId(),
|
||||
ggWave->isDSSEnabled(),
|
||||
0,
|
||||
type,
|
||||
};
|
||||
@@ -728,7 +702,7 @@ void updateCore() {
|
||||
static float tmp[2*NMax];
|
||||
|
||||
int N = ggWave->getSamplesPerFrame();
|
||||
ggWave->computeFFTR(g_buffer.stateCore.rxAmplitude.data(), tmp, N, 1.0);
|
||||
ggWave->computeFFTR(g_buffer.stateCore.rxAmplitude.data(), tmp, N);
|
||||
|
||||
g_buffer.stateCore.rxSpectrum.resize(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
@@ -1264,7 +1238,7 @@ void renderMain() {
|
||||
}
|
||||
if (ImGui::Checkbox("##direct-sequence-spread", &settings.directSequenceSpread)) {
|
||||
g_buffer.inputUI.update = true;
|
||||
g_buffer.inputUI.flags.changeDSS = true;
|
||||
g_buffer.inputUI.flags.needReinit = true;
|
||||
g_buffer.inputUI.directSequenceSpread = settings.directSequenceSpread;
|
||||
}
|
||||
|
||||
@@ -1375,6 +1349,13 @@ void renderMain() {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored({ 0.0f, 0.6f, 0.4f, interp }, "%s", settings.txProtocols.at(GGWave::TxProtocolId(message.protocolId)).name);
|
||||
ImGui::SameLine();
|
||||
if (message.dss) {
|
||||
ImGui::TextColored({ 0.4f, 0.6f, 0.4f, interp }, "DSS");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Direct Sequence Spread");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::TextDisabled("|");
|
||||
|
||||
{
|
||||
@@ -1449,7 +1430,7 @@ void renderMain() {
|
||||
if (ImGui::ButtonDisablable("Resend", {}, messageSelected.type != Message::Text)) {
|
||||
g_buffer.inputUI.update = true;
|
||||
g_buffer.inputUI.flags.newMessage = true;
|
||||
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), messageSelected.data, messageSelected.protocolId, settings.volume, Message::Text };
|
||||
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), messageSelected.data, messageSelected.protocolId, messageSelected.dss, settings.volume, Message::Text };
|
||||
|
||||
messageHistory.push_back(g_buffer.inputUI.message);
|
||||
ImGui::CloseCurrentPopup();
|
||||
@@ -1671,7 +1652,7 @@ void renderMain() {
|
||||
inputLast = std::string(inputBuf);
|
||||
g_buffer.inputUI.update = true;
|
||||
g_buffer.inputUI.flags.newMessage = true;
|
||||
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), std::string(inputBuf), settings.protocolId, settings.volume, Message::Text };
|
||||
g_buffer.inputUI.message = { false, std::chrono::system_clock::now(), std::string(inputBuf), settings.protocolId, settings.directSequenceSpread, settings.volume, Message::Text };
|
||||
|
||||
messageHistory.push_back(g_buffer.inputUI.message);
|
||||
|
||||
@@ -1798,6 +1779,7 @@ void renderMain() {
|
||||
std::chrono::system_clock::now(),
|
||||
::generateFileBroadcastMessage(),
|
||||
settings.protocolId,
|
||||
settings.directSequenceSpread,
|
||||
settings.volume,
|
||||
Message::FileBroadcast
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user