tag 292137 + pending
thanks

On Tue, Feb 01, 2005 at 02:58:50PM +0000, Paul Brossier wrote:
> i found the following patches in #60041 and #126257.  with this,
> recorded files can be played using bplay, but the file header is still
> somehow badly crafted:
> 
> $ play new.wav
> playing new.wav
> sox: Premature EOF on .wav input file

Thanks. I had already looked through the bplay BTS entries, found the
patches there and decided to craft my own. It's ready but stupid me
forgot to apply the current patches to gramofile first, so I'll have to
go through another round and do some patch merging. I'll attach the
original version against the pristine upstream source for reference.

> i also noted a few other things that could be grabbed from current
> bplay: 
>  - handling of very long files (see last patch in #126257)
>  - updated Die function to make sure the forked process is killed.
> 
> And at the end of the recording, when showing the 'Recording
> information', brec_gramo eats all the cpu available until OK is pressed.

WAV format as spec'ed is limited to a 2GB max. file size. Therefore,
apart from the sanity checks I see little use in applying the LFS
patches.

Regards,

Daniel.

# Fix endianness bugs in WAV and VOC headers on big-endian archs.
# Use POSIX size types to avoid broken headers on 64bit archs.
# Disable padding in structs that read/write raw on-disk data.
# [dk]
#PATCHOPTIONS: -p0
Index: bplaysrc/bplay.c
===================================================================
RCS file: /home/kobras/cvsroot/debian/gramofile/bplaysrc/bplay.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 bplay.c
--- bplaysrc/bplay.c    2001/05/05 14:07:15     1.1.1.2
+++ bplaysrc/bplay.c    2005/01/31 15:54:06
@@ -26,6 +26,30 @@
 #include <machine/soundcard.h>
 #endif
 
+/* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+# include <endian.h>
+# undef  _BSD_SOURCE
+#else
+# include <endian.h>
+#endif
+
+#include <sys/types.h>
+#include <byteswap.h>
+
+/* Adapted from the byteorder macros in the Linux kernel. */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define cpu_to_le32(x) (x)
+#define cpu_to_le16(x) (x)
+#else
+#define cpu_to_le32(x) bswap_32((x))
+#define cpu_to_le16(x) bswap_16((x))
+#endif
+
+#define le32_to_cpu(x) cpu_to_le32((x))
+#define le16_to_cpu(x) cpu_to_le16((x))
+
 #include "fmtheaders.h"
 
 #include "../yesnowindow.h"
@@ -290,23 +314,26 @@
                                char *data = "data";
 
                                memcpy(&(header.main_chunk), riff, 4);
-                               header.length = sizeof(wavhead) - 8 + bcount;
+                               header.length = cpu_to_le32(sizeof(wavhead)
+                                               - 8 + bcount);
                                memcpy(&(header.chunk_type), wave, 4);
 
                                memcpy(&(header.sub_chunk), fmt, 4);
-                               header.sc_len = 16;
-                               header.format = 1;
-                               header.modus = stereo + 1;
-                               header.sample_fq = speed;
-                               header.byte_p_sec = ((bits > 8)? 
2:1)*(stereo+1)*speed;
+                               header.sc_len = cpu_to_le32(16);
+                               header.format = cpu_to_le16(1);
+                               header.modus = cpu_to_le16(stereo + 1);
+                               header.sample_fq = cpu_to_le32(speed);
+                               header.byte_p_sec = cpu_to_le32(((bits > 8)?
+                                               2:1)*(stereo+1)*speed);
 /* Correction by J.A. Bezemer: */
-                               header.byte_p_spl = ((bits > 8)? 
2:1)*(stereo+1);
+                               header.byte_p_spl = cpu_to_le16(((bits > 8)?
+                                               2:1)*(stereo+1));
                        /* was: header.byte_p_spl = (bits > 8)? 2:1; */
 
-                               header.bit_p_spl = bits;
+                               header.bit_p_spl = cpu_to_le16(bits);
 
                                memcpy(&(header.data_chunk), data, 4);
-                               header.data_length = bcount;
+                               header.data_length = cpu_to_le32(bcount);
                                write(thefd, &header, sizeof(header));
                        }
                case F_RAW:
@@ -336,9 +363,9 @@
 
                                for (i=0;i<20;i++)
                                        header.Magic[i] = VOC_MAGIC[i];
-                               header.BlockOffset = 0x1a;
-                               header.Version = 0x0114;
-                               header.IDCode = 0x111F;
+                               header.BlockOffset = cpu_to_le16(0x1a);
+                               header.Version = cpu_to_le16(0x0114);
+                               header.IDCode = cpu_to_le16(0x111F);
                                write(thefd, &header, sizeof(vochead));
 
                                snd_parm(speed, bits, stereo);
