arduino-audio-tools
Loading...
Searching...
No Matches
CodecG729.h
Go to the documentation of this file.
1
10#pragma once
11
12#include <bcg729.h> // https://github.com/pschatzmann/codec-bcg729
13
15
16namespace audio_tools {
17
18// G.729 frame sizes
19static constexpr size_t G729_SAMPLES_PER_FRAME = 80; // 10 ms @ 8 kHz
20static constexpr size_t G729_PCM_SIZE =
21 G729_SAMPLES_PER_FRAME * 2; // 160 bytes PCM16
22static constexpr size_t G729_ENC_SIZE = 10; // 10 bytes speech frame
23static constexpr size_t G729_SID_SIZE = 2; // 2 bytes SID frame
24static AudioInfo audioInfoG729{8000, 1, 16};
25
48class G729Decoder : public AudioDecoder {
49 public:
51
52 const char* mime() override { return "audio/g729"; }
53
54 void setAudioInfo(AudioInfo info) override {
55 // Check if requested format is valid
56 if (info != audioInfoG729) {
57 LOGE(
58 "G.729 encoder input is fixed to 8000 Hz, mono, 16-bit PCM "
59 "(requested: %d Hz, %d ch, %d bit)",
61 }
62 // update when changed to trigger notifications, even though the actual format is fixed
64 }
65
66 bool begin() override {
67 TRACEI();
68 end();
69
72
73 decoder_ctx = initBcg729DecoderChannel();
74 if (decoder_ctx == nullptr) {
75 LOGE("initBcg729DecoderChannel");
76 return false;
77 }
78
79 input_pos = 0;
80 is_active = true;
82 return true;
83 }
84
85 void end() override {
86 TRACEI();
87 if (decoder_ctx != nullptr) {
88 closeBcg729DecoderChannel(decoder_ctx);
89 decoder_ctx = nullptr;
90 }
91 input_pos = 0;
92 is_active = false;
93 }
94
95 void setOutput(Print& out_stream) override { p_print = &out_stream; }
96
97 operator bool() override { return is_active; }
98
99 size_t write(const uint8_t* data, size_t len) override {
100 LOGD("write: %d", static_cast<int>(len));
101
102 if (!is_active) {
103 LOGE("inactive");
104 return 0;
105 }
106 if (p_print == nullptr) {
107 LOGE("output not set");
108 return 0;
109 }
110
111 // Fast path: if the caller supplies a complete framed payload and the
112 // accumulator is empty, decode directly so SID (2-byte) and speech
113 // (10-byte) frame boundaries are preserved.
114 if (input_pos == 0 && (len == G729_ENC_SIZE || len == G729_SID_SIZE)) {
115 decodeFrame(data, len);
116 return len;
117 }
118
119 // Stream mode: accumulate bytes into 10-byte speech frames.
120 for (size_t j = 0; j < len; ++j) {
121 processByte(data[j]);
122 }
123
124 return len;
125 }
126
127 protected:
128 Print* p_print = nullptr;
129 bcg729DecoderChannelContextStruct* decoder_ctx = nullptr;
132 size_t input_pos = 0;
133 bool is_active = false;
134
135 void processByte(uint8_t byte) {
136 input_buffer[input_pos++] = byte;
137
138 if (input_pos >= G729_ENC_SIZE) {
140 input_pos = 0;
141 }
142 }
143
144 void decodeFrame(const uint8_t* data, size_t frame_len) {
145 if (frame_len != G729_ENC_SIZE && frame_len != G729_SID_SIZE) {
146 LOGW("unsupported G729 frame size: %d", static_cast<int>(frame_len));
147 return;
148 }
149
150 uint8_t sid_frame = frame_len == G729_SID_SIZE ? 1 : 0;
151
152 bcg729Decoder(decoder_ctx, const_cast<uint8_t*>(data),
153 static_cast<uint8_t>(frame_len),
154 0, // frameErasureFlag
155 sid_frame, // SIDFrameFlag
156 0, // rfc3389PayloadFlag
157 reinterpret_cast<int16_t*>(result_buffer.data()));
158
160 }
161};
162
188class G729Encoder : public AudioEncoder {
189 public:
190 G729Encoder(bool is_vad_enabled = false) {
192 setVADEnabled(is_vad_enabled);
193 }
194
195 void setVADEnabled(bool enabled) { vad_enabled = enabled; }
196
197 void setAudioInfo(AudioInfo info) override {
198 // Check if requested format is valid
199 if (info != audioInfoG729) {
200 LOGE(
201 "G.729 encoder input is fixed to 8000 Hz, mono, 16-bit PCM "
202 "(requested: %d Hz, %d ch, %d bit)",
204 }
205 // update when changed to trigger notifications, even though the actual format is fixed
207 }
208
209 bool begin() override {
210 TRACEI();
211 end();
212
213 encoder_ctx = initBcg729EncoderChannel(vad_enabled ? 1 : 0);
214 if (encoder_ctx == nullptr) {
215 LOGE("initBcg729EncoderChannel");
216 return false;
217 }
218
221 buffer_pos = 0;
222 is_active = true;
223 return true;
224 }
225
226 void end() override {
227 TRACEI();
228 if (encoder_ctx != nullptr) {
229 closeBcg729EncoderChannel(encoder_ctx);
230 encoder_ctx = nullptr;
231 }
232 buffer_pos = 0;
233 is_active = false;
234 }
235
236 const char* mime() override { return "audio/g729"; }
237
238 void setOutput(Print& out_stream) override { p_print = &out_stream; }
239
240 operator bool() override { return is_active; }
241
242 size_t write(const uint8_t* data, size_t len) override {
243 LOGD("write: %d", static_cast<int>(len));
244
245 if (!is_active) {
246 LOGE("inactive");
247 return 0;
248 }
249 if (p_print == nullptr) {
250 LOGE("output not set");
251 return 0;
252 }
253
254 for (size_t j = 0; j < len; ++j) {
255 processByte(data[j]);
256 }
257 return len;
258 }
259
260 protected:
261 Print* p_print = nullptr;
262 bcg729EncoderChannelContextStruct* encoder_ctx = nullptr;
265 size_t buffer_pos = 0;
266 bool vad_enabled = false;
267 bool is_active = false;
268
269 void processByte(uint8_t byte) {
270 input_buffer[buffer_pos++] = byte;
271
272 if (buffer_pos >= G729_PCM_SIZE) {
273 uint8_t result_len = 0;
274
275 bcg729Encoder(encoder_ctx,
276 reinterpret_cast<const int16_t*>(input_buffer.data()),
277 result_buffer.data(), &result_len);
278
279 if (result_len > result_buffer.size()) {
280 LOGE("Encoder: result buffer too small: %d -> %d",
281 static_cast<int>(result_buffer.size()),
282 static_cast<int>(result_len));
283 } else if (result_len > 0) {
284 p_print->write(result_buffer.data(), result_len);
285 }
286
287 buffer_pos = 0;
288 }
289 }
290};
291
292} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:19
AudioInfo info
Definition AudioCodecsBase.h:80
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:32
Encoding of PCM data.
Definition AudioCodecsBase.h:101
AudioInfo info
Definition AudioCodecsBase.h:120
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:110
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:175
G.729 decoder using the bcg729 library.
Definition CodecG729.h:48
void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition CodecG729.h:95
bool is_active
Definition CodecG729.h:133
Vector< uint8_t > result_buffer
Definition CodecG729.h:131
G729Decoder()
Definition CodecG729.h:50
void end() override
Definition CodecG729.h:85
size_t write(const uint8_t *data, size_t len) override
Definition CodecG729.h:99
void decodeFrame(const uint8_t *data, size_t frame_len)
Definition CodecG729.h:144
void processByte(uint8_t byte)
Definition CodecG729.h:135
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition CodecG729.h:52
bool begin() override
Definition CodecG729.h:66
Print * p_print
Definition CodecG729.h:128
void setAudioInfo(AudioInfo info) override
for most decoders this is not needed
Definition CodecG729.h:54
size_t input_pos
Definition CodecG729.h:132
Vector< uint8_t > input_buffer
Definition CodecG729.h:130
bcg729DecoderChannelContextStruct * decoder_ctx
Definition CodecG729.h:129
G.729 encoder using the bcg729 library.
Definition CodecG729.h:188
void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition CodecG729.h:238
bool vad_enabled
Definition CodecG729.h:266
bool is_active
Definition CodecG729.h:267
bcg729EncoderChannelContextStruct * encoder_ctx
Definition CodecG729.h:262
Vector< uint8_t > result_buffer
Definition CodecG729.h:264
void end() override
Definition CodecG729.h:226
void setVADEnabled(bool enabled)
Definition CodecG729.h:195
size_t write(const uint8_t *data, size_t len) override
Definition CodecG729.h:242
G729Encoder(bool is_vad_enabled=false)
Definition CodecG729.h:190
void processByte(uint8_t byte)
Definition CodecG729.h:269
const char * mime() override
Provides the mime type of the encoded result.
Definition CodecG729.h:236
bool begin() override
Definition CodecG729.h:209
Print * p_print
Definition CodecG729.h:261
void setAudioInfo(AudioInfo info) override
Defines the sample rate, number of channels and bits per sample.
Definition CodecG729.h:197
size_t buffer_pos
Definition CodecG729.h:265
Vector< uint8_t > input_buffer
Definition CodecG729.h:263
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
static constexpr size_t G729_PCM_SIZE
Definition CodecG729.h:20
static AudioInfo audioInfoG729
Definition CodecG729.h:24
static constexpr size_t G729_ENC_SIZE
Definition CodecG729.h:22
static constexpr size_t G729_SID_SIZE
Definition CodecG729.h:23
static constexpr size_t G729_SAMPLES_PER_FRAME
Definition CodecG729.h:19
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57