Support for playing WAV files with "extensible format" header using aplay.

WAV files with more than 2 channels or with more than 16 bits per samples
can be saved with "extensible format" chunk
(see http://msdn2.microsoft.com/en-us/library/ms713496(VS.85).aspx).
For instance, sox, when converting data to 24- or 32-bits per sample format
uses this format, and aplay was unable to play such file. Now the problem
is solved :-)

Signed-off-by: Pawel MOLL <pawel.moll@st.com>
This commit is contained in:
Pawel MOLL 2008-03-06 17:34:21 +01:00 committed by Takashi Iwai
parent 8e2046bed5
commit 4bdb0adef1
2 changed files with 32 additions and 6 deletions

View file

@ -745,16 +745,29 @@ static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
check_wavefile_space(buffer, len, blimit); check_wavefile_space(buffer, len, blimit);
test_wavefile_read(fd, buffer, &size, len, __LINE__); test_wavefile_read(fd, buffer, &size, len, __LINE__);
f = (WaveFmtBody*) buffer; f = (WaveFmtBody*) buffer;
if (LE_SHORT(f->format) == WAV_FMT_EXTENSIBLE) {
WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
if (len < sizeof(WaveFmtExtensibleBody)) {
error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
len, (u_int)sizeof(WaveFmtExtensibleBody));
exit(EXIT_FAILURE);
}
if (memcmp(fe->guid_tag, WAV_GUID_TAG, 14) != 0) {
error(_("wrong format tag in extensible 'fmt ' chunk"));
exit(EXIT_FAILURE);
}
f->format = fe->guid_format;
}
if (LE_SHORT(f->format) != WAV_FMT_PCM && if (LE_SHORT(f->format) != WAV_FMT_PCM &&
LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) { 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)); error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (LE_SHORT(f->modus) < 1) { if (LE_SHORT(f->channels) < 1) {
error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->modus)); error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
hwparams.channels = LE_SHORT(f->modus); hwparams.channels = LE_SHORT(f->channels);
switch (LE_SHORT(f->bit_p_spl)) { switch (LE_SHORT(f->bit_p_spl)) {
case 8: case 8:
if (hwparams.format != DEFAULT_FORMAT && if (hwparams.format != DEFAULT_FORMAT &&
@ -1805,7 +1818,7 @@ static void begin_wave(int fd, size_t cnt)
f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT); f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT);
else else
f.format = LE_SHORT(WAV_FMT_PCM); f.format = LE_SHORT(WAV_FMT_PCM);
f.modus = LE_SHORT(hwparams.channels); f.channels = LE_SHORT(hwparams.channels);
f.sample_fq = LE_INT(hwparams.rate); f.sample_fq = LE_INT(hwparams.rate);
#if 0 #if 0
tmp2 = (samplesize == 8) ? 1 : 2; tmp2 = (samplesize == 8) ? 1 : 2;

View file

@ -69,6 +69,10 @@ typedef struct voc_ext_block {
#define WAV_FMT_PCM 0x0001 #define WAV_FMT_PCM 0x0001
#define WAV_FMT_IEEE_FLOAT 0x0003 #define WAV_FMT_IEEE_FLOAT 0x0003
#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092 #define WAV_FMT_DOLBY_AC3_SPDIF 0x0092
#define WAV_FMT_EXTENSIBLE 0xfffe
/* Used with WAV_FMT_EXTENSIBLE format */
#define WAV_GUID_TAG "\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
/* it's in chunks like .voc and AMIGA iff, but my source say there /* 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; are in only in this combination, so I combined them in one header;
@ -81,14 +85,23 @@ typedef struct {
} WaveHeader; } WaveHeader;
typedef struct { typedef struct {
u_short format; /* should be 1 for PCM-code */ u_short format; /* see WAV_FMT_* */
u_short modus; /* 1 Mono, 2 Stereo */ u_short channels;
u_int sample_fq; /* frequence of sample */ u_int sample_fq; /* frequence of sample */
u_int byte_p_sec; u_int byte_p_sec;
u_short byte_p_spl; /* samplesize; 1 or 2 bytes */ u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
u_short bit_p_spl; /* 8, 12 or 16 bit */ u_short bit_p_spl; /* 8, 12 or 16 bit */
} WaveFmtBody; } WaveFmtBody;
typedef struct {
WaveFmtBody format;
u_short ext_size;
u_short bit_p_spl;
u_int channel_mask;
u_short guid_format; /* WAV_FMT_* */
u_char guid_tag[14]; /* WAV_GUID_TAG */
} WaveFmtExtensibleBody;
typedef struct { typedef struct {
u_int type; /* 'data' */ u_int type; /* 'data' */
u_int length; /* samplecount */ u_int length; /* samplecount */