@@ -349,10 +376,10 @@
                                ablk.BlockLen[0] = (i + 12) & 0xFF;
                                ablk.BlockLen[1] = ((i + 12) >> 8) & 0xFF;
                                ablk.BlockLen[2] = ((i + 12) >> 16) & 0xFF;
-                               bblk.SamplesPerSec = speed;
+                               bblk.SamplesPerSec = cpu_to_le32(speed);
                                bblk.BitsPerSample = bits;
                                bblk.Channels = stereo + 1;
-                               bblk.Format = (bits == 8)? 0 : 4;
+                               bblk.Format = cpu_to_le16((bits == 8)? 0 : 4);
                                write(thefd, &ablk, sizeof(ablk));
                                write(thefd, &bblk, sizeof(bblk));
                                shmrec(thefd, i, 1);
@@ -476,6 +503,17 @@
 
     memcpy((void*)&wavhd, (void*)hd_buf, 20);
     count = read(thefd, ((char*)&wavhd)+20, sizeof(wavhd) - 20);
+
+    wavhd.length = le32_to_cpu(wavhd.length);
+    wavhd.sc_len = le32_to_cpu(wavhd.sc_len);
+    wavhd.format = le16_to_cpu(wavhd.format);
+    wavhd.modus = le16_to_cpu(wavhd.modus);
+    wavhd.sample_fq = le32_to_cpu(wavhd.sample_fq);
+    wavhd.byte_p_sec = le32_to_cpu(wavhd.byte_p_sec);
+    wavhd.byte_p_spl = le16_to_cpu(wavhd.byte_p_spl);
+    wavhd.bit_p_spl = le16_to_cpu(wavhd.bit_p_spl);
+    wavhd.data_length = le32_to_cpu(wavhd.data_length);
+
     if(wavhd.format != 1) Die("Input is not a PCM WAV file");
 #ifndef LP2CD
     if (! (mods&MSPEED))
@@ -518,6 +556,11 @@
     fprintf(stderr, "Playing Creative Labs Voice file ...\n");
     memcpy((void*)&vochd, (void*)hd_buf, 20);
     count = read(thefd, ((char*)&vochd)+20, sizeof(vochd) - 20);
+
+    vochd.BlockOffset = le16_to_cpu(vochd.BlockOffset);
+    vochd.Version = le16_to_cpu(vochd.Version);
+    vochd.IDCode = le16_to_cpu(vochd.IDCode);
+    
     fprintf(stderr, "Format version %d.%d\n", vochd.Version>>8,
        vochd.Version&0xFF);
     if (vochd.IDCode != (~vochd.Version+0x1234))
@@ -566,6 +609,9 @@
        {
        blockT8 tblock;
        read(thefd, (char*)&tblock, sizeof(tblock));
+
+       tblock.TimeConstant = le16_to_cpu(tblock.TimeConstant);
+       
        if(tblock.PackMethod != 0) Die("Non PCM VOC block");
        speed = 256000000/(65536 - tblock.TimeConstant);
        bits = 8;
@@ -578,6 +624,10 @@
        {
        blockT9 tblock;
        read(thefd, (char*)&tblock, sizeof(tblock));
+
+       tblock.SamplesPerSec = le32_to_cpu(tblock.SamplesPerSec);
+       tblock.Format = le16_to_cpu(tblock.Format);
+       
        if(tblock.Format != 0 && tblock.Format != 4)
            Die("Non PCM VOC block");
        speed = tblock.SamplesPerSec;
Index: bplaysrc/fmtheaders.h
===================================================================
RCS file: /home/kobras/cvsroot/debian/gramofile/bplaysrc/fmtheaders.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 fmtheaders.h
--- bplaysrc/fmtheaders.h       2001/05/05 13:52:25     1.1.1.1
+++ bplaysrc/fmtheaders.h       2005/01/31 15:54:06
@@ -3,44 +3,50 @@
 
 #include <sys/types.h>
 
+#ifdef __GNUC__
+# define PACKED(x)      __attribute__((packed)) x
+#else
+# define PACKED(x)     x
+#endif
+
 /* Definitions for .VOC files */
 
 #define VOC_MAGIC      "Creative Voice File\032"
 
-#define DATALEN(bp)    ((u_long)(bp.BlockLen[0]) | \
-                         ((u_long)(bp.BlockLen[1]) << 8) | \
-                         ((u_long)(bp.BlockLen[2]) << 16) )
+#define DATALEN(bp)    ((u_int32_t)(bp.BlockLen[0]) | \
+                         ((u_int32_t)(bp.BlockLen[1]) << 8) | \
+                         ((u_int32_t)(bp.BlockLen[2]) << 16) )
 
 typedef struct vochead {
-  u_char  Magic[20];   /* must be VOC_MAGIC */
-  u_short BlockOffset; /* Offset to first block from top of file */
-  u_short Version;     /* VOC-file version */
-  u_short IDCode;      /* complement of version + 0x1234 */
-} vochead;
+  u_int8_t  Magic[20]; /* must be VOC_MAGIC */
+  u_int16_t BlockOffset;       /* Offset to first block from top of file */
+  u_int16_t Version;   /* VOC-file version */
+  u_int16_t IDCode;    /* complement of version + 0x1234 */
+} PACKED(vochead);
 
 typedef struct blockTC {
-  u_char  BlockID;
-  u_char  BlockLen[3]; /* low, mid, high byte of length of rest of block */
-} blockTC;
+  u_int8_t  BlockID;
+  u_int8_t  BlockLen[3];       /* low, mid, high byte of length of rest of 
block */
+} PACKED(blockTC);
 
 typedef struct blockT1 {
-  u_char  TimeConstant;
-  u_char  PackMethod;
-} blockT1;
+  u_int8_t  TimeConstant;
+  u_int8_t  PackMethod;
+} PACKED(blockT1);
 
 typedef struct blockT8 {
-  u_short TimeConstant;
-  u_char  PackMethod;
-  u_char  VoiceMode;
-} blockT8;
+  u_int16_t TimeConstant;
+  u_int8_t  PackMethod;
+  u_int8_t  VoiceMode;
+} PACKED(blockT8);
 
 typedef struct blockT9 {
-  u_int   SamplesPerSec;
-  u_char  BitsPerSample;
-  u_char  Channels;
-  u_short Format;
-  u_char   reserved[4];
-} blockT9;
+  u_int32_t SamplesPerSec;
+  u_int8_t  BitsPerSample;
+  u_int8_t  Channels;
+  u_int16_t Format;
+  u_int8_t  reserved[4];
+} PACKED(blockT9);
   
 
 
