#include #include #include #include #include #include #include // For a few defines (AUDIO_*) #include "fixer.h" #include "3dc.h" #include "platform.h" #include "inline.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 }, 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"); 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) { fprintf (stderr, "alListenerfv() error = ...\n"); 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) { fprintf (stderr, "alGenSources () error = ..."); 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); /* these are just guessed values for now */ alSourcef (p, AL_REFERENCE_DISTANCE, 5200.0f); alSourcef (p, AL_ROLLOFF_FACTOR, 2.0f); } return 1; } void PlatEndSoundSys() { fprintf(stderr, "PlatEndSoundSys()\n"); } int PlatChangeGlobalVolume(int volume) { fprintf(stderr, "PlatChangeGlobalVolume(%d)\n", volume); return 1; } 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); alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_BUFFER, GameSounds[si].dsBufferP); if (ActiveSounds[activeIndex].loop) alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_TRUE); else alSourcei (ActiveSounds[activeIndex].ds3DBufferP, AL_LOOPING, AL_FALSE); 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) { alSourcei(ActiveSounds[activeIndex].ds3DBufferP, AL_SOURCE_RELATIVE, AL_FALSE); alSourcef(ActiveSounds[activeIndex].ds3DBufferP, AL_GAIN, 1.0f); PlatDo3dSound (activeIndex); } else { ALfloat zero[3] = { 0.0f, 0.0f, 0.0f }; int newVolume, ok; alSourcei(ActiveSounds[activeIndex].ds3DBufferP, AL_SOURCE_RELATIVE, AL_TRUE); alSourcef(ActiveSounds[activeIndex].ds3DBufferP, AL_GAIN, 0.7f); alSourcefv(ActiveSounds[activeIndex].ds3DBufferP, AL_POSITION, zero); alSourcefv(ActiveSounds[activeIndex].ds3DBufferP, AL_VELOCITY, zero); 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) { // float nv = 127.0f / (float) volume; fprintf(stderr, "PlatChangeSoundVolume(%d, %d)\n", activeIndex, volume); // 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[gsi].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) { ALint val; 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); if (ActiveSounds[activeIndex].threedee == 0) return 1; 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 (1 || 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); alSourcef(ActiveSounds[activeIndex].ds3DBufferP, AL_GAIN, 1.0f); ActiveSounds[activeIndex].PropSetP_pos[0] = ActiveSounds[activeIndex].threedeedata.position.vx; ActiveSounds[activeIndex].PropSetP_pos[1] = ActiveSounds[activeIndex].threedeedata.position.vy; ActiveSounds[activeIndex].PropSetP_pos[2] = ActiveSounds[activeIndex].threedeedata.position.vz; alSourcefv (ActiveSounds[activeIndex].ds3DBufferP, AL_POSITION, ActiveSounds[activeIndex].PropSetP_pos); printf("Sound : (%f, %f, %f) [%d]\n", ActiveSounds[activeIndex].PropSetP_pos[0], ActiveSounds[activeIndex].PropSetP_pos[1], ActiveSounds[activeIndex].PropSetP_pos[2], activeIndex); 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); } 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; } int LoadWavFile(int soundNum, char * 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; } static unsigned char *Force8to16 (unsigned char *buf, int *len) { 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; } *len *= 2; return nbuf; } 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 (1 || (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; } pos[0] = Global_VDB_Ptr->VDB_World.vx; pos[1] = Global_VDB_Ptr->VDB_World.vy; pos[2] = Global_VDB_Ptr->VDB_World.vz; } printf("Player: (%f, %f, %f) (%f, %f, %f %f, %f, %f)\n", pos[0], pos[1], pos[2], or[0], or[1], or[2], or[3], or[4], or[5]); // fixme: add reverb check alListenerfv (AL_ORIENTATION, or); // alListenerfv (AL_VELOCITY, vel); alListenerfv (AL_POSITION, pos); } void PlatEndGameSound(SOUNDINDEX index) { fprintf(stderr, "PlatEndGameSound(%d)\n", index); } unsigned int PlatMaxHWSounds() { fprintf(stderr, "PlatMaxHWSounds()\n"); return 256; } void InitialiseBaseFrequency(SOUNDINDEX soundNum) { fprintf(stderr, "InitialiseBaseFrequency(%d)\n", soundNum); } void PlatSetEnviroment(unsigned int env_index, float reverb_mix) { fprintf(stderr, "PlatSetEnvironment(%d, %f)\n", env_index, reverb_mix); } void UpdateSoundFrequencies() { fprintf(stderr, "UpdateSoundFreqncies()\n"); } int PlatChangeSoundPan (int activeIndex, int pan) { return 1; } // 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; unsigned char *nb; 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); } if (acLoadWAV (bufferPtr, (ALuint *) &rsize, &udata, &rfmt, &rchan, &rfreq) == NULL) { fprintf (stderr, "Unable to convert data\n"); return (unsigned char *)0; } len = rsize; if ((rfmt == AUDIO_U8)) { 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 (unsigned char *)0; 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; 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)); } int LoadWavFromFastFile(int soundNum, char * wavFileName) { FFILE *fp; unsigned char *buf; unsigned int len = 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; }