raze/source/exhumed/src/sound.cpp

1199 lines
27 KiB
C++
Raw Normal View History

//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT, sirlemonhead
This file is part of PCExhumed.
PCExhumed 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"
2019-09-18 16:11:06 +00:00
#include "compat.h"
#include "baselayer.h"
#include "renderlayer.h" // for win_gethwnd()
2019-09-18 16:11:06 +00:00
#include "build.h"
#include "cache1d.h"
#include "fx_man.h"
#include "keyboard.h"
#include "control.h"
2019-09-18 16:11:06 +00:00
#include "engine.h"
#include "exhumed.h"
#include "config.h"
#include "sound.h"
#include "init.h"
2019-09-18 16:11:06 +00:00
#include "object.h"
#include "player.h"
#include "random.h"
#include "snake.h"
#include "trigdat.h"
#include "sequence.h"
BEGIN_PS_NS
#if 0
extern "C" {
#include "usrhooks.h"
#include "music.h"
#include "multivoc.h"
#include "fx_man.h"
#include "midi.h"
#include "mpu401.h"
}
#endif
short gMusicVolume = 200;
short gFXVolume = 200;
short nSoundsPlaying = 0;
short nAmbientChannel = -1;
short nStopSound;
short nStoneSound;
short nSwitchSound;
short nLocalEyeSect;
short nElevSound;
short nCreepyTimer;
2019-09-18 16:11:06 +00:00
const char *SoundFiles[kMaxSoundFiles] =
{
"spl_big",
"spl_smal",
"bubble_l",
"grn_drop",
"p_click",
"grn_roll",
"cosprite",
"m_chant0",
"anu_icu",
"item_reg",
"item_spe", // 10
"item_key",
"torch_on", // 12
"jon_bnst",
"jon_gasp",
"jon_land",
"jon_gags",
"jon_fall",
"jon_drwn",
"jon_air1",
"jon_glp1", // 20
"jon_bbwl",
"jon_pois",
"amb_ston",
"cat_icu",
"bubble_h",
"set_land",
"jon_hlnd",
"jon_laf2",
"spi_jump",
"jon_scub", // 30
"item_use",
"tr_arrow",
"swi_foot",
"swi_ston",
"swi_wtr1",
"tr_fire",
"m_skull5",
"spi_atak",
"anu_hit",
"fishdies", // 40
"scrp_icu",
"jon_wade",
"amb_watr",
"tele_1",
"wasp_stg",
"res",
"drum4",
"rex_icu",
"m_hits_u",
"q_tail", // 50
"vatr_mov",
"jon_hit3",
"jon_t_2", // 53
"jon_t_1",
"jon_t_5",
"jon_t_6",
"jon_t_8",
"jon_t_4",
"rasprit1",
"jon_fdie", // 60
"wijaf1",
"ship_1",
"saw_on",
"ra_on",
"amb_ston", // 65
"vatr_stp", // 66
"mana1",
"mana2",
"ammo",
"pot_pc1", // 70?
"pot_pc2",
"weapon",
"alarm",
"tick1",
"scrp_zap", // 75
"jon_t_3",
"jon_laf1",
"blasted",
"jon_air2" // 79
};
short StaticSound[kMaxSoundFiles];
// TODO - temp location. Needs to exist within config file
//
// Sound variables
//
//int FXDevice;
//int MusicDevice;
//int FXVolume;
//int MusicVolume;
//int SoundToggle;
//int MusicToggle;
//int VoiceToggle;
//int AmbienceToggle;
//fx_blaster_config BlasterConfig;
//int NumVoices;
//int NumChannels;
//int NumBits;
//int MixRate;
//int32 MidiPort;
//int ReverseStereo;
int nNextFreq;
int nTotalSoundBytes;
int nSoundCount;
short nSwirlyFrames;
short nDistTable[256];
struct ActiveSound
{
/*
short _0
short _2
short _4
short _6
byte _7
short _10
short _12
int _14
int _18
int _22;
int _26
int _30; // x val
int _34; // y val
int _38; // z val
short _42
short _44
*/
2019-09-18 16:11:06 +00:00
short f_0;
short f_2;
short f_4;
short f_6;
short f_8;
short f_a;
short f_c;
int f_e;
int f_12;
int f_16;
int f_1a;
int f_1e;
int f_22;
int f_26;
short f_2a;
short f_2c;
};
2019-09-18 16:11:06 +00:00
ActiveSound sActiveSound[kMaxSounds];
#if 0
2019-09-18 16:11:06 +00:00
int AIL_allocate_sample_handle(int);
int AIL_allocate_sequence_handle(int);
void AIL_startup(void);
void AIL_set_preference(int, int);
int AIL_install_DIG_INI(void);
int AIL_install_MDI_INI(void);
void AIL_shutdown(void);
void AIL_end_sequence(int);
void AIL_set_sequence_volume(int, int, int);
void AIL_init_sequence(int, char*, int);
void AIL_start_sequence(int);
void AIL_set_sequence_loop_count(int, int);
void AIL_set_sequence_volume(int, int, int);
void AIL_set_sample_playback_rate(int, int);
void AIL_end_sample(int);
int AIL_sample_status(int);
void AIL_set_sample_volume(int, int);
void AIL_set_sample_pan(int, int);
void AIL_init_sample(int);
void AIL_set_sample_file(int, char*, int);
void AIL_start_sample(int);
void AIL_set_sample_loop_count(int, int);
int AIL_sample_playback_rate(int);
char AIL_error[256];
#endif
2019-09-18 16:11:06 +00:00
char pMusicBuf[45000];
char szSoundName[kMaxSounds][kMaxSoundNameLen];
char *SoundBuf[kMaxSounds];
int SoundLen[kMaxSounds];
2019-09-18 16:11:06 +00:00
char SoundLock[kMaxSounds];
extern char message_text[80];
extern short message_timer;
int S, dig, mdi, handle;
int nActiveSounds;
short nLocalSectFlags;
short nLocalChan;
uint8_t nPanTable[] = {
0, 2, 4, 6, 8, 10, 12, 14,
16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46,
48, 50, 52, 54, 56, 58, 60, 62,
64, 66, 68, 70, 72, 74, 76, 78,
80, 82, 84, 86, 88, 90, 92, 94,
96, 98, 100, 102, 104, 106, 108, 110,
112, 114, 116, 118, 120, 122, 124, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128
};
void CalcASSPan(int nPan, int nVolume, int *pLeft, int *pRight)
{
if (nPan < 0)
nPan = 0;
else if (nPan > 127)
nPan = 127;
if (nVolume < 0)
nVolume = 0;
else if (nVolume > 127)
nVolume = 127;
2019-09-21 11:02:45 +00:00
*pLeft = mulscale6(nPanTable[nPan], nVolume);
*pRight = mulscale6(nPanTable[127-nPan], nVolume);
}
void ASSCallback(intptr_t num)
2019-09-21 11:02:45 +00:00
{
// TODO: add mutex?
2019-11-21 23:17:59 +00:00
if ((int32_t)num == -1)
2019-09-21 11:02:45 +00:00
handle = -1;
2019-11-21 23:17:59 +00:00
else if ((int32_t)num >= 0 && (int32_t)num < kMaxActiveSounds)
2019-09-21 11:02:45 +00:00
sActiveSound[num].f_e = -1;
}
2019-09-18 16:11:06 +00:00
void CreateDistTable(void)
{
int eax = 260;
for (int i = 0; i < 256; i++)
{
2019-09-18 16:11:06 +00:00
if (eax > 65280)
{
2019-09-18 16:11:06 +00:00
nDistTable[i] = 255;
}
else
{
2019-09-18 16:11:06 +00:00
nDistTable[i] = eax >> 8;
eax = (eax * eax) >> 8;
}
}
}
2019-09-18 16:11:06 +00:00
void InitSoundInfo(void)
{
2019-09-18 16:11:06 +00:00
int i;
memset(sActiveSound, 255, sizeof(sActiveSound));
for (i = 0; i < kMaxSounds; i++)
{
2019-09-18 16:11:06 +00:00
sActiveSound[i].f_2c = 0;
sActiveSound[i].f_e = -1;
}
2019-09-18 16:11:06 +00:00
nActiveSounds = i;
handle = -1;
}
2019-09-18 16:11:06 +00:00
void InitFX(void)
{
#ifdef MIXERTYPEWIN
void* initdata = (void*)win_gethwnd(); // used for DirectSound
#else
void* initdata = NULL;
#endif
dig = 0;
if (!SoundEnabled())
2019-09-18 16:11:06 +00:00
return;
if (FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata) != FX_Ok)
{
2019-11-24 09:03:19 +00:00
Printf("Error initializing sound card!\n");
2019-08-27 06:08:18 +00:00
initprintf("Error initializing sound card!\n");
2019-11-24 09:03:19 +00:00
Printf("ERROR: %s\n", FX_ErrorString(FX_Error));
return;
}
dig = 1;
2019-09-21 11:02:45 +00:00
FX_SetCallBack(ASSCallback);
CreateDistTable();
InitSoundInfo();
nTotalSoundBytes = 0;
nSoundCount = 0;
nCreepyTimer = kCreepyCount;
#if 0
int status = FX_Init(FXDevice, NumVoices, NumChannels, NumBits, MixRate);
if (status == FX_Ok)
{
FX_SetVolume(FXVolume);
if (ReverseStereo == 1) {
FX_SetReverseStereo(!FX_GetReverseStereo());
}
}
if (status != FX_Ok) {
// Error("Sound startup error: %s", FX_ErrorString(FX_Error));
}
status = FX_SetCallBack(testcallback);
if (status != FX_Ok) {
// Error("Sound startup error: %s", FX_ErrorString(FX_Error));
}
#endif
}
void UnInitFX()
{
FX_Shutdown();
2019-09-18 16:11:06 +00:00
}
void InitMusic()
{
}
2019-09-18 16:11:06 +00:00
void UnInitMusic()
{
}
2019-09-18 16:11:06 +00:00
void FadeSong()
{
}
int LoadSong(const char *song)
{
UNREFERENCED_PARAMETER(song);
return 0;
}
int LoadSound(const char *sound)
{
if (!dig)
//return 0;
return -1;
int i;
for (i = 0; i < nSoundCount; i++)
{
2019-11-13 20:06:48 +00:00
if (!Bstrncasecmp(szSoundName[i], sound, kMaxSoundNameLen))
2019-09-18 16:11:06 +00:00
return i;
}
if (i >= kMaxSounds)
2019-11-24 09:03:19 +00:00
I_Error("Too many sounds being loaded... increase array size\n");
2019-09-18 16:11:06 +00:00
strncpy(szSoundName[i], sound, kMaxSoundNameLen);
char buffer[32];
buffer[0] = 0;
strncat(buffer, szSoundName[i], kMaxSoundNameLen);
char *pzTail = buffer+strlen(buffer);
while (*pzTail == ' ' && pzTail != buffer)
*pzTail-- = '\0';
strcat(buffer, ".voc");
auto hVoc = kopenFileReader(buffer, 0);
2019-09-18 16:11:06 +00:00
if (!hVoc.isOpen())
2019-09-18 16:11:06 +00:00
{
int nSize = hVoc.GetLength();
//SoundLock[i] = 255; // crap we don't need.
SoundLen[i] = nSize;
cacheAllocateBlock((intptr_t*)&SoundBuf[i], nSize, nullptr);
2019-09-18 16:11:06 +00:00
if (!SoundBuf[i])
2019-11-24 09:03:19 +00:00
I_Error("Error allocating buf '%s' to %lld (size=%ld)!\n", buffer, (intptr_t)&SoundBuf[i], nSize);
2019-09-18 16:11:06 +00:00
if (hVoc.Read(SoundBuf[i], nSize) != nSize)
Printf("Error reading '%s'!\n", buffer);
}
else
{
Printf("Unable to open sound '%s'!\n", buffer);
2019-09-18 16:11:06 +00:00
SoundBuf[i] = NULL;
SoundLen[i] = 0;
2019-09-18 16:11:06 +00:00
//return hVoc;
return -1;
}
nSoundCount++;
return i;
}
#if 0
void FreeSounds(void)
{
int i;
for (i = 0; i < nSoundCount; i++)
free(SoundBuf[i]);
}
#endif
void LoadFX(void)
{
if (!dig)
return;
2019-09-18 16:11:06 +00:00
int i;
for (i = 0; i < kMaxSoundFiles; i++)
{
StaticSound[i] = LoadSound(SoundFiles[i]);
if (StaticSound[i] < 0)
2019-11-24 09:03:19 +00:00
I_Error("error loading static sound #%d ('%.8s')\n", i, SoundFiles[i]);
}
}
2019-09-18 16:11:06 +00:00
void GetSpriteSoundPitch(short nSector, int *pVolume, int *pPitch)
{
2019-09-18 16:11:06 +00:00
if (nSector < 0)
return;
if ((SectFlag[nSector]^nLocalSectFlags) & kSectUnderwater)
{
*pVolume >>= 1;
*pPitch -= 1200;
}
}
2019-09-18 16:11:06 +00:00
void BendAmbientSound(void)
{
if (nAmbientChannel < 0)
return;
ActiveSound *pASound = &sActiveSound[nAmbientChannel];
//AIL_set_sample_playback_rate(pASound->f_e, nDronePitch+11000);
if (pASound->f_e > -1)
FX_SetFrequency(pASound->f_e, nDronePitch+11000);
}
2019-09-18 16:11:06 +00:00
short PlayFXAtXYZ(unsigned short ax, int x, int y, int z, int nSector);
2019-09-18 16:11:06 +00:00
void CheckAmbience(short nSector)
{
2019-09-18 16:11:06 +00:00
if (SectSound[nSector] != -1)
{
short nSector2 = SectSoundSect[nSector];
walltype *pWall = &wall[sector[nSector2].wallptr];
if (nAmbientChannel < 0)
{
PlayFXAtXYZ(SectSound[nSector]|0x4000, pWall->x, pWall->y, sector[nSector2].floorz, nSector);
return;
}
ActiveSound *pASound = &sActiveSound[nAmbientChannel];
if (nSector == nSector2)
{
spritetype *pSprite = &sprite[PlayerList[0].nSprite];
pASound->f_1e = pSprite->x;
pASound->f_22 = pSprite->y;
pASound->f_26 = pSprite->z;
}
else
{
pASound->f_1e = pWall->x;
pASound->f_22 = pWall->y;
pASound->f_26 = sector[nSector2].floorz;
}
}
else if (nAmbientChannel != -1)
{
if (sActiveSound[nAmbientChannel].f_e > -1)
FX_StopSound(sActiveSound[nAmbientChannel].f_e);
sActiveSound[nAmbientChannel].f_e = -1;
2019-09-18 16:11:06 +00:00
nAmbientChannel = -1;
}
}
2019-09-18 16:11:06 +00:00
int GetDistFromDXDY(int dx, int dy)
{
int nSqr = dx*dx+dy*dy;
return (nSqr>>3)-(nSqr>>5);
}
#if 0
2019-09-18 16:11:06 +00:00
void MuteSounds(void)
{
if (!dig)
return;
int i;
ActiveSound *pASound = sActiveSound;
pASound++;
for (i = 1; i < kMaxActiveSounds; i++, pASound++)
{
if (pASound->f_e > -1 && FX_SoundActive(pASound->f_e))
FX_SetPan(pASound->f_e, 0, 0, 0);
2019-09-18 16:11:06 +00:00
}
}
2019-09-18 16:11:06 +00:00
void SetChanPan(int nSound, int nPan)
{
2019-09-18 16:11:06 +00:00
AIL_set_sample_pan(sActiveSound[nSound].f_e, nPan);
}
#endif
2019-09-18 16:11:06 +00:00
void SoundBigEntrance(void)
{
StopAllSounds();
ActiveSound *pASound = sActiveSound;
for (int i = 0; i < 4; i++, pASound++)
{
#if 0
2019-09-18 16:11:06 +00:00
AIL_init_sample(pASound->f_e);
short nPitch = i*512-1200;
pASound->f_16 = nPitch;
AIL_set_sample_playback_rate(pASound->f_e, 11000+nPitch);
AIL_set_sample_file(pASound->f_e, SoundBuf[12], -1);
AIL_set_sample_volume(pASound->f_e, 200);
AIL_set_sample_pan(pASound->f_e, 63-(i&1)*127);
AIL_start_sample(pASound->f_e);
#endif
short nPitch = i*512-1200;
pASound->f_16 = nPitch;
int nLeft, nRight;
CalcASSPan(63-(i&1)*127, 200, &nLeft, &nRight);
if (pASound->f_e >= 0)
FX_StopSound(pASound->f_e);
pASound->f_e = FX_Play(SoundBuf[kSoundTorchOn], SoundLen[kSoundTorchOn], -1, 0, 0, max(nLeft, nRight), nLeft, nRight, 0, fix16_one, i);
if (pASound->f_e > -1)
FX_SetFrequency(pASound->f_e, 11000+nPitch);
2019-09-18 16:11:06 +00:00
}
}
2019-09-18 16:11:06 +00:00
void StartSwirly(int nActiveSound)
{
2019-09-18 16:11:06 +00:00
ActiveSound *pASound = &sActiveSound[nActiveSound];
pASound->f_6 &= 0x7ff;
//AIL_init_sample(pASound->f_e);
2019-09-18 16:11:06 +00:00
short nPitch = nNextFreq-RandomSize(9);
pASound->f_16 = nPitch;
nNextFreq = 25000-RandomSize(10)*6;
if (nNextFreq > 32000)
nNextFreq = 32000;
//AIL_set_sample_file(pASound->f_e, SoundBuf[StaticSound[kSound67]], -1);
2019-09-18 16:11:06 +00:00
int nVolume = nSwirlyFrames+1;
if (nVolume >= 220)
nVolume = 220;
pASound->f_4 = nVolume;
int nPan = pASound->f_6&127;
int nLeft, nRight;
CalcASSPan(nPan, nVolume, &nLeft, &nRight);
if (pASound->f_e >= 0)
FX_StopSound(pASound->f_e);
pASound->f_e = FX_Play(SoundBuf[StaticSound[kSound67]], SoundLen[StaticSound[kSound67]], -1, 0, 0, max(nLeft, nRight), nLeft, nRight, 0, fix16_one, nActiveSound);
if (pASound->f_e > -1)
FX_SetFrequency(pASound->f_e, nPitch);
#if 0
2019-09-18 16:11:06 +00:00
AIL_set_sample_volume(pASound->f_e, nVolume);
AIL_set_sample_playback_rate(pASound->f_e, nPitch);
AIL_set_sample_loop_count(pASound->f_e, 1);
AIL_set_sample_pan(pASound->f_e, pASound->f_6);
AIL_start_sample(pASound->f_e);
#endif
2019-09-18 16:11:06 +00:00
}
void StartSwirlies()
{
StopAllSounds();
2019-09-18 16:11:06 +00:00
nNextFreq = 19000;
nSwirlyFrames = 0;
for (int i = 1; i <= 4; i++)
StartSwirly(i);
}
2019-09-18 16:11:06 +00:00
void UpdateSwirlies()
{
2019-09-18 16:11:06 +00:00
nSwirlyFrames++;
ActiveSound* pASound = sActiveSound;
pASound++;
for (int i = 1; i <= 4; i++, pASound++)
{
if (pASound->f_e < 0 || !FX_SoundActive(pASound->f_e))
2019-09-18 16:11:06 +00:00
StartSwirly(i);
if (pASound->f_e >= 0)
{
int nLeft, nRight;
int nPan = 64+(Sin((int)totalclock<<(4+i))>>8);
CalcASSPan(nPan, pASound->f_4, &nLeft, &nRight);
MV_SetPan(pASound->f_e, max(nLeft, nRight), nLeft, nRight);
}
//AIL_set_sample_pan(pASound->f_e, 64+(Sin((int)totalclock<<(4+i))>>8));
2019-09-18 16:11:06 +00:00
}
}
2019-09-18 16:11:06 +00:00
void UpdateSounds()
{
2019-09-18 16:11:06 +00:00
if (!dig || nFreeze)
return;
nLocalSectFlags = SectFlag[nPlayerViewSect[nLocalPlayer]];
spritetype *pSprite = &sprite[PlayerList[nLocalPlayer].nSprite];
int x, y;
short ang;
if (nSnakeCam > -1)
{
Snake *pSnake = &SnakeList[nSnakeCam];
spritetype *pSnakeSprite = &sprite[pSnake->nSprites[0]];
x = pSnakeSprite->x;
y = pSnakeSprite->y;
ang = pSnakeSprite->ang;
}
else
{
x = initx;
y = inity;
ang = inita;
}
ActiveSound* pASound = sActiveSound;
pASound++;
for (int i = 1; i < kMaxActiveSounds; i++, pASound++)
{
if (pASound->f_e >= 0 && FX_SoundActive(pASound->f_e))
2019-09-18 16:11:06 +00:00
{
short nSoundSprite = pASound->f_0;
int dx, dy;
if (nSoundSprite < 0)
{
dx = x-pASound->f_1e;
dy = y-pASound->f_22;
}
else
{
2019-09-19 13:38:28 +00:00
dx = x-sprite[nSoundSprite].x;
dy = y-sprite[nSoundSprite].y;
2019-09-18 16:11:06 +00:00
}
dx >>= 8;
dy >>= 8;
short nSoundAng;
if ((dx|dy) == 0)
nSoundAng = 0;
else
nSoundAng = AngleDelta(GetMyAngle(dx, dy), ang, 1024);
int nDist = GetDistFromDXDY(dx, dy);
if (nDist >= 255)
{
FX_StopSound(pASound->f_e);
2019-09-18 16:11:06 +00:00
if (pASound->f_a&0x4000)
nAmbientChannel = -1;
return;
}
int nVolume = gFXVolume+10-(Sin(nDist<<1)>>6);
if (nVolume < 0)
nVolume = 0;
if (nVolume > 255)
nVolume = 255;
2019-09-18 16:11:06 +00:00
int nPitch = pASound->f_16;
short nSoundSect;
if (nSoundSprite >= 0)
{
if (nSoundSprite == nLocalSpr)
nSoundSect = nPlayerViewSect[nLocalPlayer];
else
nSoundSect = sprite[nSoundSprite].sectnum;
}
else
nSoundSect = pASound->f_2a;
GetSpriteSoundPitch(nSoundSect, &nVolume, &nPitch);
if (pASound->f_12 != nPitch)
pASound->f_12 = nPitch;
if (nVolume != pASound->f_4 || nSoundAng != pASound->f_6)
{
int nLeft, nRight;
2019-09-21 11:02:45 +00:00
int nPan = 63+(Sin(nSoundAng+1023)>>8);
CalcASSPan(nPan, nVolume, &nLeft, &nRight);
FX_SetPan(pASound->f_e, nVolume, nLeft, nRight);
2019-09-18 16:11:06 +00:00
if (nPitch < 0)
FX_SetFrequency(pASound->f_e, 7000);
2019-09-18 16:11:06 +00:00
pASound->f_4 = nVolume;
pASound->f_6 = nSoundAng;
}
}
}
}
2019-09-18 16:11:06 +00:00
void UpdateCreepySounds()
{
if (levelnum == 20 || nFreeze)
return;
spritetype *pSprite = &sprite[PlayerList[nLocalPlayer].nSprite];
nCreepyTimer--;
if (nCreepyTimer <= 0)
2019-09-18 16:11:06 +00:00
{
if (nCreaturesLeft > 0 && !(SectFlag[nPlayerViewSect[nLocalPlayer]]&0x2000))
2019-09-18 16:11:06 +00:00
{
int vsi = seq_GetFrameSound(SeqOffsets[kSeqCreepy], totalmoves%SeqSize[SeqOffsets[kSeqCreepy]]);
if (vsi >= 0 && (vsi&0x1ff) < kMaxSounds)
2019-09-18 16:11:06 +00:00
{
int vdx = (totalmoves+32)&31;
if (totalmoves & 1)
vdx = -vdx;
int vax = (totalmoves+32)&63;
if (totalmoves & 2)
vax = -vax;
PlayFXAtXYZ(vsi, pSprite->x+vdx, pSprite->y+vax, pSprite->z, pSprite->sectnum);
2019-09-18 16:11:06 +00:00
}
}
nCreepyTimer = kCreepyCount;
2019-09-18 16:11:06 +00:00
}
}
2019-09-18 16:11:06 +00:00
int LocalSoundPlaying(void)
{
2019-09-18 16:11:06 +00:00
if (!dig)
return 0;
return sActiveSound[nLocalChan].f_e >= 0 && FX_SoundActive(sActiveSound[nLocalChan].f_e);
}
2019-09-18 16:11:06 +00:00
int GetLocalSound(void)
{
2019-09-18 16:11:06 +00:00
if (LocalSoundPlaying() == -1)
return -1;
2019-09-18 16:11:06 +00:00
return sActiveSound[nLocalChan].f_2&0x1ff;
}
2019-09-18 16:11:06 +00:00
void UpdateLocalSound(void)
{
2019-09-18 16:11:06 +00:00
if (!dig)
return;
if (sActiveSound[nLocalChan].f_e >= 0)
FX_SetPan(sActiveSound[nLocalChan].f_e, gFXVolume, gFXVolume, gFXVolume);
}
2019-09-18 16:11:06 +00:00
void StopLocalSound(void)
{
2019-09-18 16:11:06 +00:00
if (!dig)
return;
if (nLocalChan == nAmbientChannel)
nAmbientChannel = -1;
2019-09-18 16:11:06 +00:00
if (LocalSoundPlaying())
FX_StopSound(sActiveSound[nLocalChan].f_e);
}
2019-09-18 16:11:06 +00:00
void SetLocalChan(int nChannel)
{
2019-09-18 16:11:06 +00:00
nLocalChan = nChannel;
}
void PlaySound(int nSound)
{
if (!dig)
return;
if (nSound < 0 || nSound >= kMaxSounds || !SoundBuf[nSound])
{
initprintf("PlaySound: Invalid sound nSound == %i\n", nSound);
return;
}
int bLoop = SoundBuf[nSound][26] == 6;
if (handle >= 0)
FX_StopSound(handle);
handle = FX_Play(SoundBuf[nSound], SoundLen[nSound], bLoop ? 0 : -1, 0, 0, gFXVolume, gFXVolume, gFXVolume, 0, fix16_one, -1);
#if 0
2019-09-18 16:11:06 +00:00
AIL_init_sample(handle);
AIL_set_sample_file(handle, SoundBuf[nSound], -1);
AIL_set_sample_volume(handle, gFXVolume>>1);
if (SoundBuf[nSound][26] == 6)
AIL_set_sample_loop_count(handle, 0);
AIL_start_sample(handle);
#endif
}
void PlayLocalSound(short nSound, short nRate)
{
2019-09-18 16:11:06 +00:00
if (!dig)
return;
if (nSound < 0 || nSound >= kMaxSounds || !SoundBuf[nSound])
{
initprintf("PlayLocalSound: Invalid sound nSound == %i, nRate == %i\n", nSound, nRate);
return;
}
2019-09-18 16:11:06 +00:00
if (nLocalChan == nAmbientChannel)
nAmbientChannel = -1;
int bLoop = SoundBuf[nSound][26] == 6;
2019-09-18 16:11:06 +00:00
ActiveSound* pASound = &sActiveSound[nLocalChan];
if (pASound->f_e >= 0)
FX_StopSound(pASound->f_e);
pASound->f_e = FX_Play(SoundBuf[nSound], SoundLen[nSound], bLoop ? 0 : -1, 0, 0, gFXVolume, gFXVolume, gFXVolume, 0, fix16_one, nLocalChan);
if (nRate)
{
int nFreq = 0;
FX_GetFrequency(pASound->f_e, &nFreq);
FX_SetFrequency(pASound->f_e, nFreq+nRate);
}
#if 0
2019-09-18 16:11:06 +00:00
AIL_init_sample(pASound->f_e);
AIL_set_sample_file(pASound->f_e, SoundBuf[nSound], -1);
AIL_set_sample_volume(pASound->f_e, gFXVolume>>1);
if (nRate)
AIL_set_sample_playback_rate(pASound->f_e, AIL_sample_playback_rate(pASound->f_e)+nRate);
if (SoundBuf[nSound][26] == 6)
AIL_set_sample_loop_count(pASound->f_e, 0);
AIL_start_sample(pASound->f_e);
#endif
2019-09-18 16:11:06 +00:00
pASound->f_2 = nSound;
SetLocalChan(0);
}
2019-09-18 16:11:06 +00:00
void PlayTitleSound(void)
{
2019-09-18 16:11:06 +00:00
PlayLocalSound(StaticSound[kSound10], 0);
}
2019-09-18 16:11:06 +00:00
void PlayLogoSound(void)
{
PlayLocalSound(StaticSound[kSound28], 7000);
}
2019-09-18 16:11:06 +00:00
void PlayGameOverSound(void)
{
PlayLocalSound(StaticSound[kSound28], 0);
}
2019-09-18 16:11:06 +00:00
int soundx, soundy, soundz;
short soundsect;
short PlayFX2(unsigned short nSound, short nSprite)
{
if (!dig)
return -1;
2019-11-21 23:17:59 +00:00
if ((nSound&0x1ff) >= kMaxSounds || !SoundBuf[(nSound&0x1ff)])
{
initprintf("PlayFX2: Invalid sound nSound == %i, nSprite == %i\n", nSound, nSprite);
return -1;
}
2019-09-18 16:11:06 +00:00
nLocalSectFlags = SectFlag[nPlayerViewSect[nLocalPlayer]];
short v1c;
short vcx;
if (nSprite < 0)
{
vcx = 0;
v1c = 0;
}
else
{
v1c = nSprite&0x2000;
vcx = nSprite&0x4000;
nSprite &= 0xfff;
soundx = sprite[nSprite].x;
soundy = sprite[nSprite].y;
soundz = sprite[nSprite].z;
}
int dx, dy;
dx = initx-soundx;
dy = inity-soundy;
dx >>= 8; dy >>= 8;
short nSoundAng;
if ((dx|dy) == 0)
nSoundAng = 0;
else
nSoundAng = AngleDelta(GetMyAngle(dx, dy), inita, 1024);
int nDist = GetDistFromDXDY(dx, dy);
if (nDist >= 255)
{
2019-11-21 23:17:59 +00:00
if ((int16_t)nSound > -1)
2019-09-18 16:11:06 +00:00
StopSpriteSound(nSound);
return -1;
}
int nVolume;
if (!v1c)
{
nVolume = gFXVolume+10-(Sin(nDist<<1)>>6)-10;
if (nVolume <= 0)
{
2019-11-21 23:17:59 +00:00
if ((int16_t)nSound > -1)
2019-09-18 16:11:06 +00:00
StopSpriteSound(nSound);
return -1;
}
if (nVolume > 255)
nVolume = 255;
}
else
nVolume = gFXVolume;
2019-09-18 16:11:06 +00:00
short vc = nSound & (~0x1ff);
short v4 = nSound & 0x2000;
short v8 = nSound & 0x1000;
short v14 = nSound & 0x4000;
2019-09-21 17:03:53 +00:00
short v10 = (nSound&0xe00)>>9;
2019-09-18 16:11:06 +00:00
int v2c = 0x7fffffff;
ActiveSound* v38 = NULL;
ActiveSound* v28 = NULL;
ActiveSound* vdi = NULL;
nSound &= 0x1ff;
short v20;
if (v8 || v14)
v20 = 1000;
else if (nSprite != -1 && vcx)
v20 = 2000;
else
v20 = 0;
ActiveSound* pASound = sActiveSound;
pASound++;
for (int i = 1; i < kMaxActiveSounds; i++, pASound++)
{
if (pASound->f_e < 0 || !FX_SoundActive(pASound->f_e))
2019-09-18 16:11:06 +00:00
vdi = pASound;
else if (v20 >= pASound->f_c)
{
if (v2c > pASound->f_1a && pASound->f_c <= v20)
{
v28 = pASound;
v2c = pASound->f_1a;
}
if (!v8)
{
if (nSound == pASound->f_2)
{
if (v4 == 0 && nSprite == pASound->f_0)
return -1;
if (v20 >= pASound->f_c)
v38 = pASound;
}
else if (nSprite == pASound->f_0)
{
if (v4 || nSound != pASound->f_2)
{
vdi = pASound;
break;
}
}
}
}
}
if (!vdi)
{
if (v38)
vdi = v38;
else if (v28)
vdi = v28;
}
if (vdi->f_e >= 0 && FX_SoundActive(vdi->f_e))
2019-09-18 16:11:06 +00:00
{
FX_StopSound(vdi->f_e);
2019-09-18 16:11:06 +00:00
if (vdi->f_2c == nAmbientChannel)
nAmbientChannel = -1;
}
int nPitch;
if (v10)
2019-09-21 17:03:53 +00:00
nPitch = -(totalmoves&((1<<v10)-1))*16;
2019-09-18 16:11:06 +00:00
else
nPitch = 0;
if (vdi)
{
vdi->f_16 = nPitch;
vdi->f_8 = nVolume;
if (nSprite < 0)
{
vdi->f_1e = soundx;
vdi->f_22 = soundy;
vdi->f_2a = soundsect;
}
GetSpriteSoundPitch(soundsect, &nVolume, &nPitch);
vdi->f_12 = nPitch;
vdi->f_4 = nVolume;
vdi->f_6 = nSoundAng;
vdi->f_0 = nSprite;
vdi->f_2 = nSound;
vdi->f_1a = (int)totalclock;
vdi->f_c = v20;
vdi->f_a = vc;
2019-09-21 11:02:45 +00:00
short nPan = 63+(Sin(nSoundAng+1023)>>8);
int nLeft, nRight;
int bLoop = SoundBuf[nSound][26] == 6;
CalcASSPan(nPan, nVolume>>1, &nLeft, &nRight);
vdi->f_e = FX_Play(SoundBuf[nSound], SoundLen[nSound], bLoop ? 0 : -1, 0, 0, max(nLeft, nRight), nLeft, nRight, 0, fix16_one, vdi-sActiveSound);
2019-09-18 16:11:06 +00:00
if (nPitch)
{
int nFreq = 0;
FX_GetFrequency(vdi->f_e, &nFreq);
FX_SetFrequency(vdi->f_e, nFreq+nPitch);
}
#if 0
2019-09-18 16:11:06 +00:00
AIL_init_sample(vdi->f_e);
AIL_set_sample_file(vdi->f_e, SoundBuf[nSound], -1);
AIL_set_sample_pan(vdi->f_e, nPan);
AIL_set_sample_volume(vdi->f_e, nVolume>>1);
if (SoundBuf[nSound][26] == 6)
AIL_set_sample_loop_count(vdi->f_e, 0);
2019-09-18 16:11:06 +00:00
if (nPitch)
AIL_set_sample_playback_rate(vdi->f_e, AIL_sample_playback_rate(vdi->f_e)+nPitch);
2019-09-18 16:11:06 +00:00
AIL_start_sample(vdi->f_e);
#endif
2019-09-18 16:11:06 +00:00
if (v14)
nAmbientChannel = v14;
// Nuke: added nSprite >= 0 check
if (nSprite != nLocalSpr && nSprite >= 0 && (sprite[nSprite].cstat&257))
nCreepyTimer = kCreepyCount;
2019-09-18 16:11:06 +00:00
return v14;
}
return -1;
}
2019-09-18 16:11:06 +00:00
short PlayFXAtXYZ(unsigned short ax, int x, int y, int z, int nSector)
{
2019-09-18 16:11:06 +00:00
soundx = x;
soundy = y;
soundz = z;
soundsect = nSector&0x3fff;
short nSnd = PlayFX2(ax, -1);
if (nSnd > -1 && (nSector&0x4000))
sActiveSound[nSnd].f_c = 2000;
return nSnd;
}
2019-09-18 16:11:06 +00:00
short D3PlayFX(unsigned short nSound, short nVal)
{
return PlayFX2(nSound, nVal);
}
2019-09-18 16:11:06 +00:00
void StopSpriteSound(short nSprite)
{
if (!dig)
return;
for (int i = 0; i < kMaxActiveSounds; i++)
{
if (sActiveSound[i].f_e >= 0 && FX_SoundActive(sActiveSound[i].f_e) && nSprite == sActiveSound[i].f_0)
2019-09-18 16:11:06 +00:00
{
FX_StopSound(sActiveSound[i].f_e);
2019-09-18 16:11:06 +00:00
return;
}
}
}
void StopAllSounds(void)
{
if (!dig)
return;
for (int i = 0; i < kMaxActiveSounds; i++)
{
if (sActiveSound[i].f_e >= 0)
FX_StopSound(sActiveSound[i].f_e);
// AIL_end_sample(sActiveSound[i].f_e);
2019-09-18 16:11:06 +00:00
}
nSoundsPlaying = 0;
nAmbientChannel = -1;
}
#if 0
void Lock(void)
{
AIL_lock();
}
void Unlock(void)
{
AIL_unlock();
}
#endif
END_PS_NS