mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-26 03:30:46 +00:00
693095bffb
The idea here is to completely merge the resource management into the file system so that Blood's DICTNODE is merely an alias to the internal FResourceLump. A two-tiered resource system is not something I consider worthwile, it made sense to get around Builds crappy cache but in the long term this is not a good solution for a multi-game port to have a resource management system in the backend and another one put over it in the front end, both with their own caching logic that might interfere with each other. Better merge it into one that can handle everything.
531 lines
16 KiB
C++
531 lines
16 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
Copyright (C) 2019 Nuke.YKT
|
|
|
|
This file is part of NBlood.
|
|
|
|
NBlood is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
#include <string.h>
|
|
#include "build.h"
|
|
#include "compat.h"
|
|
#include "common_game.h"
|
|
#include "fx_man.h"
|
|
|
|
#include "config.h"
|
|
#include "gameutil.h"
|
|
#include "player.h"
|
|
#include "resource.h"
|
|
#include "sfx.h"
|
|
#include "sound.h"
|
|
#include "trig.h"
|
|
|
|
BEGIN_BLD_NS
|
|
|
|
POINT2D earL, earR, earL0, earR0; // Ear position
|
|
VECTOR2D earVL, earVR; // Ear velocity ?
|
|
int lPhase, rPhase, lVol, rVol, lPitch, rPitch;
|
|
|
|
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;
|
|
};
|
|
|
|
BONKLE Bonkle[256];
|
|
BONKLE *BonkleCache[256];
|
|
|
|
int nBonkles;
|
|
|
|
void sfxInit(void)
|
|
{
|
|
for (int i = 0; i < 256; i++)
|
|
BonkleCache[i] = &Bonkle[i];
|
|
nBonkles = 0;
|
|
}
|
|
|
|
void sfxTerm()
|
|
{
|
|
}
|
|
|
|
int Vol3d(int angle, int dist)
|
|
{
|
|
return dist - mulscale16(dist, 0x2000 - mulscale30(0x2000, Cos(angle)));
|
|
}
|
|
|
|
void Calc3DValues(BONKLE *pBonkle)
|
|
{
|
|
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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
int phaseMin = ClipHigh(phaseLeft, phaseRight);
|
|
lPhase = phaseRight - phaseMin;
|
|
rPhase = phaseLeft - phaseMin;
|
|
}
|
|
|
|
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;
|
|
|
|
SFX *pEffect = (SFX*)gSoundRes.Load(hRes);
|
|
hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
|
|
if (!hRes) return;
|
|
|
|
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)
|
|
{
|
|
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();
|
|
}
|
|
|
|
|
|
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 (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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sfxKillAllSounds(void)
|
|
{
|
|
for (int i = nBonkles - 1; i >= 0; i--)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
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_SetReverbDelay(10);
|
|
}
|
|
else
|
|
FX_SetReverb(0);
|
|
}
|
|
|
|
void sfxSetReverb2(bool toggle)
|
|
{
|
|
if (toggle)
|
|
{
|
|
FX_SetReverb(128);
|
|
FX_SetReverbDelay(20);
|
|
}
|
|
else
|
|
FX_SetReverb(0);
|
|
}
|
|
|
|
END_BLD_NS
|