ref: 99836a4eda75945dc6c9eb456f06a0e170ab59ea
parent: 23ed47d1be94af912c5635c3b6a25508ec2378c4
author: Mans Rullgard <mans@mansr.com>
date: Thu Aug 6 06:02:17 EDT 2020
wav: get sample count from fact chunk if present
--- a/src/wav.c
+++ b/src/wav.c
@@ -824,6 +824,20 @@
goto next;
}
+ if (!memcmp(magic, "fact", 4)) {
+ uint32_t val;
+
+ if (clen < 4) {
+ lsx_fail_errno(ft, SOX_EHDR, "fact chunk too small");
+ return SOX_EOF;
+ }
+
+ lsx_readdw(ft, &val);
+ wav->numSamples = val;
+
+ goto next;
+ }
+
if (!memcmp(magic, "data", 4)) {
if (isRF64 && clen == UINT32_MAX)
clen = ds64_data_size;
@@ -875,7 +889,12 @@
if (ft->seekable)
lsx_seeki(ft, wav->dataStart, SEEK_SET);
- if (qwDataLength == UINT32_MAX || qwDataLength == MS_UNSPEC) {
+ /* some files wrongly report total samples across all channels */
+ if (wav->numSamples * wav->blockAlign == qwDataLength * ft->signal.channels)
+ wav->numSamples /= ft->signal.channels;
+
+ if ((qwDataLength == UINT32_MAX && !wav->numSamples) ||
+ qwDataLength == MS_UNSPEC) {
lsx_warn("WAV data length is magic value or UINT32_MAX, ignoring");
wav->ignoreSize = 1;
}
@@ -911,7 +930,8 @@
break;
default:
- wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample) / ft->signal.channels;
+ if (!wav->numSamples)
+ wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample) / ft->signal.channels;
ft->signal.length = wav->numSamples * ft->signal.channels;
}