]> git.alsa-project.org Git - alsa-utils.git/commitdiff
Better .wav detection
authorAbramo Bagnara <abramo@alsa-project.org>
Mon, 29 May 2000 18:54:23 +0000 (18:54 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Mon, 29 May 2000 18:54:23 +0000 (18:54 +0000)
aplay/aplay.c
aplay/formats.h

index b32da5ec4d389465674ffc00a9cf07df5c5d7531..ec737ad0246590eaefbbdfe8c0a0347ebc9b84f8 100644 (file)
@@ -377,7 +377,6 @@ int main(int argc, char *argv[])
                                fprintf(stderr, "Error: wrong extended format '%s'\n", optarg);
                                exit(EXIT_FAILURE);
                        }
-                       active_format = FORMAT_RAW;
                        break;
                case 'm':
                case 'M':
@@ -514,42 +513,61 @@ static int test_vocfile(void *buffer)
 }
 
 /*
- * test, if it's a .WAV file, 0 if ok (and set the speed, stereo etc.)
- *                            < 0 if not
+ * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
+ *                            == 0 if not
+ * Value returned is bytes to be discarded.
  */
-static int test_wavefile(void *buffer)
+static int test_wavefile(void *buffer, size_t size)
 {
-       WaveHeader *wp = buffer;
+       WaveHeader *h = buffer;
+       WaveFmtHeader *f;
+       WaveChunkHeader *c;
 
-       if (wp->main_chunk == WAV_RIFF && wp->chunk_type == WAV_WAVE &&
-           wp->sub_chunk == WAV_FMT && wp->data_chunk == WAV_DATA) {
-               if (LE_SHORT(wp->format) != WAV_PCM_CODE) {
-                       fprintf(stderr, "%s: can't play not PCM-coded WAVE-files\n", command);
+       if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
+               return 0;
+       c = (WaveChunkHeader*)((char *)buffer + sizeof(WaveHeader));
+       while (c->type != WAV_FMT) {
+               c = (WaveChunkHeader*)((char*)c + sizeof(*c) + c->length);
+               if ((char *)c + sizeof(*c) > (char*) buffer + size) {
+                       fprintf(stderr, "%s: cannot found WAVE fmt chunk\n", command);
                        exit(EXIT_FAILURE);
                }
-               if (LE_SHORT(wp->modus) < 1 || LE_SHORT(wp->modus) > 32) {
-                       fprintf(stderr, "%s: can't play WAVE-files with %d tracks\n",
-                               command, LE_SHORT(wp->modus));
+       }
+       f = (WaveFmtHeader*) c;
+       if (LE_SHORT(f->format) != WAV_PCM_CODE) {
+               fprintf(stderr, "%s: can't play not PCM-coded WAVE-files\n", command);
+               exit(EXIT_FAILURE);
+       }
+       if (LE_SHORT(f->modus) < 1) {
+               fprintf(stderr, "%s: can't play WAVE-files with %d tracks\n",
+                       command, LE_SHORT(f->modus));
+               exit(EXIT_FAILURE);
+       }
+       format.channels = LE_SHORT(f->modus);
+       switch (LE_SHORT(f->bit_p_spl)) {
+       case 8:
+               format.format = SND_PCM_SFMT_U8;
+               break;
+       case 16:
+               format.format = SND_PCM_SFMT_S16_LE;
+               break;
+       default:
+               fprintf(stderr, "%s: can't play WAVE-files with sample %d bits wide\n",
+                       command, LE_SHORT(f->bit_p_spl));
+               exit(EXIT_FAILURE);
+       }
+       format.rate = LE_INT(f->sample_fq);
+       while (c->type != WAV_DATA) {
+               c = (WaveChunkHeader*)((char*)c + sizeof(*c) + c->length);
+               if ((char *)c + sizeof(*c) > (char*) buffer + size) {
+                       fprintf(stderr, "%s: cannot found WAVE data chunk\n", command);
                        exit(EXIT_FAILURE);
                }
-               format.channels = LE_SHORT(wp->modus);
-               switch (LE_SHORT(wp->bit_p_spl)) {
-               case 8:
-                       format.format = SND_PCM_SFMT_U8;
-                       break;
-               case 16:
-                       format.format = SND_PCM_SFMT_S16_LE;
-                       break;
-               default:
-                       fprintf(stderr, "%s: can't play WAVE-files with sample %d bits wide\n",
-                               command, LE_SHORT(wp->bit_p_spl));
-               }
-               format.rate = LE_INT(wp->sample_fq);
-               count = LE_INT(wp->data_length);
-               check_new_format(&format);
-               return 0;
        }
-       return -1;
+
+       count = LE_INT(c->length);
+       check_new_format(&format);
+       return (char *)c + sizeof(*c) - (char *) buffer;
 }
 
 /*
@@ -1209,7 +1227,9 @@ static void begin_voc(int fd, size_t cnt)
 /* write a WAVE-header */
 static void begin_wave(int fd, size_t cnt)
 {
-       WaveHeader wh;
+       WaveHeader h;
+       WaveFmtHeader f;
+       WaveChunkHeader c;
        int bits;
 
        bits = 8;
@@ -1224,25 +1244,30 @@ static void begin_wave(int fd, size_t cnt)
                fprintf(stderr, "%s: Wave doesn't support %s format...\n", command, snd_pcm_get_format_name(format.format));
                exit(EXIT_FAILURE);
        }
-       wh.main_chunk = WAV_RIFF;
-       wh.length = cnt + sizeof(WaveHeader) - 8;
-       wh.chunk_type = WAV_WAVE;
-       wh.sub_chunk = WAV_FMT;
-       wh.sc_len = 16;
-       wh.format = WAV_PCM_CODE;
-       wh.modus = format.channels;
-       wh.sample_fq = format.rate;
+       h.magic = WAV_RIFF;
+       h.length = cnt + sizeof(WaveHeader) + sizeof(WaveFmtHeader) + sizeof(WaveChunkHeader) - 8;
+       h.type = WAV_WAVE;
+
+       f.type = WAV_FMT;
+       f.length = 16;
+       f.format = WAV_PCM_CODE;
+       f.modus = format.channels;
+       f.sample_fq = format.rate;
 #if 0
-       wh.byte_p_spl = (samplesize == 8) ? 1 : 2;
-       wh.byte_p_sec = dsp_speed * wh.modus * wh.byte_p_spl;
+       f.byte_p_spl = (samplesize == 8) ? 1 : 2;
+       f.byte_p_sec = dsp_speed * f.modus * f.byte_p_spl;
 #else
-       wh.byte_p_spl = wh.modus * ((bits + 7) / 8);
-       wh.byte_p_sec = wh.byte_p_spl * format.rate;
+       f.byte_p_spl = f.modus * ((bits + 7) / 8);
+       f.byte_p_sec = f.byte_p_spl * format.rate;
 #endif
-       wh.bit_p_spl = bits;
-       wh.data_chunk = WAV_DATA;
-       wh.data_length = cnt;
-       if (write(fd, &wh, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+       f.bit_p_spl = bits;
+
+       c.type = WAV_DATA;
+       c.length = cnt;
+
+       if (write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
+           write(fd, &f, sizeof(WaveFmtHeader)) != sizeof(WaveFmtHeader) ||
+           write(fd, &c, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
                fprintf(stderr, "%s: write error\n", command);
                exit(EXIT_FAILURE);
        }
@@ -1427,19 +1452,20 @@ static void playback(char *name)
        }
        /* read bytes for WAVE-header */
        if (read(fd, audiobuf + sizeof(VocHeader),
-                sizeof(WaveHeader) - sizeof(VocHeader)) !=
-           sizeof(WaveHeader) - sizeof(VocHeader)) {
+                64 - sizeof(VocHeader)) !=
+           64 - sizeof(VocHeader)) {
                fprintf(stderr, "%s: read error", command);
                exit(EXIT_FAILURE);
        }
-       if (test_wavefile(audiobuf) >= 0) {
-               playback_go(fd, 0, count, FORMAT_WAVE, name);
+       if ((ofs = test_wavefile(audiobuf, 64)) > 0) {
+               memmove(audiobuf, audiobuf + ofs, 64 - ofs);
+               playback_go(fd, 64 - ofs, count, FORMAT_WAVE, name);
        } else {
                /* should be raw data */
                check_new_format(&rformat);
                init_raw_data();
                count = calc_count();
-               playback_go(fd, sizeof(WaveHeader), count, FORMAT_RAW, name);
+               playback_go(fd, 50, count, FORMAT_RAW, name);
        }
       __end:
        if (fd != 0)
index aa5b5afb789134a66f921c8c4ff10cc439c3f41a..a26b4733bce420481e9b087544774dc0385404ca 100644 (file)
@@ -64,23 +64,27 @@ typedef struct voc_ext_block {
    are in only in this combination, so I combined them in one header;
    it works on all WAVE-file I have
  */
-typedef struct wav_header {
-       u_int main_chunk;       /* 'RIFF' */
+typedef struct {
+       u_int magic;            /* 'RIFF' */
        u_int length;           /* filelen */
-       u_int chunk_type;       /* 'WAVE' */
+       u_int type;             /* 'WAVE' */
+} WaveHeader;
 
-       u_int sub_chunk;        /* 'fmt ' */
-       u_int sc_len;           /* length of sub_chunk, =16 */
+typedef struct {
+       u_int type;             /* 'fmt ' */
+       u_int length;           /* length of chunk */
        u_short format;         /* should be 1 for PCM-code */
        u_short modus;          /* 1 Mono, 2 Stereo */
        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 */
+} WaveFmtHeader;
 
-       u_int data_chunk;       /* 'data' */
-       u_int data_length;      /* samplecount */
-} WaveHeader;
+typedef struct {
+       u_int type;             /* 'data' */
+       u_int length;           /* samplecount */
+} WaveChunkHeader;
 
 /* Definitions for Sparc .au header */