arduino-audio-tools
CodecILBC.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include "AudioCodecs/AudioEncoded.h"
14 #include "iLBC.h"
15 
16 
17 namespace audio_tools {
18 
27 class ILBCDecoder : public AudioDecoder {
28  public:
29  ILBCDecoder(EnumLBCFrameSize frameSize = ms30, bool useEnhancer = true) {
30  info.sample_rate = 8000;
31  info.channels = 1;
32  info.bits_per_sample = 16;
33  frame_size = frameSize;
34  use_enhancer = useEnhancer;
35  }
36 
37  ~ILBCDecoder(){
38  end();
39  }
40 
41  virtual bool begin() {
42  TRACEI();
43  if (p_print==nullptr){
44  LOGE("Output not defined");
45  return false;
46  }
47 
48  if (p_ilbc==nullptr){
49  p_ilbc = new iLBCDecode(frame_size, use_enhancer);
50  }
51 
52  // setup buffer
53  decoded_buffer.resize(p_ilbc->getSamples());
54  encoded_buffer.resize(p_ilbc->getEncodedBytes());
55 
56  // update audio information
57  notifyAudioChange(info);
58  return true;
59  }
60 
61  virtual void end() {
62  TRACEI();
63  delete p_ilbc;
64  p_ilbc = nullptr;
65  }
66 
67  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
68 
69  operator bool() { return p_ilbc != nullptr; }
70 
71  virtual size_t write(const void *input_buffer, size_t length) {
72  if (p_ilbc==nullptr) return 0;
73  LOGI("write: %d", length);
74  int samples = length / sizeof(int16_t);
75  int16_t *p_samples = (int16_t *)input_buffer;
76  for (int j=0;j<samples;j++){
77  encoded_buffer[encoded_buffer_pos++]=p_samples[j];
78  if (encoded_buffer_pos>=encoded_buffer.size()){
79  memset(decoded_buffer.data(),0,decoded_buffer.size()*sizeof(int16_t));
80  p_ilbc->decode(encoded_buffer.data(), decoded_buffer.data());
81  if (p_print!=nullptr){
82  p_print->write((uint8_t*)decoded_buffer.data(), decoded_buffer.size()*sizeof(int16_t));
83  delay(2);
84  }
85  encoded_buffer_pos = 0;
86  }
87  }
88  return length;
89  }
90 
91  protected:
92  Print *p_print = nullptr;
93  iLBCDecode *p_ilbc = nullptr;
94  Vector<int16_t> decoded_buffer{0};
95  Vector<uint8_t> encoded_buffer{0};
96  int16_t encoded_buffer_pos = 0;
97  EnumLBCFrameSize frame_size;
98  bool use_enhancer;
99 
100 };
101 
110 class ILBCEncoder : public AudioEncoder {
111  public:
112  ILBCEncoder(EnumLBCFrameSize frameSize = ms30) {
113  info.sample_rate = 8000;
114  info.channels = 1;
115  info.bits_per_sample = 16;
116  frame_size = frameSize;
117  }
118 
119  ~ILBCEncoder(){
120  end();
121  }
122 
123  bool begin() {
124  TRACEI();
125  if (p_print==nullptr){
126  LOGE("Output not defined");
127  return false;
128  }
129  if (info.bits_per_sample!=16){
130  LOGE("bits_per_sample must be 16: %d",info.bits_per_sample);
131  return false;
132  }
133  if (info.sample_rate!=8000){
134  LOGW("The sample rate should be 8000: %d", info.sample_rate);
135  }
136  if (info.channels!=1){
137  LOGW("channels should be 1: %d", info.channels);
138  }
139  if (p_ilbc==nullptr){
140  p_ilbc = new iLBCEncode(frame_size);
141  }
142  decoded_buffer.resize(p_ilbc->getSamples());
143  encoded_buffer.resize(p_ilbc->getEncodedBytes());
144  decoded_buffer_pos = 0;
145  return true;
146  }
147 
148  virtual void end() {
149  TRACEI();
150  if (p_ilbc != nullptr) {
151  delete p_ilbc;
152  p_ilbc = nullptr;
153  }
154  }
155 
156  virtual const char *mime() { return "audio/ilbc"; }
157 
158  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
159 
160  operator bool() { return p_ilbc != nullptr; }
161 
162  virtual size_t write(const void *in_data, size_t in_size) {
163  if (p_ilbc==nullptr) return 0;
164  LOGI("write: %d", in_size);
165 
166  int samples = in_size / sizeof(int16_t);
167  int16_t *p_samples = (int16_t *)in_data;
168 
169  for (int j=0;j<samples;j++){
170  decoded_buffer[decoded_buffer_pos++]=p_samples[j];
171  if (decoded_buffer_pos>=decoded_buffer.size()){
172  memset(encoded_buffer.data(),0,encoded_buffer.size());
173  p_ilbc->encode(decoded_buffer.data(), encoded_buffer.data());
174  if (p_print!=nullptr){
175  p_print->write(encoded_buffer.data(), encoded_buffer.size());
176  }
177  decoded_buffer_pos = 0;
178  }
179  }
180  return in_size;
181  }
182 
183  protected:
184  Print *p_print = nullptr;
185  iLBCEncode *p_ilbc = nullptr;
186  Vector<float> decoded_buffer{0};
187  Vector<uint8_t> encoded_buffer{0};
188  int16_t decoded_buffer_pos = 0;
189  EnumLBCFrameSize frame_size;
190 };
191 
192 } // namespace audio_tools
Docoding of encoded audio into PCM data.
Definition: AudioEncoded.h:18
Encoding of PCM data.
Definition: AudioEncoded.h:88
Decoder for iLBC. Depends on https://github.com/pschatzmann/libilbc.
Definition: CodecILBC.h:27
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition: CodecILBC.h:67
Encoder for iLBC - Depends on https://github.com/pschatzmann/libopenilbc.
Definition: CodecILBC.h:110
virtual const char * mime()
Provides the mime type of the encoded result.
Definition: CodecILBC.h:156
Definition: NoArduino.h:58
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
void delay(uint32_t ms)
Waits for the indicated milliseconds.
Definition: Millis.h:11
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