mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-03-27 14:29:00 +08:00
c, python : add option to query encode size
This commit is contained in:
@@ -37,7 +37,8 @@ cdef extern from "ggwave.h" nogil:
|
||||
int dataSize,
|
||||
ggwave_TxProtocolId txProtocolId,
|
||||
int volume,
|
||||
char * outputBuffer);
|
||||
char * outputBuffer,
|
||||
int query);
|
||||
|
||||
int ggwave_decode(
|
||||
ggwave_Instance instance,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cimport cython
|
||||
|
||||
from cpython.mem cimport PyMem_Malloc, PyMem_Free
|
||||
|
||||
import re
|
||||
@@ -27,22 +28,21 @@ def encode(payload, txProtocolId = 1, volume = 10, instance = None):
|
||||
cdef bytes data_bytes = payload.encode()
|
||||
cdef char* cdata = data_bytes
|
||||
|
||||
cdef bytes output_bytes = bytes(1024*1024)
|
||||
cdef char* coutput = output_bytes
|
||||
|
||||
own = False
|
||||
if (instance is None):
|
||||
own = True
|
||||
instance = init(getDefaultParameters())
|
||||
|
||||
n = cggwave.ggwave_encode(instance, cdata, len(data_bytes), txProtocolId, volume, coutput)
|
||||
n = cggwave.ggwave_encode(instance, cdata, len(data_bytes), txProtocolId, volume, NULL, 1)
|
||||
|
||||
cdef bytes output_bytes = bytes(n)
|
||||
cdef char* coutput = output_bytes
|
||||
|
||||
n = cggwave.ggwave_encode(instance, cdata, len(data_bytes), txProtocolId, volume, coutput, 0)
|
||||
|
||||
if (own):
|
||||
free(instance)
|
||||
|
||||
# add short silence at the end
|
||||
n += 16*1024
|
||||
|
||||
return struct.unpack("h"*n, output_bytes[0:2*n])
|
||||
|
||||
def decode(instance, waveform):
|
||||
|
||||
@@ -3,9 +3,9 @@ import ggwave
|
||||
|
||||
testFailed = False
|
||||
|
||||
n, samples = ggwave.encode("hello python")
|
||||
samples = ggwave.encode("hello python")
|
||||
|
||||
if not (samples and n > 1024):
|
||||
if not (samples):
|
||||
testFailed = True
|
||||
|
||||
if testFailed:
|
||||
|
||||
@@ -192,8 +192,8 @@ bool GGWave_init(
|
||||
GGWave::SampleFormat sampleFormatOut = GGWAVE_SAMPLE_FORMAT_UNDEFINED;
|
||||
|
||||
switch (g_obtainedSpecInp.format) {
|
||||
case AUDIO_U8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_U8; break;
|
||||
case AUDIO_S8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I8; break;
|
||||
case AUDIO_U8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_U8; break;
|
||||
case AUDIO_S8: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I8; break;
|
||||
case AUDIO_U16SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_U16; break;
|
||||
case AUDIO_S16SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_I16; break;
|
||||
case AUDIO_S32SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_F32; break;
|
||||
@@ -201,8 +201,8 @@ bool GGWave_init(
|
||||
}
|
||||
|
||||
switch (g_obtainedSpecOut.format) {
|
||||
case AUDIO_U8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8; break;
|
||||
case AUDIO_S8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I8; break;
|
||||
case AUDIO_U8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U8; break;
|
||||
case AUDIO_S8: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I8; break;
|
||||
case AUDIO_U16SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_U16; break;
|
||||
case AUDIO_S16SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_I16; break;
|
||||
case AUDIO_S32SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_F32; break;
|
||||
|
||||
@@ -10,6 +10,7 @@ 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)
|
||||
stream.write(np.array(waveform).astype(np.int16), len(waveform))
|
||||
stream.write(np.zeros(16*1024), 16*1024) # short silence at the end
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
|
||||
|
||||
@@ -73,8 +73,11 @@ extern "C" {
|
||||
// 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
|
||||
// query - if != 0, do not perform encoding.
|
||||
// if == 1, return waveform size in bytes
|
||||
// if != 1, return waveform size in samples
|
||||
//
|
||||
// returns the number of generated samples
|
||||
// returns the number of generated bytes or samples (see query)
|
||||
//
|
||||
// returns -1 if there was an error
|
||||
//
|
||||
@@ -87,7 +90,8 @@ extern "C" {
|
||||
int dataSize,
|
||||
ggwave_TxProtocolId txProtocolId,
|
||||
int volume,
|
||||
char * outputBuffer);
|
||||
char * outputBuffer,
|
||||
int query);
|
||||
|
||||
// Decode an audio waveform into data
|
||||
// instance - the GGWave instance to use
|
||||
@@ -182,24 +186,39 @@ public:
|
||||
static const Parameters & getDefaultParameters();
|
||||
|
||||
// set Tx data to encode
|
||||
//
|
||||
// This prepares the GGWave instance for transmission.
|
||||
// To perform the actual encoding, the encode() method must be called
|
||||
//
|
||||
// returns false upon invalid parameters or failure to initialize
|
||||
//
|
||||
bool init(const std::string & text, const int volume = kDefaultVolume);
|
||||
bool init(const std::string & text, const TxProtocol & txProtocol, const int volume = kDefaultVolume);
|
||||
bool init(int dataSize, const char * dataBuffer, const int volume = kDefaultVolume);
|
||||
bool init(int dataSize, const char * dataBuffer, const TxProtocol & txProtocol, const int volume = kDefaultVolume);
|
||||
|
||||
// expected waveform size of the encoded Tx data
|
||||
// expected waveform size of the encoded Tx data in bytes
|
||||
uint32_t encodeSize_bytes() const;
|
||||
|
||||
// expected waveform size of the encoded Tx data in samples
|
||||
uint32_t encodeSize_samples() const;
|
||||
|
||||
// encode Tx data into an audio waveform
|
||||
//
|
||||
// The generated waveform is returned by calling the cbWaveformOut callback.
|
||||
//
|
||||
// returns false if the encoding fails
|
||||
//
|
||||
bool encode(const CBWaveformOut & cbWaveformOut);
|
||||
|
||||
// decode an audio waveform
|
||||
//
|
||||
// This methods calls cbWaveformInp multiple times (at least once) until it returns 0.
|
||||
// Use the Rx methods to check if any data was decoded successfully.
|
||||
//
|
||||
void decode(const CBWaveformInp & cbWaveformInp);
|
||||
|
||||
// instance state
|
||||
const bool & hasTxData() const { return m_hasNewTxData; }
|
||||
const bool & isReceiving() const { return m_receivingData; }
|
||||
const bool & isAnalyzing() const { return m_analyzingData; }
|
||||
@@ -215,17 +234,22 @@ public:
|
||||
const float & getSampleRateInp() const { return m_sampleRateInp; }
|
||||
const float & getSampleRateOut() const { return m_sampleRateOut; }
|
||||
|
||||
// Tx
|
||||
|
||||
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); }
|
||||
|
||||
int takeTxAmplitudeDataI16(AmplitudeDataI16 & dst);
|
||||
|
||||
// Rx
|
||||
|
||||
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 takeTxAmplitudeDataI16(AmplitudeDataI16 & dst);
|
||||
bool takeSpectrum(SpectrumData & dst);
|
||||
|
||||
private:
|
||||
|
||||
@@ -49,7 +49,8 @@ int ggwave_encode(
|
||||
int dataSize,
|
||||
ggwave_TxProtocolId txProtocolId,
|
||||
int volume,
|
||||
char * outputBuffer) {
|
||||
char * outputBuffer,
|
||||
int query) {
|
||||
GGWave * ggWave = (GGWave *) g_instances[instance];
|
||||
|
||||
if (ggWave == nullptr) {
|
||||
@@ -62,6 +63,14 @@ int ggwave_encode(
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (query != 0) {
|
||||
if (query == 1) {
|
||||
return ggWave->encodeSize_bytes();
|
||||
}
|
||||
|
||||
return ggWave->encodeSize_samples();
|
||||
}
|
||||
|
||||
int nSamples = 0;
|
||||
|
||||
GGWave::CBWaveformOut cbWaveformOut = [&](const void * data, uint32_t nBytes) {
|
||||
|
||||
@@ -21,11 +21,13 @@ int main() {
|
||||
ggwave_Instance instance = ggwave_init(parameters);
|
||||
|
||||
int ret;
|
||||
char waveform[1024*1024];
|
||||
const char * payload = "test";
|
||||
char decoded[256];
|
||||
|
||||
ret = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 50, waveform);
|
||||
int n = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 50, NULL, 1);
|
||||
char waveform[n];
|
||||
|
||||
ret = ggwave_encode(instance, payload, 4, GGWAVE_TX_PROTOCOL_AUDIBLE_FAST, 50, waveform, 0);
|
||||
CHECK(ret > 0);
|
||||
|
||||
ret = ggwave_decode(instance, waveform, sizeof(int16_t)*ret, decoded);
|
||||
|
||||
Reference in New Issue
Block a user