mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-02-07 01:11:22 +08:00
ggwave : refactoring + comments
This commit is contained in:
4
bindings/python/.gitignore
vendored
4
bindings/python/.gitignore
vendored
@@ -1 +1,5 @@
|
||||
ggwave.so
|
||||
README.rst
|
||||
ggwave.bycython.cpp
|
||||
ggwave.cpython-36m-x86_64-linux-gnu.so
|
||||
ggwave/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<std::mutex> lock(mutex);
|
||||
ggWave->init(input.size(), input.data(), ggWave->getTxProtocols()[txProtocol], 10);
|
||||
ggWave->init(input.size(), input.data(), ggWave->getTxProtocol(txProtocol), 10);
|
||||
}
|
||||
inputOld = input;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<char> 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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 <cstdint>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
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<TxProtocol>;
|
||||
using TxProtocols = std::map<TxProtocolId, TxProtocol>;
|
||||
|
||||
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<float>;
|
||||
using TxRxData = std::vector<std::uint8_t>;
|
||||
|
||||
// todo : rename to CBEnqueueAudio
|
||||
using CBQueueAudio = std::function<void(const void * data, uint32_t nBytes)>;
|
||||
using CBEnqueueAudio = std::function<void(const void * data, uint32_t nBytes)>;
|
||||
using CBDequeueAudio = std::function<uint32_t(void * data, uint32_t nMaxBytes)>;
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user