@@ -304,6 +304,7 @@ class WAVDecoder : public AudioDecoder {
304
304
TRACED ();
305
305
header.clear ();
306
306
setupEncodedAudio ();
307
+ byte_buffer.reset ();
307
308
buffer24.reset ();
308
309
isFirst = true ;
309
310
active = true ;
@@ -312,6 +313,7 @@ class WAVDecoder : public AudioDecoder {
312
313
313
314
void end () override {
314
315
TRACED ();
316
+ byte_buffer.reset ();
315
317
buffer24.reset ();
316
318
active = false ;
317
319
}
@@ -326,6 +328,11 @@ class WAVDecoder : public AudioDecoder {
326
328
info.bits_per_sample == 8 ) {
327
329
info.bits_per_sample = 16 ;
328
330
}
331
+ // 32 bits gives better result
332
+ if (convert24 && info.format == AudioFormat::PCM &&
333
+ info.bits_per_sample == 24 ) {
334
+ info.bits_per_sample = 32 ;
335
+ }
329
336
return info;
330
337
}
331
338
@@ -350,6 +357,16 @@ class WAVDecoder : public AudioDecoder {
350
357
351
358
virtual operator bool () override { return active; }
352
359
360
+ // / Convert 8 bit to 16 bit PCM data
361
+ void setConvert8Bit (bool enable) {
362
+ convert8to16 = enable;
363
+ }
364
+
365
+ // / Convert 24 bit (3 byte) to 32 bit (4 byte) PCM data
366
+ void setConvert24Bit (bool enable) {
367
+ convert24 = enable;
368
+ }
369
+
353
370
protected:
354
371
WAVHeader header;
355
372
bool isFirst = true ;
@@ -358,15 +375,17 @@ class WAVDecoder : public AudioDecoder {
358
375
AudioFormat decoder_format = AudioFormat::PCM;
359
376
AudioDecoderExt *p_decoder = nullptr ;
360
377
EncodedAudioOutput dec_out;
361
- SingleBuffer<uint8_t > buffer24;
378
+ SingleBuffer<uint8_t > byte_buffer{0 };
379
+ SingleBuffer<int32_t > buffer24{0 };
362
380
bool convert8to16 = true ; // Optional conversion flag
381
+ bool convert24 = true ; // Optional conversion flag
363
382
364
383
Print &out () { return p_decoder == nullptr ? *p_print : dec_out; }
365
384
366
385
virtual size_t write_out (const uint8_t *in_ptr, size_t in_size) {
367
386
// check if we need to convert int24 data from 3 bytes to 4 bytes
368
387
size_t result = 0 ;
369
- if (header.audioInfo ().format == AudioFormat::PCM &&
388
+ if (convert24 && header.audioInfo ().format == AudioFormat::PCM &&
370
389
header.audioInfo ().bits_per_sample == 24 && sizeof (int24_t ) == 4 ) {
371
390
write_out_24 (in_ptr, in_size);
372
391
result = in_size;
@@ -392,51 +411,40 @@ class WAVDecoder : public AudioDecoder {
392
411
for (size_t i = 0 ; i < current_batch; ++i) {
393
412
out_buf[i] = ((int16_t )in_ptr[offset + i] - 128 ) << 8 ;
394
413
}
395
- size_t written =
396
- out ().write ((uint8_t *)out_buf, current_batch * sizeof (int16_t ));
397
- total_written += written / sizeof (int16_t );
414
+ writeDataT<int16_t >(&out (), out_buf, current_batch);
398
415
offset += current_batch;
399
416
samples_remaining -= current_batch;
400
417
}
401
- return total_written / 2 ;
418
+ return in_size ;
402
419
}
403
420
404
- // convert int24 to int32
421
+ // convert 3 byte int24 to 4 byte int32
405
422
size_t write_out_24 (const uint8_t *in_ptr, size_t in_size) {
406
- // make sure we can store a frame of 24bit (3bytes)
407
- AudioInfo &info = header.audioInfo ();
408
- // in_size might be not a multiple of 3, so we use a buffer for a single
409
- // frame
410
- buffer24.resize (info.channels * 3 );
411
- int result = 0 ;
412
- int32_t frame[info.channels ];
413
- uint8_t val24[3 ] = {0 };
414
-
415
- // add all bytes to buffer
416
- for (int j = 0 ; j < in_size; j++) {
417
- buffer24.write (in_ptr[j]);
418
- // if buffer is full convert and output
419
- if (buffer24.availableForWrite () == 0 ) {
420
- for (int ch = 0 ; ch < info.channels ; ch++) {
421
- buffer24.readArray ((uint8_t *)&val24[0 ], 3 );
422
- frame[ch] = interpret24bitAsInt32 (val24);
423
- // LOGW("%d", frame[ch]);
423
+ // store 1 sample
424
+ const size_t batch_size = 256 ;
425
+ buffer24.resize (batch_size);
426
+ byte_buffer.resize (3 );
427
+
428
+ for (size_t i = 0 ; i < in_size; i++) {
429
+ // Add byte to buffer
430
+ byte_buffer.write (in_ptr[i]);
431
+
432
+ // Process complete sample when buffer is full
433
+ if (byte_buffer.isFull ()) {
434
+ int24_3bytes_t sample24{byte_buffer.data ()};
435
+ int32_t converted_sample = sample24.scale32 ();
436
+ buffer24.write (converted_sample);
437
+ if (buffer24.isFull ()) {
438
+ writeDataT<int32_t >(&out (), buffer24.data (), buffer24.available ());
439
+ buffer24.reset ();
424
440
}
425
- assert (buffer24.available () == 0 );
426
- buffer24.reset ();
427
- size_t written = out ().write ((uint8_t *)frame, sizeof (frame));
428
- assert (written == sizeof (frame));
429
- result += written;
441
+ byte_buffer.reset ();
430
442
}
431
443
}
432
- return result;
444
+
445
+ return in_size;
433
446
}
434
447
435
- int32_t interpret24bitAsInt32 (uint8_t *byteArray) {
436
- return ((static_cast <int32_t >(byteArray[2 ]) << 24 ) |
437
- (static_cast <int32_t >(byteArray[1 ]) << 16 ) |
438
- (static_cast <int32_t >(byteArray[0 ]) << 8 ));
439
- }
440
448
441
449
// / Decodes the header data: Returns the start pos of the data
442
450
int decodeHeader (uint8_t *in_ptr, size_t in_size) {
0 commit comments