3#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
5#include "AudioTools/AudioCodecs/AudioEncoded.h"
6#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
8#define READ_BUFFER_SIZE 512
9#define MAX_WAV_HEADER_LEN 200
30 bool is_streamed =
true;
31 bool is_valid =
false;
32 uint32_t data_length = 0;
33 uint32_t file_size = 0;
37static const char *wav_mime =
"audio/wav";
51 int write(uint8_t *data,
size_t data_len) {
51 int write(uint8_t *data,
size_t data_len) {
…}
57 LOGI(
"WAVHeader::begin: %u", (
unsigned)buffer.
available());
61 if (!setPos(
"RIFF"))
return false;
62 headerInfo.file_size = read_int32();
63 if (!setPos(
"WAVE"))
return false;
64 if (!setPos(
"fmt "))
return false;
65 int fmt_length = read_int32();
67 headerInfo.channels = read_int16();
68 headerInfo.sample_rate = read_int32();
69 headerInfo.byte_rate = read_int32();
70 headerInfo.block_align = read_int16();
71 headerInfo.bits_per_sample = read_int16();
72 if (!setPos(
"data"))
return false;
73 headerInfo.data_length = read_int32();
74 if (headerInfo.data_length==0 || headerInfo.data_length >= 0x7fff0000) {
75 headerInfo.is_streamed =
true;
76 headerInfo.data_length = ~0;
87 return pos > 0 && buffer.
available() >= pos;
98 return pos > 0 ? pos + 8 : 0;
111 writeRiffHeader(buffer);
113 writeDataHeader(buffer);
133 for (
int j = 0; j< buffer.
available();j++){
134 char c = (char)buffer.
data()[j];
140 LOGI(
"Header: %s", msg);
145 struct WAVAudioInfo headerInfo;
146 SingleBuffer<uint8_t> buffer{MAX_WAV_HEADER_LEN};
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;
157 int indexOf(
const char* str){
158 return StrView((
char*)buffer.
data(),MAX_WAV_HEADER_LEN, buffer.
available()).indexOf(str);
161 uint32_t read_tag() {
163 tag = (tag << 8) | getChar();
164 tag = (tag << 8) | getChar();
165 tag = (tag << 8) | getChar();
166 tag = (tag << 8) | getChar();
170 uint32_t getChar32() {
return getChar(); }
172 uint32_t read_int32() {
174 value |= getChar32() << 0;
175 value |= getChar32() << 8;
176 value |= getChar32() << 16;
177 value |= getChar32() << 24;
181 uint16_t read_int16() {
183 value |= getChar() << 0;
184 value |= getChar() << 8;
190 for (i = 0; i < n; i++) getChar();
194 if (data_pos < buffer.size())
195 return buffer.
data()[data_pos++];
200 void seek(
long int offset,
int origin) {
201 if (origin == SEEK_SET) {
203 }
else if (origin == SEEK_CUR) {
208 size_t tell() {
return data_pos; }
210 bool eof() {
return data_pos >= buffer.size() - 1; }
213 LOGI(
"WAVHeader sound_pos: %d",
getDataPos());
214 LOGI(
"WAVHeader channels: %d ", headerInfo.
channels);
216 LOGI(
"WAVHeader sample_rate: %d ", (
int) headerInfo.
sample_rate);
217 LOGI(
"WAVHeader format: %d", (
int)headerInfo.format);
220 void writeRiffHeader(BaseBuffer<uint8_t> &buffer) {
221 buffer.writeArray((uint8_t *)
"RIFF", 4);
222 write32(buffer, headerInfo.file_size - 8);
223 buffer.writeArray((uint8_t *)
"WAVE", 4);
226 void writeFMT(BaseBuffer<uint8_t> &buffer) {
227 uint16_t fmt_len = 16;
228 buffer.writeArray((uint8_t *)
"fmt ", 4);
229 write32(buffer, fmt_len);
230 write16(buffer, (uint16_t)headerInfo.format);
231 write16(buffer, headerInfo.
channels);
233 write32(buffer, headerInfo.byte_rate);
234 write16(buffer, headerInfo.block_align);
238 void write32(BaseBuffer<uint8_t> &buffer, uint64_t value) {
239 buffer.writeArray((uint8_t *)&value, 4);
242 void write16(BaseBuffer<uint8_t> &buffer, uint16_t value) {
243 buffer.writeArray((uint8_t *)&value, 2);
246 void writeDataHeader(BaseBuffer<uint8_t> &buffer) {
247 buffer.writeArray((uint8_t *)
"data", 4);
248 write32(buffer, headerInfo.file_size);
249 int offset = headerInfo.offset;
251 uint8_t empty[offset];
252 memset(empty, 0, offset);
253 buffer.writeArray(empty, offset);
289 decoder_format = fmt;
296 bool begin()
override {
306 void end()
override {
312 const char *mime() {
return wav_mime; }
314 WAVAudioInfo &audioInfoEx() {
return header.
audioInfo(); }
318 virtual size_t write(
const uint8_t *data,
size_t len)
override {
325 if (data_start == 0)
return len;
327 result = data_start + write_out((uint8_t *)data+data_start, len-data_start);
329 }
else if (isValid) {
330 result = write_out((uint8_t *)data, len);
336 virtual operator bool()
override {
return active; }
344 AudioDecoderExt *p_decoder =
nullptr;
345 EncodedAudioOutput dec_out;
346 SingleBuffer<uint8_t> buffer24;
349 return p_decoder==
nullptr ? *p_print : dec_out;
352 virtual size_t write_out(
const uint8_t *in_ptr,
size_t in_size) {
355 if (header.audioInfo().format == AudioFormat::PCM
356 && header.audioInfo().bits_per_sample == 24 &&
sizeof(int24_t)==4){
357 write_out_24(in_ptr, in_size);
360 result = out().write(in_ptr, in_size);
366 size_t write_out_24(
const uint8_t *in_ptr,
size_t in_size) {
368 AudioInfo& info = header.audioInfo();
370 buffer24.resize(info.channels*3);
372 int32_t frame[info.channels];
373 uint8_t val24[3]={0};
376 for (
int j=0;j<in_size;j++){
377 buffer24.write(in_ptr[j]);
379 if (buffer24.availableForWrite()==0){
380 for (
int ch=0;ch<info.channels;ch++){
381 buffer24.readArray((uint8_t*)&val24[0], 3);
382 frame[ch] = interpret24bitAsInt32(val24);
385 assert(buffer24.available()==0);
387 size_t written = out().write((uint8_t*)frame,
sizeof(frame));
388 assert(written==
sizeof(frame));
395 int32_t interpret24bitAsInt32(uint8_t* byteArray) {
397 (
static_cast<int32_t
>(byteArray[2]) << 24)
398 | (
static_cast<int32_t
>(byteArray[1]) << 16)
399 | (
static_cast<int32_t
>(byteArray[0]) << 8)
405 int result = in_size;
407 int written = header.write(in_ptr, in_size);
408 if (!header.isDataComplete()) {
409 LOGW(
"WAV header misses 'data' section in len: %d", (
int) header.available());
414 if (!header.parse()){
415 LOGE(
"WAV header parsing failed");
420 isValid = header.audioInfo().is_valid;
422 LOGI(
"WAV sample_rate: %d", (
int) header.audioInfo().sample_rate);
423 LOGI(
"WAV data_length: %u", (
unsigned)header.audioInfo().data_length);
424 LOGI(
"WAV is_streamed: %d", header.audioInfo().is_streamed);
425 LOGI(
"WAV is_valid: %s",
426 header.audioInfo().is_valid ?
"true" :
"false");
430 isValid = format == decoder_format;
433 if(p_decoder!=
nullptr){
434 int block_size = header.audioInfo().block_align;
435 p_decoder->setBlockSize(block_size);
441 bi.
channels = header.audioInfo().channels;
443 notifyAudioChange(bi);
445 LOGE(
"WAV format not supported: %d", (
int)format);
447 return header.getDataPos();
450 void setupEncodedAudio() {
451 if (p_decoder!=
nullptr){
452 assert(p_print!=
nullptr);
453 dec_out.setOutput(p_print);
454 dec_out.setDecoder(p_decoder);
480 setEncoder(enc, fmt);
485 audioInfo.format = fmt;
496 const char *
mime()
override {
return wav_mime; }
501 info.format = AudioFormat::PCM;
505 info.is_streamed =
true;
506 info.is_valid =
true;
507 info.data_length = 0x7fff0000;
508 info.file_size = info.data_length + 36;
526 LOGI(
"sample_rate: %d", (
int)audioInfo.
sample_rate);
527 LOGI(
"channels: %d", audioInfo.
channels);
530 if (audioInfo.format == AudioFormat::PCM){
533 if (audioInfo.is_streamed || audioInfo.data_length == 0 ||
534 audioInfo.data_length >= 0x7fff0000) {
535 LOGI(
"is_streamed! because length is %u",
536 (
unsigned)audioInfo.data_length);
537 audioInfo.is_streamed =
true;
538 audioInfo.data_length = ~0;
540 size_limit = audioInfo.data_length;
541 LOGI(
"size_limit is %d", (
int)size_limit);
556 header_written =
false;
562 void end()
override { is_open =
false; }
565 virtual size_t write(
const uint8_t *data,
size_t len)
override {
567 LOGE(
"The WAVEncoder is not open - please call begin()");
571 if (p_print ==
nullptr) {
572 LOGE(
"No output stream was provided");
576 if (!header_written) {
577 LOGI(
"Writing Header");
578 header.setAudioInfo(audioInfo);
579 int len = header.writeHeader(p_print);
580 audioInfo.file_size -= len;
581 header_written =
true;
585 Print *p_out = p_encoder==
nullptr ? p_print : &enc_out;;
586 if (audioInfo.is_streamed) {
587 result = p_out->write((uint8_t *)data, len);
588 }
else if (size_limit > 0) {
589 size_t write_size = min((
size_t)len, (
size_t)size_limit);
590 result = p_out->write((uint8_t *)data, write_size);
591 size_limit -= result;
593 if (size_limit <= 0) {
594 LOGI(
"The defined size was written - so we close the WAVEncoder now");
565 virtual size_t write(
const uint8_t *data,
size_t len)
override {
…}
601 operator bool()
override {
return is_open; }
603 bool isOpen() {
return is_open; }
610 Print *p_print =
nullptr;
614 int64_t size_limit = 0;
615 bool header_written =
false;
616 volatile bool is_open =
false;
618 void setupEncodedAudio() {
619 if (p_encoder!=
nullptr){
620 assert(p_print!=
nullptr);
622 enc_out.setEncoder(p_encoder);
626 audioInfo.block_align = p_encoder->blockSize();
AudioFormat
Audio format codes used by Microsoft e.g. in avi or wav files.
Definition AudioFormat.h:19