arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
CodecGGWave.h
Go to the documentation of this file.
1
11#pragma once
12
13#include "AudioTools/AudioCodecs/AudioEncoded.h"
14#include "AudioTools/CoreAudio/Buffers.h"
15#include "AudioTools/CoreAudio/AudioEffects/SoundGenerator.h"
16#include <ggwave.h>
17
18#define GGWAVE_DEFAULT_SAMPLE_RATE 48000
19#define GGWAVE_DEFAULT_PAYLOAD_LEN 16
20#define GGWAVE_DEFAULT_SAMPLES_PER_FRAME 256
21#define GGWAVE_DEFAULT_BYTES_PER_FRAME GGWAVE_DEFAULT_SAMPLES_PER_FRAME*GGWAVE_DEFAULT_PAYLOAD_LEN
22#define GGWAVE_DEFAULT_PROTOCOL GGWAVE_PROTOCOL_AUDIBLE_FAST
23#define GGWAVE_DEFAULT_SAMPLE_BYTESIZE 2
24
25//GGWAVE_PROTOCOL_DT_FAST
26
27namespace audio_tools {
28
37public:
38 GGWaveDecoder() {
39 info.sample_rate = GGWAVE_DEFAULT_SAMPLE_RATE;
40 }
41
42 GGWaveDecoder(Print &out_stream) : GGWaveDecoder() { TRACED(); pt_print=&out_stream; }
43
44 virtual void setOutput(Print &out_stream) {pt_print=&out_stream;}
45
46 AudioInfo audioInfo() { return info; }
47
48 void setAudioInfo(AudioInfo ai) { info = ai; }
49
52 template <int N>
53 void setProtocols(ggwave_ProtocolId protocolsArray[N]){
54 for (int j=0;j<N;j++){
55 protocols.push_back(protocolsArray[j]);
56 }
57 }
58
59 void setSamplesFormatInput(ggwave_SampleFormat fmt){
60 samples_format_input = fmt;
61 }
62
63 void setSamplesFromatOutput(ggwave_SampleFormat fmt) {
64 samples_format_output = fmt;
65 }
66
67 void setSamplesPerFrame(int samples){
68 samples_per_frame = samples;
69 }
70
71 void setPayloadLen(int len){
72 playload_len = len;
73 }
74
75 void setSampleByteSize(int size){
76 sample_byte_size = size;
77 }
78
79 void begin() {
80 if (pt_print==nullptr){
81 LOGE("final destination not defined");
82 return;
83 }
84
85 receive_buffer.resize(samples_per_frame*sample_byte_size);
86 ggwave.setLogFile(nullptr);
87
88 auto p = GGWave::getDefaultParameters();
89 p.payloadLength = playload_len;
90 p.sampleRateInp = info.sample_rate;
91 p.sampleRateOut = info.sample_rate;
92 p.sampleRate = info.sample_rate;
93 p.samplesPerFrame = samples_per_frame;
94 p.sampleFormatInp = samples_format_input;
95 p.sampleFormatOut = samples_format_output;
96 p.operatingMode = GGWAVE_OPERATING_MODE_RX | GGWAVE_OPERATING_MODE_USE_DSS ;
97
98
99 // Remove the ones that you don't need to reduce memory usage
100 GGWave::Protocols::tx().disableAll();
101 GGWave::Protocols::rx().disableAll();
102
103 // activate additional protocols
104 GGWave::Protocols::rx().toggle(GGWAVE_DEFAULT_PROTOCOL, true);
105 for (auto protocol: protocols){
106 GGWave::Protocols::rx().toggle(protocol, true);
107 }
108
109 // Initialize the "ggwave" instance:
110 active = true;
111 if (!ggwave.prepare(p, true)){
112 active = false;
113 LOGE("prepare failed");
114 }
115 }
116
117
118 void end() {
119 ggwave.rxStopReceiving();
120 active = false;
121 }
122
123 size_t write(const uint8_t *data, size_t len) {
124 if (!active) return 0;
125 uint8_t *p_byte = (uint8_t *)data;
126 for (int j=0;j<len;j++){
127 receive_buffer.write(p_byte[j]);
128 if (receive_buffer.availableForWrite()==0){
129 decode();
130 }
131 }
132 return len;
133 }
134
135 operator bool() { return active; }
136
137 // The result is encoded data
138 virtual bool isResultPCM() { return false;}
139
140protected:
141 Print *pt_print=nullptr;
142 AudioInfo info;
143 GGWave ggwave;
144 GGWave::TxRxData data;
145 SingleBuffer<uint8_t> receive_buffer{0};
146 Vector<ggwave_ProtocolId> protocols;
147 ggwave_SampleFormat samples_format_input = GGWAVE_SAMPLE_FORMAT_I16;
148 ggwave_SampleFormat samples_format_output = GGWAVE_SAMPLE_FORMAT_U8;
149 int samples_per_frame = 0; //GGWAVE_DEFAULT_SAMPLES_PER_FRAME;
150 int playload_len = GGWAVE_DEFAULT_PAYLOAD_LEN;
151 int sample_byte_size = GGWAVE_DEFAULT_SAMPLE_BYTESIZE;
152 bool active = false;
153
154 void decode() {
155 if (receive_buffer.available()>0){
156 if (ggwave.decode(receive_buffer.address(), receive_buffer.available()/(info.bits_per_sample/8))) {
157 // Check if we have successfully decoded any data:
158 int nr = ggwave.rxTakeData(data);
159 if (nr > 0) {
160 pt_print->write((uint8_t*) &data[0], nr);
161 }
162 } else {
163 LOGW("decoding error");
164 }
165 receive_buffer.reset();
166 }
167 }
168};
169
178public:
179 GGWaveEncoder() {
180 info.sample_rate = GGWAVE_DEFAULT_SAMPLE_RATE;
181 }
182
183 GGWaveEncoder(Print &out_stream) : GGWaveEncoder() {
184 TRACED();
185 pt_print=&out_stream;
186 }
187
188 void setOutput(Print &out_stream) {pt_print=&out_stream;}
189
190 void setSamplesFormatInput(ggwave_SampleFormat fmt){
191 samples_format_input = fmt;
192 }
193
194 void setSamplesFromatOutput(ggwave_SampleFormat fmt) {
195 samples_format_output = fmt;
196 }
197
198 void setSamplesPerFrame(int samples){
199 samples_per_frame = samples;
200 }
201
202 void setPayloadLen(int len){
203 playload_len = len;
204 }
205
206 void setProtocol(ggwave_ProtocolId protocol){
207 protocolId = protocol;
208 }
209
210 void setSampleByteSize(int size){
211 sample_byte_size = size;
212 }
213
214 void begin() {
215 TRACEI();
216 ggwave.setLogFile(nullptr);
217 if (pt_print==nullptr){
218 LOGE("final destination not defined");
219 return;
220 }
221 sine_wave.begin(info.channels, info.sample_rate, 0);
222
223 auto parameters = GGWave::getDefaultParameters();
224 parameters.payloadLength = playload_len;
225 parameters.sampleRateInp = info.sample_rate;
226 parameters.sampleRateOut = info.sample_rate;
227 parameters.sampleRate = info.sample_rate;
228 parameters.samplesPerFrame = samples_per_frame;
229 parameters.sampleFormatInp = samples_format_input;
230 parameters.sampleFormatOut = samples_format_output;
231 parameters.operatingMode = GGWAVE_OPERATING_MODE_TX | GGWAVE_OPERATING_MODE_USE_DSS;
232
233 // Remove the ones that you don't need to reduce memory usage
234 GGWave::Protocols::tx().only(protocolId);
235
236 // Sometimes, the speaker might not be able to produce frequencies in the Mono-tone range of 1-2 kHz.
237 // In such cases, you can shift the base frequency up by changing the "freqStart" parameter of the protocol.
238 // Make sure that in the receiver (for example, the "Waver" app) the base frequency is shifted by the same amount.
239 // Here we shift the frequency by +48 bins. Each bin is equal to 48000/1024 = 46.875 Hz.
240 // So the base frequency is shifted by +2250 Hz.
241 //GGWave::Protocols::tx()[protocolId].freqStart += 48;
242
243 ggwave.prepare(parameters);
244 active = true;
245 }
246
247 void end() {
248 TRACEI();
249 active = false;
250 }
251
252 size_t write(const uint8_t *data, size_t len) {
253 if (!active) return 0;
254
255 if (!ggwave.init(len, (const char*)data, protocolId)){
256 LOGE("init faild");
257 return 0;
258 }
259 size_t bytes = ggwave.encode();
260 LOGI("write %d", bytes);
261 //int written = pt_print->write((uint8_t*)ggwave.txWaveform(), bytes);
262
263 const auto &protocol = GGWave::Protocols::tx()[protocolId];
264 const auto tones = ggwave.txTones();
265 const auto duration_ms = protocol.txDuration_ms(ggwave.samplesPerFrame(), ggwave.sampleRateOut());
266 for (auto & curTone : tones) {
267 const auto freq_hz = (protocol.freqStart + curTone)*ggwave.hzPerSample();
268 play(freq_hz, duration_ms);
269 }
270
271 silence(info.sample_rate / 2); // 500 ms
272 return len;
273 }
274
275 operator bool(){
276 return active;
277 }
278
279 virtual const char *mime() {
280 return "audio/pcm";
281 }
282
283protected:
284 Print *pt_print=nullptr;
285 GGWave ggwave;
286 ggwave_ProtocolId protocolId = GGWAVE_DEFAULT_PROTOCOL;
287 int samples_per_frame = GGWAVE_DEFAULT_SAMPLES_PER_FRAME;
288 ggwave_SampleFormat samples_format_input = GGWAVE_SAMPLE_FORMAT_I16;
289 ggwave_SampleFormat samples_format_output = GGWAVE_SAMPLE_FORMAT_U8;
290 int playload_len = GGWAVE_DEFAULT_PAYLOAD_LEN;
291 int volume = GGWave::kDefaultVolume;
292 int sample_byte_size = GGWAVE_DEFAULT_SAMPLE_BYTESIZE;
293 bool active = false;
294 //SineFromTable<int16_t> sine_wave;
296
297 virtual void play(int freq, int ms){
298 // adjust amplitude by pitch bcause high values are too loud
299 int amplitude = 10000; // / (freq/1000);
300 sine_wave.setAmplitude(amplitude);
301 sine_wave.setFrequency(freq);
302 uint64_t end = millis()+ms;
303 while(millis()<end){
304 int16_t sample = sine_wave.readSample();
305 for (int ch=0;ch<info.channels;ch++){
306 pt_print->write((uint8_t*)&sample,2);
307 }
308 }
309 }
310
311 virtual void silence(int samples){
312 // adjust amplitude by pitch bcause high values are too loud
313 int16_t sample = 0;
314 for (int ch=0;ch<info.channels;ch++){
315 pt_print->write((uint8_t*)&sample,2);
316 }
317 }
318
319};
320
321}
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
Encoding of PCM data.
Definition AudioCodecsBase.h:90
Sine wave which is based on a fast approximation function.
Definition SoundGenerator.h:235
virtual T readSample() override
Provides a single sample.
Definition SoundGenerator.h:242
GGWaveDecoder: Translates audio into text Codec using https://github.com/ggerganov/ggwave-arduino.
Definition CodecGGWave.h:36
void setProtocols(ggwave_ProtocolId protocolsArray[N])
Activate multiple protocols.
Definition CodecGGWave.h:53
virtual bool isResultPCM()
Returns true to indicate that the decoding result is PCM data.
Definition CodecGGWave.h:138
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition CodecGGWave.h:44
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition CodecGGWave.h:46
void setAudioInfo(AudioInfo ai)
for most decoders this is not needed
Definition CodecGGWave.h:48
GGWaveEncoder: Translates text into audio Codec using https://github.com/ggerganov/ggwave-arduino.
Definition CodecGGWave.h:177
virtual const char * mime()
Provides the mime type of the encoded result.
Definition CodecGGWave.h:279
Definition NoArduino.h:62
void setFrequency(float frequency) override
Defines the frequency - after the processing has been started.
Definition SoundGenerator.h:193
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:166
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:191
int available() override
provides the number of entries that are available to read
Definition Buffers.h:218
int availableForWrite() override
provides the number of entries that are available to write
Definition Buffers.h:223
T * address() override
Provides address to beginning of the buffer.
Definition Buffers.h:249
void reset() override
clears the buffer
Definition Buffers.h:254
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59