arduino-audio-tools
Loading...
Searching...
No Matches
CodecWAV.h
1#pragma once
2
3#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
4#include "AudioTools/AudioCodecs/AudioEncoded.h"
6#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
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
27 AudioFormat format = AudioFormat::PCM;
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;
35};
36
37static const char *wav_mime = "audio/wav";
38
46class WAVHeader {
47 public:
48 WAVHeader() = default;
49
52 int write(uint8_t *data, size_t data_len) {
53 return buffer.writeArray(data, data_len);
54 }
55
57 bool parse() {
58 LOGI("WAVHeader::begin: %u", (unsigned)buffer.available());
59 this->data_pos = 0l;
60 memset((void *)&headerInfo, 0, sizeof(WAVAudioInfo));
61
62 if (!setPos("RIFF")) return false;
63 headerInfo.file_size = read_int32();
64 if (!setPos("WAVE")) return false;
65 if (!setPos("fmt ")) return false;
66 int fmt_length = read_int32();
67 headerInfo.format = (AudioFormat)read_int16();
68 headerInfo.channels = read_int16();
69 headerInfo.sample_rate = read_int32();
70 headerInfo.byte_rate = read_int32();
71 headerInfo.block_align = read_int16();
72 headerInfo.bits_per_sample = read_int16();
73 if (!setPos("data")) return false;
74 headerInfo.data_length = read_int32();
75 if (headerInfo.data_length == 0 || headerInfo.data_length >= 0x7fff0000) {
76 headerInfo.is_streamed = true;
77 headerInfo.data_length = ~0;
78 }
79
80 logInfo();
81 buffer.clear();
82 return true;
83 }
84
87 int pos = getDataPos();
88 return pos > 0 && buffer.available() >= pos;
89 }
90
92 size_t available() { return buffer.available(); }
93
95 int getDataPos() {
96 int pos =
97 StrView((char *)buffer.data(), MAX_WAV_HEADER_LEN, buffer.available())
98 .indexOf("data");
99 return pos > 0 ? pos + 8 : 0;
100 }
101
103 WAVAudioInfo &audioInfo() { return headerInfo; }
104
106 void setAudioInfo(WAVAudioInfo info) { headerInfo = info; }
107
109 int writeHeader(Print *out) {
110 writeRiffHeader(buffer);
111 writeFMT(buffer);
112 writeDataHeader(buffer);
113 int len = buffer.available();
114 out->write(buffer.data(), buffer.available());
115 return len;
116 }
117
119 void clear() {
120 data_pos = 0;
121 WAVAudioInfo empty;
122 empty.sample_rate = 0;
123 empty.channels = 0;
124 empty.bits_per_sample = 0;
125 headerInfo = empty;
126 buffer.setClearWithZero(true);
127 buffer.reset();
128 }
129
131 void dumpHeader() {
132 char msg[buffer.available() + 1];
133 memset(msg, 0, buffer.available() + 1);
134 for (int j = 0; j < buffer.available(); j++) {
135 char c = (char)buffer.data()[j];
136 if (!isalpha(c)) {
137 c = '.';
138 }
139 msg[j] = c;
140 }
141 LOGI("Header: %s", msg);
142 }
143
144 protected:
145 struct WAVAudioInfo headerInfo;
146 SingleBuffer<uint8_t> buffer{MAX_WAV_HEADER_LEN};
147 size_t data_pos = 0;
148
149 bool setPos(const char *id) {
150 int id_len = strlen(id);
151 int pos = indexOf(id);
152 if (pos < 0) return false;
153 data_pos = pos + id_len;
154 return true;
155 }
156
157 int indexOf(const char *str) {
158 return StrView((char *)buffer.data(), MAX_WAV_HEADER_LEN,
159 buffer.available())
160 .indexOf(str);
161 }
162
163 uint32_t read_tag() {
164 uint32_t tag = 0;
165 tag = (tag << 8) | getChar();
166 tag = (tag << 8) | getChar();
167 tag = (tag << 8) | getChar();
168 tag = (tag << 8) | getChar();
169 return tag;
170 }
171
172 uint32_t getChar32() { return getChar(); }
173
174 uint32_t read_int32() {
175 uint32_t value = 0;
176 value |= getChar32() << 0;
177 value |= getChar32() << 8;
178 value |= getChar32() << 16;
179 value |= getChar32() << 24;
180 return value;
181 }
182
183 uint16_t read_int16() {
184 uint16_t value = 0;
185 value |= getChar() << 0;
186 value |= getChar() << 8;
187 return value;
188 }
189
190 void skip(int n) {
191 int i;
192 for (i = 0; i < n; i++) getChar();
193 }
194
195 int getChar() {
196 if (data_pos < buffer.size())
197 return buffer.data()[data_pos++];
198 else
199 return -1;
200 }
201
202 void seek(long int offset, int origin) {
203 if (origin == SEEK_SET) {
204 data_pos = offset;
205 } else if (origin == SEEK_CUR) {
206 data_pos += offset;
207 }
208 }
209
210 size_t tell() { return data_pos; }
211
212 bool eof() { return data_pos >= buffer.size() - 1; }
213
214 void logInfo() {
215 LOGI("WAVHeader sound_pos: %d", getDataPos());
216 LOGI("WAVHeader channels: %d ", headerInfo.channels);
217 LOGI("WAVHeader bits_per_sample: %d", headerInfo.bits_per_sample);
218 LOGI("WAVHeader sample_rate: %d ", (int)headerInfo.sample_rate);
219 LOGI("WAVHeader format: %d", (int)headerInfo.format);
220 }
221
222 void writeRiffHeader(BaseBuffer<uint8_t> &buffer) {
223 buffer.writeArray((uint8_t *)"RIFF", 4);
224 write32(buffer, headerInfo.file_size - 8);
225 buffer.writeArray((uint8_t *)"WAVE", 4);
226 }
227
228 void writeFMT(BaseBuffer<uint8_t> &buffer) {
229 uint16_t fmt_len = 16;
230 buffer.writeArray((uint8_t *)"fmt ", 4);
231 write32(buffer, fmt_len);
232 write16(buffer, (uint16_t)headerInfo.format); // PCM
233 write16(buffer, headerInfo.channels);
234 write32(buffer, headerInfo.sample_rate);
235 write32(buffer, headerInfo.byte_rate);
236 write16(buffer, headerInfo.block_align); // frame size
237 write16(buffer, headerInfo.bits_per_sample);
238 }
239
240 void write32(BaseBuffer<uint8_t> &buffer, uint64_t value) {
241 buffer.writeArray((uint8_t *)&value, 4);
242 }
243
244 void write16(BaseBuffer<uint8_t> &buffer, uint16_t value) {
245 buffer.writeArray((uint8_t *)&value, 2);
246 }
247
248 void writeDataHeader(BaseBuffer<uint8_t> &buffer) {
249 buffer.writeArray((uint8_t *)"data", 4);
250 write32(buffer, headerInfo.file_size);
251 int offset = headerInfo.offset;
252 if (offset > 0) {
253 uint8_t empty[offset];
254 memset(empty, 0, offset);
255 buffer.writeArray(empty, offset); // resolve issue with wrong aligment
256 }
257 }
258};
259
281class WAVDecoder : public AudioDecoder {
282
283 public:
287 WAVDecoder() = default;
288
294
297 TRACED();
298 decoder_format = fmt;
299 p_decoder = &dec;
300 }
301
303 void setOutput(Print &out_stream) override { this->p_print = &out_stream; }
304
306 bool begin() override {
307 TRACED();
308 header.clear();
309 setupEncodedAudio();
310 byte_buffer.reset();
311 buffer24.reset();
312 isFirst = true;
313 active = true;
314 return true;
315 }
316
318 void end() override {
319 TRACED();
320 byte_buffer.reset();
321 buffer24.reset();
322 active = false;
323 }
324
326 const char *mime() { return wav_mime; }
327
329 WAVAudioInfo &audioInfoEx() { return header.audioInfo(); }
330
332 AudioInfo audioInfo() override {
333 WAVAudioInfo info = header.audioInfo();
334 if (convert8to16 && info.format == AudioFormat::PCM &&
335 info.bits_per_sample == 8) {
336 info.bits_per_sample = 16;
337 }
338 // 32 bits gives better result
339 if (convert24 && info.format == AudioFormat::PCM &&
340 info.bits_per_sample == 24) {
341 info.bits_per_sample = 32;
342 }
343 return info;
344 }
345
347 virtual size_t write(const uint8_t *data, size_t len) override {
348 TRACED();
349 size_t result = 0;
350 if (active) {
351 if (isFirst) {
352 int data_start = decodeHeader((uint8_t *)data, len);
353 // we do not have the complete header yet: need more data
354 if (data_start == 0) return len;
355 // process the outstanding data
356 result = data_start +
357 write_out((uint8_t *)data + data_start, len - data_start);
358
359 } else if (isValid) {
360 result = write_out((uint8_t *)data, len);
361 }
362 }
363 return result;
364 }
365
367 virtual operator bool() override { return active; }
368
370 void setConvert8Bit(bool enable) {
371 convert8to16 = enable;
372 }
373
375 void setConvert24Bit(bool enable) {
376 convert24 = enable;
377 }
378
379 protected:
380 WAVHeader header;
381 bool isFirst = true;
382 bool isValid = true;
383 bool active = false;
384 AudioFormat decoder_format = AudioFormat::PCM;
385 AudioDecoderExt *p_decoder = nullptr;
386 EncodedAudioOutput dec_out;
387 SingleBuffer<uint8_t> byte_buffer{0};
388 SingleBuffer<int32_t> buffer24{0};
389 bool convert8to16 = true; // Optional conversion flag
390 bool convert24 = true; // Optional conversion flag
391 const size_t batch_size = 256;
392
393 Print &out() { return p_decoder == nullptr ? *p_print : dec_out; }
394
395 virtual size_t write_out(const uint8_t *in_ptr, size_t in_size) {
396 // check if we need to convert int24 data from 3 bytes to 4 bytes
397 size_t result = 0;
398 if (convert24 && header.audioInfo().format == AudioFormat::PCM &&
399 header.audioInfo().bits_per_sample == 24 && sizeof(int24_t) == 4) {
400 write_out_24(in_ptr, in_size);
401 result = in_size;
402 } else if (convert8to16 && header.audioInfo().format == AudioFormat::PCM &&
403 header.audioInfo().bits_per_sample == 8) {
404 result = write_out_8to16(in_ptr, in_size);
405 } else {
406 result = out().write(in_ptr, in_size);
407 }
408 return result;
409 }
410
412 size_t write_out_8to16(const uint8_t *in_ptr, size_t in_size) {
413 size_t total_written = 0;
414 size_t samples_remaining = in_size;
415 size_t offset = 0;
416 int16_t out_buf[batch_size];
417 while (samples_remaining > 0) {
418 size_t current_batch =
419 samples_remaining > batch_size ? batch_size : samples_remaining;
420 for (size_t i = 0; i < current_batch; ++i) {
421 out_buf[i] = ((int16_t)in_ptr[offset + i] - 128) << 8;
422 }
423 writeDataT<int16_t>(&out(), out_buf, current_batch);
424 offset += current_batch;
425 samples_remaining -= current_batch;
426 }
427 return in_size;
428 }
429
431 size_t write_out_24(const uint8_t *in_ptr, size_t in_size) {
432 // store 1 sample
433 buffer24.resize(batch_size);
434 byte_buffer.resize(3);
435
436 for (size_t i = 0; i < in_size; i++) {
437 // Add byte to buffer
438 byte_buffer.write(in_ptr[i]);
439
440 // Process complete sample when buffer is full
441 if (byte_buffer.isFull()) {
442 int24_3bytes_t sample24{byte_buffer.data()};
443 int32_t converted_sample = sample24.scale32();
444 buffer24.write(converted_sample);
445 if (buffer24.isFull()) {
446 writeDataT<int32_t>(&out(), buffer24.data(), buffer24.available());
447 buffer24.reset();
448 }
449 byte_buffer.reset();
450 }
451 }
452
453 return in_size;
454 }
455
456
458 int decodeHeader(uint8_t *in_ptr, size_t in_size) {
459 int result = in_size;
460 // we expect at least the full header
461 int written = header.write(in_ptr, in_size);
462 if (!header.isDataComplete()) {
463 LOGW("WAV header misses 'data' section in len: %d",
464 (int)header.available());
465 header.dumpHeader();
466 return 0;
467 }
468 // parse header
469 if (!header.parse()) {
470 LOGE("WAV header parsing failed");
471 return 0;
472 }
473
474 isFirst = false;
475 isValid = header.audioInfo().is_valid;
476
477 LOGI("WAV sample_rate: %d", (int)header.audioInfo().sample_rate);
478 LOGI("WAV data_length: %u", (unsigned)header.audioInfo().data_length);
479 LOGI("WAV is_streamed: %d", header.audioInfo().is_streamed);
480 LOGI("WAV is_valid: %s", header.audioInfo().is_valid ? "true" : "false");
481
482 // check format
483 AudioFormat format = header.audioInfo().format;
484 isValid = format == decoder_format;
485 if (isValid) {
486 // update blocksize
487 if (p_decoder != nullptr) {
488 int block_size = header.audioInfo().block_align;
489 p_decoder->setBlockSize(block_size);
490 }
491
492 // update sampling rate if the target supports it
493 AudioInfo bi = audioInfo();
494 notifyAudioChange(bi);
495 } else {
496 LOGE("WAV format not supported: %d", (int)format);
497 }
498 return header.getDataPos();
499 }
500
501 void setupEncodedAudio() {
502 if (p_decoder != nullptr) {
503 assert(p_print != nullptr);
504 dec_out.setOutput(p_print);
505 dec_out.setDecoder(p_decoder);
506 dec_out.begin(info);
507 }
508 }
509};
510
521class WAVEncoder : public AudioEncoder {
522 public:
526 WAVEncoder() = default;
527
532
535 TRACED();
536 audioInfo.format = fmt;
537 p_encoder = &enc;
538 }
539
541 void setOutput(Print &out) override {
542 TRACED();
543 p_print = &out;
544 }
545
547 const char *mime() override { return wav_mime; }
548
551 WAVAudioInfo info;
552 info.format = AudioFormat::PCM;
553 info.sample_rate = DEFAULT_SAMPLE_RATE;
554 info.bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
555 info.channels = DEFAULT_CHANNELS;
556 info.is_streamed = true;
557 info.is_valid = true;
558 info.data_length = 0x7fff0000;
559 info.file_size = info.data_length + 36;
560 return info;
561 }
562
564 virtual void setAudioInfo(AudioInfo from) override {
565 audioInfo.sample_rate = from.sample_rate;
566 audioInfo.channels = from.channels;
567 audioInfo.bits_per_sample = from.bits_per_sample;
568 // recalculate byte rate, block align...
569 setAudioInfo(audioInfo);
570 }
571
573 virtual void setAudioInfo(WAVAudioInfo ai) {
575 if (p_encoder) p_encoder->setAudioInfo(ai);
576 audioInfo = ai;
577 LOGI("sample_rate: %d", (int)audioInfo.sample_rate);
578 LOGI("channels: %d", audioInfo.channels);
579 // bytes per second
580 audioInfo.byte_rate = audioInfo.sample_rate * audioInfo.channels *
581 audioInfo.bits_per_sample / 8;
582 if (audioInfo.format == AudioFormat::PCM) {
583 audioInfo.block_align =
584 audioInfo.bits_per_sample / 8 * audioInfo.channels;
585 }
586 if (audioInfo.is_streamed || audioInfo.data_length == 0 ||
587 audioInfo.data_length >= 0x7fff0000) {
588 LOGI("is_streamed! because length is %u",
589 (unsigned)audioInfo.data_length);
590 audioInfo.is_streamed = true;
591 audioInfo.data_length = ~0;
592 } else {
593 size_limit = audioInfo.data_length;
594 LOGI("size_limit is %d", (int)size_limit);
595 }
596 }
597
600 header.clear();
601 setAudioInfo(ai);
602 return begin();
603 }
604
606 virtual bool begin() override {
607 TRACED();
608 setupEncodedAudio();
609 header_written = false;
610 is_open = true;
611 return true;
612 }
613
615 void end() override { is_open = false; }
616
618 virtual size_t write(const uint8_t *data, size_t len) override {
619 if (!is_open) {
620 LOGE("The WAVEncoder is not open - please call begin()");
621 return 0;
622 }
623
624 if (p_print == nullptr) {
625 LOGE("No output stream was provided");
626 return 0;
627 }
628
629 if (!header_written) {
630 LOGI("Writing Header");
631 header.setAudioInfo(audioInfo);
632 int len = header.writeHeader(p_print);
633 audioInfo.file_size -= len;
634 header_written = true;
635 }
636
637 int32_t result = 0;
638 Print *p_out = p_encoder == nullptr ? p_print : &enc_out;
639 ;
640 if (audioInfo.is_streamed) {
641 result = p_out->write((uint8_t *)data, len);
642 } else if (size_limit > 0) {
643 size_t write_size = min((size_t)len, (size_t)size_limit);
644 result = p_out->write((uint8_t *)data, write_size);
645 size_limit -= result;
646
647 if (size_limit <= 0) {
648 LOGI("The defined size was written - so we close the WAVEncoder now");
649 is_open = false;
650 }
651 }
652 return result;
653 }
654
656 operator bool() override { return is_open; }
657
659 bool isOpen() { return is_open; }
660
662 void setDataOffset(uint16_t offset) { audioInfo.offset = offset; }
663
664 protected:
665 WAVHeader header;
666 Print *p_print = nullptr; // final output CopyEncoder copy; // used for PCM
667 AudioEncoderExt *p_encoder = nullptr;
668 EncodedAudioOutput enc_out;
669 WAVAudioInfo audioInfo = defaultConfig();
670 int64_t size_limit = 0;
671 bool header_written = false;
672 volatile bool is_open = false;
673
674 void setupEncodedAudio() {
675 if (p_encoder != nullptr) {
676 assert(p_print != nullptr);
677 enc_out.setOutput(p_print);
678 enc_out.setEncoder(p_encoder);
679 enc_out.setAudioInfo(audioInfo);
680 enc_out.begin();
681 // block size only available after begin(): update block size
682 audioInfo.block_align = p_encoder->blockSize();
683 }
684 }
685};
686
687} // namespace audio_tools
WAV Audio Formats used by Microsoft e.g. in AVI video files.
Definition AudioCodecsBase.h:119
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
Definition AudioCodecsBase.h:124
Encoding of PCM data.
Definition AudioCodecsBase.h:97
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:106
void clear()
same as reset
Definition Buffers.h:95
A more natural Print class to process encoded data (aac, wav, mp3...). Just define the output and the...
Definition AudioEncoded.h:21
bool begin() override
Starts the processing - sets the status to active.
Definition AudioEncoded.h:155
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition AudioEncoded.h:84
void setOutput(Print *outputStream)
Defines the output.
Definition AudioEncoded.h:104
Definition NoArduino.h:62
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:205
void setClearWithZero(bool flag)
Sets the buffer to 0 on clear.
Definition Buffers.h:313
int available() override
provides the number of entries that are available to read
Definition Buffers.h:232
bool isFull() override
checks if the buffer is full
Definition Buffers.h:239
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:304
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:200
T * data()
Provides address of actual data.
Definition Buffers.h:283
void reset() override
clears the buffer
Definition Buffers.h:285
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:281
virtual size_t write(const uint8_t *data, size_t len) override
Write incoming WAV data (header + PCM) into output.
Definition CodecWAV.h:347
void setOutput(Print &out_stream) override
Defines the output Stream.
Definition CodecWAV.h:303
void setDecoder(AudioDecoderExt &dec, AudioFormat fmt)
Defines an optional decoder if the format is not PCM.
Definition CodecWAV.h:296
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:431
int decodeHeader(uint8_t *in_ptr, size_t in_size)
Decodes the header data: Returns the start pos of the data.
Definition CodecWAV.h:458
void setConvert8Bit(bool enable)
Convert 8 bit to 16 bit PCM data (default: enabled)
Definition CodecWAV.h:370
void end() override
Finish decoding and release temporary buffers.
Definition CodecWAV.h:318
const char * mime()
Provides MIME type "audio/wav".
Definition CodecWAV.h:326
WAVDecoder()=default
Construct a new WAVDecoder object for PCM data.
WAVAudioInfo & audioInfoEx()
Extended WAV specific info (original header values)
Definition CodecWAV.h:329
WAVDecoder(AudioDecoderExt &dec, AudioFormat fmt)
Construct a new WAVDecoder object for ADPCM data.
Definition CodecWAV.h:293
void setConvert24Bit(bool enable)
Convert 24 bit (3 byte) to 32 bit (4 byte) PCM data (default: enabled)
Definition CodecWAV.h:375
bool begin() override
Prepare decoder for a new WAV stream.
Definition CodecWAV.h:306
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:412
AudioInfo audioInfo() override
Exposed AudioInfo (may reflect conversion flags)
Definition CodecWAV.h:332
A simple WAV file encoder. If no AudioEncoderExt is specified the WAV file contains PCM data,...
Definition CodecWAV.h:521
virtual size_t write(const uint8_t *data, size_t len) override
Writes PCM data to be encoded as WAV.
Definition CodecWAV.h:618
void setOutput(Print &out) override
Defines the otuput stream.
Definition CodecWAV.h:541
bool isOpen()
Check if encoder is open.
Definition CodecWAV.h:659
virtual bool begin() override
starts the processing using the actual WAVAudioInfo
Definition CodecWAV.h:606
bool begin(WAVAudioInfo ai)
starts the processing
Definition CodecWAV.h:599
void end() override
stops the processing
Definition CodecWAV.h:615
virtual void setAudioInfo(WAVAudioInfo ai)
Defines the WAVAudioInfo.
Definition CodecWAV.h:573
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:662
WAVEncoder(AudioEncoderExt &enc, AudioFormat fmt)
Construct a new WAVEncoder object for ADPCM data.
Definition CodecWAV.h:531
WAVAudioInfo defaultConfig()
Provides the default configuration.
Definition CodecWAV.h:550
const char * mime() override
Provides "audio/wav".
Definition CodecWAV.h:547
virtual void setAudioInfo(AudioInfo from) override
Update actual WAVAudioInfo.
Definition CodecWAV.h:564
void setEncoder(AudioEncoderExt &enc, AudioFormat fmt)
Associates an external encoder for non-PCM formats.
Definition CodecWAV.h:534
Parser for Wav header data for details see https://de.wikipedia.org/wiki/RIFF_WAVE.
Definition CodecWAV.h:46
bool parse()
Call begin when header data is complete to parse the data.
Definition CodecWAV.h:57
bool isDataComplete()
Returns true if the header is complete (containd data tag)
Definition CodecWAV.h:86
void setAudioInfo(WAVAudioInfo info)
Sets the info in the header.
Definition CodecWAV.h:106
size_t available()
number of bytes available in the header buffer
Definition CodecWAV.h:92
int getDataPos()
Determines the data start position using the data tag.
Definition CodecWAV.h:95
WAVAudioInfo & audioInfo()
provides the info from the header
Definition CodecWAV.h:103
int write(uint8_t *data, size_t data_len)
Definition CodecWAV.h:52
void clear()
Reset internal stored header information and buffer.
Definition CodecWAV.h:119
int writeHeader(Print *out)
Just write a wav header to the indicated outputbu.
Definition CodecWAV.h:109
void dumpHeader()
Debug helper: dumps header bytes as printable characters.
Definition CodecWAV.h:131
24bit integer which is used for I2S sound processing. The values are really using 3 bytes....
Definition Int24_3bytes_t.h:16
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 AudioCodecsBase.h:10
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59
Sound information which is available in the WAV header.
Definition CodecWAV.h:19