mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 03:00:46 +00:00
- 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.
This commit is contained in:
parent
4d5755ca67
commit
706157d623
21 changed files with 353 additions and 713 deletions
|
@ -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)); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
if (soundEngine->IsSourcePlayingSomething(SOURCE_Ambient, pChannel, CHAN_BODY, -1))
|
||||
{
|
||||
if (pChannel->distance > 0)
|
||||
{
|
||||
soundEngine->ChangeSoundVolume(SOURCE_Ambient, pChannel, CHAN_BODY, pChannel->distance / 255.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
// 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;
|
||||
pChannel->soundID = FSoundID(snd);
|
||||
pChannel->check = nSFX;
|
||||
pChannel->distance = 0;
|
||||
nAmbChannels++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<uint8_t> 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<uint8_t> 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;
|
||||
|
||||
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 (gMe && gMe->pSprite) camera = GetSoundPos(&gMe->pSprite->pos);
|
||||
else camera = { 0, 0, 0 }; // don't crash if there is no player.
|
||||
|
||||
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 (vel) vel->Zero();
|
||||
|
||||
int phaseMin = ClipHigh(phaseLeft, phaseRight);
|
||||
lPhase = phaseRight - phaseMin;
|
||||
rPhase = phaseLeft - phaseMin;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
|
||||
DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX");
|
||||
if (!hRes)return;
|
||||
vec3_t xyz = { x, y, z };
|
||||
auto svec = GetSoundPos(&xyz);
|
||||
|
||||
SFX *pEffect = (SFX*)gSoundRes.Load(hRes);
|
||||
hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
|
||||
if (!hRes) return;
|
||||
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
|
||||
|
||||
enum EPlayFlags
|
||||
{
|
||||
pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v1c, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0);
|
||||
pBonkle->at4 = 0;
|
||||
FX_GlobalChannel = 1,
|
||||
FX_SoundMatch = 2,
|
||||
FX_ChannelMatch = 4,
|
||||
};
|
||||
|
||||
void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume)
|
||||
{
|
||||
if (!SoundEnabled() || soundId < 0 || !pSprite) return;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
|
||||
auto svec = GetSoundPos(&pSprite->pos);
|
||||
|
||||
float attenuation;
|
||||
sid = getSfx(sid, attenuation, pitch, volume);
|
||||
|
||||
if (a3 >= 0)
|
||||
{
|
||||
a3++; // This is to make 0 a valid channel value.
|
||||
if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int
|
||||
{
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
})) return;
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!SoundEnabled())
|
||||
return;
|
||||
if (!pSprite)
|
||||
return;
|
||||
if (soundId < 0)
|
||||
return;
|
||||
DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX");
|
||||
if (!hRes)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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))
|
||||
{
|
||||
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 = ((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();
|
||||
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--)
|
||||
|
||||
if (a2 >= 0) a2++;
|
||||
soundEngine->EnumerateChannels([=](FSoundChan* channel)
|
||||
{
|
||||
BONKLE *pBonkle = BonkleCache[i];
|
||||
if (pBonkle->at10 == pSprite && (a2 < 0 || a2 == pBonkle->at14) && (a3 < 0 || a3 == pBonkle->atc))
|
||||
if (channel->SourceType == SOURCE_Actor && channel->Source == pSprite && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || a3 == channel->OrgID))
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
soundEngine->StopChannel(channel);
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "<lumpname>.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 (nChannel >= 7) nChannel = -1;
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
if (snd > 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
auto udata = (int*)soundEngine->GetUserData(snd);
|
||||
if (udata) nVolume = udata[2];
|
||||
else nVolume = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
pChannel->at0 = FX_PlayRaw(pData, nSize, sndGetRate(pEffect->format), 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0);
|
||||
pChannel->at4 &= ~1;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,12 +173,9 @@ 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.
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// sound channels
|
||||
|
@ -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);
|
||||
|
@ -434,3 +432,17 @@ inline void FX_SetReverb(int strength)
|
|||
{
|
||||
// todo: investigate how this works and set a proper environment.
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@ xx(SEQ)
|
|||
xx(SFX)
|
||||
xx(RAW)
|
||||
xx(MAP)
|
||||
xx(WAV)
|
||||
xx(OGG)
|
||||
xx(FLAC)
|
||||
xx(VOC)
|
||||
xx(Controlmessage)
|
||||
|
||||
xx(MainMenu)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue