]> git.alsa-project.org Git - alsa-utils.git/commitdiff
Support for playing WAV files with "extensible format" header using aplay.
authorPawel MOLL <pawel.moll@st.com>
Thu, 6 Mar 2008 16:34:21 +0000 (17:34 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 6 Mar 2008 16:34:21 +0000 (17:34 +0100)
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>
aplay/aplay.c
aplay/formats.h

index 9b22eb52c80d63f6d2e7cdcf2d883b62bc6b527b..e02ca9844c68ef173966437e2fe9475463337a99 100644 (file)
@@ -745,16 +745,29 @@ 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_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 &&
             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) {
-               error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->modus));
+       if (LE_SHORT(f->channels) < 1) {
+               error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
                exit(EXIT_FAILURE);
        }
-       hwparams.channels = LE_SHORT(f->modus);
+       hwparams.channels = LE_SHORT(f->channels);
        switch (LE_SHORT(f->bit_p_spl)) {
        case 8:
                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);
         else
                 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);
 #if 0
        tmp2 = (samplesize == 8) ? 1 : 2;
index 3ba0bfabc146d306e4fb3ea8a49328ac3537a14e..b5314f94228786db925e51c1cb6e82d276b0ff5b 100644 (file)
@@ -69,6 +69,10 @@ typedef struct voc_ext_block {
 #define WAV_FMT_PCM             0x0001
 #define WAV_FMT_IEEE_FLOAT      0x0003
 #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
    are in only in this combination, so I combined them in one header;
@@ -81,14 +85,23 @@ typedef struct {
 } WaveHeader;
 
 typedef struct {
-       u_short format;         /* should be 1 for PCM-code */
-       u_short modus;          /* 1 Mono, 2 Stereo */
+       u_short format;         /* see WAV_FMT_* */
+       u_short channels;
        u_int sample_fq;        /* frequence of sample */
        u_int byte_p_sec;
        u_short byte_p_spl;     /* samplesize; 1 or 2 bytes */
        u_short bit_p_spl;      /* 8, 12 or 16 bit */
 } 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 {
        u_int type;             /* 'data' */
        u_int length;           /* samplecount */