arduino-audio-tools
Loading...
Searching...
No Matches
CodecWAV.h
Go to the documentation of this file.
1#pragma once
2
7
8#define READ_BUFFER_SIZE 512
9#define MAX_WAV_HEADER_LEN 200
10
11namespace audio_tools {
12
20 WAVAudioInfo() = default;
21 WAVAudioInfo(const AudioInfo &from) {
23 channels = from.channels;
25 }
26
28 int byte_rate = 0;
29 int block_align = 0;
30 bool is_streamed = true;
31 bool is_valid = false;
32 uint32_t data_length = 0;
33 uint32_t file_size = 0;
34 int offset = 0;
36 bool ext_adpcm_header = false;
37};
38
39static const char *wav_mime = "audio/wav";
40
67class WAVHeader {
68 public:
69 WAVHeader() = default;
70
73 int write(uint8_t *data, size_t data_len) {
74 return buffer.writeArray(data, data_len);
75 }
76
78 bool parse() {
79 LOGI("WAVHeader::begin: %u", (unsigned)buffer.available());
80 this->data_pos = 0l;
81 memset((void *)&headerInfo, 0, sizeof(WAVAudioInfo));
82
83 if (!setPos("RIFF")) return false;
84 // RIFF stores chunk_size (= file_size - 8): normalize to full file size
86 if (!setPos("WAVE")) return false;
87 if (!setPos("fmt ")) return false;
88 int fmt_length = read_int32();
95 if (!setPos("data")) return false;
97 if (headerInfo.data_length == 0 || headerInfo.data_length >= 0x7fff0000) {
100 }
101
102 logInfo();
103 buffer.clear();
104 return true;
105 }
106
109 int pos = getDataPos();
110 return pos > 0 && buffer.available() >= pos;
111 }
112
114 size_t available() { return buffer.available(); }
115
118 int pos =
120 .indexOf("data");
121 return pos > 0 ? pos + 8 : 0;
122 }
123
126
128 void setAudioInfo(WAVAudioInfo info) { headerInfo = info; }
129
131 bool writeHeader(Print *out) {
132 return writeHeader(out, headerInfo);
133 }
134
136 bool writeHeader(Print *out, const WAVAudioInfo &info) {
137 // reset first: buffer otherwise keeps accumulating bytes from earlier calls
138 buffer.reset();
139 writeRiffHeader(buffer, info);
140 writeFMT(buffer, info);
141 if (isADPCM(info.format) && info.ext_adpcm_header) {
142 writeFactChunk(buffer, info);
143 }
144 writeDataHeader(buffer, info);
145 int len = buffer.available();
146 int written = out->write(buffer.data(), len);
147 if (written != len) {
148 LOGE("Failed to write WAV header to output: written %d of %d bytes", written, len);
149 }
150 return written == len;
151 }
152
157 static int extraHeaderBytes(const WAVAudioInfo &info) {
158 if (!info.ext_adpcm_header) return 0;
159 switch (info.format) {
160 case AudioFormat::ADPCM: // MS ADPCM: 34 byte fmt extension + 12 byte fact chunk
161 return 34 + 12;
162 case AudioFormat::DVI_ADPCM: // IMA/DVI ADPCM: 4 byte fmt extension + 12 byte fact chunk
163 return 4 + 12;
164 default:
165 return 0;
166 }
167 }
168
170 void clear() {
171 data_pos = 0;
172 WAVAudioInfo empty;
173 empty.sample_rate = 0;
174 empty.channels = 0;
175 empty.bits_per_sample = 0;
176 headerInfo = empty;
178 buffer.reset();
179 }
180
182 void dumpHeader() {
183 char msg[buffer.available() + 1];
184 memset(msg, 0, buffer.available() + 1);
185 for (int j = 0; j < buffer.available(); j++) {
186 char c = (char)buffer.data()[j];
187 if (!isalpha(c)) {
188 c = '.';
189 }
190 msg[j] = c;
191 }
192 LOGI("Header: %s", msg);
193 }
194
195 protected:
198 size_t data_pos = 0;
199
200 bool setPos(const char *id) {
201 int id_len = strlen(id);
202 int pos = indexOf(id);
203 if (pos < 0) return false;
204 data_pos = pos + id_len;
205 return true;
206 }
207
208 int indexOf(const char *str) {
209 return StrView((char *)buffer.data(), MAX_WAV_HEADER_LEN,
211 .indexOf(str);
212 }
213
214 uint32_t read_tag() {
215 uint32_t tag = 0;
216 tag = (tag << 8) | getChar();
217 tag = (tag << 8) | getChar();
218 tag = (tag << 8) | getChar();
219 tag = (tag << 8) | getChar();
220 return tag;
221 }
222
223 uint32_t getChar32() { return getChar(); }
224
225 uint32_t read_int32() {
226 uint32_t value = 0;
227 value |= getChar32() << 0;
228 value |= getChar32() << 8;
229 value |= getChar32() << 16;
230 value |= getChar32() << 24;
231 return value;
232 }
233
234 uint16_t read_int16() {
235 uint16_t value = 0;
236 value |= getChar() << 0;
237 value |= getChar() << 8;
238 return value;
239 }
240
241 void skip(int n) {
242 int i;
243 for (i = 0; i < n; i++) getChar();
244 }
245
246 int getChar() {
247 if (data_pos < buffer.size())
248 return buffer.data()[data_pos++];
249 else
250 return -1;
251 }
252
253 void seek(long int offset, int origin) {
254 if (origin == SEEK_SET) {
255 data_pos = offset;
256 } else if (origin == SEEK_CUR) {
257 data_pos += offset;
258 }
259 }
260
261 size_t tell() { return data_pos; }
262
263 bool eof() { return data_pos >= buffer.size() - 1; }
264
265 void logInfo() {
266 LOGI("WAVHeader sound_pos: %d", getDataPos());
267 LOGI("WAVHeader channels: %d ", headerInfo.channels);
268 LOGI("WAVHeader bits_per_sample: %d", headerInfo.bits_per_sample);
269 LOGI("WAVHeader sample_rate: %d ", (int)headerInfo.sample_rate);
270 LOGI("WAVHeader format: %d", (int)headerInfo.format);
271 }
272
274 const WAVAudioInfo &info) {
275 buffer.writeArray((uint8_t *)"RIFF", 4);
276 // chunk_size = file_size - 8 (RIFF header size)
277 uint32_t chunk_size = info.file_size > 8 ? info.file_size - 8 : 0;
278 LOGI("writeRiffHeader: file_size=%u riff_size=%u", info.file_size, chunk_size);
279 write32(buffer, chunk_size);
280 buffer.writeArray((uint8_t *)"WAVE", 4);
281 }
282
284 bool is_ms_adpcm = info.ext_adpcm_header && info.format == AudioFormat::ADPCM;
285 bool is_ima_adpcm = info.ext_adpcm_header && info.format == AudioFormat::DVI_ADPCM;
286 uint16_t fmt_len = 16;
287 if (is_ima_adpcm) fmt_len = 20;
288 else if (is_ms_adpcm) fmt_len = 50;
289
290 uint16_t spb = samplesPerBlock(info);
291 uint32_t byte_rate = info.byte_rate;
292 if ((is_ms_adpcm || is_ima_adpcm) && spb > 0 && info.block_align > 0) {
293 // average bytes/sec = (sample_rate * block_align) / samples_per_block
294 byte_rate = ((uint64_t)info.sample_rate * info.block_align) / spb;
295 }
296
297 buffer.writeArray((uint8_t *)"fmt ", 4);
298 write32(buffer, fmt_len);
299 write16(buffer, (uint16_t)info.format);
300 write16(buffer, info.channels);
302 write32(buffer, byte_rate);
303 write16(buffer, info.block_align); // frame size
305
306 if (is_ima_adpcm) {
307 write16(buffer, 2); // cbSize: size of extra format bytes
308 write16(buffer, spb); // wSamplesPerBlock
309 } else if (is_ms_adpcm) {
310 // standard MS ADPCM coefficient table (7 predictor pairs)
311 static const int16_t ms_adpcm_coef[7][2] = {
312 {256, 0}, {512, -256}, {0, 0}, {192, 64},
313 {240, 0}, {460, -208}, {392, -232}};
314 write16(buffer, 32); // cbSize: size of extra format bytes
315 write16(buffer, spb); // wSamplesPerBlock
316 write16(buffer, 7); // wNumCoef
317 for (auto &c : ms_adpcm_coef) {
318 write16(buffer, (uint16_t)c[0]);
319 write16(buffer, (uint16_t)c[1]);
320 }
321 }
322 }
323
327 buffer.writeArray((uint8_t *)"fact", 4);
328 write32(buffer, 4); // chunk size
329 uint32_t sample_length = 0;
330 uint16_t spb = samplesPerBlock(info);
331 if (!info.is_streamed && spb > 0 && info.block_align > 0) {
332 sample_length = (info.data_length / info.block_align) * spb;
333 }
334 write32(buffer, sample_length);
335 }
336
338 buffer.writeArray((uint8_t *)"data", 4);
339 uint32_t data_length = info.data_length;
340 uint32_t header_bytes = 36 + extraHeaderBytes(info);
341 if (headerInfo.is_streamed && data_length == 0) {
342 data_length = ~0; // use max value for streamed data if not set
343 }
344 if (!headerInfo.is_streamed && info.file_size >= header_bytes && (data_length == 0 || data_length == ~0)) {
345 data_length = info.file_size - header_bytes; // data length = file size - header size
346 }
347 LOGI("writeDataHeader: data_length=%u", data_length);
348 write32(buffer, data_length);
349 int offset = info.offset;
350 if (offset > 0) {
351 uint8_t empty[offset];
352 memset(empty, 0, offset);
353 buffer.writeArray(empty, offset); // resolve issue with wrong aligment
354 }
355 }
356
357 static bool isADPCM(AudioFormat format) {
358 return format == AudioFormat::ADPCM || format == AudioFormat::DVI_ADPCM;
359 }
360
363 static uint16_t samplesPerBlock(const WAVAudioInfo &info) {
364 if (info.channels <= 0 || info.block_align <= 0) return 0;
365 switch (info.format) {
366 case AudioFormat::ADPCM: // MS ADPCM
367 return ((info.block_align / info.channels) - 7) * 2 + 2;
368 case AudioFormat::DVI_ADPCM: // IMA/DVI ADPCM
369 return ((info.block_align / info.channels) - 4) * 2 + 1;
370 default:
371 return 0;
372 }
373 }
374
375 void write32(BaseBuffer<uint8_t> &buffer, uint64_t value) {
376 buffer.writeArray((uint8_t *)&value, 4);
377 }
378
379 void write16(BaseBuffer<uint8_t> &buffer, uint16_t value) {
380 buffer.writeArray((uint8_t *)&value, 2);
381 }
382
383};
384
406class WAVDecoder : public AudioDecoder {
407
408 public:
412 WAVDecoder() = default;
413
419
422 TRACED();
423 decoder_format = fmt;
424 p_decoder = &dec;
425 }
426
428 void setOutput(Print &out_stream) override { this->p_print = &out_stream; }
429
431 bool begin() override {
432 TRACED();
433 header.clear();
436 buffer24.reset();
437 isFirst = true;
438 active = true;
439 return true;
440 }
441
443 void end() override {
444 TRACED();
446 buffer24.reset();
447 active = false;
448 }
449
451 const char *mime() { return wav_mime; }
452
455
457 AudioInfo audioInfo() override {
459 if (convert8to16 && info.format == AudioFormat::PCM &&
460 info.bits_per_sample == 8) {
462 }
463 // 32 bits gives better result
464 if (convert24 && info.format == AudioFormat::PCM &&
465 info.bits_per_sample == 24) {
467 }
468 // non-PCM (e.g. ADPCM) is decoded by p_decoder to 16-bit PCM
469 if (info.format != AudioFormat::PCM) {
471 }
472 return info;
473 }
474
476 virtual size_t write(const uint8_t *data, size_t len) override {
477 TRACED();
478 size_t result = 0;
479 if (active) {
480 if (isFirst) {
481 int data_start = decodeHeader((uint8_t *)data, len);
482 // we do not have the complete header yet: need more data
483 if (data_start == 0) return len;
484 // process the outstanding data
485 result = data_start +
486 write_out((uint8_t *)data + data_start, len - data_start);
487
488 } else if (isValid) {
489 result = write_out((uint8_t *)data, len);
490 }
491 }
492 return result;
493 }
494
496 virtual operator bool() override { return active; }
497
499 void setConvert8Bit(bool enable) {
500 convert8to16 = enable;
501 }
502
504 void setConvert24Bit(bool enable) {
505 convert24 = enable;
506 }
507
510
511 protected:
513 bool isFirst = true;
514 bool isValid = true;
515 bool active = false;
521 bool convert8to16 = true; // Optional conversion flag
522 bool convert24 = true; // Optional conversion flag
523 const size_t batch_size = 256;
524
525 Print &out() { return p_decoder == nullptr ? *p_print : dec_out; }
526
527 virtual size_t write_out(const uint8_t *in_ptr, size_t in_size) {
528 // check if we need to convert int24 data from 3 bytes to 4 bytes
529 size_t result = 0;
531 header.audioInfo().bits_per_sample == 24 && sizeof(int24_t) == 4) {
532 write_out_24(in_ptr, in_size);
533 result = in_size;
536 result = write_out_8to16(in_ptr, in_size);
537 } else {
538 result = out().write(in_ptr, in_size);
539 }
540 return result;
541 }
542
544 size_t write_out_8to16(const uint8_t *in_ptr, size_t in_size) {
545 size_t total_written = 0;
546 size_t samples_remaining = in_size;
547 size_t offset = 0;
548 int16_t out_buf[batch_size];
549 while (samples_remaining > 0) {
550 size_t current_batch =
551 samples_remaining > batch_size ? batch_size : samples_remaining;
552 for (size_t i = 0; i < current_batch; ++i) {
553 out_buf[i] = ((int16_t)in_ptr[offset + i] - 128) << 8;
554 }
555 writeDataT<int16_t>(&out(), out_buf, current_batch);
556 offset += current_batch;
557 samples_remaining -= current_batch;
558 }
559 return in_size;
560 }
561
563 size_t write_out_24(const uint8_t *in_ptr, size_t in_size) {
564 // store 1 sample
567
568 for (size_t i = 0; i < in_size; i++) {
569 // Add byte to buffer
570 byte_buffer.write(in_ptr[i]);
571
572 // Process complete sample when buffer is full
573 if (byte_buffer.isFull()) {
574 int24_3bytes_t sample24{byte_buffer.data()};
575 int32_t converted_sample = sample24.scale32();
576 buffer24.write(converted_sample);
577 if (buffer24.isFull()) {
578 writeDataT<int32_t>(&out(), buffer24.data(), buffer24.available());
579 buffer24.reset();
580 }
582 }
583 }
584
585 return in_size;
586 }
587
588
590 int decodeHeader(uint8_t *in_ptr, size_t in_size) {
591 int result = in_size;
592 // we expect at least the full header
593 int written = header.write(in_ptr, in_size);
594 if (!header.isDataComplete()) {
595 LOGW("WAV header misses 'data' section in len: %d",
596 (int)header.available());
598 return 0;
599 }
600 // parse header
601 if (!header.parse()) {
602 LOGE("WAV header parsing failed");
603 return 0;
604 }
605
606 isFirst = false;
608
609 LOGI("WAV sample_rate: %d", (int)header.audioInfo().sample_rate);
610 LOGI("WAV data_length: %u", (unsigned)header.audioInfo().data_length);
611 LOGI("WAV is_streamed: %d", header.audioInfo().is_streamed);
612 LOGI("WAV is_valid: %s", header.audioInfo().is_valid ? "true" : "false");
613
614 // check format
616 isValid = format == decoder_format;
617 if (isValid) {
618 // update blocksize
619 if (p_decoder != nullptr) {
620 int block_size = header.audioInfo().block_align;
621 p_decoder->setBlockSize(block_size);
622 }
623
624 // update sampling rate if the target supports it
625 AudioInfo bi = audioInfo();
627 } else {
628 LOGE("WAV format not supported: %d", (int)format);
629 }
630 return header.getDataPos();
631 }
632
634 if (p_decoder != nullptr) {
635 assert(p_print != nullptr);
639 }
640 }
641};
642
653class WAVEncoder : public AudioEncoder {
654 public:
658 WAVEncoder() = default;
659
664
667 TRACED();
668 wav_info.format = fmt;
669 p_encoder = &enc;
670 }
671
673 void setOutput(Print &out) override {
674 TRACED();
675 p_print = &out;
676 }
677
679 const char *mime() override { return wav_mime; }
680
684 info.format = AudioFormat::PCM;
688 info.is_streamed = true;
689 info.is_valid = true;
690 info.data_length = 0x7fff0000;
691 info.file_size = info.data_length + 36;
692 return info;
693 }
694
696 virtual void setAudioInfo(AudioInfo from) override {
700 // recalculate byte rate, block align...
702 }
703
705 virtual void setAudioInfo(WAVAudioInfo ai) {
708 wav_info = ai;
709 LOGI("sample_rate: %d", (int)wav_info.sample_rate);
710 LOGI("channels: %d", wav_info.channels);
711 LOGI("bits_per_sample: %d", wav_info.bits_per_sample);
712 // bytes per second
718 }
719 }
720
723 header.clear();
724 setAudioInfo(ai);
725 return begin();
726 }
727
729 virtual bool begin() override {
730 TRACED();
732
733 // normalize streaming mode and payload limits at start time
735 wav_info.data_length >= 0x7fff0000) {
736 LOGI("is_streamed! because length is %u",
737 (unsigned)wav_info.data_length);
738 wav_info.is_streamed = true;
740 size_limit = 0;
741 } else {
742 wav_info.is_streamed = false;
744 LOGI("size_limit is %d", (int)size_limit);
745 }
746
747 header_written = false;
748 is_open = true;
749 return true;
750 }
751
753 void end() override { is_open = false; }
754
756 virtual size_t write(const uint8_t *data, size_t len) override {
757 if (!is_open) {
758 LOGE("The WAVEncoder is not open - please call begin()");
759 return 0;
760 }
761
762 if (p_print == nullptr) {
763 LOGE("No output stream was provided");
764 return 0;
765 }
766
767 if (!header_written) {
768 LOGI("Writing Header");
770 LOGE("Failed to write WAV header");
771 is_open = false;
772 return 0;
773 }
774 header_written = true;
775 }
776
777 int32_t result = 0;
778 Print *p_out = p_encoder == nullptr ? p_print : &enc_out;
779
780 if (wav_info.is_streamed) {
781 result = p_out->write((uint8_t *)data, len);
782 } else if (size_limit > 0) {
783 size_t write_size = min((size_t)len, (size_t)size_limit);
784 result = p_out->write((uint8_t *)data, write_size);
785 size_limit -= result;
786
787 if (size_limit <= 0) {
788 LOGI("The defined size was written - so we close the WAVEncoder now");
789 is_open = false;
790 }
791 }
792 return result;
793 }
794
796 operator bool() override { return is_open; }
797
799 bool isOpen() { return is_open; }
800
802 void setDataOffset(uint16_t offset) { wav_info.offset = offset; }
803
806 void setExtADPCMHeader(bool enable) { wav_info.ext_adpcm_header = enable; }
807
809 void setDataLength(uint32_t data_length) {
810 wav_info.data_length = data_length;
812 (data_length == 0 || data_length >= 0x7fff0000);
813 if (!wav_info.is_streamed) {
814 // full file size = RIFF chunk (36) + format specific extra header
815 // bytes (e.g. ADPCM 'fmt ' extension + 'fact' chunk) + data chunk payload
818 }
820 }
821
824
827
828 protected:
830 Print *p_print = nullptr; // final output CopyEncoder copy; // used for PCM
834 int64_t size_limit = 0;
835 bool header_written = false;
836 volatile bool is_open = false;
837
839 if (p_encoder != nullptr) {
840 assert(p_print != nullptr);
844 enc_out.begin();
845 // block size only available after begin(): update block size
847 }
848 }
849};
850
851} // namespace audio_tools
WAV Audio Formats used by Microsoft e.g. in AVI video files.
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define DEFAULT_BITS_PER_SAMPLE
Definition AudioToolsConfig.h:104
#define DEFAULT_CHANNELS
Definition AudioToolsConfig.h:100
#define DEFAULT_SAMPLE_RATE
Definition AudioToolsConfig.h:96
#define MAX_WAV_HEADER_LEN
Definition CodecWAV.h:9
#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
Extended AudioDecoder interface to support block size configuration.
Definition AudioCodecsBase.h:120
virtual void setBlockSize(int blockSize)=0
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
AudioInfo info
Definition AudioCodecsBase.h:76
Print * p_print
Definition AudioCodecsBase.h:75
Extended AudioEncoder interface to support block size configuration.
Definition AudioCodecsBase.h:126
Encoding of PCM data.
Definition AudioCodecsBase.h:97
AudioInfo info
Definition AudioCodecsBase.h:116
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:106
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:174
Shared functionality of all buffers.
Definition Buffers.h:23
void clear()
same as reset
Definition Buffers.h:96
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition AudioEncoded.h:21
void setEncoder(AudioEncoder *encoder)
Definition AudioEncoded.h:131
bool begin() override
Starts the processing - sets the status to active.
Definition AudioEncoded.h:161
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioEncoded.h:87
void setDecoder(AudioDecoder *decoder)
Definition AudioEncoded.h:144
void setOutput(Print *outputStream)
Defines the output.
Definition AudioEncoded.h:107
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:184
size_t size() override
Definition Buffers.h:315
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:218
void setClearWithZero(bool flag)
Sets the buffer to 0 on clear.
Definition Buffers.h:326
int available() override
provides the number of entries that are available to read
Definition Buffers.h:245
bool isFull() override
checks if the buffer is full
Definition Buffers.h:252
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:213
T * data()
Provides address of actual data.
Definition Buffers.h:296
bool resize(size_t size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:317
void reset() override
clears the buffer
Definition Buffers.h:298
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition StrView.h:28
virtual int indexOf(const char c, int start=0)
Definition StrView.h:260
A simple WAVDecoder: We parse the header data on the first record to determine the format....
Definition CodecWAV.h:406
virtual size_t write(const uint8_t *data, size_t len) override
Write incoming WAV data (header + PCM) into output.
Definition CodecWAV.h:476
bool active
Definition CodecWAV.h:515
void setOutput(Print &out_stream) override
Defines the output Stream.
Definition CodecWAV.h:428
bool isFirst
Definition CodecWAV.h:513
void setDecoder(AudioDecoderExt &dec, AudioFormat fmt)
Defines an optional decoder if the format is not PCM.
Definition CodecWAV.h:421
size_t write_out_24(const uint8_t *in_ptr, size_t in_size)
convert 3 byte int24 to 4 byte int32
Definition CodecWAV.h:563
Print & out()
Definition CodecWAV.h:525
int decodeHeader(uint8_t *in_ptr, size_t in_size)
Decodes the header data: Returns the start pos of the data.
Definition CodecWAV.h:590
AudioDecoderExt * p_decoder
Definition CodecWAV.h:517
void setConvert8Bit(bool enable)
Convert 8 bit to 16 bit PCM data (default: enabled)
Definition CodecWAV.h:499
void setupEncodedAudio()
Definition CodecWAV.h:633
void end() override
Finish decoding and release temporary buffers.
Definition CodecWAV.h:443
AudioFormat decoder_format
Definition CodecWAV.h:516
WAVHeader & getHeader()
Access to the internal header parser and info.
Definition CodecWAV.h:509
const char * mime()
Provides MIME type "audio/wav".
Definition CodecWAV.h:451
bool isValid
Definition CodecWAV.h:514
WAVDecoder()=default
Construct a new WAVDecoder object for PCM data.
const size_t batch_size
Definition CodecWAV.h:523
SingleBuffer< uint8_t > byte_buffer
Definition CodecWAV.h:519
WAVAudioInfo & audioInfoEx()
Extended WAV specific info (original header values)
Definition CodecWAV.h:454
WAVHeader header
Definition CodecWAV.h:512
WAVDecoder(AudioDecoderExt &dec, AudioFormat fmt)
Construct a new WAVDecoder object for ADPCM data.
Definition CodecWAV.h:418
void setConvert24Bit(bool enable)
Convert 24 bit (3 byte) to 32 bit (4 byte) PCM data (default: enabled)
Definition CodecWAV.h:504
bool begin() override
Prepare decoder for a new WAV stream.
Definition CodecWAV.h:431
size_t write_out_8to16(const uint8_t *in_ptr, size_t in_size)
Convert 8-bit PCM to 16-bit PCM and write out.
Definition CodecWAV.h:544
EncodedAudioOutput dec_out
Definition CodecWAV.h:518
bool convert24
Definition CodecWAV.h:522
virtual size_t write_out(const uint8_t *in_ptr, size_t in_size)
Definition CodecWAV.h:527
AudioInfo audioInfo() override
Exposed AudioInfo (may reflect conversion flags)
Definition CodecWAV.h:457
bool convert8to16
Definition CodecWAV.h:521
SingleBuffer< int32_t > buffer24
Definition CodecWAV.h:520
A simple WAV file encoder. If no AudioEncoderExt is specified the WAV file contains PCM data,...
Definition CodecWAV.h:653
virtual size_t write(const uint8_t *data, size_t len) override
Writes PCM data to be encoded as WAV.
Definition CodecWAV.h:756
void setOutput(Print &out) override
Defines the otuput stream.
Definition CodecWAV.h:673
volatile bool is_open
Definition CodecWAV.h:836
bool isOpen()
Check if encoder is open.
Definition CodecWAV.h:799
void setupEncodedAudio()
Definition CodecWAV.h:838
virtual bool begin() override
starts the processing using the actual WAVAudioInfo
Definition CodecWAV.h:729
bool header_written
Definition CodecWAV.h:835
AudioEncoderExt * p_encoder
Definition CodecWAV.h:831
bool begin(WAVAudioInfo ai)
starts the processing
Definition CodecWAV.h:722
WAVAudioInfo wav_info
Definition CodecWAV.h:833
void end() override
stops the processing
Definition CodecWAV.h:753
virtual void setAudioInfo(WAVAudioInfo ai)
Defines the WAVAudioInfo.
Definition CodecWAV.h:705
int64_t size_limit
Definition CodecWAV.h:834
WAVEncoder()=default
Construct a new WAVEncoder object for PCM data.
void setDataOffset(uint16_t offset)
Adds n empty bytes at the beginning of the data.
Definition CodecWAV.h:802
WAVHeader & getHeader()
Access to the internal header parser and info.
Definition CodecWAV.h:826
EncodedAudioOutput enc_out
Definition CodecWAV.h:832
void setExtADPCMHeader(bool enable)
Definition CodecWAV.h:806
WAVAudioInfo & audioInfoEx()
Extended WAV specific info.
Definition CodecWAV.h:823
WAVEncoder(AudioEncoderExt &enc, AudioFormat fmt)
Construct a new WAVEncoder object for ADPCM data.
Definition CodecWAV.h:663
WAVAudioInfo defaultConfig()
Provides the default configuration.
Definition CodecWAV.h:682
WAVHeader header
Definition CodecWAV.h:829
const char * mime() override
Provides "audio/wav".
Definition CodecWAV.h:679
virtual void setAudioInfo(AudioInfo from) override
Update actual WAVAudioInfo.
Definition CodecWAV.h:696
Print * p_print
Definition CodecWAV.h:830
void setEncoder(AudioEncoderExt &enc, AudioFormat fmt)
Associates an external encoder for non-PCM formats.
Definition CodecWAV.h:666
void setDataLength(uint32_t data_length)
Defines the WAV payload length in bytes (without header)
Definition CodecWAV.h:809
Parser for Wav header data for details see https://de.wikipedia.org/wiki/RIFF_WAVE.
Definition CodecWAV.h:67
void writeDataHeader(BaseBuffer< uint8_t > &buffer, const WAVAudioInfo &info)
Definition CodecWAV.h:337
void logInfo()
Definition CodecWAV.h:265
void write16(BaseBuffer< uint8_t > &buffer, uint16_t value)
Definition CodecWAV.h:379
bool parse()
Call when header data write is complete to parse the data.
Definition CodecWAV.h:78
bool isDataComplete()
Returns true if the header is complete (containd data tag)
Definition CodecWAV.h:108
void skip(int n)
Definition CodecWAV.h:241
void seek(long int offset, int origin)
Definition CodecWAV.h:253
void setAudioInfo(WAVAudioInfo info)
Sets the info in the header.
Definition CodecWAV.h:128
bool eof()
Definition CodecWAV.h:263
void writeFMT(BaseBuffer< uint8_t > &buffer, const WAVAudioInfo &info)
Definition CodecWAV.h:283
bool writeHeader(Print *out, const WAVAudioInfo &info)
Just write a wav header with explicit info to the indicated output.
Definition CodecWAV.h:136
size_t available()
number of bytes available in the header buffer
Definition CodecWAV.h:114
bool writeHeader(Print *out)
Just write a wav header to the indicated outputbu.
Definition CodecWAV.h:131
int getChar()
Definition CodecWAV.h:246
int getDataPos()
Determines the data start position using the data tag.
Definition CodecWAV.h:117
SingleBuffer< uint8_t > buffer
Definition CodecWAV.h:197
WAVAudioInfo & audioInfo()
provides the info from the header
Definition CodecWAV.h:125
static uint16_t samplesPerBlock(const WAVAudioInfo &info)
Definition CodecWAV.h:363
static bool isADPCM(AudioFormat format)
Definition CodecWAV.h:357
int write(uint8_t *data, size_t data_len)
Definition CodecWAV.h:73
void clear()
Reset internal stored header information and buffer.
Definition CodecWAV.h:170
uint32_t read_tag()
Definition CodecWAV.h:214
void writeRiffHeader(BaseBuffer< uint8_t > &buffer, const WAVAudioInfo &info)
Definition CodecWAV.h:273
WAVAudioInfo headerInfo
Definition CodecWAV.h:196
uint16_t read_int16()
Definition CodecWAV.h:234
bool setPos(const char *id)
Definition CodecWAV.h:200
uint32_t read_int32()
Definition CodecWAV.h:225
int indexOf(const char *str)
Definition CodecWAV.h:208
void writeFactChunk(BaseBuffer< uint8_t > &buffer, const WAVAudioInfo &info)
Definition CodecWAV.h:326
size_t data_pos
Definition CodecWAV.h:198
static int extraHeaderBytes(const WAVAudioInfo &info)
Definition CodecWAV.h:157
void write32(BaseBuffer< uint8_t > &buffer, uint64_t value)
Definition CodecWAV.h:375
void dumpHeader()
Debug helper: dumps header bytes as printable characters.
Definition CodecWAV.h:182
size_t tell()
Definition CodecWAV.h:261
uint32_t getChar32()
Definition CodecWAV.h:223
24bit integer which is used for I2S sound processing. The values are really using 3 bytes....
Definition Int24_3bytes_t.h:21
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition Int24_4bytes_t.h:22
AudioFormat
Audio format codes used by Microsoft e.g. in avi or wav files.
Definition AudioFormat.h:19
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
static const char * wav_mime
Definition CodecWAV.h:39
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
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
Sound information which is available in the WAV header.
Definition CodecWAV.h:19
AudioFormat format
Definition CodecWAV.h:27
bool is_streamed
Definition CodecWAV.h:30
bool is_valid
Definition CodecWAV.h:31
int block_align
Definition CodecWAV.h:29
WAVAudioInfo(const AudioInfo &from)
Definition CodecWAV.h:21
uint32_t file_size
Definition CodecWAV.h:33
int offset
Definition CodecWAV.h:34
int byte_rate
Definition CodecWAV.h:28
uint32_t data_length
Definition CodecWAV.h:32
bool ext_adpcm_header
write the extended 'fmt ' chunk + 'fact' chunk for ADPCM formats
Definition CodecWAV.h:36