arduino-audio-tools
CodecADPCM.h
1 #pragma once
2 #include "ADPCM.h" // https://github.com/pschatzmann/adpcm
3 #include "AudioCodecs/AudioEncoded.h"
4 
5 namespace audio_tools {
6 
14 class ADPCMDecoder : public AudioDecoderExt {
15  public:
16  ADPCMDecoder(AVCodecID id, int blockSize = ADAPCM_DEFAULT_BLOCK_SIZE) {
17  info.sample_rate = 44100;
18  info.channels = 2;
19  info.bits_per_sample = 16;
20  decoder.setCodecID(id);
21  decoder.setBlockSize(blockSize);
22  }
23 
24  // defines the block size
25  void setBlockSize(int blockSize) override {
26  decoder.setBlockSize(blockSize);
27  }
28 
30  int blockSize() {
31  return decoder.blockSize();
32  }
33 
35  int frameSize() {
36  return decoder.frameSize()*2;
37  }
38 
39 
40  bool begin() override {
41  TRACEI();
42  if (is_started) return true;
43  current_byte = 0;
44  LOGI("sample_rate: %d, channels: %d", info.sample_rate, info.channels);
45  decoder.begin(info.sample_rate, info.channels);
46  LOGI("frameSize: %d", (int)frameSize());
47  LOGI("blockSize: %d", (int)blockSize());
48  block_size = decoder.blockSize();
49  assert(block_size > 0);
50  assert(decoder.frameSize() > 0);
51  adpcm_block.resize(block_size);
52 
53  notifyAudioChange(info);
54  is_started = true;
55  return true;
56  }
57 
58  void end() override {
59  TRACEI();
60  decoder.end();
61  adpcm_block.resize(0);
62  is_started = false;
63  }
64 
65  virtual void setOutput(Print &out_stream) override { p_print = &out_stream; }
66 
67  virtual size_t write(const void *input_buffer, size_t length) override {
68  TRACED();
69 
70  uint8_t *input_buffer8 = (uint8_t *)input_buffer;
71  LOGD("write: %d", (int)length);
72  for (int j = 0; j < length; j++) {
73  decode(input_buffer8[j]);
74  }
75  return length;
76  }
77 
78  operator bool() override { return is_started; }
79 
80  protected:
81  adpcm_ffmpeg::ADPCMDecoder decoder;
82  Vector<uint8_t> adpcm_block;
83  Print *p_print = nullptr;
84  int current_byte = 0;
85  int block_size = 0;
86  bool is_started = false;
87 
88  virtual bool decode(uint8_t byte) {
89  adpcm_block[current_byte++] = byte;
90 
91  if (current_byte >= block_size) {
92  TRACED();
93  AVFrame &frame = decoder.decode(&adpcm_block[0], block_size);
94  // print the result
95  int16_t *data = (int16_t *)frame.data[0];
96  size_t byte_count = frame.nb_samples * sizeof(int16_t) * info.channels;
97  size_t written = p_print->write((uint8_t *)data, byte_count);
98  if (written != byte_count) {
99  LOGE("decode %d -> %d -> %d",block_size, (int)byte_count, (int)written);
100  } else {
101  LOGD("decode %d -> %d -> %d",block_size, (int)byte_count, (int)written);
102  }
103 
104  // restart from array begin
105  current_byte = 0;
106  }
107  return true;
108  }
109 };
110 
119  public:
120  ADPCMEncoder(AVCodecID id, int blockSize = ADAPCM_DEFAULT_BLOCK_SIZE) {
121  info.sample_rate = 44100;
122  info.channels = 2;
123  info.bits_per_sample = 16;
124  encoder.setCodecID(id);
125  encoder.setBlockSize(blockSize);
126  }
127 
129  int blockSize() override {
130  return encoder.blockSize();
131  }
132 
134  int frameSize() {
135  return encoder.frameSize()*2;
136  }
137 
138  bool begin() override {
139  TRACEI();
140  if (is_started) return true;
141  LOGI("sample_rate: %d, channels: %d", info.sample_rate, info.channels);
142  encoder.begin(info.sample_rate, info.channels);
143  LOGI("frameSize: %d", (int)frameSize());
144  LOGI("blockSize: %d", (int)blockSize());
145  assert(info.sample_rate != 0);
146  assert(encoder.frameSize() != 0);
147  total_samples = encoder.frameSize()*info.channels;
148  pcm_block.resize(total_samples);
149  current_sample = 0;
150 
151  is_started = true;
152  return true;
153  }
154 
155  void end() override {
156  TRACEI();
157  pcm_block.resize(0);
158  encoder.end();
159  is_started = false;
160  }
161 
162  const char *mime() override { return "audio/adpcm"; }
163 
164  void setOutput(Print &out_stream) override { p_print = &out_stream; }
165 
166  operator bool() override { return is_started; }
167 
168  size_t write(const void *in_ptr, size_t in_size) override {
169  LOGD("write: %d", (int)in_size);
170  int16_t *data16 = (int16_t *)in_ptr;
171  for (int j = 0; j < in_size / 2; j++) {
172  encode(data16[j]);
173  }
174  return in_size;
175  }
176 
177  protected:
178  adpcm_ffmpeg::ADPCMEncoder encoder;
179  Vector<int16_t> pcm_block;
180  Print *p_print = nullptr;
181  bool is_started = false;
182  int current_sample = 0;
183  int total_samples=0;
184 
185  virtual bool encode(int16_t sample) {
186  pcm_block[current_sample++] = sample;
187  if (current_sample >= total_samples) {
188  TRACED();
189  AVPacket &packet = encoder.encode(&pcm_block[0], total_samples);
190  if (packet.size > 0) {
191  size_t written = p_print->write(packet.data, packet.size);
192  if (written != packet.size) {
193  LOGE("encode %d->%d->%d",2*total_samples, (int)packet.size, (int)written);
194  } else {
195  LOGD("encode %d->%d->%d",2*total_samples, (int)packet.size, (int)written);
196  }
197  }
198  // restart from array begin
199  current_sample = 0;
200  }
201  return true;
202  }
203 };
204 
205 } // namespace audio_tools
Decoder for ADPCM. Depends on https://github.com/pschatzmann/adpcm.
Definition: CodecADPCM.h:14
int frameSize()
Provides the frame size (size of decoded frame) (only available after calling begin)
Definition: CodecADPCM.h:35
int blockSize()
Provides the block size (size of encoded frame) (only available after calling begin)
Definition: CodecADPCM.h:30
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition: CodecADPCM.h:65
Encoder for ADPCM - Depends on https://github.com/pschatzmann/adpcm.
Definition: CodecADPCM.h:118
int frameSize()
Provides the frame size (size of decoded frame) (only available after calling begin)
Definition: CodecADPCM.h:134
const char * mime() override
Provides the mime type of the encoded result.
Definition: CodecADPCM.h:162
int blockSize() override
Provides the block size (size of encoded frame) (only available after calling begin)
Definition: CodecADPCM.h:129
Definition: AudioEncoded.h:104
Definition: AudioEncoded.h:109
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
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57