@@ -51,21 +57,21 @@
    it works on all WAVE-file I have
 */
 typedef struct wavhead {
-  u_long       main_chunk;     /* 'RIFF' */
-  u_long       length;         /* Length of rest of file */
-  u_long       chunk_type;     /* 'WAVE' */
-
-  u_long       sub_chunk;      /* 'fmt ' */
-  u_long       sc_len;         /* length of sub_chunk, =16 (rest of chunk) */
-  u_short      format;         /* should be 1 for PCM-code */
-  u_short      modus;          /* 1 Mono, 2 Stereo */
-  u_long       sample_fq;      /* frequence of sample */
-  u_long       byte_p_sec;
-  u_short      byte_p_spl;     /* samplesize; 1 or 2 bytes */
-  u_short      bit_p_spl;      /* 8, 12 or 16 bit */ 
-
-  u_long       data_chunk;     /* 'data' */
-  u_long       data_length;    /* samplecount (lenth of rest of block?)*/
-} wavhead;
+  u_int32_t    main_chunk;     /* 'RIFF' */
+  u_int32_t    length;         /* Length of rest of file */
+  u_int32_t    chunk_type;     /* 'WAVE' */
+
+  u_int32_t    sub_chunk;      /* 'fmt ' */
+  u_int32_t    sc_len;         /* length of sub_chunk, =16 (rest of chunk) */
+  u_int16_t    format;         /* should be 1 for PCM-code */
+  u_int16_t    modus;          /* 1 Mono, 2 Stereo */
+  u_int32_t    sample_fq;      /* frequence of sample */
+  u_int32_t    byte_p_sec;
+  u_int16_t    byte_p_spl;     /* samplesize; 1 or 2 bytes */
+  u_int16_t    bit_p_spl;      /* 8, 12 or 16 bit */ 
+
+  u_int32_t    data_chunk;     /* 'data' */
+  u_int32_t    data_length;    /* samplecount (lenth of rest of block?)*/
+} PACKED(wavhead);
 
 #endif
Index: bplaysrc/sndfunc.c
===================================================================
RCS file: /home/kobras/cvsroot/debian/gramofile/bplaysrc/sndfunc.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 sndfunc.c
--- bplaysrc/sndfunc.c  2001/05/05 14:07:15     1.1.1.2
+++ bplaysrc/sndfunc.c  2005/01/31 15:54:06
@@ -64,6 +64,9 @@
        sync_audio();
 
        /* Set the sample speed, size and stereoness */
+       /* We only use values of 8 and 16 for bits. This implies
+        * unsigned data for 8 bits, and little-endian signed for 16 bits.
+        */
        if (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &bits) < 0)
            ErrDie(AUDIO);
        if (ioctl(audio, SNDCTL_DSP_STEREO, &stereo) < 0)

Reply via email to