From 71204923ad88753a5969727a9078a876dc043010 Mon Sep 17 00:00:00 2001 From: Steven Fuller Date: Sat, 13 Jan 2007 07:48:52 +0000 Subject: [PATCH] wrote a simple wave loader to remove dependency on a private openal function. --- Makefile | 12 +-- src/openal.c | 274 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 172 insertions(+), 114 deletions(-) diff --git a/Makefile b/Makefile index 5296f67..db408e5 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,10 @@ CFLAGS = -g -Wall -pipe -O2 CFLAGS += -DLINUX CFLAGS += -Dengine=1 -I. -Iinclude -Iwin95 -Iavp -Iavp/win95 -Iavp/support -Iavp/win95/frontend -Iavp/win95/gadgets -CFLAGS += $(shell sdl-config --cflags) +CFLAGS += $(shell sdl-config --cflags) $(shell openal-config --cflags) CXXFLAGS = $(CFLAGS) -LDLIBS = $(shell sdl-config --libs) -lopenal +LDLIBS = $(shell sdl-config --libs) $(shell openal-config --libs) ROOT = main.c files.c winapi.c stubs.c version.c mathline.c opengl.c oglfunc.c openal.c cdplayer.c menus.c net.c frustum.c kshape.c map.c maths.c md5.c mem3dc.c mem3dcpp.cpp module.c morph.c object.c shpanim.c sphere.c tables.c vdb.c AVP = ai_sight.c avpview.c bh_agun.c bh_ais.c bh_alien.c bh_binsw.c bh_cable.c bh_corpse.c bh_deathvol.c bh_debri.c bh_dummy.c bh_fan.c bh_far.c bh_fhug.c bh_gener.c bh_ldoor.c bh_lift.c bh_light.c bh_lnksw.c bh_ltfx.c bh_marin.c bh_mission.c bh_near.c bh_pargen.c bh_plachier.c bh_plift.c bh_pred.c bh_queen.c bh_rubberduck.c bh_selfdest.c bh_snds.c bh_spcl.c bh_swdor.c bh_track.c bh_types.c bh_videoscreen.c bh_waypt.c bh_weap.c bh_xeno.c bonusabilities.c cconvars.cpp cdtrackselection.cpp cheatmodes.c comp_map.c comp_shp.c consolelog.cpp davehook.cpp deaths.c decal.c detaillevels.c dynamics.c dynblock.c equipmnt.c equiputl.cpp extents.c game.c game_statistics.c gamecmds.cpp gamevars.cpp hmodel.c hud.c inventry.c language.c lighting.c load_shp.c los.c maps.c mempool.c messagehistory.c missions.cpp movement.c paintball.c particle.c pfarlocs.c pheromon.c player.c pmove.c psnd.c psndproj.c pvisible.c savegame.c scream.cpp secstats.c sfx.c stratdef.c targeting.c track.c triggers.c weapons.c @@ -48,15 +48,15 @@ WIN95OBJ = $(call OBJNAMES,$(WIN95),win95) SRC = $(ROOTSRC) $(AVPSRC) $(SHAPESSRC) $(SUPPORTSRC) $(AVPWIN95SRC) $(FRONTENDSRC) $(GADGETSSRC) $(WIN95SRC) OBJ = $(ROOTOBJ) $(AVPOBJ) $(SHAPESOBJ) $(SUPPORTOBJ) $(AVPWIN95OBJ) $(FRONTENDOBJ) $(GADGETSOBJ) $(WIN95OBJ) -all: AvP +all: AvP.bin -AvP: $(OBJ) # depend $(OBJ) - $(CXX) -o AvP $(OBJ) $(LDLIBS) +AvP.bin: $(OBJ) # depend $(OBJ) + $(CXX) -o AvP.bin $(OBJ) $(LDLIBS) compile: $(OBJ) clean: - -rm -rf depend depend.bak $(OBJ) AvP + -rm -rf depend depend.bak $(OBJ) AvP.bin distclean: clean -rm -rf `find . -name "*~"` diff --git a/src/openal.c b/src/openal.c index 9dc4d66..f1f067f 100644 --- a/src/openal.c +++ b/src/openal.c @@ -5,9 +5,6 @@ #include #include -#include - -#include // For a few defines (AUDIO_*) #include "fixer.h" @@ -35,6 +32,112 @@ extern int WantSound; static int SoundActivated = 0; +/* start simplistic riff wave parsing */ +#define lsb8 (buf, x) (((unsigned int)buf[(x)+0] << 0)) +#define lsb16(buf, x) (((unsigned int)buf[(x)+0] << 0) | ((unsigned int)buf[(x)+1] << 8)) +#define lsb32(buf, x) (((unsigned int)buf[(x)+0] << 0) | ((unsigned int)buf[(x)+1] << 8) | ((unsigned int)buf[(x)+2] << 16) | ((unsigned int)buf[(x)+3] << 24)) + +typedef struct FormatChunk { + short wFormatTag; + unsigned short wChannels; + unsigned long dwSamplesPerSec; + unsigned long dwAvgBytesPerSec; + unsigned short wBlockAlign; + unsigned short wBitsPerSample; +} FormatChunk; + +typedef struct DataChunk { + unsigned char* pData; + unsigned int dwLength; +} DataChunk; + +static int ParseWAV( const unsigned char* data, unsigned char** pFmtPtr, unsigned char** pDataPtr ) +{ + unsigned char* pData; + unsigned char* pDataEnd; + unsigned char* fmtPtr; + int riffLength; + int chunkLength; + + if( data == NULL || pFmtPtr == NULL || pDataPtr == NULL ) { + return 0; + } + + /* assuming input data is complete and not corrupt... */ + + pData = (unsigned char*) data; + + /* bytes 0-3 are the RIFF groupId */ + if( pData[ 0 ] != 'R' || pData[ 1 ] != 'I' || pData[ 2 ] != 'F' || pData[ 3 ] != 'F' ) { + /* bad group id */ + return 0; + } + + /* bytes 4-7 are the RIFF length. */ + riffLength = lsb32( pData, 4 ); + + pDataEnd = pData + 8 + riffLength; + + if( pData[ 8 ] != 'W' || pData[ 9 ] != 'A' || pData[ 10 ] != 'V' || pData[ 11 ] != 'E' ) { + /* bad riff type */ + return 0; + } + + /* all valid wave files have the 'fmt ' chunk before the 'data' chunk. */ + + /* skip passed the initial header. */ + pData += 12; + + /* look for the 'fmt ' and 'data' chunks. */ + fmtPtr = NULL; + + while( pData+8 < pDataEnd ) { + + chunkLength = lsb32( pData, 4 ); + + if( fmtPtr == NULL && pData[ 0 ] == 'f' && pData[ 1 ] == 'm' && pData[ 2 ] == 't' && pData[ 3 ] == ' ' ) { + fmtPtr = pData; + } else if( fmtPtr != NULL && pData[ 0 ] == 'd' && pData[ 1 ] == 'a' && pData[ 2 ] == 't' && pData[ 3 ] == 'a' ) { + + *pFmtPtr = fmtPtr; + *pDataPtr = pData; + + return 1; + } + + pData += 8 + chunkLength; + } + + return 0; +} + +static int SimpleLoadWAV( const unsigned char* data, FormatChunk* pFmtChunk, DataChunk* pDataChunk) +{ + unsigned char* fmtPtr; + unsigned char* dataPtr; + + if( data == NULL || pFmtChunk == NULL || pDataChunk == NULL ) { + return 0; + } + + if( !ParseWAV( data, &fmtPtr, &dataPtr ) ) { + return 0; + } + + pFmtChunk->wFormatTag = lsb16( fmtPtr, 8 ); + pFmtChunk->wChannels = lsb16( fmtPtr, 10 ); + pFmtChunk->dwSamplesPerSec = lsb32( fmtPtr, 12 ); + pFmtChunk->dwAvgBytesPerSec = lsb32( fmtPtr, 16 ); + pFmtChunk->wBlockAlign = lsb16( fmtPtr, 20 ); + pFmtChunk->wBitsPerSample = lsb16( fmtPtr, 22 ); + + pDataChunk->pData = &dataPtr[ 8 ]; + pDataChunk->dwLength = lsb32( dataPtr, 4 ); + + return 1; +} +/* end simplistic riff wave parsing */ + /* openal.c TODO: 1. There is no EAX/Reverb. But there's probably not much I can do... @@ -821,29 +924,54 @@ void UpdateSoundFrequencies() } } - -// In libopenal -extern void *acLoadWAV (void *data, ALuint *size, void **udata, - ALushort *fmt, ALushort *chan, ALushort *freq); - - -static unsigned char *Force8to16 (unsigned char *buf, int *len) +static int LoadWAV( ALvoid* data, ALvoid** bufferPtr, ALushort* format, ALushort* freq, int* len, int* seclen ) { - unsigned char *nbuf; - unsigned int i; - - nbuf = (unsigned char *) AllocateMem (*len * 2); - - for (i = 0; i < *len; i++) { - short int x = ((buf[i] << 8) | buf[i]) ^ 0x8000; - nbuf[i*2+0] = (x & 0x00ff); - nbuf[i*2+1] = (x >> 8) & 0xff; + FormatChunk fmtChunk; + DataChunk dataChunk; + + if( !SimpleLoadWAV( (unsigned char*)data, &fmtChunk, &dataChunk ) ) { +printf("WAV DEBUG: file didn't parse\n"); + return 0; } - *len *= 2; - return nbuf; + if( fmtChunk.wFormatTag != 1 ) { +printf("WAV DEBUG: got format tag %d\n", fmtChunk.wFormatTag ); + return 0; + } + + if( fmtChunk.wBitsPerSample == 8 ) { + if( fmtChunk.wChannels == 1 ) { + *format = AL_FORMAT_MONO8; + } else if( fmtChunk.wChannels == 2 ) { + *format = AL_FORMAT_STEREO8; + } else { +printf("WAV DEBUG: too many channels\n" ); + return 0; + } + } else if( fmtChunk.wBitsPerSample == 16 ) { + if( fmtChunk.wChannels == 1 ) { + *format = AL_FORMAT_MONO16; + } else if( fmtChunk.wChannels == 2 ) { + *format = AL_FORMAT_STEREO16; + } else { +printf("WAV DEBUG: too many channels\n" ); + return 0; + } + } else { +printf("WAV DEBUG: bad bit setup\n"); + return 0; + } + + *freq = fmtChunk.dwSamplesPerSec; + *len = dataChunk.dwLength; + *bufferPtr = dataChunk.pData; + + *seclen = DIV_FIXED( dataChunk.dwLength, fmtChunk.dwAvgBytesPerSec ); + + return 1; } + int LoadWavFile(int soundNum, char * wavFileName) { ALuint size; @@ -851,7 +979,8 @@ int LoadWavFile(int soundNum, char * wavFileName) ALvoid *data, *bufferPtr; int len, seclen; FILE *fp; - + char* wavname; + #ifdef OPENAL_DEBUG fprintf(stderr, "LoadWavFile(%d, %s) - sound\n", soundNum, wavFileName); #endif @@ -872,57 +1001,22 @@ int LoadWavFile(int soundNum, char * wavFileName) fread(data, 1, len, fp); fclose(fp); - if (acLoadWAV (data, &size, &bufferPtr, &format, - &chan, &freq) == NULL) { - fprintf(stderr, "LoadWavFile: Unable to convert data\n"); - free(data); - return 0; - } - - free(data); - - data = bufferPtr; - - len = size; - - /* openal conv. 8->16 is not good at all */ - if (format == AUDIO_U8) { - unsigned char *nb = Force8to16 (data, &len); - format = AUDIO_S16LSB; - - free (data); - data = nb; - } - - if ((format == AUDIO_S16LSB) || (format == AUDIO_S16MSB)) { - int bps; - - if (chan == 2) { - format = AL_FORMAT_STEREO16; - bps = freq * 2 * 2; - } /* else if (rchan == 1) */ { - format = AL_FORMAT_MONO16; - bps = freq * 2 * 1; - } - - seclen = DIV_FIXED(len, bps); - } else { - free(data); + if( !LoadWAV( data, &bufferPtr, &format, &len, &seclen, &freq ) ) { + free( data ); return 0; } alGenBuffers (1, &(GameSounds[soundNum].dsBufferP)); - alBufferData (GameSounds[soundNum].dsBufferP, format, data, len, freq); + alBufferData (GameSounds[soundNum].dsBufferP, format, bufferPtr, len, freq); -{ - char * wavname = strrchr (wavFileName, '\\'); + wavname = strrchr (wavFileName, '\\'); if (wavname) wavname++; else wavname = wavFileName; GameSounds[soundNum].wavName = (char *)AllocateMem (strlen (wavname) + 1); strcpy (GameSounds[soundNum].wavName, wavname); -} + GameSounds[soundNum].flags = SAMPLE_IN_HW; GameSounds[soundNum].length = (seclen != 0) ? seclen : 1; GameSounds[soundNum].dsFrequency = freq; @@ -957,58 +1051,22 @@ fprintf(stderr, "OPENAL: ExtractWavFile(%d, %p)\n", soundIndex, bufferPtr); fprintf(stderr, "OPENAL: Loaded %s\n", GameSounds[soundIndex].wavName); #endif -#if 1 /* TODO: replace with own routine later */ - if (acLoadWAV (bufferPtr, &rsize, &udata, &rfmt, - &rchan, &rfreq) == NULL) { - fprintf(stderr, "ExtractWavFile: Unable to convert data\n"); - return NULL; + if( LoadWAV( bufferPtr, &udata, &rfmt, &len, &seclen, &rfreq ) ) { + alGenBuffers (1, &(GameSounds[soundIndex].dsBufferP)); + alBufferData (GameSounds[soundIndex].dsBufferP, + rfmt, udata, len, rfreq); + + /* GameSounds[soundIndex].loaded = 1; */ + GameSounds[soundIndex].flags = SAMPLE_IN_HW; + GameSounds[soundIndex].length = (seclen != 0) ? seclen : 1; + GameSounds[soundIndex].dsFrequency = rfreq; + /* GameSounds[soundIndex].pitch = PITCH_DEFAULTPLAT; */ } - len = rsize; - - /* openal conv. 8->16 is not good at all */ - if (rfmt == AUDIO_U8) { - unsigned char *nb = Force8to16 (udata, &len); - rfmt = AUDIO_S16LSB; - - free (udata); - udata = nb; - } - - if ((rfmt == AUDIO_S16LSB) || (rfmt == AUDIO_S16MSB)) { - int bps; - - if (rchan == 2) { - rfmt = AL_FORMAT_STEREO16; - bps = rfreq * 2 * 2; - } /* else if (rchan == 1) */ { - rfmt = AL_FORMAT_MONO16; - bps = rfreq * 2 * 1; - } - - seclen = DIV_FIXED(len, bps); - } else - return NULL; -#endif - - alGenBuffers (1, &(GameSounds[soundIndex].dsBufferP)); - alBufferData (GameSounds[soundIndex].dsBufferP, - rfmt, udata, len, rfreq); - -/* GameSounds[soundIndex].loaded = 1; */ - GameSounds[soundIndex].flags = SAMPLE_IN_HW; - GameSounds[soundIndex].length = (seclen != 0) ? seclen : 1; - GameSounds[soundIndex].dsFrequency = rfreq; -/* GameSounds[soundIndex].pitch = PITCH_DEFAULTPLAT; */ - -#if 1 /* TODO: see above */ - free (udata); - /* read RIFF chunk length and jump past it */ return bufferPtr + 8 + ((bufferPtr[4] << 0) | (bufferPtr[5] << 8) | (bufferPtr[6] << 16) | (bufferPtr[7] << 24)); -#endif } int LoadWavFromFastFile(int soundNum, char * wavFileName)