# 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. # Merged with endianness patch by Tom Harvey # [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 #endif +/* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */ +#ifndef _BSD_SOURCE +# define _BSD_SOURCE +# include +# undef _BSD_SOURCE +#else +# include +#endif + +#include +#include + +/* 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 +#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) diff -ur endian.c endian.c --- endian.c Sat May 5 15:52:25 2001 +++ endian.c Fri Jun 8 09:51:44 2001 @@ -24,10 +24,10 @@ return (tmp); } -u_long -SwapFourBytes (u_long dw) +u_int32_t +SwapFourBytes (u_int32_t dw) { - register u_long tmp; + register u_int32_t tmp; tmp = (dw & 0x000000FF); tmp = ((dw & 0x0000FF00) >> 0x08) | (tmp << 0x08); tmp = ((dw & 0x00FF0000) >> 0x10) | (tmp << 0x08); diff -ur endian.h endian.h --- endian.h Sat May 5 15:52:25 2001 +++ endian.h Fri Jun 8 09:57:11 2001 @@ -4,8 +4,10 @@ #ifndef _GETBIG #define _GETBIG 1 +#include + extern u_short SwapTwoBytes (u_short); -extern u_long SwapFourBytes (u_long); +extern u_int32_t SwapFourBytes (u_int32_t); extern sample_t SwapSample (sample_t); #endif diff -ur fmtheaders.h fmtheaders.h --- fmtheaders.h 2001-05-05 15:52:25.000000000 +0200 +++ fmtheaders.h 2005-03-01 14:48:54.000000000 +0100 @@ -3,55 +3,51 @@ #include +#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) ) - -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; - -typedef struct blockTC - { - u_char BlockID; - u_char BlockLen[3]; /* low, mid, high byte of length of rest of block */ - } -blockTC; - -typedef struct blockT1 - { - u_char TimeConstant; - u_char PackMethod; - } -blockT1; - -typedef struct blockT8 - { - u_short TimeConstant; - u_char PackMethod; - u_char VoiceMode; - } -blockT8; - -typedef struct blockT9 - { - u_int SamplesPerSec; - u_char BitsPerSample; - u_char Channels; - u_short Format; - u_char reserved[4]; - } -blockT9; - +#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_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_int8_t BlockID; + u_int8_t BlockLen[3]; /* low, mid, high byte of length of rest of block */ +} PACKED(blockTC); + +typedef struct blockT1 { + u_int8_t TimeConstant; + u_int8_t PackMethod; +} PACKED(blockT1); + +typedef struct blockT8 { + u_int16_t TimeConstant; + u_int8_t PackMethod; + u_int8_t VoiceMode; +} PACKED(blockT8); + +typedef struct blockT9 { + u_int32_t SamplesPerSec; + u_int8_t BitsPerSample; + u_int8_t Channels; + u_int16_t Format; + u_int8_t reserved[4]; +} PACKED(blockT9); + /* Definitions for Microsoft WAVE format */ @@ -59,25 +55,23 @@ /* 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; 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; +*/ +typedef struct 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