2
2
3
3
#include " AudioCodecs/AudioCodecsBase.h"
4
4
#include " AudioCodecs/AudioFormat.h"
5
-
5
+ # include " AudioBasic/Str.h "
6
6
7
7
#define TAG (a, b, c, d ) \
8
8
((static_cast <uint32_t >(a) << 24 ) | (static_cast <uint32_t >(b) << 16 ) | \
9
9
(static_cast <uint32_t >(c) << 8 ) | (d))
10
10
#define READ_BUFFER_SIZE 512
11
+ #define MAX_WAV_HEADER_LEN 50
11
12
12
13
namespace audio_tools {
13
14
@@ -50,95 +51,48 @@ class WAVHeader {
50
51
51
52
// / Adds data to the 44 byte wav header data buffer and make it available for parsing
52
53
int write (uint8_t *data, size_t data_len) {
53
- int write_len = min (data_len, 44 - len);
54
- memmove (buffer, data + len, write_len);
55
- len += write_len;
56
- LOGI (" WAVHeader::write: %u -> %d -> %d" , (unsigned )data_len, write_len,
57
- (int )len);
58
- return write_len;
54
+ return buffer.writeArray (data, data_len);
59
55
}
60
56
61
57
// / Call begin when header data is complete to parse the data
62
- void parse () {
63
- LOGI (" WAVHeader::begin: %u" , (unsigned )len );
58
+ bool parse () {
59
+ LOGI (" WAVHeader::begin: %u" , (unsigned )buffer. size () );
64
60
this ->data_pos = 0l ;
65
61
memset ((void *)&headerInfo, 0 , sizeof (WAVAudioInfo));
66
- while (!eof ()) {
67
- uint32_t tag, tag2, length;
68
- tag = read_tag ();
69
- if (eof ()) break ;
70
- length = read_int32 ();
71
- if (!length || length >= 0x7fff0000 ) {
72
- headerInfo.is_streamed = true ;
73
- length = ~0 ;
74
- }
75
- if (tag != TAG (' R' , ' I' , ' F' , ' F' ) || length < 4 ) {
76
- seek (length, SEEK_CUR);
77
- continue ;
78
- }
79
- headerInfo.file_size = length;
80
- tag2 = read_tag ();
81
- length -= 4 ;
82
- if (tag2 != TAG (' W' , ' A' , ' V' , ' E' )) {
83
- seek (length, SEEK_CUR);
84
- continue ;
85
- }
86
- // RIFF chunk found, iterate through it
87
- while (length >= 8 ) {
88
- uint32_t subtag, sublength;
89
- subtag = read_tag ();
90
- if (eof ()) break ;
91
- sublength = read_int32 ();
92
- length -= 8 ;
93
- if (length < sublength) break ;
94
- if (subtag == TAG (' f' , ' m' , ' t' , ' ' )) {
95
- if (sublength < 16 ) {
96
- // Insufficient data for 'fmt '
97
- break ;
98
- }
99
- headerInfo.format = (AudioFormat)read_int16 ();
100
- headerInfo.channels = read_int16 ();
101
- headerInfo.sample_rate = read_int32 ();
102
- headerInfo.byte_rate = read_int32 ();
103
- headerInfo.block_align = read_int16 ();
104
- headerInfo.bits_per_sample = read_int16 ();
105
- if (headerInfo.format == (AudioFormat) 0xfffe ) {
106
- if (sublength < 28 ) {
107
- // Insufficient data for waveformatex
108
- break ;
109
- }
110
- skip (8 );
111
- headerInfo.format = (AudioFormat)read_int32 ();
112
- skip (sublength - 28 );
113
- } else {
114
- skip (sublength - 16 );
115
- }
116
- headerInfo.is_valid = true ;
117
- } else if (subtag == TAG (' d' , ' a' , ' t' , ' a' )) {
118
- sound_pos = tell ();
119
- headerInfo.data_length = sublength;
120
- if (!headerInfo.data_length || headerInfo.is_streamed ) {
121
- headerInfo.is_streamed = true ;
122
- logInfo ();
123
- return ;
124
- }
125
- seek (sublength, SEEK_CUR);
126
- } else {
127
- skip (sublength);
128
- }
129
- length -= sublength;
130
- }
131
- if (length > 0 ) {
132
- // Bad chunk?
133
- seek (length, SEEK_CUR);
134
- }
62
+
63
+ if (!setPos (" RIFF" )) return false ;
64
+ int riff_len = read_int32 ();
65
+ if (!setPos (" WAVE" )) return false ;
66
+ if (!setPos (" fmt " )) return false ;
67
+ int fmt_length = read_int32 ();
68
+ headerInfo.format = (AudioFormat)read_int16 ();
69
+ headerInfo.channels = read_int16 ();
70
+ headerInfo.sample_rate = read_int32 ();
71
+ headerInfo.byte_rate = read_int32 ();
72
+ headerInfo.block_align = read_int16 ();
73
+ headerInfo.bits_per_sample = read_int16 ();
74
+ if (!setPos (" data" )) return false ;
75
+ headerInfo.data_length = read_int32 ();
76
+ if (!headerInfo.data_length ==0 || headerInfo.data_length >= 0x7fff0000 ) {
77
+ headerInfo.is_streamed = true ;
78
+ headerInfo.data_length = ~0 ;
135
79
}
80
+
136
81
logInfo ();
137
- len = 0 ;
82
+ buffer.clear ();
83
+ return true ;
138
84
}
139
85
140
- // / Returns true if the header is complete (with 44 bytes)
141
- bool isDataComplete () { return len == 44 ; }
86
+ // / Returns true if the header is complete (with 44 bytes): contains data + 4 byte len
87
+ bool isDataComplete () {
88
+ int pos = getDataPos ();
89
+ return pos > 0 && buffer.available () >= pos;;
90
+ }
91
+
92
+ int getDataPos () {
93
+ int pos = Str ((char *)buffer.data (),MAX_WAV_HEADER_LEN, buffer.size ()).indexOf (" data" );
94
+ return pos > 0 ? pos + 8 : 0 ;
95
+ }
142
96
143
97
// / provides the info from the header
144
98
WAVAudioInfo &audioInfo () { return headerInfo; }
@@ -148,23 +102,40 @@ class WAVHeader {
148
102
headerInfo = info;
149
103
}
150
104
151
- // / Just write a wav header to the indicated output
105
+ // / Just write a wav header to the indicated outputbu
152
106
int writeHeader (Print *out) {
153
- SingleBuffer<uint8_t > buffer (50 );
154
107
writeRiffHeader (buffer);
155
108
writeFMT (buffer);
156
109
writeDataHeader (buffer);
157
- len = buffer.available ();
110
+ int len = buffer.available ();
158
111
out->write (buffer.data (), buffer.available ());
159
112
return len;
160
113
}
161
114
115
+ void clear () {
116
+ data_pos = 0 ;
117
+ memset (&headerInfo,0 ,sizeof (WAVAudioInfo));
118
+ buffer.setClearWithZero (true );
119
+ buffer.reset ();
120
+ }
121
+
122
+
162
123
protected:
163
124
struct WAVAudioInfo headerInfo;
164
- uint8_t buffer[44 ];
165
- size_t len = 0 ;
125
+ SingleBuffer<uint8_t > buffer{MAX_WAV_HEADER_LEN};
166
126
size_t data_pos = 0 ;
167
- size_t sound_pos = 0 ;
127
+
128
+ bool setPos (const char *id){
129
+ int id_len = strlen (id);
130
+ int pos = indexOf (id);
131
+ if (pos < 0 ) return false ;
132
+ data_pos = pos + id_len;
133
+ return true ;
134
+ }
135
+
136
+ int indexOf (const char * str){
137
+ return Str ((char *)buffer.data (),MAX_WAV_HEADER_LEN, buffer.available ()).indexOf (str);
138
+ }
168
139
169
140
uint32_t read_tag () {
170
141
uint32_t tag = 0 ;
@@ -199,8 +170,8 @@ class WAVHeader {
199
170
}
200
171
201
172
int getChar () {
202
- if (data_pos < len )
203
- return buffer[data_pos++];
173
+ if (data_pos < buffer. size () )
174
+ return buffer. data () [data_pos++];
204
175
else
205
176
return -1 ;
206
177
}
@@ -215,10 +186,10 @@ class WAVHeader {
215
186
216
187
size_t tell () { return data_pos; }
217
188
218
- bool eof () { return data_pos >= len - 1 ; }
189
+ bool eof () { return data_pos >= buffer. size () - 1 ; }
219
190
220
191
void logInfo () {
221
- LOGI (" WAVHeader sound_pos: %lu " , ( unsigned long )sound_pos );
192
+ LOGI (" WAVHeader sound_pos: %d " , getDataPos () );
222
193
LOGI (" WAVHeader channels: %d " , headerInfo.channels );
223
194
LOGI (" WAVHeader bits_per_sample: %d" , headerInfo.bits_per_sample );
224
195
LOGI (" WAVHeader sample_rate: %d " , (int ) headerInfo.sample_rate );
@@ -301,6 +272,7 @@ class WAVDecoder : public AudioDecoder {
301
272
302
273
bool begin () override {
303
274
TRACED ();
275
+ header.clear ();
304
276
setupEncodedAudio ();
305
277
buffer24.reset ();
306
278
isFirst = true ;
@@ -325,10 +297,12 @@ class WAVDecoder : public AudioDecoder {
325
297
size_t result = 0 ;
326
298
if (active) {
327
299
if (isFirst) {
328
- result = decodeHeader ((uint8_t *) data, len);
329
- // if (result<len){
330
- // result += write_out((uint8_t *)data+result, len-result);
331
- // }
300
+ int data_start = decodeHeader ((uint8_t *) data, len);
301
+ // we do not have the complete header yet: need more data
302
+ if (data_start == 0 ) return len;
303
+ // process the outstanding data
304
+ result = data_start + write_out ((uint8_t *)data+data_start, len-data_start);
305
+
332
306
} else if (isValid) {
333
307
result = write_out ((uint8_t *)data, len);
334
308
}
@@ -405,7 +379,7 @@ class WAVDecoder : public AudioDecoder {
405
379
406
380
407
381
int decodeHeader (uint8_t *in_ptr, size_t in_size) {
408
- int result = 0 ;
382
+ int result = in_size ;
409
383
// we expect at least the full header
410
384
int written = header.write (in_ptr, in_size);
411
385
if (!header.isDataComplete ()) {
@@ -414,8 +388,6 @@ class WAVDecoder : public AudioDecoder {
414
388
// parse header
415
389
header.parse ();
416
390
417
- size_t len = in_size - written;
418
- uint8_t *sound_ptr = (uint8_t *)in_ptr + written;
419
391
isFirst = false ;
420
392
isValid = header.audioInfo ().is_valid ;
421
393
@@ -441,15 +413,10 @@ class WAVDecoder : public AudioDecoder {
441
413
bi.channels = header.audioInfo ().channels ;
442
414
bi.bits_per_sample = header.audioInfo ().bits_per_sample ;
443
415
notifyAudioChange (bi);
444
- // write prm data from first record
445
- if (len > 0 ) {
446
- LOGI (" WAVDecoder writing first sound data" );
447
- result = out ().write (sound_ptr, len);
448
- }
449
416
} else {
450
417
LOGE (" WAV format not supported: %d" , (int )format);
451
418
}
452
- return result ;
419
+ return header. getDataPos () ;
453
420
}
454
421
455
422
void setupEncodedAudio () {
@@ -549,6 +516,7 @@ class WAVEncoder : public AudioEncoder {
549
516
550
517
// / starts the processing
551
518
bool begin (WAVAudioInfo ai) {
519
+ header.clear ();
552
520
setAudioInfo (ai);
553
521
return begin ();
554
522
}
0 commit comments