arduino-audio-tools
CodecGSM.h
Go to the documentation of this file.
1 
9 #pragma once
10 
11 #include "AudioCodecs/AudioEncoded.h"
12 #include "gsm.h"
13 
14 
15 namespace audio_tools {
16 
26 class GSMDecoder : public AudioDecoder {
27  public:
28  GSMDecoder() {
29  info.sample_rate = 8000;
30  info.channels = 1;
31  }
32 
33  virtual bool begin() {
34  TRACEI();
35  // 160 13-bit samples
36  result_buffer.resize(160 * sizeof(int16_t));
37  // gsm_frame of 33 bytes
38  input_buffer.resize(33);
39 
40  v_gsm = gsm_create();
41  notifyAudioChange(info);
42  is_active = true;
43  return true;
44  }
45 
46  virtual void end() {
47  TRACEI();
48  gsm_destroy(v_gsm);
49  is_active = false;
50  }
51 
52  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
53 
54  operator bool() { return is_active; }
55 
56  virtual size_t write(const void *data, size_t length) {
57  LOGD("write: %d", length);
58  if (!is_active) {
59  LOGE("inactive");
60  return 0;
61  }
62 
63  uint8_t *p_byte = (uint8_t *) data;
64  for (int j = 0; j < length; j++) {
65  processByte(p_byte[j]);
66  }
67 
68  return length;
69  }
70 
71  protected:
72  Print *p_print = nullptr;
73  gsm v_gsm;
74  bool is_active = false;
75  Vector<uint8_t> input_buffer;
76  Vector<uint8_t> result_buffer;
77  int input_pos = 0;
78 
80  void processByte(uint8_t byte) {
81  // add byte to buffer
82  input_buffer[input_pos++] = byte;
83 
84  // decode if buffer is full
85  if (input_pos >= input_buffer.size()) {
86  if (gsm_decode(v_gsm, input_buffer.data(), (gsm_signal*)result_buffer.data())!=0){
87  LOGE("gsm_decode");
88  }
89 
90  //fromBigEndian(result_buffer);
91  // scale to 13 to 16-bit samples
92  scale(result_buffer);
93 
94  p_print->write(result_buffer.data(), result_buffer.size());
95  input_pos = 0;
96  }
97  }
98 
99  void scale(Vector<uint8_t> &vector){
100  int16_t *pt16 = (int16_t *)vector.data();
101  for (int j = 0; j < vector.size() / 2; j++) {
102  if (abs(pt16[j])<=4095){
103  pt16[j] = pt16[j] * 8;
104  } else if(pt16[j]<0){
105  pt16[j] = -32767;
106  } else if(pt16[j]>0){
107  pt16[j] = 32767;
108  }
109  }
110  }
111 
112  void fromBigEndian(Vector<uint8_t> &vector){
113  int size = vector.size() / 2;
114  int16_t *data16 = (int16_t*) vector.data();
115  for (int i=0; i<size; i++){
116  data16[i] = ntohs(data16[i]);
117  }
118  }
119 
120 
121 };
122 
132 class GSMEncoder : public AudioEncoder {
133  public:
134  GSMEncoder(bool scaling=true) {
135  info.sample_rate = 8000;
136  info.channels = 1;
137  scaling_active = scaling;
138  }
139 
140  bool begin() {
141  TRACEI();
142 
143  if (info.sample_rate != 8000) {
144  LOGW("Sample rate is supposed to be 8000 - it was %d", info.sample_rate);
145  }
146  if (info.channels != 1) {
147  LOGW("channels is supposed to be 1 - it was %d", info.channels);
148  }
149 
150  v_gsm = gsm_create();
151  // 160 13-bit samples
152  input_buffer.resize(160 * sizeof(int16_t));
153  // gsm_frame of 33 bytes
154  result_buffer.resize(33);
155  is_active = true;
156  return true;
157  }
158 
159  virtual void end() {
160  TRACEI();
161  gsm_destroy(v_gsm);
162  is_active = false;
163  }
164 
165  virtual const char *mime() { return "audio/gsm"; }
166 
167  virtual void setOutput(Print &out_stream) { p_print = &out_stream; }
168 
169  operator bool() { return is_active; }
170 
171  virtual size_t write(const void *in_ptr, size_t in_size) {
172  LOGD("write: %d", in_size);
173  if (!is_active) {
174  LOGE("inactive");
175  return 0;
176  }
177  // encode bytes
178  uint8_t *p_byte = (uint8_t *) in_ptr;
179  for (int j = 0; j < in_size; j++) {
180  processByte(p_byte[j]);
181  }
182  return in_size;
183  }
184 
185  protected:
186  Print *p_print = nullptr;
187  gsm v_gsm;
188  bool is_active = false;
189  int buffer_pos = 0;
190  bool scaling_active;
191  Vector<uint8_t> input_buffer;
192  Vector<uint8_t> result_buffer;
193 
194  // add byte to decoding buffer and decode if buffer is full
195  void processByte(uint8_t byte) {
196  input_buffer[buffer_pos++] = byte;
197  if (buffer_pos >= input_buffer.size()) {
198  scaleValues(input_buffer);
199  // toBigEndian(input_buffer);
200  // encode
201  gsm_encode(v_gsm, (gsm_signal*)input_buffer.data(), result_buffer.data());
202  size_t written = p_print->write(result_buffer.data(), result_buffer.size());
203  assert(written == result_buffer.size());
204  buffer_pos = 0;
205  }
206  }
207 
208  void toBigEndian(Vector<uint8_t> &vector){
209  int size = vector.size() / 2;
210  int16_t *data16 = (int16_t*) vector.data();
211  for (int i=0; i<size; i++){
212  data16[i] = htons(data16[i]);
213  }
214  }
215 
216  void scaleValues(Vector<uint8_t> &vector) {
217  int16_t *pt16 = (int16_t *)vector.data();
218  int size = vector.size() / 2;
219  if (scaling_active){
220  // scale to 16 to 13-bit samples
221  for (int j = 0; j < size; j++) {
222  pt16[j] = pt16[j] / 8;
223  }
224  } else {
225  // clip value to 13-bits
226  for (int j = 0; j < size; j++) {
227  if ( pt16[j]>4095){
228  pt16[j] = 4095;
229  }
230  if ( pt16[j]<-4095){
231  pt16[j] = -4095;
232  }
233  }
234  }
235  }
236 };
237 
238 } // namespace audio_tools
Docoding of encoded audio into PCM data.
Definition: AudioEncoded.h:18
Encoding of PCM data.
Definition: AudioEncoded.h:88
Decoder for GSM. Depends on https://github.com/pschatzmann/arduino-libgsm. Inspired by gsmdec....
Definition: CodecGSM.h:26
virtual void setOutput(Print &out_stream)
Defines where the decoded result is written to.
Definition: CodecGSM.h:52
void processByte(uint8_t byte)
Build decoding buffer and decode when frame is full.
Definition: CodecGSM.h:80
Encoder for GSM - Depends on https://github.com/pschatzmann/arduino-libgsm. Inspired by gsmenc....
Definition: CodecGSM.h:132
virtual const char * mime()
Provides the mime type of the encoded result.
Definition: CodecGSM.h:165
Definition: NoArduino.h:58
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
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