From ce7692a68f3a226f8f52021ba1d98b7d062e4bee Mon Sep 17 00:00:00 2001 From: gewlitys Date: Tue, 13 May 2003 22:16:18 +0000 Subject: [PATCH] Wav loader is now endian safe (bug #165) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@962 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 1 + sc2/src/msvc++/UrQuanMasters.dsp | 4 + sc2/src/sc2code/libs/sound/decoders/decoder.c | 15 +- sc2/src/sc2code/libs/sound/decoders/decoder.h | 2 +- sc2/src/sc2code/libs/sound/decoders/wav.c | 266 ++++++++---------- sc2/src/sc2code/libs/sound/decoders/wav.h | 34 +-- 6 files changed, 137 insertions(+), 185 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 38ab57ee8..c2009b7af 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,5 @@ Changes towards version 0.3: +- Wav loader is now endian safe (bug #165) -Mika - Dialogue patch for Melnorme, fixing bug #335 - Two dialogue spots where visit count could run away patched; fixes bug #333, from Stas Sergeev diff --git a/sc2/src/msvc++/UrQuanMasters.dsp b/sc2/src/msvc++/UrQuanMasters.dsp index d48ae0bc2..73292a922 100644 --- a/sc2/src/msvc++/UrQuanMasters.dsp +++ b/sc2/src/msvc++/UrQuanMasters.dsp @@ -3304,6 +3304,10 @@ SOURCE=..\types.h # End Source File # Begin Source File +SOURCE=..\endian.h +# End Source File +# Begin Source File + SOURCE=..\starcon2.c # End Source File # End Group diff --git a/sc2/src/sc2code/libs/sound/decoders/decoder.c b/sc2/src/sc2code/libs/sound/decoders/decoder.c index 2e02c7ae3..d6cc74bb4 100644 --- a/sc2/src/sc2code/libs/sound/decoders/decoder.c +++ b/sc2/src/sc2code/libs/sound/decoders/decoder.c @@ -505,24 +505,11 @@ uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) { case SOUNDDECODER_WAV: { - bool loop; - LoadWAVFile (decoder->filename ,&decoder->format, &decoder->buffer, - &decoder->buffer_size, &decoder->frequency, &loop); + &decoder->buffer_size, &decoder->frequency, decoder_formats.want_big_endian); if (decoder->buffer_size != 0) { - - /* WAVs are loaded in little-endian order - * may need to do a word-swap - */ - if (decoder_formats.want_big_endian && - (decoder->format == decoder_formats.stereo16 - || decoder->format == decoder_formats.mono16)) - { - SoundDecoder_SwapWords ( - decoder->buffer, decoder->buffer_size); - } decoder->type = SOUNDDECODER_BUF; decoder->data = decoder->buffer; decoder->pos = 0; diff --git a/sc2/src/sc2code/libs/sound/decoders/decoder.h b/sc2/src/sc2code/libs/sound/decoders/decoder.h index c77ed1aa3..5a2ff65bc 100644 --- a/sc2/src/sc2code/libs/sound/decoders/decoder.h +++ b/sc2/src/sc2code/libs/sound/decoders/decoder.h @@ -79,7 +79,7 @@ enum }; extern TFB_DecoderFormats decoder_formats; - +void SoundDecoder_SwapWords (uint16* data, uint32 size); sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats* formats); void SoundDecoder_Uninit (void); TFB_SoundDecoder* SoundDecoder_Load (char *filename, uint32 buffer_size, diff --git a/sc2/src/sc2code/libs/sound/decoders/wav.c b/sc2/src/sc2code/libs/sound/decoders/wav.c index 81b16bf5d..94b086a58 100644 --- a/sc2/src/sc2code/libs/sound/decoders/wav.c +++ b/sc2/src/sc2code/libs/sound/decoders/wav.c @@ -1,184 +1,150 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* NOTE by Mika: Wav loader, (c) Creative, taken from their OpenAL - * implementation and modified. +/* Loader for .wav files + * Code is based on Creative's Win32 OpenAL implementation. */ #include -#include #include #include "libs/misc.h" #include "wav.h" #include "decoder.h" +#include "endian.h" -#if defined _MSC_VER - #pragma pack (push,1) /* Turn off alignment */ -#elif defined __GNUC__ - #define PADOFF_VAR __attribute__((packed)) -#endif +#define FMT 0x20746D66 /* "fmt " */ +#define DATA 0x61746164 /* "data" */ -#ifndef PADOFF_VAR - #define PADOFF_VAR -#endif - -typedef struct /* WAV File-header */ +typedef struct { - uint8 Id[4] PADOFF_VAR; - sint32 Size PADOFF_VAR; - uint8 Type[4] PADOFF_VAR; + uint32 Id; + sint32 Size; + uint32 Type; } WAVFileHdr_Struct; -typedef struct /* WAV Fmt-header */ +typedef struct { - uint16 Format PADOFF_VAR; - uint16 Channels PADOFF_VAR; - uint32 SamplesPerSec PADOFF_VAR; - uint32 BytesPerSec PADOFF_VAR; - uint16 BlockAlign PADOFF_VAR; - uint16 BitsPerSample PADOFF_VAR; + uint16 Format; + uint16 Channels; + uint32 SamplesPerSec; + uint32 BytesPerSec; + uint16 BlockAlign; + uint16 BitsPerSample; } WAVFmtHdr_Struct; -typedef struct /* WAV FmtEx-header */ +typedef struct { - uint16 Size PADOFF_VAR; - uint16 SamplesPerBlock PADOFF_VAR; -} WAVFmtExHdr_Struct; - -typedef struct /* WAV Smpl-header */ -{ - uint32 Manufacturer PADOFF_VAR; - uint32 Product PADOFF_VAR; - uint32 SamplePeriod PADOFF_VAR; - uint32 Note PADOFF_VAR; - uint32 FineTune PADOFF_VAR; - uint32 SMPTEFormat PADOFF_VAR; - uint32 SMPTEOffest PADOFF_VAR; - uint32 Loops PADOFF_VAR; - uint32 SamplerData PADOFF_VAR; - struct - { - uint32 Identifier PADOFF_VAR; - uint32 Type PADOFF_VAR; - uint32 Start PADOFF_VAR; - uint32 End PADOFF_VAR; - uint32 Fraction PADOFF_VAR; - uint32 Count PADOFF_VAR; - } Loop[1] PADOFF_VAR; -} WAVSmplHdr_Struct; - -typedef struct /* WAV Chunk-header */ -{ - uint8 Id[4] PADOFF_VAR; - uint32 Size PADOFF_VAR; + uint32 Id; + uint32 Size; } WAVChunkHdr_Struct; -#ifdef PADOFF_VAR /* Default alignment */ - #undef PADOFF_VAR -#endif - -#if defined _MSC_VER - #pragma pack (pop) -#endif - -/* loads the WAV file in little endian byte order */ -void LoadWAVFile (char *file, uint32 *format, void **data, uint32 *size, uint32 *freq, bool *loop) +void +LoadWAVFile (const char *file, uint32 *format, void **data, uint32 *size, + uint32 *freq, bool want_big_endian) { WAVChunkHdr_Struct ChunkHdr; - WAVFmtExHdr_Struct FmtExHdr; WAVFileHdr_Struct FileHdr; - WAVSmplHdr_Struct SmplHdr; WAVFmtHdr_Struct FmtHdr; - FILE *Stream; + FILE *fp; - *format=decoder_formats.mono16; - *data=NULL; - *size=0; - *freq=22050; - *loop=false; - if (file) + *format = decoder_formats.mono16; + *data = NULL; + *size = 0; + *freq = 22050; + + fp = fopen (file, "rb"); + if (fp) { - Stream=fopen(file,"rb"); - if (Stream) - { - fread(&FileHdr,1,sizeof(WAVFileHdr_Struct),Stream); - FileHdr.Size=((FileHdr.Size+1)&~1)-4; - while ((FileHdr.Size!=0)&&(fread(&ChunkHdr,1,sizeof(WAVChunkHdr_Struct),Stream))) - { - if (!memcmp(ChunkHdr.Id,"fmt ",4)) - { - fread(&FmtHdr,1,sizeof(WAVFmtHdr_Struct),Stream); - if (FmtHdr.Format==0x0001) - { - *format=(FmtHdr.Channels == 1 ? - (FmtHdr.BitsPerSample == 8 ? - decoder_formats.mono8 - : decoder_formats.mono16) - : (FmtHdr.BitsPerSample == 8 ? - decoder_formats.stereo8 - : decoder_formats.stereo16) - ); - *freq=FmtHdr.SamplesPerSec; - fseek(Stream,ChunkHdr.Size-sizeof(WAVFmtHdr_Struct),SEEK_CUR); - } - else - { - fread(&FmtExHdr,1,sizeof(WAVFmtExHdr_Struct),Stream); - fseek(Stream,ChunkHdr.Size-sizeof(WAVFmtHdr_Struct)- - sizeof(WAVFmtExHdr_Struct),SEEK_CUR); - } - } - else if (!memcmp(ChunkHdr.Id,"data",4)) - { - if (FmtHdr.Format==0x0001) - { - *size=ChunkHdr.Size; - *data=HMalloc(ChunkHdr.Size+31); - if (*data) - fread(*data,FmtHdr.BlockAlign, - ChunkHdr.Size/FmtHdr.BlockAlign,Stream); - memset(((char *)*data)+ChunkHdr.Size,0,31); - } - else if (FmtHdr.Format==0x0011) - { - //IMA ADPCM - } - else if (FmtHdr.Format==0x0055) - { - //MP3 WAVE - } - } - else if (!memcmp(ChunkHdr.Id,"smpl",4)) - { - fread(&SmplHdr,1,sizeof(WAVSmplHdr_Struct),Stream); - *loop = (SmplHdr.Loops ? true : false); - fseek(Stream,ChunkHdr.Size-sizeof(WAVSmplHdr_Struct),SEEK_CUR); - } - else - fseek(Stream,ChunkHdr.Size,SEEK_CUR); + fread(&FileHdr.Id, 4, 1, fp); + FileHdr.Id = UQM_SwapLE32 (FileHdr.Id); + fread(&FileHdr.Size, 4, 1, fp); + FileHdr.Size = UQM_SwapLE32 (FileHdr.Size); + fread(&FileHdr.Type, 4, 1, fp); + FileHdr.Type = UQM_SwapLE32 (FileHdr.Type); - fseek(Stream,ChunkHdr.Size&1,SEEK_CUR); - FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8); + FileHdr.Size = ((FileHdr.Size + 1) & ~1) - 4; + while (FileHdr.Size != 0) + { + if (!fread (&ChunkHdr.Id, 4, 1, fp)) + break; + ChunkHdr.Id = UQM_SwapLE32 (ChunkHdr.Id); + if (!fread (&ChunkHdr.Size, 4, 1, fp)) + break; + ChunkHdr.Size = UQM_SwapLE32 (ChunkHdr.Size); + + if (ChunkHdr.Id == FMT) + { + fread (&FmtHdr.Format, 2, 1, fp); + FmtHdr.Format = UQM_SwapLE16 (FmtHdr.Format); + fread (&FmtHdr.Channels, 2, 1, fp); + FmtHdr.Channels = UQM_SwapLE16 (FmtHdr.Channels); + fread (&FmtHdr.SamplesPerSec, 4, 1, fp); + FmtHdr.SamplesPerSec = UQM_SwapLE32 (FmtHdr.SamplesPerSec); + fread (&FmtHdr.BytesPerSec, 4, 1, fp); + FmtHdr.BytesPerSec = UQM_SwapLE32 (FmtHdr.BytesPerSec); + fread (&FmtHdr.BlockAlign, 2, 1, fp); + FmtHdr.BlockAlign = UQM_SwapLE16 (FmtHdr.BlockAlign); + fread (&FmtHdr.BitsPerSample, 2, 1, fp); + FmtHdr.BitsPerSample = UQM_SwapLE16 (FmtHdr.BitsPerSample); + + if (FmtHdr.Format == 0x0001) + { + *format=(FmtHdr.Channels == 1 ? + (FmtHdr.BitsPerSample == 8 ? + decoder_formats.mono8 + : decoder_formats.mono16) + : (FmtHdr.BitsPerSample == 8 ? + decoder_formats.stereo8 + : decoder_formats.stereo16) + ); + *freq = FmtHdr.SamplesPerSec; + fseek (fp, ChunkHdr.Size - 16, SEEK_CUR); + } + else + { + fprintf (stderr, "LoadWAVFile(): unsupported format %x\n", FmtHdr.Format); + fclose (fp); + return; + } } - fclose(Stream); - } + else if (ChunkHdr.Id == DATA) + { + *size = ChunkHdr.Size; + if ((*data = HMalloc (ChunkHdr.Size + 31))) + fread (*data, FmtHdr.BlockAlign, ChunkHdr.Size / FmtHdr.BlockAlign, fp); + memset(((char *)*data) + ChunkHdr.Size, 0, 31); + } + else + { + fseek(fp, ChunkHdr.Size, SEEK_CUR); + } + + fseek (fp, ChunkHdr.Size & 1, SEEK_CUR); + FileHdr.Size -= (((ChunkHdr.Size + 1) & ~1) + 8); + } + fclose(fp); } + + if (want_big_endian && + (*format == decoder_formats.stereo16 || *format == decoder_formats.mono16)) + { + SoundDecoder_SwapWords (*data, *size); + } + + if (*size == 0) + fprintf (stderr, "LoadWAVFile(): loading %s failed!\n", file); } diff --git a/sc2/src/sc2code/libs/sound/decoders/wav.h b/sc2/src/sc2code/libs/sound/decoders/wav.h index b9b85a6fc..81aa23bbb 100644 --- a/sc2/src/sc2code/libs/sound/decoders/wav.h +++ b/sc2/src/sc2code/libs/sound/decoders/wav.h @@ -1,33 +1,27 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* NOTE by Mika: Wav loader, (c) Creative, taken from their OpenAL - * implementation and modified. - */ +/* Loader for .wav files */ #ifndef WAV_H #define WAV_H #include "types.h" -/* loads the WAV file in little endian byte order */ -void LoadWAVFile (char *file, uint32 *format, void **data, uint32 *size, uint32 *freq, bool *loop); +void LoadWAVFile (const char *file, uint32 *format, void **data, uint32 *size, + uint32 *freq, bool want_big_endian); #endif