On Tue, Feb 01, 2005 at 05:04:42PM +0100, Daniel Kobras wrote: > 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.
nice. attached is the patch corrected for fmtheaders (could benefit fiddling a bit with the line numbers to avoid the warnings). your patch seems to produce cleaner files than mine (aplay like them), altough i still get Premature EOF with. > > 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. agreed. the cpu eating is quite a problem though, but this is another story. i guess shmbuf.c would need a bit of cleanup too. ciao, piem.
# 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 @@ -4,43 +4,49 @@ #include <sys/types.h> #include <inttypes.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) ((uint32_t)(bp.BlockLen[0]) | \ - ((uint32_t)(bp.BlockLen[1]) << 8) | \ - ((uint32_t)(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 */ + 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 */ } vochead; typedef struct blockTC { - u_char BlockID; - u_char BlockLen[3]; /* low, mid, high byte of length of rest of block */ + u_int8_t BlockID; + u_int8_t BlockLen[3]; /* low, mid, high byte of length of rest of block */ } blockTC; typedef struct blockT1 { - u_char TimeConstant; - u_char PackMethod; + u_int8_t TimeConstant; + u_int8_t PackMethod; } blockT1; typedef struct blockT8 { - u_short TimeConstant; - u_char PackMethod; - u_char VoiceMode; + u_int16_t TimeConstant; + u_int8_t PackMethod; + u_int8_t VoiceMode; } blockT8; typedef struct blockT9 { u_int SamplesPerSec; - u_char BitsPerSample; - u_char Channels; - u_short Format; - u_char reserved[4]; + u_int8_t BitsPerSample; + u_int8_t Channels; + u_int16_t Format; + u_int8_t reserved[4]; } blockT9; @@ -52,21 +58,21 @@ it works on all WAVE-file I have */ typedef struct wavhead { - uint32_t main_chunk; /* 'RIFF' */ - uint32_t length; /* Length of rest of file */ - uint32_t chunk_type; /* 'WAVE' */ + u_int32_t main_chunk; /* 'RIFF' */ + u_int32_t length; /* Length of rest of file */ + u_int32_t chunk_type; /* 'WAVE' */ - uint32_t sub_chunk; /* 'fmt ' */ - uint32_t 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 */ - uint32_t sample_fq; /* frequence of sample */ - uint32_t byte_p_sec; - u_short byte_p_spl; /* samplesize; 1 or 2 bytes */ - u_short bit_p_spl; /* 8, 12 or 16 bit */ + 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 */ - uint32_t data_chunk; /* 'data' */ - uint32_t data_length; /* samplecount (lenth of rest of block?)*/ + u_int32_t data_chunk; /* 'data' */ + u_int32_t data_length; /* samplecount (lenth of rest of block?)*/ } 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)