arduino-audio-tools
CodecG7xx.h
1 #pragma once
2 
3 extern "C"{
4  #include "g72x.h"
5 }
6 
7 
8 namespace audio_tools {
9 
16 enum G7xxCODEC_e {g723_24, g721, g723_40, others};
17 
26 class G7xxDecoder : public AudioDecoder {
27  public:
28  G7xxDecoder(G7xxCODEC_e codec) {
29  info.channels = 1;
30  info.sample_rate = 8000;
31  info.bits_per_sample = 16;
32 
33  switch(codec){
34  case g723_24:
35  dec_routine = g723_24_decoder;
36  dec_bits = 3;
37  break;
38 
39  case g721:
40  dec_routine = g721_decoder;
41  dec_bits = 4;
42  break;
43 
44  case g723_40:
45  dec_routine = g723_40_decoder;
46  dec_bits = 5;
47  break;
48  }
49  }
50 
51  void setAudioInfo(AudioInfo info) override {
52  bool ok = true;
53  if (info.channels!=1){
54  LOGE("channels must be 1 instead of %d", info.channels);
55  ok = false;
56  }
57  if (info.sample_rate!=8000){
58  LOGE("sample_rate must be 8000 instead of %d", info.sample_rate);
59  ok = false;
60  }
61  if (info.bits_per_sample!=16){
62  LOGE("bits_per_sample must be 16 instead of %d", info.bits_per_sample);
63  ok = false;
64  }
65  if (ok) AudioDecoder::setAudioInfo(info);
66  }
67 
68  bool begin() override {
69  TRACEI();
70  in_buffer = 0;
71  in_bits = 0;
72  out_size = sizeof(int16_t);
73  g72x_init_state(&state);
74 
75  is_active = true;
76  return true;
77  }
78 
79  void end() override {
80  TRACEI();
81  is_active = false;
82  }
83 
84  void setOutput(Print &out_stream) override { p_print = &out_stream; }
85 
86  operator bool() { return is_active; }
87 
88  size_t write(const void *data, size_t length) override {
89  LOGD("write: %d", length);
90  if (!is_active) {
91  LOGE("inactive");
92  return 0;
93  }
94 
95  uint8_t *p_byte = (uint8_t *)data;
96  for (int j = 0; j < length; j++) {
97  sample = (*dec_routine)(p_byte[j], AUDIO_ENCODING_LINEAR, &state);
98  p_print->write((uint8_t*)&sample, out_size);
99  }
100 
101  return length;
102  }
103 
104  protected:
105  Print *p_print = nullptr;
106  int input_pos = 0;
107  bool is_active = false;
108  int16_t sample;
109  unsigned char code;
110  int n;
111  struct g72x_state state;
112  int out_size;
113  int (*dec_routine)(int code, int out_coding, struct g72x_state* state_ptr);
114  int dec_bits;
115  unsigned int in_buffer = 0;
116  int in_bits = 0;
117 
118 };
119 
127 class G7xxEncoder : public AudioEncoder {
128  public:
129  G7xxEncoder(G7xxCODEC_e codec) {
130  info.channels = 1;
131  info.sample_rate = 8000;
132  info.bits_per_sample = 16;
133 
134  switch(codec){
135 
136  case g721:
137  enc_routine = g721_encoder;
138  enc_bits = 4;
139  p_mime = "audio/g721";
140  break;
141 
142  case g723_24:
143  enc_routine = g723_24_encoder;
144  enc_bits = 3;
145  p_mime = "audio/g723_24";
146  break;
147 
148  case g723_40:
149  enc_routine = g723_40_encoder;
150  enc_bits = 5;
151  p_mime = "audio/g723_40";
152  break;
153  }
154  }
155 
156  bool begin() override {
157  TRACEI();
158  g72x_init_state(&state);
159  out_buffer = 0;
160  out_bits = 0;
161 
162  is_active = true;
163  return true;
164  }
165 
166  void end() override {
167  TRACEI();
168  is_active = false;
169  }
170 
171  const char *mime() override { return p_mime; }
172 
173  virtual void setAudioInfo(AudioInfo info) {
174  bool ok = true;
175  if (info.channels!=1){
176  LOGE("channels must be 1 instead of %d", info.channels);
177  ok = false;
178  }
179  if (info.sample_rate!=8000){
180  LOGE("sample_rate must be 8000 instead of %d", info.sample_rate);
181  ok = false;
182  }
183  if (info.bits_per_sample!=16){
184  LOGE("bits_per_sample must be 16 instead of %d", info.bits_per_sample);
185  ok = false;
186  }
187  if (ok) AudioEncoder::setAudioInfo(info);
188  }
189 
190  void setOutput(Print &out_stream) override { p_print = &out_stream; }
191 
192  operator bool() { return is_active; }
193 
194  size_t write(const void *in_ptr, size_t byte_count) override {
195  LOGD("write: %d", byte_count);
196  if (!is_active) {
197  LOGE("inactive");
198  return 0;
199  }
200  // encode bytes
201  int16_t *p_16 = (int16_t *)in_ptr;
202  int samples = byte_count / sizeof(int16_t);
203  for (int j = 0; j < samples; j++) {
204  code = (*enc_routine)(p_16[j], AUDIO_ENCODING_LINEAR, &state);
205  p_print->write(&code, 1);
206  }
207 
208  return byte_count;
209  }
210 
211  protected:
212  Print *p_print = nullptr;
213  bool is_active = false;
214  const char *p_mime = nullptr;
215  int resid;
216  struct g72x_state state;
217  unsigned char sample_char;
218  int16_t sample_int16;
219  unsigned char code;
220  int (*enc_routine)(int sample, int in_coding, struct g72x_state* state_ptr);
221  int enc_bits;
222  unsigned int out_buffer = 0;
223  int out_bits = 0;
224 
225 };
226 
234 class G721Decoder : public G7xxDecoder {
235  public:
236  G721Decoder() : G7xxDecoder(g721) {};
237 };
245 class G721Encoder : public G7xxEncoder {
246  public:
247  G721Encoder() : G7xxEncoder(g721) {};
248 };
256 class G723_24Decoder : public G7xxDecoder {
257  public:
258  G723_24Decoder() : G7xxDecoder(g723_24) {};
259 };
267 class G723_24Encoder : public G7xxEncoder {
268  public:
269  G723_24Encoder() : G7xxEncoder(g723_24) {};
270 };
278 class G723_40Decoder : public G7xxDecoder {
279  public:
280  G723_40Decoder() : G7xxDecoder(g723_40) {};
281 };
289 class G723_40Encoder : public G7xxEncoder {
290  public:
291  G723_40Encoder() : G7xxEncoder(g723_40) {};
292 };
293 
302 class G711Encoder : public G7xxEncoder {
303  public:
304  G711Encoder(uint8_t(*enc)(int)) : G7xxEncoder(others) {
305  this->enc = enc;
306  assert(this->enc!=nullptr);
307  };
308  size_t write(const void *in_ptr, size_t in_size) override {
309  LOGD("write: %d", in_size);
310  if (!is_active) {
311  LOGE("inactive");
312  return 0;
313  }
314  // encode bytes
315  int samples = in_size/2;
316  int16_t *p_16 = (int16_t *)in_ptr;
317  uint8_t buffer[samples];
318  for (int j = 0; j < samples; j++) {
319  buffer[j] = enc(p_16[j]);
320  }
321  p_print->write(buffer,samples);
322  return in_size;
323  }
324  protected:
325  uint8_t(*enc)(int)=nullptr;
326 };
327 
336 class G711Decoder : public G7xxDecoder {
337  public:
338  G711Decoder(int (*dec)(uint8_t a_val)) : G7xxDecoder(others) {
339  this->dec = dec;
340  assert(this->dec!=nullptr);
341  };
342 
343  size_t write(const void *in_ptr, size_t in_size) override {
344  LOGD("write: %d", in_size);
345  if (!is_active) {
346  LOGE("inactive");
347  return 0;
348  }
349  // decode bytes
350  uint8_t *p_8 = (uint8_t *)in_ptr;
351  for (int j = 0; j < in_size; j++) {
352  int16_t result = dec(p_8[j]);
353  p_print->write((uint8_t*)&result,sizeof(int16_t));
354  }
355  return in_size;
356  }
357  protected:
358  int (*dec)(uint8_t a_val)=nullptr;
359 };
360 
361 
370  public:
371  G711_ALAWEncoder() : G711Encoder(linear2alaw) {};
372 };
373 
382  public:
383  G711_ALAWDecoder() : G711Decoder(alaw2linear) {};
384 };
385 
394  public:
395  G711_ULAWEncoder() : G711Encoder(linear2ulaw) {};
396 };
397 
406  public:
407  G711_ULAWDecoder() : G711Decoder(ulaw2linear) {};
408 };
409 
410 } // namespace audio_tools
Docoding of encoded audio into PCM data.
Definition: AudioEncoded.h:18
virtual void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition: AudioEncoded.h:28
Encoding of PCM data.
Definition: AudioEncoded.h:88
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition: AudioEncoded.h:97
64 kbit/s g711 ALOW Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:381
64 kbit/s g711 ALOW Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:369
64 kbit/s g711 ULOW Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:405
64 kbit/s g711 ULOW Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:393
64 kbit/s g711 ULOW Decoder based on https://github.com/pschatzmann/arduino-libg7xx Supported decoder...
Definition: CodecG7xx.h:336
64 kbit/s g711 ULOW Encoder based on https://github.com/pschatzmann/arduino-libg7xx Supported encoder...
Definition: CodecG7xx.h:302
32Kbps G721 Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:234
32Kbps G721 Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:245
24Kbps G723 Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:256
24Kbps G723 Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:267
40Kbps G723 Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:278
40Kbps G723 Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:289
g723_24, g721, g723_40 Decoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:26
void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition: CodecG7xx.h:84
void setAudioInfo(AudioInfo info) override
for most decoders this is not needed
Definition: CodecG7xx.h:51
g723_24, g721, g723_40 Encoder based on https://github.com/pschatzmann/arduino-libg7xx
Definition: CodecG7xx.h:127
const char * mime() override
Provides the mime type of the encoded result.
Definition: CodecG7xx.h:171
virtual void setAudioInfo(AudioInfo info)
Defines the sample rate, number of channels and bits per sample.
Definition: CodecG7xx.h:173
Definition: NoArduino.h:58
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
G7xxCODEC_e
Supported codecs by G7xxDecoder and G7xxEncoder.
Definition: CodecG7xx.h:16
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
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