arduino-audio-tools
Loading...
Searching...
No Matches
CodecADPCM.h
Go to the documentation of this file.
1#pragma once
2#include "ADPCM.h" // https://github.com/pschatzmann/codec-adpcm
4
5namespace audio_tools {
6
15 public:
16 ADPCMDecoder() = default;
17
18 ADPCMDecoder(AVCodecID id, int blockSize = ADAPCM_DEFAULT_BLOCK_SIZE) {
20 setId(id);
21 }
22
25 if (p_decoder) delete p_decoder;
26 }
27
28 const char *mime() override { return "audio/adpcm"; }
29
30 // (re) defines the codec id: set the block size first
31 void setId(AVCodecID id) {
32 codec_id = id;
33 if (p_decoder != nullptr) {
35 }
36 }
37
38 // defines the block size (= size of encoded frame)
39 void setBlockSize(int blockSize) override {
41 if (p_decoder == nullptr) return;
42 p_decoder->setBlockSize(blockSize);
43 }
44
47 int blockSize() {
48 if (p_decoder == nullptr) return block_size;
49 return p_decoder->blockSize();
50 }
51
54 int frameSize() {
55 if (p_decoder == nullptr) return 0;
56 return p_decoder->frameSize() * 2;
57 }
58
59 bool begin() override {
60 TRACEI();
61 if (p_decoder == nullptr) {
63 }
64 if (is_started) return true;
65 current_byte = 0;
66 LOGI("sample_rate: %d, channels: %d", info.sample_rate, info.channels);
68 LOGI("frameSize: %d", (int)frameSize());
69 LOGI("blockSize: %d", (int)blockSize());
70 block_size = p_decoder->blockSize();
71 assert(block_size > 0);
72 assert(p_decoder->frameSize() > 0);
74
76 is_started = true;
77 return true;
78 }
79
80 void end() override {
81 TRACEI();
82 if (p_decoder != nullptr) p_decoder->end();
84 is_started = false;
85 }
86
87 virtual void setOutput(Print &out_stream) override { p_print = &out_stream; }
88
89 virtual size_t write(const uint8_t *data, size_t len) override {
90 TRACED();
91
92 uint8_t *input_buffer8 = (uint8_t *)data;
93 LOGD("write: %d", (int)len);
94 for (int j = 0; j < len; j++) {
95 decode(input_buffer8[j]);
96 }
97 return len;
98 }
99
100 void flush() {
101 if (p_decoder != nullptr) p_decoder->flush();
102 }
103
104 operator bool() override { return is_started; }
105
111 switch (codec_id) {
112 case AV_CODEC_ID_ADPCM_MS:
113 return AudioFormat::ADPCM;
114 case AV_CODEC_ID_ADPCM_IMA_WAV:
116 case AV_CODEC_ID_ADPCM_YAMAHA:
118 default:
120 }
121 }
122
123 protected:
124 adpcm_ffmpeg::ADPCMDecoder *p_decoder = nullptr;
126 Print *p_print = nullptr;
128 int block_size = ADAPCM_DEFAULT_BLOCK_SIZE;
129 AVCodecID codec_id = AV_CODEC_ID_ADPCM_MS;
130 bool is_started = false;
131
132 virtual bool decode(uint8_t byte) {
133 if (p_decoder == nullptr) return false;
134 adpcm_block[current_byte++] = byte;
135
136 if (current_byte >= block_size) {
137 TRACED();
138 adpcm_ffmpeg::AVFrame &frame =
139 p_decoder->decode(&adpcm_block[0], block_size);
140 // print the result
141 int16_t *data = (int16_t *)frame.data[0];
142 size_t byte_count = frame.nb_samples * sizeof(int16_t) * info.channels;
143 size_t written = p_print->write((uint8_t *)data, byte_count);
144 if (written != byte_count) {
145 LOGE("decode %d -> %d -> %d", block_size, (int)byte_count,
146 (int)written);
147 } else {
148 LOGD("decode %d -> %d -> %d", block_size, (int)byte_count,
149 (int)written);
150 }
151
152 // restart from array begin
153 current_byte = 0;
154 }
155 return true;
156 }
157
160 // delete the old decoder
161 if (p_decoder != nullptr) {
162 p_decoder->end();
163 delete p_decoder;
164 p_decoder = nullptr;
165 }
166
167 if (codec_id == AV_CODEC_ID_ADPCM_IMA_AMV) {
168 info.sample_rate = 22050;
169 info.channels = 1;
171 }
172 p_decoder = adpcm_ffmpeg::ADPCMDecoderFactory::create(codec_id);
173 if (p_decoder != nullptr) {
174 p_decoder->setCodecID(codec_id);
175 p_decoder->setBlockSize(block_size);
176 } else {
177 LOGE("Decoder not implemented");
178 }
179 }
180};
181
190 public:
191 ADPCMEncoder() = default;
192
193 ADPCMEncoder(AVCodecID id, int blockSize = ADAPCM_DEFAULT_BLOCK_SIZE) {
194 setId(id);
196 }
197
200 if (p_encoder != nullptr) delete p_encoder;
201 }
202
204 void setId(AVCodecID id) {
205 codec_id = id;
206 if (p_encoder != nullptr) {
208 }
209 }
210
214 if (p_encoder == nullptr) return;
215 p_encoder->setBlockSize(blockSize);
216 }
217
220 int blockSize() override {
221 if (p_encoder == nullptr) return 0;
222 return p_encoder->blockSize();
223 }
224
227 int frameSize() {
228 if (p_encoder == nullptr) return 0;
229 return p_encoder->frameSize() * 2;
230 }
231
232 bool begin() override {
233 TRACEI();
234 if (p_encoder == nullptr) {
236 };
237 if (is_started) return true;
238 LOGI("sample_rate: %d, channels: %d", info.sample_rate, info.channels);
240 LOGI("frameSize: %d", (int)frameSize());
241 LOGI("blockSize: %d", (int)blockSize());
242 assert(info.sample_rate != 0);
243 assert(p_encoder->frameSize() != 0);
244 total_samples = p_encoder->frameSize() * info.channels;
246 current_sample = 0;
247
248 is_started = true;
249 return true;
250 }
251
252 void end() override {
253 TRACEI();
254 pcm_block.resize(0);
255 if (p_encoder == nullptr) return;
256 p_encoder->end();
257 is_started = false;
258 }
259
260 const char *mime() override { return "audio/adpcm"; }
261
262 void setOutput(Print &out_stream) override { p_print = &out_stream; }
263
264 operator bool() override { return is_started; }
265
266 size_t write(const uint8_t *data, size_t len) override {
267 LOGD("write: %d", (int)len);
268 int16_t *data16 = (int16_t *)data;
269 for (int j = 0; j < len / 2; j++) {
270 encode(data16[j]);
271 }
272 return len;
273 }
274
276 virtual uint32_t frameDurationUs() override {
277 if (p_encoder == nullptr || info.sample_rate == 0) {
278 return 20000; // Default 20ms if not initialized
279 }
280
281 // Get the number of samples per frame from the encoder
282 int samplesPerFrame = p_encoder->frameSize();
283 if (samplesPerFrame <= 0) {
284 return 20000; // Default 20ms if invalid frame size
285 }
286
287 // Calculate frame duration: (samples_per_frame / sample_rate) * 1000000 us
288 uint32_t durationUs = (samplesPerFrame * 1000000) / info.sample_rate;
289 return durationUs;
290 }
291
292 protected:
293 AVCodecID codec_id = AV_CODEC_ID_ADPCM_MS;
294 adpcm_ffmpeg::ADPCMEncoder *p_encoder = nullptr;
296 Print *p_print = nullptr;
297 bool is_started = false;
300 int current_id = -1;
301 int block_size = ADAPCM_DEFAULT_BLOCK_SIZE;
302
303 virtual bool encode(int16_t sample) {
304 if (p_encoder == nullptr) return false;
305 pcm_block[current_sample++] = sample;
307 TRACED();
308 adpcm_ffmpeg::AVPacket &packet =
309 p_encoder->encode(&pcm_block[0], total_samples);
310 if (packet.size > 0) {
311 size_t written = p_print->write(packet.data, packet.size);
312 if (written != packet.size) {
313 LOGE("encode %d->%d->%d", 2 * total_samples, (int)packet.size,
314 (int)written);
315 } else {
316 LOGD("encode %d->%d->%d", 2 * total_samples, (int)packet.size,
317 (int)written);
318 }
319 }
320 // restart from array begin
321 current_sample = 0;
322 }
323 return true;
324 }
325
328 bool rc = true;
329 // delete the old encoder
330 if (p_encoder != nullptr) {
331 p_encoder->end();
332 delete p_encoder;
333 p_encoder = nullptr;
334 }
335
336 if (codec_id == AV_CODEC_ID_ADPCM_IMA_AMV) {
337 info.sample_rate = 22050;
338 info.channels = 1;
340 }
341 p_encoder = adpcm_ffmpeg::ADPCMEncoderFactory::create(codec_id);
342 if (p_encoder != nullptr) {
343 p_encoder->setCodecID(codec_id);
344 p_encoder->setBlockSize(block_size);
345 } else {
346 LOGE("Encoder not implemented");
347 rc = false;
348 }
349 return rc;
350 }
351};
352
353} // namespace audio_tools
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define assert(T)
Definition avr.h:10
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Decoder for ADPCM. Depends on https://github.com/pschatzmann/adpcm.
Definition CodecADPCM.h:14
virtual size_t write(const uint8_t *data, size_t len) override
Definition CodecADPCM.h:89
int frameSize()
Definition CodecADPCM.h:54
adpcm_ffmpeg::ADPCMDecoder * p_decoder
Definition CodecADPCM.h:124
int blockSize()
Definition CodecADPCM.h:47
AudioFormat wavFormat() override
Definition CodecADPCM.h:110
bool is_started
Definition CodecADPCM.h:130
Vector< uint8_t > adpcm_block
Definition CodecADPCM.h:125
void setBlockSize(int blockSize) override
Definition CodecADPCM.h:39
void end() override
Definition CodecADPCM.h:80
int block_size
Definition CodecADPCM.h:128
void setId(AVCodecID id)
Definition CodecADPCM.h:31
int current_byte
Definition CodecADPCM.h:127
ADPCMDecoder(AVCodecID id, int blockSize=ADAPCM_DEFAULT_BLOCK_SIZE)
Definition CodecADPCM.h:18
~ADPCMDecoder()
Destructor.
Definition CodecADPCM.h:24
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition CodecADPCM.h:28
bool begin() override
Definition CodecADPCM.h:59
virtual void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition CodecADPCM.h:87
Print * p_print
Definition CodecADPCM.h:126
void flush()
Definition CodecADPCM.h:100
virtual bool decode(uint8_t byte)
Definition CodecADPCM.h:132
AVCodecID codec_id
Definition CodecADPCM.h:129
void setImplementation()
change the decoder implementation
Definition CodecADPCM.h:159
Encoder for ADPCM - Depends on https://github.com/pschatzmann/adpcm>
Definition CodecADPCM.h:189
void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition CodecADPCM.h:262
virtual bool encode(int16_t sample)
Definition CodecADPCM.h:303
int frameSize()
Definition CodecADPCM.h:227
adpcm_ffmpeg::ADPCMEncoder * p_encoder
Definition CodecADPCM.h:294
void setBlockSize(int blockSize)
(re) defines the block size
Definition CodecADPCM.h:212
bool setImplementation()
change the encoder implementation
Definition CodecADPCM.h:327
bool is_started
Definition CodecADPCM.h:297
void end() override
Definition CodecADPCM.h:252
~ADPCMEncoder()
Destructor.
Definition CodecADPCM.h:199
int block_size
Definition CodecADPCM.h:301
void setId(AVCodecID id)
(re) defines the codec id
Definition CodecADPCM.h:204
size_t write(const uint8_t *data, size_t len) override
Definition CodecADPCM.h:266
virtual uint32_t frameDurationUs() override
provides the frame duration in us (for rtsp)
Definition CodecADPCM.h:276
int current_id
Definition CodecADPCM.h:300
ADPCMEncoder(AVCodecID id, int blockSize=ADAPCM_DEFAULT_BLOCK_SIZE)
Definition CodecADPCM.h:193
Vector< int16_t > pcm_block
Definition CodecADPCM.h:295
const char * mime() override
Provides the mime type of the encoded result.
Definition CodecADPCM.h:260
int total_samples
Definition CodecADPCM.h:299
bool begin() override
Definition CodecADPCM.h:232
int blockSize() override
Definition CodecADPCM.h:220
Print * p_print
Definition CodecADPCM.h:296
int current_sample
Definition CodecADPCM.h:298
AVCodecID codec_id
Definition CodecADPCM.h:293
Extended AudioDecoder interface to support block size configuration.
Definition AudioCodecsBase.h:124
AudioInfo info
Definition AudioCodecsBase.h:80
int id
custom id to be used by application
Definition AudioCodecsBase.h:66
Extended AudioEncoder interface to support block size configuration.
Definition AudioCodecsBase.h:137
AudioInfo info
Definition AudioCodecsBase.h:120
virtual uint16_t samplesPerFrame()
Optional rtsp function: provide samples per the frame.
Definition AudioCodecsBase.h:117
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:175
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
AudioFormat
Audio format codes used by Microsoft e.g. in avi or wav files.
Definition AudioFormat.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
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