summaryrefslogtreecommitdiff
path: root/src/openal.c
diff options
context:
space:
mode:
authorSteven Fuller <relnev@icculus.org>2007-01-13 07:48:52 +0000
committerPatryk Obara <dreamer.tan@gmail.com>2019-08-20 02:22:37 +0200
commit71204923ad88753a5969727a9078a876dc043010 (patch)
tree1d3d33ea687991c81a6712a8d8f394d430be78c9 /src/openal.c
parent0e484b73da4e8b577a0c7e368c52cfee281c1ef7 (diff)
wrote a simple wave loader to remove dependency on a private openal function.
Diffstat (limited to 'src/openal.c')
-rw-r--r--src/openal.c268
1 files changed, 163 insertions, 105 deletions
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 <AL/al.h>
#include <AL/alc.h>
-#include <AL/alut.h>
-
-#include <SDL/SDL_audio.h> // 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;
+ FormatChunk fmtChunk;
+ DataChunk dataChunk;
+
+ if( !SimpleLoadWAV( (unsigned char*)data, &fmtChunk, &dataChunk ) ) {
+printf("WAV DEBUG: file didn't parse\n");
+ return 0;
+ }
- nbuf = (unsigned char *) AllocateMem (*len * 2);
+ if( fmtChunk.wFormatTag != 1 ) {
+printf("WAV DEBUG: got format tag %d\n", fmtChunk.wFormatTag );
+ return 0;
+ }
- 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;
+ 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 );
- *len *= 2;
- return nbuf;
+ 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);
- 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;
+ /* 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 ((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)