arduino-audio-tools
CodecG722.h
1 
9 #pragma once
10 
11 #include "AudioTools/AudioCodecs/AudioCodecsBase.h"
12 #include "g722_codec.h"
13 
14 // size in bytes
15 #define G722_PCM_SIZE 80
16 #define G722_ENC_SIZE 40
17 
18 
19 namespace audio_tools {
20 
29 class G722Decoder : public AudioDecoder {
30  public:
31  G722Decoder() = default;
32 
34  void setOptions(int options){
35  this->options = options;
36  }
37 
38  virtual bool begin() {
39  TRACEI();
40  input_buffer.resize(10);
41  result_buffer.resize(40);
42 
43  g722_dctx = g722_decoder_new(info.sample_rate, options);
44  if (g722_dctx == nullptr) {
45  LOGE("g722_decoder_new");
46  return false;
47  }
48 
49  notifyAudioChange(info);
50  is_active = true;
51  return true;
52  }
53 
54  virtual void end() {
55  TRACEI();
56  g722_decoder_destroy(g722_dctx);
57  is_active = false;
58  }
59 
60  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
61 
62  operator bool() { return is_active; }
63 
64  virtual size_t write(const uint8_t *data, size_t len) {
65  LOGD("write: %d", len);
66  if (!is_active) {
67  LOGE("inactive");
68  return 0;
69  }
70 
71  uint8_t *p_byte = (uint8_t *)data;
72  for (int j = 0; j < len; j++) {
73  processByte(p_byte[j]);
74  }
75 
76  return len;
77  }
78 
79  protected:
80  Print *p_print = nullptr;
81  G722_DEC_CTX *g722_dctx=nullptr;
82  Vector<uint8_t> input_buffer;
83  Vector<uint8_t> result_buffer;
84  int options = G722_SAMPLE_RATE_8000;
85  int input_pos = 0;
86  bool is_active = false;
87 
89  void processByte(uint8_t byte) {
90  // add byte to buffer
91  input_buffer[input_pos++] = byte;
92 
93  // decode if buffer is full
94  if (input_pos >= input_buffer.size()) {
95  int result_samples = g722_decode(g722_dctx, input_buffer.data(), input_buffer.size(),
96  (int16_t *)result_buffer.data());
97 
98  if (result_samples*2>result_buffer.size()){
99  LOGE("Decoder:Result buffer too small: %d -> %d",result_buffer.size(),result_samples*2);
100  }
101 
102  p_print->write(result_buffer.data(), result_samples);
103  input_pos = 0;
104  }
105  }
106 };
107 
117 class G722Encoder : public AudioEncoder {
118  public:
119  G722Encoder() = default;
120 
122  void setOptions(int options){
123  this->options = options;
124  }
125 
126  bool begin() {
127  TRACEI();
128  if (info.channels != 1) {
129  LOGW("1 channel expected, was: %d", info.channels);
130  }
131 
132  g722_ectx = g722_encoder_new(info.sample_rate, options);
133  if (g722_ectx == NULL) {
134  LOGE("g722_encoder_new");
135  return false;
136  }
137 
138  input_buffer.resize(G722_PCM_SIZE);
139  result_buffer.resize(G722_ENC_SIZE);
140  is_active = true;
141  return true;
142  }
143 
144  virtual void end() {
145  TRACEI();
146  g722_encoder_destroy(g722_ectx);
147  is_active = false;
148  }
149 
150  virtual const char *mime() { return "audio/g722"; }
151 
152  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
153 
154  operator bool() { return is_active; }
155 
156  virtual size_t write(const uint8_t *data, size_t len) {
157  LOGD("write: %d", len);
158  if (!is_active) {
159  LOGE("inactive");
160  return 0;
161  }
162  // encode bytes
163  uint8_t *p_byte = (uint8_t *)data;
164  for (int j = 0; j < len; j++) {
165  processByte(p_byte[j]);
166  }
167  return len;
168  }
169 
170  protected:
171  Print *p_print = nullptr;
172  G722_ENC_CTX *g722_ectx = nullptr;
173  Vector<uint8_t> input_buffer;
174  Vector<uint8_t> result_buffer;
175  int options = G722_SAMPLE_RATE_8000;
176  int buffer_pos = 0;
177  bool is_active = false;
178 
179  // add byte to decoding buffer and decode if buffer is full
180  void processByte(uint8_t byte) {
181  input_buffer[buffer_pos++] = byte;
182  if (buffer_pos >= input_buffer.size()) {
183  // convert for little endian
184  int samples = input_buffer.size() / 2;
185  // encode
186  int result_len = g722_encode(g722_ectx,(const int16_t*) input_buffer.data(), samples,
187  result_buffer.data());
188  if (result_len>result_buffer.size()){
189  LOGE("Encoder:Result buffer too small: %d -> %d",result_buffer.size(),result_len);
190  }
191  p_print->write(result_buffer.data(), result_len);
192  buffer_pos = 0;
193  }
194  }
195 };
196 
197 } // namespace audio_tools
Docoding of encoded audio into PCM data.
Definition: AudioCodecsBase.h:16
Encoding of PCM data.
Definition: AudioCodecsBase.h:84
Decoder for G.722. Depends on https://github.com/pschatzmann/arduino-libg722.
Definition: CodecG722.h:29
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition: CodecG722.h:60
void processByte(uint8_t byte)
Build decoding buffer and decode when frame is full.
Definition: CodecG722.h:89
void setOptions(int options)
Defines the options for the G.722 Codec: G722_SAMPLE_RATE_8000,G722_PACKED.
Definition: CodecG722.h:34
Encoder for G.722 - Depends on https://github.com/pschatzmann/arduino-libg722. Inspired by g722enc....
Definition: CodecG722.h:117
void setOptions(int options)
Defines the options for the G.722 Codec: G722_SAMPLE_RATE_8000,G722_PACKED.
Definition: CodecG722.h:122
virtual const char * mime()
Provides the mime type of the encoded result.
Definition: CodecG722.h:150
Definition: NoArduino.h:58
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
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