From 0200ee9777e3dcb9bb04bf64d933ef6f1a121d4e Mon Sep 17 00:00:00 2001 From: Steven Fuller Date: Tue, 14 Aug 2001 17:51:26 +0000 Subject: Checking in basic OpenAL support (Chuck Mason). Don't default to fullscreen for now. --- src/openal.c | 458 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 448 insertions(+), 10 deletions(-) (limited to 'src/openal.c') diff --git a/src/openal.c b/src/openal.c index ab668c0..a7de9bb 100644 --- a/src/openal.c +++ b/src/openal.c @@ -2,23 +2,85 @@ #include #include +#include +#include +#include + +#include // For a few defines (AUDIO_*) + #include "fixer.h" #include "3dc.h" #include "platform.h" #include "psndplat.h" +#include "gamedef.h" +#include "avpview.h" +#include "ffstdio.h" +#include "dynamics.h" +#include "dynblock.h" +#include "stratdef.h" /* psndplat.cpp */ ACTIVESOUNDSAMPLE ActiveSounds[SOUND_MAXACTIVE]; -ACTIVESOUNDSAMPLE BlankActiveSound = {SID_NOSOUND,ASP_Minimum,0,0,NULL,0,0,0,0,0, { {0,0,0},{0,0,0},0,0 }, NULL, NULL, NULL}; -SOUNDSAMPLEDATA BlankGameSound = {0,0,0,0,NULL,0,0,NULL,0}; +ACTIVESOUNDSAMPLE BlankActiveSound = {SID_NOSOUND,ASP_Minimum,0,0,NULL,0,0,0,0,0, { {0,0,0},{0,0,0},0,0 }, 0, 0, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, NULL, NULL, NULL}; +SOUNDSAMPLEDATA BlankGameSound = {0,0,0,0,0,NULL,0,0,NULL,0}; SOUNDSAMPLEDATA GameSounds[SID_MAXIMUM]; +ALCdevice *AvpSoundDevice; +ALvoid *AvpSoundContext; + int PlatStartSoundSys() { + int i; + ALfloat pos[] = { 0.0, 0.0, 0.0 }, + vel[] = { 0.0, 0.0, 0.0 }, + or[] = { 0.0, 0.0, 1.0, 0.0, -1.0, 0.0 }; + int attrlist[] = { + ALC_FREQUENCY, 22050, + ALC_SYNC, AL_FALSE, + 0 + }; + fprintf(stderr, "PlatStartSoundSys()\n"); - return 0; + AvpSoundDevice = alcOpenDevice ("'( (sampling-rate 22050 ))"); + AvpSoundContext = alcCreateContext (AvpSoundDevice, attrlist); + alcMakeContextCurrent (AvpSoundContext); + + alListenerfv (AL_POSITION, pos); + alListenerfv (AL_VELOCITY, vel); + alListenerfv (AL_ORIENTATION, or); + + if (alGetError () != AL_NO_ERROR) { + perror ("alListenerfv()"); + exit (1); + } + + for (i = 0; i < SOUND_MAXACTIVE; i++) { + ALuint p; + + alGenSources (1, &(ActiveSounds[i].ds3DBufferP)); + p = ActiveSounds[i].ds3DBufferP; + + ActiveSounds[i].PropSetP_pos[0] = 0.0; + ActiveSounds[i].PropSetP_pos[1] = 0.0; + ActiveSounds[i].PropSetP_pos[2] = 0.0; + ActiveSounds[i].PropSetP_vel[0] = 0.0; + ActiveSounds[i].PropSetP_vel[1] = 0.0; + ActiveSounds[i].PropSetP_vel[2] = 0.0; + + if (alGetError () != AL_NO_ERROR) { + perror ("alGenSources ()"); + return -1; + } + + alSourcef (p, AL_PITCH, 1.0f); + alSourcef (p, AL_GAIN, 1.0f); + alSourcefv (p, AL_POSITION, ActiveSounds[i].PropSetP_pos); + alSourcefv (p, AL_VELOCITY, ActiveSounds[i].PropSetP_vel); + } + + return 1; } void PlatEndSoundSys() @@ -35,44 +97,270 @@ int PlatChangeGlobalVolume(int volume) int PlatPlaySound(int activeIndex) { + int si; + fprintf(stderr, "PlatPlaySound(%d)\n", activeIndex); + + if ((activeIndex < 0) || (activeIndex >= SOUND_MAXACTIVE)) + return 0; + si = ActiveSounds[activeIndex].soundIndex; + if ((si < 0) || (si >= SID_MAXIMUM)) + return 0; + if (!GameSounds[si].loaded) + return 0; + + if (!PlatSoundHasStopped(activeIndex)) + PlatStopSound (activeIndex); + + if (ActiveSounds[activeIndex].loop) + alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_TRUE); + else + alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_FALSE); + + alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_BUFFER, + GameSounds[si].dsBufferP); + + + if (ActiveSounds[activeIndex].pitch != GameSounds[si].pitch) { + int ok = PlatChangeSoundPitch (activeIndex, ActiveSounds[activeIndex].pitch); + if (ok == SOUND_PLATFORMERROR) { + PlatStopSound (activeIndex); + return ok; + } + } + + if (ActiveSounds[activeIndex].threedee) { + int ok; + + /* set distance at which attenuation starts */ + + + ok = PlatDo3dSound (activeIndex); + + if (ok == SOUND_PLATFORMERROR) { + PlatStopSound (activeIndex); + return ok; + } + } else { + int newVolume, ok; + + newVolume = ActiveSounds[activeIndex].volume; + newVolume = (newVolume * VOLUME_PLAT2DSCALE) >> 7; + ActiveSounds[activeIndex].volume = newVolume; + + ok = PlatChangeSoundVolume (activeIndex, ActiveSounds[activeIndex].volume); + if (ok == SOUND_PLATFORMERROR) { + PlatStopSound (activeIndex); + return ok; + } + } + + + + if (!ActiveSounds[activeIndex].paused) { + alSourcePlay (ActiveSounds[activeIndex].ds3DBufferP); + if (ActiveSounds[activeIndex].loop) { + fprintf (stderr, "Playing sound %i %s looping in slot %i\n", + si, GameSounds[si].wavName, activeIndex); + } else { + fprintf (stderr, "Playing sound %i %s once in slot %i\n", + si, GameSounds[si].wavName, activeIndex); + } + } + return 1; } void PlatStopSound(int activeIndex) { fprintf(stderr, "PlatStopSound(%d)\n", activeIndex); + +// if (ActiveSounds[activeIndex].paused) +// alSourcePause (ActiveSounds[activeIndex].ds3DBufferP); +// else +// alSourceStop (ActiveSounds[activeIndex].ds3DBufferP); + if (!PlatSoundHasStopped (activeIndex)) + alSourceStop (ActiveSounds[activeIndex].ds3DBufferP); } int PlatChangeSoundVolume(int activeIndex, int volume) { - fprintf(stderr, "PlatChangeSoundVolume(%d, %d)\n", activeIndex, volume); + float nv = 127.0f / (float) volume; + fprintf(stderr, "PlatChangeSoundVolume(%d, %d) - %f\n", activeIndex, volume, nv); + + if (nv > 1.0) + nv = 1.0; + + alSourcef (ActiveSounds[activeIndex].ds3DBufferP, + AL_MAX_GAIN, nv); + return 1; } int PlatChangeSoundPitch(int activeIndex, int pitch) { + float frequency; + fprintf(stderr, "PlatChangeSoundPitch(%d, %d)\n", activeIndex, pitch); + + if ((pitch < PITCH_MIN) || (pitch >= PITCH_MAX)) + return 0; + + if (pitch == PITCH_DEFAULTPLAT) + frequency = 0; + else { + SOUNDINDEX gsi = ActiveSounds[activeIndex].soundIndex; + frequency = ToneToFrequency (GameSounds[gsi].dsFrequency, + GameSounds[gameSoundIndex].pitch, pitch); + frequency = (128.0f / ((float)pitch + 127.0)); + } + + ActiveSounds[activeIndex].pitch = pitch; +// alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_PITCH, frequency); + return 1; } int PlatSoundHasStopped(int activeIndex) { - fprintf(stderr, "PlatSoundHasStopped(%d)\n", activeIndex); + ALint val; - return 1; + fprintf(stderr, "PlatSoundHasStopped(%d)\n", activeIndex); + + alGetSourceiv (ActiveSounds[activeIndex].ds3DBufferP, + AL_SOURCE_STATE, &val); + + if (alGetError () != AL_NO_ERROR) + return SOUND_PLATFORMERROR; + + if ((val != AL_PLAYING) && (val != AL_PAUSED)) + return 1; + + return 0; } int PlatDo3dSound(int activeIndex) { + int distance; + VECTORCH relativePosn; + int newPan, newVolume; + fprintf(stderr, "PlatDo3dSound(%d)\n", activeIndex); + + relativePosn.vx = ActiveSounds[activeIndex].threedeedata.position.vx - + Global_VDB_Ptr->VDB_World.vx; + relativePosn.vy = ActiveSounds[activeIndex].threedeedata.position.vy - + Global_VDB_Ptr->VDB_World.vy; + relativePosn.vz = ActiveSounds[activeIndex].threedeedata.position.vz - + Global_VDB_Ptr->VDB_World.vz; + + distance = Magnitude (&relativePosn); + + if (ActiveSounds[activeIndex].paused) { + if (distance < (ActiveSounds[activeIndex].threedeedata.outer_range + SOUND_DEACTIVATERANGE)) { + PlatStopSound (activeIndex); + + if (ActiveSounds[activeIndex].loop) + alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_TRUE); + else + alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_FALSE); + + alSourcePlay (ActiveSounds[activeIndex].ds3DBufferP); + newVolume = 0; + ActiveSounds[activeIndex].paused = 0; + } else { + return 1; + } + } + + if (distance < ActiveSounds[activeIndex].threedeedata.inner_range) { + newVolume = ActiveSounds[activeIndex].volume; + } else { + if (distance < ActiveSounds[activeIndex].threedeedata.outer_range) { + float in_to_dis_to_out = ActiveSounds[activeIndex].threedeedata.outer_range - distance; + float in_to_out = ActiveSounds[activeIndex].threedeedata.outer_range - ActiveSounds[activeIndex].threedeedata.inner_range; + + if (in_to_out > 0.0) { + newVolume = (int) + ((float)ActiveSounds[activeIndex].volume * (in_to_dis_to_out / in_to_out)); + } else { + newVolume = 0; + } + } else { + newVolume = 0; + + if ((distance < (ActiveSounds[activeIndex].threedeedata.outer_range + SOUND_DEACTIVATERANGE)) && + ActiveSounds[activeIndex].loop) { + PlatStopSound (activeIndex); + ActiveSounds[activeIndex].paused = 1; + } + } + } + if (newVolume > VOLUME_MAX) + newVolume = VOLUME_MAX; + if (newVolume < VOLUME_MIN) + newVolume = VOLUME_MIN; + + if (PlatChangeSoundVolume (activeIndex, newVolume) == SOUND_PLATFORMERROR) { + return SOUND_PLATFORMERROR; + } + + if (distance < ActiveSounds[activeIndex].threedeedata.outer_range) { + ActiveSounds[activeIndex].PropSetP_pos[0] = + relativePosn.vx; + ActiveSounds[activeIndex].PropSetP_pos[1] = + relativePosn.vy; + ActiveSounds[activeIndex].PropSetP_pos[2] = + relativePosn.vz; + alSourcefv (ActiveSounds[activeIndex].ds3DBufferP, + AL_POSITION, ActiveSounds[activeIndex].PropSetP_pos); + +#if 1 + ActiveSounds[activeIndex].PropSetP_vel[0] = + ActiveSounds[activeIndex].threedeedata.velocity.vx; + ActiveSounds[activeIndex].PropSetP_vel[1] = + ActiveSounds[activeIndex].threedeedata.velocity.vy; + ActiveSounds[activeIndex].PropSetP_vel[2] = + ActiveSounds[activeIndex].threedeedata.velocity.vz; + alSourcefv (ActiveSounds[activeIndex].ds3DBufferP, + AL_VELOCITY, ActiveSounds[activeIndex].PropSetP_vel); +#endif + } else { + int angle; + Normalise (&relativePosn); + angle = ArcTan (relativePosn.vx, relativePosn.vz); + if (angle >= Player->ObEuler.EulerY) + angle -= Player->ObEuler.EulerY; + else + angle += (4096 - Player->ObEuler.EulerY); + + // LOCALASSERT ((angle>=0)&&(angle<=4095)) + if (angle > 1024) { + if (angle < 3072) + angle = (2048-angle); + else + angle = (angle-4096); + } + // LOCALASSERT((angle>=-1024)&&(angle<=1024)); + newPan = (PAN_MAXPLAT * angle) >> 10; + + if ((distance < ActiveSounds[activeIndex].threedeedata.inner_range) && (newPan != 0)) { + newPan = (newPan * distance) / ActiveSounds[activeIndex].threedeedata.inner_range; + } + + if (PlatChangeSoundPan (activeIndex, newPan) == SOUND_PLATFORMERROR) { + return SOUND_PLATFORMERROR; + } + } + return 1; } + void PlatEndGameSound(SOUNDINDEX index) { fprintf(stderr, "PlatEndGameSound(%d)\n", index); @@ -92,28 +380,173 @@ void InitialiseBaseFrequency(SOUNDINDEX soundNum) int LoadWavFile(int soundNum, char * wavFileName) { - fprintf(stderr, "LoadWavFile(%d, %s)\n", soundNum, wavFileName); + ALsizei size, freq, bits; + ALenum format; + ALvoid *data; + + fprintf(stderr, "LoadWavFile(%d, %s) - sound\n", soundNum, wavFileName); + + alutLoadWAV (wavFileName, &data, &format, &size, &bits, &freq); + alGenBuffers (1, &(GameSounds[soundNum].dsBufferP)); + alBufferData (GameSounds[soundNum].dsBufferP, format, data, size, freq); + + GameSounds[soundNum].loaded = 1; + free (data); return 0; } +// In libopenal +extern void *acLoadWAV (void *data, ALuint *size, void **udata, + ALushort *fmt, ALushort *chan, ALushort *freq); + unsigned char *ExtractWavFile(int soundIndex, unsigned char *bufferPtr) { + ALint len, seclen = 0; + void *udata; + ALushort rfmt, rchan, rfreq, rsize; + fprintf(stderr, "ExtractWavFile(%d, %p)\n", soundIndex, bufferPtr); + + { + int slen = strlen (bufferPtr) + 1; + GameSounds[soundIndex].wavName = (char *)AllocateMem (slen); + strcpy (GameSounds[soundIndex].wavName, bufferPtr); + bufferPtr += slen; +fprintf (stderr, "Loaded %s\n", GameSounds[soundIndex].wavName); + } - return 0; + if (acLoadWAV (bufferPtr, (ALuint *) &len, &udata, &rfmt, + &rchan, &rfreq) == NULL) { + fprintf (stderr, "Unable to convert data\n"); + return (unsigned char *)0; + } + +printf("rfmt = %d, rchan = %d, rfreq = %d, len = %d\n", rfmt, rchan, rfreq, len); + + if ((rfmt == AUDIO_U8)) { + if (rchan == 2) { + rfmt = AL_FORMAT_STEREO8; + seclen = len / (rfreq * 1 * 2); + } else if (rchan == 1) { + rfmt = AL_FORMAT_MONO8; + seclen = len / rfreq; + } + } else if ((rfmt == AUDIO_S16LSB) || (rfmt == AUDIO_S16MSB)) { + if (rchan == 2) { + rfmt = AL_FORMAT_STEREO16; + seclen = len / (rfreq * 2 * 2); + } else if (rchan == 1) { + rfmt = AL_FORMAT_MONO16; + seclen = len / (rfreq * 2); + } + } else + return (unsigned char *)0; + + rsize = len; + + alGenBuffers (1, &(GameSounds[soundIndex].dsBufferP)); + alBufferData (GameSounds[soundIndex].dsBufferP, + rfmt, udata, rsize, rfreq); + +{ + ALint t, val; + alGenSources(1, &t); + alSourcei(t, AL_BUFFER, GameSounds[soundIndex].dsBufferP); + alSourcePlay(t); + do { + sleep(1); + + alGetSourceiv(t, AL_SOURCE_STATE, &val); + } while (val == AL_PLAYING); +} + + 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; + + free (udata); + + return (bufferPtr + rsize); } int LoadWavFromFastFile(int soundNum, char * wavFileName) { - fprintf(stderr, "LoadWavFromFastFile(%d, %s)\n", soundNum, wavFileName); + FFILE *fp; + unsigned char *buf; + unsigned int len = 0; - return 0; + fprintf(stderr, "LoadWavFromFastFile(%d, %s)\n", soundNum, wavFileName); + + if ((fp = ffopen (wavFileName, "rb")) != NULL) { + ffseek (fp, 0, SEEK_END); + len = fftell (fp); + ffseek (fp, 0, SEEK_SET); + buf = (unsigned char *) malloc (len + strlen (wavFileName) + 1); + strcpy (buf, wavFileName); + ffread (&buf[strlen(wavFileName)+1], len, 1, fp); + ffclose (fp); + len = (int)ExtractWavFile (soundNum, buf); + free (buf); + } + + return len; } void PlatUpdatePlayer() { + ALfloat vel[3], or[6], pos[3]; fprintf(stderr, "PlatUpdatePlayer()\n"); + + if (Global_VDB_Ptr) { + extern int NormalFrameTime; + extern int DopplerShiftIsOn; + + if (AvP.PlayerType != I_Alien) { + or[0] = (float) ((Global_VDB_Ptr->VDB_Mat.mat13) / 65536.0F); + or[1] = 0.0; + or[2] = (float) ((Global_VDB_Ptr->VDB_Mat.mat33) / 65536.0F); + or[3] = 0.0; + or[4] = 1.0; + or[5] = 0.0; + } else { + or[0] = (float) ((Global_VDB_Ptr->VDB_Mat.mat13) / 65536.0F); + or[1] = (float) ((Global_VDB_Ptr->VDB_Mat.mat23) / 65536.0F); + or[2] = (float) ((Global_VDB_Ptr->VDB_Mat.mat33) / 65536.0F); + or[3] = (float) ((Global_VDB_Ptr->VDB_Mat.mat12) / 65536.0F); + or[4] = (float) ((Global_VDB_Ptr->VDB_Mat.mat22) / 65536.0F); + or[5] = (float) ((Global_VDB_Ptr->VDB_Mat.mat32) / 65536.0F); + } + + if (AvP.PlayerType == I_Alien && DopplerShiftIsOn && NormalFrameTime) { + DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr; + float invFrameTime = 100000.0f/(float)NormalFrameTime; + + vel[0] = (float)(dynPtr->Position.vx - dynPtr->PrevPosition.vx) * invFrameTime; + vel[1] = (float)(dynPtr->Position.vy - dynPtr->PrevPosition.vy) * invFrameTime; + vel[2] = (float)(dynPtr->Position.vz - dynPtr->PrevPosition.vz) * invFrameTime; + } else { + vel[0] = 0.0; + vel[1] = 0.0; + vel[2] = 0.0; + } + +#if 1 + { + pos[0] = Global_VDB_Ptr->VDB_World.vx; + pos[1] = Global_VDB_Ptr->VDB_World.vy; + pos[2] = Global_VDB_Ptr->VDB_World.vz; + } +#endif + } + + + // fixme: add reverb check + alListenerfv (AL_ORIENTATION, or); + alListenerfv (AL_VELOCITY, vel); + alListenerfv (AL_POSITION, pos); } void PlatSetEnviroment(unsigned int env_index, float reverb_mix) @@ -125,3 +558,8 @@ void UpdateSoundFrequencies() { fprintf(stderr, "UpdateSoundFreqncies()\n"); } + +int PlatChangeSoundPan (int activeIndex, int pan) +{ + return 1; +} -- cgit v1.3