From 6f438b9b9ad63bcfc16afc4c4be9cc71b897211e Mon Sep 17 00:00:00 2001 From: Andrew Paprocki Date: Wed, 6 Feb 2008 14:05:07 +0100 Subject: [PATCH] aplay/arecord - Add support for IEEE float 32-bit WAV files This patch modifies aplay/arecord to support playing/capturing IEEE float 32-bit WAV files. Tested on HDA hardware in both stereo and multi-channel modes. Added the WAV file constant for Dolby AC-3 S/PDIF passthrough to formats.h for future use when AC-3 passthrough is better supported. Signed-off-by: Andrew Paprocki --- aplay/aplay.c | 16 ++++++++++++---- aplay/formats.h | 6 +++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/aplay/aplay.c b/aplay/aplay.c index 88d1ef2..9b22eb5 100644 --- a/aplay/aplay.c +++ b/aplay/aplay.c @@ -745,8 +745,9 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) check_wavefile_space(buffer, len, blimit); test_wavefile_read(fd, buffer, &size, len, __LINE__); f = (WaveFmtBody*) buffer; - if (LE_SHORT(f->format) != WAV_PCM_CODE) { - error(_("can't play not PCM-coded WAVE-files")); + if (LE_SHORT(f->format) != WAV_FMT_PCM && + LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) { + error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format)); exit(EXIT_FAILURE); } if (LE_SHORT(f->modus) < 1) { @@ -788,7 +789,10 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size) } break; case 32: - hwparams.format = SND_PCM_FORMAT_S32_LE; + if (LE_SHORT(f->format) == WAV_FMT_PCM) + hwparams.format = SND_PCM_FORMAT_S32_LE; + else if (LE_SHORT(f->format) == WAV_FMT_IEEE_FLOAT) + hwparams.format = SND_PCM_FORMAT_FLOAT_LE; break; default: error(_(" can't play WAVE-files with sample %d bits wide"), @@ -1778,6 +1782,7 @@ static void begin_wave(int fd, size_t cnt) bits = 16; break; case SND_PCM_FORMAT_S32_LE: + case SND_PCM_FORMAT_FLOAT_LE: bits = 32; break; case SND_PCM_FORMAT_S24_LE: @@ -1796,7 +1801,10 @@ static void begin_wave(int fd, size_t cnt) cf.type = WAV_FMT; cf.length = LE_INT(16); - f.format = LE_SHORT(WAV_PCM_CODE); + if (hwparams.format == SND_PCM_FORMAT_FLOAT_LE) + f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT); + else + f.format = LE_SHORT(WAV_FMT_PCM); f.modus = LE_SHORT(hwparams.channels); f.sample_fq = LE_INT(hwparams.rate); #if 0 diff --git a/aplay/formats.h b/aplay/formats.h index 2c4f724..3ba0bfa 100644 --- a/aplay/formats.h +++ b/aplay/formats.h @@ -64,7 +64,11 @@ typedef struct voc_ext_block { #define WAV_WAVE COMPOSE_ID('W','A','V','E') #define WAV_FMT COMPOSE_ID('f','m','t',' ') #define WAV_DATA COMPOSE_ID('d','a','t','a') -#define WAV_PCM_CODE 1 + +/* WAVE fmt block constants from Microsoft mmreg.h header */ +#define WAV_FMT_PCM 0x0001 +#define WAV_FMT_IEEE_FLOAT 0x0003 +#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092 /* it's in chunks like .voc and AMIGA iff, but my source say there are in only in this combination, so I combined them in one header;