From 4f7e1af85ad79797cf7195def1564930072d2cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20S=C5=82awi=C5=84ski?= Date: Fri, 11 Nov 2022 00:45:01 +0100 Subject: [PATCH] aplay: Fix parsing of format with WAV_FMT_EXTENSIBLE header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WAV_FMT_EXTENSIBLE header contains valid bits per sample, which can be different than bits per sample. Make sure it is taken into account when parsing headers and choosing playback format. BugLink: https://github.com/alsa-project/alsa-utils/pull/178 Signed-off-by: Amadeusz Sławiński Signed-off-by: Jaroslav Kysela --- aplay/aplay.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/aplay/aplay.c b/aplay/aplay.c index 6ce7191..2b06abc 100644 --- a/aplay/aplay.c +++ b/aplay/aplay.c @@ -1002,6 +1002,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) u_int type, len; unsigned short format, channels; int big_endian, native_format; + u_char vbps = 0; if (size < sizeof(WaveHeader)) return -1; @@ -1058,6 +1059,7 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) error(_("wrong format tag in extensible 'fmt ' chunk")); prg_exit(EXIT_FAILURE); } + vbps = TO_CPU_SHORT(fe->bit_p_spl, big_endian); format = TO_CPU_SHORT(fe->guid_format, big_endian); } if (format != WAV_FMT_PCM && @@ -1071,6 +1073,10 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) prg_exit(EXIT_FAILURE); } hwparams.channels = channels; + if (vbps > TO_CPU_SHORT(f->bit_p_spl, big_endian)) { + error(_("valid bps greater than bps: %d > %d"), vbps, TO_CPU_SHORT(f->bit_p_spl, big_endian)); + prg_exit(EXIT_FAILURE); + } switch (TO_CPU_SHORT(f->bit_p_spl, big_endian)) { case 8: if (hwparams.format != DEFAULT_FORMAT && @@ -1123,10 +1129,20 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) break; case 32: if (format == WAV_FMT_PCM) { - if (big_endian) - native_format = SND_PCM_FORMAT_S32_BE; - else - native_format = SND_PCM_FORMAT_S32_LE; + switch (vbps) { + case 24: + if (big_endian) + native_format = SND_PCM_FORMAT_S24_BE; + else + native_format = SND_PCM_FORMAT_S24_LE; + break; + default: + if (big_endian) + native_format = SND_PCM_FORMAT_S32_BE; + else + native_format = SND_PCM_FORMAT_S32_LE; + break; + } hwparams.format = native_format; } else if (format == WAV_FMT_IEEE_FLOAT) { if (big_endian)