From 706157d62330c9cca6242b0f0a0a14632487dce3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Dec 2019 19:37:05 +0100 Subject: [PATCH] - converted Blood's sound system to the OpenAL sound engine. Now, this code was one big mess of strange design, let's hope it sounds better with a real 3D mixer now. --- source/audiolib/include/fx_man.h | 1 - source/blood/src/aiunicult.cpp | 7 +- source/blood/src/asound.cpp | 75 +-- source/blood/src/blood.cpp | 4 +- source/blood/src/credits.cpp | 4 +- source/blood/src/endgame.cpp | 2 +- source/blood/src/osdcmd.cpp | 14 - source/blood/src/seq.cpp | 10 +- source/blood/src/sfx.cpp | 537 +++++------------- source/blood/src/sfx.h | 30 +- source/blood/src/sound.cpp | 288 +++------- source/blood/src/sound.h | 1 - source/build/include/compat.h | 10 + source/common/filesystem/filesystem.cpp | 9 + source/common/filesystem/filesystem.h | 1 + source/common/sound/backend/i_soundinternal.h | 1 + source/common/sound/s_sound.cpp | 13 +- source/common/sound/s_soundinternal.h | 34 +- source/common/utility/namedef.h | 4 + source/duke3d/src/sounds.cpp | 10 +- source/rr/src/sounds.cpp | 11 +- 21 files changed, 353 insertions(+), 713 deletions(-) diff --git a/source/audiolib/include/fx_man.h b/source/audiolib/include/fx_man.h index 66c0d73c7..9187db937 100644 --- a/source/audiolib/include/fx_man.h +++ b/source/audiolib/include/fx_man.h @@ -94,7 +94,6 @@ static FORCE_INLINE int FX_GetReverseStereo(void) { return MV_GetReverseStereo() static FORCE_INLINE void FX_SetReverb_(int reverb) { MV_SetReverb(reverb); } static FORCE_INLINE int FX_GetMaxReverbDelay(void) { return MV_GetMaxReverbDelay(); } static FORCE_INLINE int FX_GetReverbDelay(void) { return MV_GetReverbDelay(); } -static FORCE_INLINE void FX_SetReverbDelay(int delay) { MV_SetReverbDelay(delay); } static FORCE_INLINE int FX_VoiceAvailable(int priority) { return MV_VoiceAvailable(priority); } static FORCE_INLINE int FX_PauseVoice(int handle, int pause) { return FX_CheckMVErr(MV_PauseVoice(handle, pause)); } static FORCE_INLINE int FX_EndLooping(int handle) { return FX_CheckMVErr(MV_EndLooping(handle)); } diff --git a/source/blood/src/aiunicult.cpp b/source/blood/src/aiunicult.cpp index c81d69b17..a45377787 100644 --- a/source/blood/src/aiunicult.cpp +++ b/source/blood/src/aiunicult.cpp @@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "endgame.h" #include "view.h" #include "tile.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS static void genDudeAttack1(int, int); @@ -902,6 +903,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { // let's check if there same sounds already played by other dudes // so we won't get a lot of annoying screams in the same time and ensure sound played in it's full length (if not interruptable) if (pExtra->sndPlaying && !sndInfo->interruptable) { +#if 0 for (int i = 0; i < 256; i++) { if (Bonkle[i].atc <= 0) continue; for (int a = 0; a < rand; a++) { @@ -915,6 +917,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { } } } +#endif pExtra->sndPlaying = false; @@ -928,7 +931,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { int maxRetries = 5; while (maxRetries-- > 0) { int random = Random(rand); - if (!gSoundRes.Lookup(sndId + random, "SFX")) continue; + if (!soundEngine->FindSoundByResID(sndId + random)) continue; sndId = sndId + random; gotSnd = true; break; @@ -938,7 +941,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { if (gotSnd == false) { int maxSndId = sndId + rand; while (sndId++ <= maxSndId) { - if (!gSoundRes.Lookup(sndId, "SFX")) continue; + if (!soundEngine->FindSoundByResID(sndId)) continue; gotSnd = true; break; } diff --git a/source/blood/src/asound.cpp b/source/blood/src/asound.cpp index 0502732cb..1acfdc0b6 100644 --- a/source/blood/src/asound.cpp +++ b/source/blood/src/asound.cpp @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "player.h" #include "resource.h" #include "sound.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -40,13 +41,9 @@ BEGIN_BLD_NS struct AMB_CHANNEL { - int at0; - int at4; - int at8; - DICTNODE *atc; - char *at10; - int at14; - int at18; + FSoundID soundID; + int distance; + int check; }; AMB_CHANNEL ambChannels[kMaxAmbChannel]; @@ -75,22 +72,31 @@ void ambProcess(void) dz >>= 8; int nDist = ksqrt(dx*dx+dy*dy+dz*dz); int vs = mulscale16(pXSprite->data4, pXSprite->busy); - ambChannels[pSprite->owner].at4 += ClipRange(scale(nDist, pXSprite->data1, pXSprite->data2, vs, 0), 0, vs); + ambChannels[pSprite->owner].distance += ClipRange(scale(nDist, pXSprite->data1, pXSprite->data2, vs, 0), 0, vs); } } } AMB_CHANNEL *pChannel = ambChannels; for (int i = 0; i < nAmbChannels; i++, pChannel++) { - if (pChannel->at0 > 0) - FX_SetPan(pChannel->at0, pChannel->at4, pChannel->at4, pChannel->at4); - else + if (soundEngine->IsSourcePlayingSomething(SOURCE_Ambient, pChannel, CHAN_BODY, -1)) { - int end = ClipLow(pChannel->at14-1, 0); - pChannel->at0 = FX_PlayLoopedRaw(pChannel->at10, pChannel->at14, pChannel->at10, pChannel->at10+end, sndGetRate(pChannel->at18), 0, - pChannel->at4, pChannel->at4, pChannel->at4, pChannel->at4, 1.f, (intptr_t)&pChannel->at0); + if (pChannel->distance > 0) + { + soundEngine->ChangeSoundVolume(SOURCE_Ambient, pChannel, CHAN_BODY, pChannel->distance / 255.f); + } + else + { + // Stop the sound if it cannot be heard so that it doesn't occupy a physical channel. + soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY); + } } - pChannel->at4 = 0; + else if (pChannel->distance > 0) + { + FVector3 pt{}; + soundEngine->StartSound(SOURCE_Ambient, pChannel, &pt, CHAN_BODY, CHANF_LOOP, pChannel->soundID, pChannel->distance / 255.f, ATTN_NONE); + } + pChannel->distance = 0; } } @@ -99,16 +105,8 @@ void ambKillAll(void) AMB_CHANNEL *pChannel = ambChannels; for (int i = 0; i < nAmbChannels; i++, pChannel++) { - if (pChannel->at0 > 0) - { - FX_EndLooping(pChannel->at0); - FX_StopSound(pChannel->at0); - } - if (pChannel->atc) - { - gSoundRes.Unlock(pChannel->atc); - pChannel->atc = NULL; - } + soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY); + pChannel->soundID = 0; } nAmbChannels = 0; } @@ -125,7 +123,7 @@ void ambInit(void) int i; AMB_CHANNEL *pChannel = ambChannels; for (i = 0; i < nAmbChannels; i++, pChannel++) - if (pXSprite->data3 == pChannel->at8) break; + if (pXSprite->data3 == pChannel->check) break; if (i == nAmbChannels) { @@ -135,30 +133,17 @@ void ambInit(void) } int nSFX = pXSprite->data3; - DICTNODE *pSFXNode = gSoundRes.Lookup(nSFX, "SFX"); - if (!pSFXNode) { + auto snd = soundEngine->FindSoundByResID(nSFX); + if (!snd) { //ThrowError("Missing sound #%d used in ambient sound generator %d\n", nSFX); viewSetSystemMessage("Missing sound #%d used in ambient sound generator #%d\n", nSFX); continue; } - SFX *pSFX = (SFX*)gSoundRes.Load(pSFXNode); - DICTNODE *pRAWNode = gSoundRes.Lookup(pSFX->rawName, "RAW"); - if (!pRAWNode) { - //ThrowError("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX); - viewSetSystemMessage("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX); - continue; - } - - if (pRAWNode->Size() > 0) { - pChannel->at14 = pRAWNode->Size(); - pChannel->at8 = nSFX; - pChannel->atc = pRAWNode; - pChannel->at14 = pRAWNode->Size(); - pChannel->at10 = (char*)gSoundRes.Lock(pRAWNode); - pChannel->at18 = pSFX->format; - nAmbChannels++; - } + pChannel->soundID = FSoundID(snd); + pChannel->check = nSFX; + pChannel->distance = 0; + nAmbChannels++; } diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index e09857edf..08ac12a5e 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -172,7 +172,7 @@ void ShutDown(void) if (!in3dmode()) return; netDeinitialize(); - sndTerm(); + //sndTerm(); sfxTerm(); scrUnInit(); // PORT_TODO: Check argument @@ -915,7 +915,6 @@ void ProcessFrame(void) actProcessSprites(); actPostProcess(); viewCorrectPrediction(); - sndProcess(); ambProcess(); viewUpdateDelirium(); viewUpdateShake(); @@ -1198,7 +1197,6 @@ int GameInterface::app_main() viewResizeView(gViewSize); initprintf("Initializing sound system\n"); sndInit(); - sfxInit(); gChoke.sub_83ff0(518, sub_84230); if (bAddUserMap) { diff --git a/source/blood/src/credits.cpp b/source/blood/src/credits.cpp index cfc3db162..775a61688 100644 --- a/source/blood/src/credits.cpp +++ b/source/blood/src/credits.cpp @@ -238,13 +238,13 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav) nScale = divscale16(200, nHeight); if (nWav) - sndStartWavID(nWav, snd_fxvolume); + sndStartWavID(nWav, 255); else { auto nHandleWAV = credKOpen4Load(pzWAV); if (nHandleWAV.isOpen()) { - sndStartWavDisk(pzWAV, snd_fxvolume); + sndStartWavDisk(pzWAV, 255); } } diff --git a/source/blood/src/endgame.cpp b/source/blood/src/endgame.cpp index caadd4c48..958d6d17b 100644 --- a/source/blood/src/endgame.cpp +++ b/source/blood/src/endgame.cpp @@ -220,7 +220,7 @@ void CSecretMgr::Found(int nType) } else at8++; if (gGameOptions.nGameType == 0) { - viewSetMessage(GStrings(FStringf("TXT_SECRET%d", Random(2))), 0, MESSAGE_PRIORITY_SECRET); + viewSetMessage(GStrings(FStringf("TXTB_SECRET%d", Random(2))), 0, MESSAGE_PRIORITY_SECRET); } } diff --git a/source/blood/src/osdcmd.cpp b/source/blood/src/osdcmd.cpp index 926cca533..efee1bb54 100644 --- a/source/blood/src/osdcmd.cpp +++ b/source/blood/src/osdcmd.cpp @@ -270,20 +270,6 @@ static int osdcmd_noclip(osdcmdptr_t UNUSED(parm)) return OSDCMD_OK; } -/* -static int osdcmd_restartsound(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - sfxTerm(); - sndTerm(); - - sndInit(); - sfxInit(); - - return OSDCMD_OK; -} -*/ - void onvideomodechange(int32_t newmode) { UNREFERENCED_PARAMETER(newmode); diff --git a/source/blood/src/seq.cpp b/source/blood/src/seq.cpp index 6c3290e2f..819b58277 100644 --- a/source/blood/src/seq.cpp +++ b/source/blood/src/seq.cpp @@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "actor.h" #include "tile.h" #include "view.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -327,8 +328,13 @@ void SEQINST::Update(ACTIVE *pActive) }; int sndId = surfSfxMove[surf][Random(2)]; - DICTNODE * hRes = gSoundRes.Lookup(sndId, "SFX"); SFX * pEffect = (SFX*)gSoundRes.Load(hRes); - sfxPlay3DSoundCP(pSprite, sndId, -1, 0, 0, (surfSfxMove[surf][2] != pEffect->relVol) ? pEffect->relVol : surfSfxMove[surf][3]); + auto snd = soundEngine->FindSoundByResID(sndId); + if (snd > 0) + { + auto udata = (int*)soundEngine->GetUserData(snd); + int relVol = udata ? udata[2] : 255; + sfxPlay3DSoundCP(pSprite, sndId, -1, 0, 0, (surfSfxMove[surf][2] != relVol) ? relVol : surfSfxMove[surf][3]); + } } diff --git a/source/blood/src/sfx.cpp b/source/blood/src/sfx.cpp index e5329dbb2..c66365ed5 100644 --- a/source/blood/src/sfx.cpp +++ b/source/blood/src/sfx.cpp @@ -35,338 +35,175 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sfx.h" #include "sound.h" #include "trig.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS -POINT2D earL, earR, earL0, earR0; // Ear position -VECTOR2D earVL, earVR; // Ear velocity ? -int lPhase, rPhase, lVol, rVol, lPitch, rPitch; +class BloodSoundEngine : public SoundEngine +{ + // client specific parts of the sound engine go in this class. + void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel) override; + TArray ReadSound(int lumpnum); -BONKLE Bonkle[256]; -BONKLE *BonkleCache[256]; - -int nBonkles; +public: + BloodSoundEngine() + { + S_Rolloff.RolloffType = ROLLOFF_Doom; + S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code. + S_Rolloff.MaxDistance = 850; + } +}; void sfxInit(void) { - for (int i = 0; i < 256; i++) - BonkleCache[i] = &Bonkle[i]; - nBonkles = 0; + soundEngine = new BloodSoundEngine; } void sfxTerm() { } -int Vol3d(int angle, int dist) +//========================================================================== +// +// +// +//========================================================================== + +TArray BloodSoundEngine::ReadSound(int lumpnum) { - return dist - mulscale16(dist, 0x2000 - mulscale30(0x2000, Cos(angle))); + auto wlump = fileSystem.OpenFileReader(lumpnum); + return wlump.Read(); } -void Calc3DValues(BONKLE *pBonkle) +void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel) { - int dx = pBonkle->at20.x - gMe->pSprite->x; - int dy = pBonkle->at20.y - gMe->pSprite->y; - int dz = pBonkle->at20.z - gMe->pSprite->z; - int angle = getangle(dx, dy); - dx >>= 4; - dy >>= 4; - dz >>= 8; - int distance = ksqrt(dx*dx + dy * dy + dz * dz); - distance = ClipLow((distance >> 2) + (distance >> 3), 64); - int v14, v18; - v14 = v18 = scale(pBonkle->at1c, 80, distance); - int sinVal = Sin(angle); - int cosVal = Cos(angle); - int v8 = dmulscale30r(cosVal, pBonkle->at20.x - pBonkle->at2c.x, sinVal, pBonkle->at20.y - pBonkle->at2c.y); + if (pos != nullptr && type != SOURCE_None) + { + FVector3 camera; + + if (gMe && gMe->pSprite) camera = GetSoundPos(&gMe->pSprite->pos); + else camera = { 0, 0, 0 }; // don't crash if there is no player. - int distanceL = approxDist(pBonkle->at20.x - earL.x, pBonkle->at20.y - earL.y); - lVol = Vol3d(angle - (gMe->pSprite->ang - 85), v18); - int phaseLeft = mulscale16r(distanceL, pBonkle->at3c == 1 ? 4114 : 8228); - lPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVL.dx, sinVal, earVL.dy) + 5853, v8 + 5853); + if (vel) vel->Zero(); - int distanceR = approxDist(pBonkle->at20.x - earR.x, pBonkle->at20.y - earR.y); - rVol = Vol3d(angle - (gMe->pSprite->ang + 85), v14); - int phaseRight = mulscale16r(distanceR, pBonkle->at3c == 1 ? 4114 : 8228); - rPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVR.dx, sinVal, earVR.dy) + 5853, v8 + 5853); + if (type == SOURCE_Unattached) + { + pos->X = pt[0]; + pos->Y = pt[1]; + pos->Z = pt[2]; + } + else if (type == SOURCE_Actor) + { + auto actor = (spritetype*)source; + assert(actor != nullptr); + size_t index = actor - sprite; + // Engine expects velocity in units per second, not units per tic. + if (vel) *vel = { xvel[index] * (30 / 65536.f), zvel[index] * (-30 / 65536.f), yvel[index] * (-30 / 65536.f) }; + *pos = GetSoundPos(&actor->pos); + } + else if (type == SOURCE_Ambient) + { + *pos = camera; // just to be safe. Ambient sounds are in the world but unpositioned + } + if ((chanflags & CHANF_LISTENERZ)) + { + pos->Y = camera.Y; + } + } +} - int phaseMin = ClipHigh(phaseLeft, phaseRight); - lPhase = phaseRight - phaseMin; - rPhase = phaseLeft - phaseMin; + +void sfxUpdate3DSounds(void) +{ + SoundListener listener; + + listener.angle = -(float)gMe->pSprite->ang * pi::pi() / 1024; // Build uses a period of 2048. + listener.velocity.Zero(); + listener.position = GetSoundPos(&gMe->pSprite->pos); + listener.underwater = false; + // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. + // listenactor->waterlevel == 3; + //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); + listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; + listener.valid = true; + + listener.ListenerObject = gMe->pSprite; + soundEngine->SetListener(listener); + soundEngine->UpdateSounds((int)totalclock); +} + +FSoundID getSfx(FSoundID soundId, float &attenuation, int &pitch, int relvol) +{ + auto udata = (int*)soundEngine->GetUserData(soundId); + if (pitch < 0) pitch = udata ? udata[0] : 0x10000; + + if (relvol < 0) relvol = udata && udata[2] ? udata[2] : 80; + if (relvol > 255) relvol = 255; + attenuation = relvol > 0 ? 80.f / relvol : 1.f; + return soundId; } void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector) { if (!SoundEnabled() || soundId < 0) return; - - DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes)return; + auto sid = soundEngine->FindSoundByResID(soundId); + if (sid == 0) return; - SFX *pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) return; + vec3_t xyz = { x, y, z }; + auto svec = GetSoundPos(&xyz); + + float attenuation; + int pitch = -1; + sid = getSfx(sid, attenuation, pitch, -1); + + soundEngine->StartSound(SOURCE_Unattached, nullptr, &svec, -1, CHANF_OVERLAP, sid, 0.8f, attenuation, nullptr, pitch / 65536.f); - int v1c, v18; - v1c = v18 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format)); - if (nBonkles >= 256) - return; - BONKLE *pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - pBonkle->at20.x = x; - pBonkle->at20.y = y; - pBonkle->at20.z = z; - pBonkle->at38 = nSector; - FindSector(x, y, z, &pBonkle->at38); - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = pEffect->relVol; - pBonkle->at18 = v18; - pBonkle->at3c = pEffect->format; - int size = hRes->Size(); - char *pData = (char*)gSoundRes.Lock(hRes); - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - if (snd_doppler) - { - MV_Lock(); - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - MV_Unlock(); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v1c, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } } -void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3, int a4) +enum EPlayFlags { - if (!SoundEnabled()) - return; - if (!pSprite) - return; - if (soundId < 0) - return; - DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes) - return; + FX_GlobalChannel = 1, + FX_SoundMatch = 2, + FX_ChannelMatch = 4, +}; - SFX *pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) - return; - int size = hRes->Size(); - if (size <= 0) - return; - int v14; - v14 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format)); - BONKLE *pBonkle = NULL; - if (a3 >= 0) - { - int i; - for (i = 0; i < nBonkles; i++) - { - pBonkle = BonkleCache[i]; - if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0)) - { - if ((a4 & 4) != 0 && pBonkle->at14 == a3) - return; - if ((a4 & 2) != 0 && pBonkle->atc == soundId) - return; - if (pBonkle->at0 > 0) - FX_StopSound(pBonkle->at0); - if (pBonkle->at4 > 0) - FX_StopSound(pBonkle->at4); - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - break; - } - } - if (i == nBonkles) - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - } - pBonkle->at10 = pSprite; - pBonkle->at14 = a3; - } - else - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - } - pBonkle->at20.x = pSprite->x; - pBonkle->at20.y = pSprite->y; - pBonkle->at20.z = pSprite->z; - pBonkle->at38 = pSprite->sectnum; - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = pEffect->relVol; - pBonkle->at18 = v14; - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - int loopStart = pEffect->loopStart; - int loopEnd = ClipLow(size - 1, 0); - if (a3 < 0) - loopStart = -1; - MV_Lock(); - char *pData = (char*)gSoundRes.Lock(hRes); - if (loopStart >= 0) - { - if (snd_doppler) - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } - } - else - { - pData = (char*)gSoundRes.Lock(pBonkle->at8); - if (snd_doppler) - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } - } - MV_Unlock(); -} - -// By NoOne: same as previous, but allows to set custom pitch for sound AND volume. Used by SFX gen now. void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume) { - if (!SoundEnabled() || !pSprite || soundId < 0) return; - DICTNODE* hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes) return; + if (!SoundEnabled() || soundId < 0 || !pSprite) return; + auto sid = soundEngine->FindSoundByResID(soundId); + if (sid == 0) return; - SFX* pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) return; - int size = hRes->Size(); - if (size <= 0) return; - - if (pitch <= 0) pitch = pEffect->pitch; - else pitch -= Random(pEffect->pitchRange); + auto svec = GetSoundPos(&pSprite->pos); + + float attenuation; + sid = getSfx(sid, attenuation, pitch, volume); - int v14; - v14 = mulscale16(pitch, sndGetRate(pEffect->format)); - - BONKLE * pBonkle = NULL; if (a3 >= 0) { - int i; - for (i = 0; i < nBonkles; i++) - { - pBonkle = BonkleCache[i]; - if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0)) + a3++; // This is to make 0 a valid channel value. + if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int { - if ((a4 & 4) != 0 && pBonkle->at14 == a3) - return; - if ((a4 & 2) != 0 && pBonkle->atc == soundId) - return; - if (pBonkle->at0 > 0) - FX_StopSound(pBonkle->at0); - if (pBonkle->at4 > 0) - FX_StopSound(pBonkle->at4); - if (pBonkle->at8) + if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business. + if (chan->EntChannel == a3 && (chan->Source == pSprite || (a4 & FX_GlobalChannel) != 0)) { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; + if ((a4 & FX_ChannelMatch) != 0 && chan->EntChannel == a3) + return true; + if ((a4 & FX_SoundMatch) != 0 && chan->OrgID == sid) + return true; + soundEngine->StopChannel(chan); + return -1; } - break; - } - } - if (i == nBonkles) - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - } - pBonkle->at10 = pSprite; - pBonkle->at14 = a3; + return false; + })) return; + } - else - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - } - pBonkle->at20.x = pSprite->x; - pBonkle->at20.y = pSprite->y; - pBonkle->at20.z = pSprite->z; - pBonkle->at38 = pSprite->sectnum; - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = ((volume == 0) ? pEffect->relVol : ((volume == -1) ? 0 : ((volume > 255) ? 255 : volume))); - pBonkle->at18 = v14; - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - int loopStart = pEffect->loopStart; - int loopEnd = ClipLow(size - 1, 0); - if (a3 < 0) - loopStart = -1; - MV_Lock(); - char* pData = (char*)gSoundRes.Lock(hRes); - if (loopStart >= 0) - { - if (snd_doppler) - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)& pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = 0; - } - } - else - { - pData = (char*)gSoundRes.Lock(pBonkle->at8); - if (snd_doppler) - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)& pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = 0; - } - } - MV_Unlock(); + + soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, a3, a3 == -1? CHANF_OVERLAP : CHANF_NONE , sid, 0.8f, attenuation, nullptr, pitch / 65536.f); +} + +void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4) +{ + sfxPlay3DSoundCP(pSprite, soundId, a3, a4, -1, -1); } @@ -374,136 +211,48 @@ void sfxKill3DSound(spritetype *pSprite, int a2, int a3) { if (!pSprite) return; - for (int i = nBonkles - 1; i >= 0; i--) - { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at10 == pSprite && (a2 < 0 || a2 == pBonkle->at14) && (a3 < 0 || a3 == pBonkle->atc)) + + if (a2 >= 0) a2++; + soundEngine->EnumerateChannels([=](FSoundChan* channel) { - if (pBonkle->at0 > 0) + if (channel->SourceType == SOURCE_Actor && channel->Source == pSprite && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || a3 == channel->OrgID)) { - FX_EndLooping(pBonkle->at0); - FX_StopSound(pBonkle->at0); + soundEngine->StopChannel(channel); } - if (pBonkle->at4 > 0) - { - FX_EndLooping(pBonkle->at4); - FX_StopSound(pBonkle->at4); - } - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - break; - } - } + return false; + }); } void sfxKillAllSounds(void) { - for (int i = nBonkles - 1; i >= 0; i--) + soundEngine->EnumerateChannels([](FSoundChan* channel) { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at0 > 0) - { - FX_EndLooping(pBonkle->at0); - FX_StopSound(pBonkle->at0); - } - if (pBonkle->at4 > 0) - { - FX_EndLooping(pBonkle->at4); - FX_StopSound(pBonkle->at4); - } - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - } + if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel); + return false; + }); } -void sfxUpdate3DSounds(void) -{ - int dx = mulscale30(Cos(gMe->pSprite->ang + 512), 43); - earL0 = earL; - int dy = mulscale30(Sin(gMe->pSprite->ang + 512), 43); - earR0 = earR; - earL.x = gMe->pSprite->x - dx; - earL.y = gMe->pSprite->y - dy; - earR.x = gMe->pSprite->x + dx; - earR.y = gMe->pSprite->y + dy; - earVL.dx = earL.x - earL0.x; - earVL.dy = earL.y - earL0.y; - earVR.dx = earR.x - earR0.x; - earVR.dy = earR.y - earR0.y; - for (int i = nBonkles - 1; i >= 0; i--) - { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at0 > 0 || pBonkle->at4 > 0) - { - if (!pBonkle->at8) - continue; - if (pBonkle->at10) - { - pBonkle->at2c = pBonkle->at20; - pBonkle->at20.x = pBonkle->at10->x; - pBonkle->at20.y = pBonkle->at10->y; - pBonkle->at20.z = pBonkle->at10->z; - pBonkle->at38 = pBonkle->at10->sectnum; - } - Calc3DValues(pBonkle); - MV_Lock(); - if (pBonkle->at0 > 0) - { - if (pBonkle->at4 > 0) - { - FX_SetPan(pBonkle->at0, lVol, lVol, 0); - FX_SetFrequency(pBonkle->at0, lPitch); - } - else - FX_SetPan(pBonkle->at0, lVol, lVol, rVol); - } - if (pBonkle->at4 > 0) - { - FX_SetPan(pBonkle->at4, rVol, 0, rVol); - FX_SetFrequency(pBonkle->at4, rPitch); - } - MV_Unlock(); - } - else - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - } - } -} void sfxSetReverb(bool toggle) { if (toggle) { - FX_SetReverb_(128); + FX_SetReverb(128); FX_SetReverbDelay(10); } else - FX_SetReverb_(0); + FX_SetReverb(0); } void sfxSetReverb2(bool toggle) { if (toggle) { - FX_SetReverb_(128); + FX_SetReverb(128); FX_SetReverbDelay(20); } else - FX_SetReverb_(0); + FX_SetReverb(0); } END_BLD_NS diff --git a/source/blood/src/sfx.h b/source/blood/src/sfx.h index 4bc8f1abd..4126012f2 100644 --- a/source/blood/src/sfx.h +++ b/source/blood/src/sfx.h @@ -25,30 +25,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +#if 0 struct BONKLE { - int at0; - int at4; - DICTNODE* at8; - int atc; - spritetype* at10; - int at14; - int at18; - int at1c; - POINT3D at20; - POINT3D at2c; - //int at20; - //int at24; - //int at28; - //int at2c; - //int at30; - //int at34; - int at38; - int at3c; + int left; + int right; + DICTNODE* data; + int soundId; + spritetype* origin; + int channel; + int pitch; + int relVol; + POINT3D originPt; + POINT3D oldOriginPt; }; extern BONKLE Bonkle[256]; extern BONKLE* BonkleCache[256]; +#endif void sfxInit(void); void sfxTerm(void); diff --git a/source/blood/src/sound.cpp b/source/blood/src/sound.cpp index c844d5e3a..c5a07d1f1 100644 --- a/source/blood/src/sound.cpp +++ b/source/blood/src/sound.cpp @@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "al_midi.h" #include "openaudio.h" #include "z_music.h" +#include "sfx.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -57,6 +59,72 @@ int soundRates[13] = { }; #define kChannelMax 32 + +//========================================================================== +// +// S_AddBloodSFX +// +// Registers a new sound with the name ".sfx" +// Actual sound data is searched for in the ns_bloodraw namespace. +// +//========================================================================== + +static void S_AddBloodSFX(int lumpnum) +{ + auto sfxlump = fileSystem.ReadFile(lumpnum); + const SFX* sfx = (SFX*)sfxlump.GetMem(); + FStringf rawname("%s.raw", sfx->rawName); + auto rawlump = fileSystem.FindFile(rawname); + int sfxnum; + + if (rawlump != -1) + { + auto& S_sfx = soundEngine->GetSounds(); + sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6); + if (sfx->format < 5 || sfx->format > 12) + { // [0..4] + invalid formats + S_sfx[sfxnum].RawRate = 11025; + } + else if (sfx->format < 9) + { // [5..8] + S_sfx[sfxnum].RawRate = 22050; + } + else + { // [9..12] + S_sfx[sfxnum].RawRate = 44100; + } + S_sfx[sfxnum].bLoadRAW = true; + S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart); + //S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional. + S_sfx[sfxnum].UserData.Resize(8); + int* udata = (int*)S_sfx[sfxnum].UserData.Data(); + udata[0] = sfx->pitch; + udata[1] = sfx->pitchRange; + udata[2] = sfx->relVol; } +} + +void sndInit(void) +{ + sfxInit(); + for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--) + { + auto type = fileSystem.GetResourceType(i); + if (type == NAME_SFX) + { + if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0) + S_AddBloodSFX(i); + } + else if (type == NAME_WAV || type == NAME_OGG || type == NAME_FLAC || type == NAME_VOC) + { + soundEngine->AddSoundLump(fileSystem.GetFileName(i), i, 0, fileSystem.GetResourceId(i)| 0x40000000, 6); // mark the resource ID as special. + } + } + soundEngine->HashSounds(); +} + + + + int sndGetRate(int format) { if (format < 13) @@ -64,22 +132,6 @@ int sndGetRate(int format) return 11025; } -SAMPLE2D Channel[kChannelMax]; - -SAMPLE2D * FindChannel(void) -{ - for (int i = kChannelMax - 1; i >= 0; i--) - if (Channel[i].at5 == 0) return &Channel[i]; - consoleSysMsg("No free channel available for sample"); - //ThrowError("No free channel available for sample"); - return NULL; -} - -void sndSetFXVolume(int nVolume) -{ - snd_fxvolume = nVolume; - FX_SetVolume(nVolume); -} void SoundCallback(intptr_t val) @@ -88,8 +140,6 @@ void SoundCallback(intptr_t val) pChannel->at0 = 0; } -void sndKillSound(SAMPLE2D *pChannel); - void sndStartSample(const char *pzSound, int nVolume, int nChannel) { if (!SoundEnabled()) @@ -97,19 +147,11 @@ void sndStartSample(const char *pzSound, int nVolume, int nChannel) if (!strlen(pzSound)) return; dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(pzSound, "RAW"); - if (!pChannel->at5) - return; - int nSize = pChannel->at5->Size(); - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - pChannel->at0 = FX_PlayRaw(pData, nSize, sndGetRate(1), 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); + auto snd = soundEngine->FindSound(pzSound); + if (snd > 0) + { + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, nChannel + 1, 0, snd, nVolume / 255.f, ATTN_NONE); + } } void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop) @@ -117,193 +159,35 @@ void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop) if (!SoundEnabled()) return; dassert(nChannel >= -1 && nChannel < kChannelMax); - DICTNODE *hSfx = gSoundRes.Lookup(nSound, "SFX"); - if (!hSfx) - return; - SFX *pEffect = (SFX*)gSoundRes.Lock(hSfx); - dassert(pEffect != NULL); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!pChannel->at5) - return; - if (nVolume < 0) - nVolume = pEffect->relVol; - int nSize = pChannel->at5->Size(); - int nLoopEnd = nSize - 1; - if (nLoopEnd < 0) - nLoopEnd = 0; - if (nSize <= 0) - return; - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - if (nChannel < 0) - bLoop = false; - if (bLoop) + if (nChannel >= 7) nChannel = -1; + auto snd = soundEngine->FindSoundByResID(nSound); + if (snd > 0) { - pChannel->at0 = FX_PlayLoopedRaw(pData, nSize, pData + pEffect->loopStart, pData + nLoopEnd, sndGetRate(pEffect->format), - 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); - pChannel->at4 |= 1; - } - else - { - pChannel->at0 = FX_PlayRaw(pData, nSize, sndGetRate(pEffect->format), 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); - pChannel->at4 &= ~1; + if (nVolume < 0) + { + auto udata = (int*)soundEngine->GetUserData(snd); + if (udata) nVolume = udata[2]; + else nVolume = 255; + } + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), (bLoop? CHANF_LOOP : EChanFlags::FromInt(0)), snd, nVolume / 255.f, ATTN_NONE); } } void sndStartWavID(unsigned int nSound, int nVolume, int nChannel) { - if (!SoundEnabled()) - return; - dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(nSound, "WAV"); - if (!pChannel->at5) - return; - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - pChannel->at0 = FX_Play(pData, pChannel->at5->Size(), 0, -1, 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); -} - -void sndKillSound(SAMPLE2D *pChannel) -{ - if (pChannel->at4 & 1) - { - FX_EndLooping(pChannel->at0); - pChannel->at4 &= ~1; - } - FX_StopSound(pChannel->at0); + return sndStartSample(nSound | 0x40000000, nVolume, nChannel); } void sndStartWavDisk(const char *pzFile, int nVolume, int nChannel) { - dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - auto hFile = fileSystem.OpenFileReader(pzFile, 0); - if (!hFile.isOpen()) - return; - int nLength = hFile.GetLength(); - char* pData = nullptr; - cacheAllocateBlock((intptr_t*)pData, nLength, nullptr); // use this obsolete call to indicate that some work is needed here! - if (!pData) - { - return; - } - hFile.Read(pData, nLength); - pChannel->at5 = (DICTNODE*)pData; - pChannel->at4 |= 2; - pChannel->at0 = FX_Play(pData, nLength, 0, -1, 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); + return sndStartSample(pzFile, nVolume, nChannel); } void sndKillAllSounds(void) { - for (int i = 0; i < kChannelMax; i++) - { - SAMPLE2D *pChannel = &Channel[i]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - if (pChannel->at5) - { - if (pChannel->at4 & 2) - { - pChannel->at4 &= ~2; - } - else // This 'else' needs to be removed once the file system is up (when cacheAllocateBlock gets replaced.) - { - gSoundRes.Unlock(pChannel->at5); - } - pChannel->at5 = 0; - } - } -} - -void sndProcess(void) -{ - for (int i = 0; i < kChannelMax; i++) - { - if (Channel[i].at0 <= 0 && Channel[i].at5) - { - if (Channel[i].at4 & 2) - { - Channel[i].at4 &= ~2; - } - else // This 'else' needs to be removed once the file system is up (when cacheAllocateBlock gets replaced.) - { - gSoundRes.Unlock(Channel[i].at5); - } - Channel[i].at5 = 0; - } - } -} - -void InitSoundDevice(void) -{ -#ifdef MIXERTYPEWIN - void *initdata = (void *)win_gethwnd(); // used for DirectSound -#else - void *initdata = NULL; -#endif - int nStatus; - nStatus = FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata); - if (nStatus != 0) - { - initprintf("InitSoundDevice: %s\n", FX_ErrorString(nStatus)); - return; - } - snd_reversestereo.Callback(); - snd_fxvolume.Callback(); - FX_SetCallBack(SoundCallback); -} - -void DeinitSoundDevice(void) -{ - int nStatus = FX_Shutdown(); - if (nStatus != 0) - ThrowError(FX_ErrorString(nStatus)); + soundEngine->StopSound(CHAN_AUTO); } -bool sndActive = false; - -void sndTerm(void) -{ - if (!sndActive) - return; - sndActive = false; - Mus_Stop(); - DeinitSoundDevice(); - //DeinitMusicDevice(); -} -extern char *pUserSoundRFF; -void sndInit(void) -{ - memset(Channel, 0, sizeof(Channel)); -#if 0 - pSongPtr = NULL; - nSongSize = 0; - bWaveMusic = false; - nWaveMusicHandle = -1; -#endif - InitSoundDevice(); - //InitMusicDevice(); - //atexit(sndTerm); - sndActive = true; -} END_BLD_NS diff --git a/source/blood/src/sound.h b/source/blood/src/sound.h index ccc31501e..917896bc7 100644 --- a/source/blood/src/sound.h +++ b/source/blood/src/sound.h @@ -45,7 +45,6 @@ struct SFX }; int sndGetRate(int format); -void sndSetFXVolume(int nVolume); void sndStartSample(const char *pzSound, int nVolume, int nChannel = -1); void sndStartSample(unsigned int nSound, int nVolume, int nChannel = -1, bool bLoop = false); void sndStartWavID(unsigned int nSound, int nVolume, int nChannel = -1); diff --git a/source/build/include/compat.h b/source/build/include/compat.h index e0da70d05..0cf64c827 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -1300,6 +1300,16 @@ static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffe #include "fix16.h" #include "libdivide.h" #include "clockticks.hpp" +#include "vectors.h" + +inline FVector3 GetSoundPos(const vec3_t *pos) +{ + // converts a Build coordinate to a sound system coordinate + const float xmul = 1 / 16.f; + const float ymul = -1 / 16.f; + const float zmul = -1 / 256.f; + return { pos->x* xmul, pos->z* zmul, pos->y* ymul }; +} /* End dependence on compat.o object. */ diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 97466fb50..759cb4af0 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -550,6 +550,15 @@ int FileSystem::GetResourceId(int lump) const return FileInfo[lump].lump->ResourceId; } +FName FileSystem::GetResourceType(int lump) const +{ + if ((size_t)lump >= NumEntries) + return NAME_None; + else + return FileInfo[lump].lump->LumpName[FResourceLump::ExtensionType]; +} + + //========================================================================== // // GetLumpFile diff --git a/source/common/filesystem/filesystem.h b/source/common/filesystem/filesystem.h index dd464ba50..ae4a02db9 100644 --- a/source/common/filesystem/filesystem.h +++ b/source/common/filesystem/filesystem.h @@ -164,6 +164,7 @@ public: bool IsEncryptedFile(int file) const noexcept; int GetResourceId(int file) const; + FName GetResourceType(int file) const; int GetNumResourceFiles() const { return NumFiles; } int GetNumEntries () const { return NumEntries; } diff --git a/source/common/sound/backend/i_soundinternal.h b/source/common/sound/backend/i_soundinternal.h index aac498b00..08dd311a2 100644 --- a/source/common/sound/backend/i_soundinternal.h +++ b/source/common/sound/backend/i_soundinternal.h @@ -22,6 +22,7 @@ enum EChanFlag CHANF_PICKUP = CHANF_MAYBE_LOCAL, + CHANF_NONE = 0, CHANF_IS3D = 1, // internal: Sound is 3D. CHANF_EVICTED = 2, // internal: Sound was evicted. CHANF_FORGETTABLE = 4, // internal: Forget channel data when sound stops. diff --git a/source/common/sound/s_sound.cpp b/source/common/sound/s_sound.cpp index 28fe3a6d0..a0a5627a1 100644 --- a/source/common/sound/s_sound.cpp +++ b/source/common/sound/s_sound.cpp @@ -727,7 +727,8 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) // then set this one up as a link, and don't load the sound again. for (i = 0; i < S_sfx.Size(); i++) { - if (S_sfx[i].data.isValid() && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum) + if (S_sfx[i].data.isValid() && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum && + (!sfx->bLoadRAW || (sfx->RawRate == S_sfx[i].RawRate))) // Raw sounds with different sample rates may not share buffers, even if they use the same source data. { //DPrintf (DMSG_NOTIFY, "Linked %s to %s (%d)\n", sfx->name.GetChars(), S_sfx[i].name.GetChars(), i); sfx->link = i; @@ -803,7 +804,7 @@ void SoundEngine::LoadSound3D(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) { snd = GSnd->LoadSoundBuffered(pBuffer, true); } - else if (sfx->lumpnum >= 0) + else { auto sfxdata = ReadSound(sfx->lumpnum); int size = sfxdata.Size(); @@ -1555,6 +1556,14 @@ int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitc return (int)S_sfx.Size()-1; } +int SoundEngine::AddSfx(sfxinfo_t &sfx) +{ + S_sfx.Push(sfx); + if (sfx.ResourceId >= 0) ResIdMap[sfx.ResourceId] = S_sfx.Size() - 1; + return (int)S_sfx.Size() - 1; +} + + //========================================================================== // // S_FindSoundTentative diff --git a/source/common/sound/s_soundinternal.h b/source/common/sound/s_soundinternal.h index fe8712d36..f3823b5cd 100644 --- a/source/common/sound/s_soundinternal.h +++ b/source/common/sound/s_soundinternal.h @@ -95,8 +95,8 @@ enum ROLLOFF_Custom // Lookup volume from SNDCURVE }; -int S_FindSound(const char *logicalname); -int S_FindSoundByResID(int snd_id); +int S_FindSoundByResID(int ndx); +int S_FindSound(const char* name); // An index into the S_sfx[] array. class FSoundID @@ -173,11 +173,8 @@ struct FSoundChan : public FISoundChannel int16_t NearLimit; uint8_t SourceType; float LimitRange; - union - { - const void *Source; - float Point[3]; // Sound is not attached to any source. - }; + const void *Source; + float Point[3]; // Sound is not attached to any source. }; @@ -217,8 +214,7 @@ enum // This cannot be remain as this, but for now it has to suffice. SOURCE_Any = -1, // Input for check functions meaning 'any source' SOURCE_None, // Sound is always on top of the listener. SOURCE_Actor, // Sound is coming from an actor. - SOURCE_Sector, // Sound is coming from a sector. - SOURCE_Polyobj, // Sound is coming from a polyobject. + SOURCE_Ambient, // Sound is coming from a blood ambient definition. SOURCE_Unattached, // Sound is not attached to any particular emitter. }; @@ -383,7 +379,8 @@ public: { for (FSoundChan* chan = Channels; chan; chan = chan->NextChan) { - if (callback(chan)) return true; + int res = callback(chan); + if (res) return res > 0; } return false; } @@ -406,6 +403,7 @@ public: int FindSoundNoHash(const char* logicalname); int FindSoundByLump(int lump); int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2); + int AddSfx(sfxinfo_t &sfx); int FindSoundTentative(const char* name); void CacheRandomSound(sfxinfo_t* sfx); unsigned int GetMSLength(FSoundID sound); @@ -433,4 +431,18 @@ inline void FX_StopAllSounds(void) inline void FX_SetReverb(int strength) { // todo: investigate how this works and set a proper environment. -} \ No newline at end of file +} + +inline void FX_SetReverbDelay(int delay) +{ +} + +inline int S_FindSoundByResID(int ndx) +{ + return soundEngine->FindSoundByResID(ndx); +} + +inline int S_FindSound(const char* name) +{ + return soundEngine->FindSound(name); +} diff --git a/source/common/utility/namedef.h b/source/common/utility/namedef.h index 643d1378a..3f0048f4a 100644 --- a/source/common/utility/namedef.h +++ b/source/common/utility/namedef.h @@ -14,6 +14,10 @@ xx(SEQ) xx(SFX) xx(RAW) xx(MAP) +xx(WAV) +xx(OGG) +xx(FLAC) +xx(VOC) xx(Controlmessage) xx(MainMenu) diff --git a/source/duke3d/src/sounds.cpp b/source/duke3d/src/sounds.cpp index 4f4d2b7c8..3dbda3fde 100644 --- a/source/duke3d/src/sounds.cpp +++ b/source/duke3d/src/sounds.cpp @@ -30,10 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_DUKE_NS -// Coordinate factors to map Build coordinate space to sound system coordinate space. -const float xmul = 1 / 16.f; -const float ymul = -1 / 16.f; -const float zmul = -1 / 256.f; class DukeSoundEngine : public SoundEngine { @@ -211,8 +207,8 @@ static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, if (sndPos) { - FVector3 sndorg = { pos->x * xmul, pos->z * zmul, pos->y * ymul }; - FVector3 campos = { cam->x * xmul, cam->z * zmul, cam->y * ymul }; + FVector3 sndorg = GetSoundPos(pos); + FVector3 campos = GetSoundPos(cam); // Now calculate the virtual position in sound system coordinates. FVector3 sndvec = sndorg - campos; if (orgsndist > 0) @@ -325,7 +321,7 @@ void S_Update(void) { listener.angle = -(float)ca * pi::pi() / 1024; // Build uses a period of 2048. listener.velocity.Zero(); - listener.position = { c->x * xmul, c->z * zmul, c->y * ymul }; + listener.position = GetSoundPos(c); listener.underwater = false; // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. // listenactor->waterlevel == 3; diff --git a/source/rr/src/sounds.cpp b/source/rr/src/sounds.cpp index 2d07b1acd..2362f40ca 100644 --- a/source/rr/src/sounds.cpp +++ b/source/rr/src/sounds.cpp @@ -30,11 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_RR_NS -// Coordinate factors to map Build coordinate space to sound system coordinate space. -const float xmul = 1 / 16.f; -const float ymul = -1 / 16.f; -const float zmul = -1 / 256.f; - class DukeSoundEngine : public SoundEngine { // client specific parts of the sound engine go in this class. @@ -211,8 +206,8 @@ static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, if (sndPos) { - FVector3 sndorg = { pos->x * xmul, pos->z * zmul, pos->y * ymul }; - FVector3 campos = { cam->x * xmul, cam->z * zmul, cam->y * ymul }; + FVector3 sndorg = GetSoundPos(pos); + FVector3 campos = GetSoundPos(cam); // Now calculate the virtual position in sound system coordinates. FVector3 sndvec = sndorg - campos; if (orgsndist > 0) @@ -330,7 +325,7 @@ void S_Update(void) { listener.angle = -(float)ca * pi::pi() / 1024; // Build uses a period of 2048. listener.velocity.Zero(); - listener.position = { c->x * xmul, c->z * zmul, c->y * ymul }; + listener.position = GetSoundPos(c); listener.underwater = false; // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. // listenactor->waterlevel == 3;