ggwave : switch to floating point sampling rate

This commit is contained in:
Georgi Gerganov
2021-02-27 12:23:25 +02:00
parent 5b5293d764
commit 1c59e38696
10 changed files with 35 additions and 61 deletions

View File

@@ -45,7 +45,7 @@ extern "C" {
}
EMSCRIPTEN_KEEPALIVE
int getSampleRate() { return g_ggWave->getSampleRateInp(); }
float getSampleRate() { return g_ggWave->getSampleRateInp(); }
EMSCRIPTEN_KEEPALIVE
int getFramesToRecord() { return g_ggWave->getFramesToRecord(); }
@@ -79,7 +79,7 @@ bool GGWave_init(
const int playbackId,
const int captureId,
const int payloadLength,
const int sampleRateOffset) {
const float sampleRateOffset) {
if (g_devIdInp && g_devIdOut) {
return false;
@@ -217,8 +217,8 @@ bool GGWave_init(
g_ggWave = new GGWave({
payloadLength,
g_obtainedSpecInp.freq,
g_obtainedSpecOut.freq,
(float) g_obtainedSpecInp.freq,
(float) g_obtainedSpecOut.freq,
GGWave::kDefaultSamplesPerFrame,
GGWave::kDefaultSoundMarkerThreshold,
sampleFormatInp,

View File

@@ -7,7 +7,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 int sampleRateOffset = 0);
bool GGWave_init(const int playbackId, const int captureId, const int payloadLength = -1, const float sampleRateOffset = 0);
GGWave *& GGWave_instance();
bool GGWave_mainLoop();
bool GGWave_deinit();

View File

@@ -5,7 +5,7 @@ Output a generated waveform to an uncompressed WAV file.
```
Usage: ./bin/ggwave-to-file [-vN] [-sN] [-pN]
-vN - output volume, N in (0, 100], (default: 50)
-sN - output sample rate, N in [1024, 48000], (default: 48000)
-sN - output sample rate, N in [6000, 96000], (default: 48000)
-pN - select the transmission protocol (default: 1)
Available protocols:
@@ -59,11 +59,11 @@ curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello world!&p=4' --output hel
### browser
- Audible example
https://ggwave-to-file.ggerganov.com/?m=Hello%20world%21
- Ultrasound example
https://ggwave-to-file.ggerganov.com/?m=Hello%20world%21&p=4
@@ -72,7 +72,7 @@ curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello world!&p=4' --output hel
```python
import requests
def ggwave(message: str, protocolId: int = 1, sampleRate: int = 48000, volume: int = 50):
def ggwave(message: str, protocolId: int = 1, sampleRate: float = 48000, volume: int = 50):
url = 'https://ggwave-to-file.ggerganov.com/'

View File

@@ -1,7 +1,7 @@
import sys
import requests
def ggwave(message: str, protocolId: int = 1, sampleRate: int = 48000, volume: int = 50):
def ggwave(message: str, protocolId: int = 1, sampleRate: float = 48000, volume: int = 50):
url = 'https://ggwave-to-file.ggerganov.com/'

View File

@@ -34,7 +34,7 @@ int main(int argc, char** argv) {
}
int volume = argm["v"].empty() ? 50 : std::stoi(argm["v"]);
int sampleRateOut = argm["s"].empty() ? GGWave::kBaseSampleRate : std::stoi(argm["s"]);
float sampleRateOut = argm["s"].empty() ? GGWave::kBaseSampleRate : std::stof(argm["s"]);
int protocolId = argm["p"].empty() ? 1 : std::stoi(argm["p"]);
if (volume <= 0 || volume > 100) {
@@ -42,8 +42,8 @@ int main(int argc, char** argv) {
return -1;
}
if (sampleRateOut < 1024 || sampleRateOut > GGWave::kBaseSampleRate) {
fprintf(stderr, "Invalid sample rate\n");
if (sampleRateOut < GGWave::kSampleRateMin || sampleRateOut > GGWave::kSampleRateMax) {
fprintf(stderr, "Invalid sample rate: %g\n", sampleRateOut);
return -1;
}

View File

@@ -42,7 +42,7 @@ int g_freqDataHead = 0;
int g_freqDataSize = 0;
std::vector<FreqData> g_freqData;
int g_sampleRateOffset = 0;
float g_sampleRateOffset = 0;
}
@@ -84,8 +84,6 @@ bool GGWave_init(
}
}
bool reinit = false;
if (g_devIdOut == 0) {
printf("Initializing playback ...\n");
@@ -127,8 +125,6 @@ bool GGWave_init(
return false;
}
reinit = true;
}
}
@@ -158,33 +154,9 @@ bool GGWave_init(
printf(" - Format: %d (required: %d)\n", g_obtainedSpecInp.format, captureSpec.format);
printf(" - Channels: %d (required: %d)\n", g_obtainedSpecInp.channels, captureSpec.channels);
printf(" - Samples per frame: %d\n", g_obtainedSpecInp.samples);
reinit = true;
}
}
GGWave::SampleFormat sampleFormatInp = GGWAVE_SAMPLE_FORMAT_UNDEFINED;
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_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;
case AUDIO_F32SYS: sampleFormatInp = GGWAVE_SAMPLE_FORMAT_F32; break;
}
switch (g_obtainedSpecOut.format) {
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;
case AUDIO_F32SYS: sampleFormatOut = GGWAVE_SAMPLE_FORMAT_F32; break;
break;
}
return true;
}
@@ -477,7 +449,7 @@ int main(int argc, char** argv) {
ImGui::DragInt("Min", &g_binMin, 1, 0, g_binMax - 1);
ImGui::DragInt("Max", &g_binMax, 1, g_binMin + 1, g_nSamplesPerFrame/2);
ImGui::DragFloat("Scale", &g_scale, 1.0f, 1.0f, 1000.0f);
if (ImGui::SliderInt("Offset", &g_sampleRateOffset, -2048, 2048)) {
if (ImGui::SliderFloat("Offset", &g_sampleRateOffset, -2048, 2048)) {
GGWave_deinit();
GGWave_init(0, 0);
}

View File

@@ -259,7 +259,7 @@ struct Input {
Message message;
// reinit
int sampleRateOffset = 0;
float sampleRateOffset = 0;
int payloadLength = -1;
// spectrum
@@ -607,8 +607,8 @@ void updateCore() {
}
if (inputCurrent.flags.needReinit) {
static int sampleRateInpOld = ggWave->getSampleRateInp();
static int sampleRateOutOld = ggWave->getSampleRateOut();
static auto sampleRateInpOld = ggWave->getSampleRateInp();
static auto sampleRateOutOld = ggWave->getSampleRateOut();
GGWave::SampleFormat sampleFormatInpOld = ggWave->getSampleFormatInp();
GGWave::SampleFormat sampleFormatOutOld = ggWave->getSampleFormatOut();
auto rxProtocolsOld = ggWave->getRxProtocols();
@@ -817,7 +817,7 @@ void renderMain() {
struct Settings {
int protocolId = GGWAVE_TX_PROTOCOL_AUDIBLE_FAST;
bool isSampleRateOffset = false;
int sampleRateOffset = -512;
float sampleRateOffset = -512.0f;
bool isFixedLength = false;
int payloadLength = 8;
float volume = 0.10f;
@@ -1112,7 +1112,7 @@ void renderMain() {
ImGui::SetCursorScreenPos({ posSave.x + kLabelWidth, posSave.y });
}
{
const float df = float(statsCurrent.sampleRateBase)/statsCurrent.samplesPerFrame;
const float df = statsCurrent.sampleRateBase/statsCurrent.samplesPerFrame;
const auto & protocol = settings.txProtocols.at(GGWave::TxProtocolId(settings.protocolId));
ImGui::Text("%6.2f Hz - %6.2f Hz", df*protocol.freqStart, df*(protocol.freqStart + 2*16*protocol.bytesPerTx));
}
@@ -1173,7 +1173,7 @@ void renderMain() {
if (settings.isSampleRateOffset) {
ImGui::SameLine();
ImGui::PushItemWidth(0.5*ImGui::GetContentRegionAvailWidth());
if (ImGui::SliderInt("Samples", &settings.sampleRateOffset, -1000, 1000)) {
if (ImGui::SliderFloat("Samples", &settings.sampleRateOffset, -1000, 1000, "%.0f")) {
g_buffer.inputUI.update = true;
g_buffer.inputUI.flags.needReinit = true;
g_buffer.inputUI.sampleRateOffset = settings.isSampleRateOffset ? settings.sampleRateOffset : 0;