2006-04-13 20:47:06 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
2016-02-07 02:38:03 +00:00
|
|
|
Copyright (C) 2016 EDuke32 developers and contributors
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-05-25 10:56:00 +00:00
|
|
|
This file is part of EDuke32.
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
EDuke32 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
|
2014-07-20 08:55:56 +00:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2006-04-13 20:47:06 +00:00
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
2019-09-21 18:59:54 +00:00
|
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
|
2017-02-25 08:15:45 +00:00
|
|
|
#include "compat.h"
|
2012-11-05 02:49:08 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
#include "duke3d.h"
|
2016-02-07 02:38:03 +00:00
|
|
|
#include "renderlayer.h" // for win_gethwnd()
|
2019-10-19 23:48:20 +00:00
|
|
|
#include "al_midi.h"
|
2018-04-21 06:04:56 +00:00
|
|
|
#include <atomic>
|
2010-07-19 15:14:00 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
#include "vfs.h"
|
|
|
|
|
2019-09-21 20:53:00 +00:00
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
|
|
|
|
2019-01-12 00:21:58 +00:00
|
|
|
#define DQSIZE 256
|
2015-02-11 05:22:00 +00:00
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
int32_t g_numEnvSoundsPlaying, g_highestSoundIdx;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
static char *MusicPtr;
|
|
|
|
|
|
|
|
static int32_t MusicIsWaveform;
|
2009-07-27 05:33:12 +00:00
|
|
|
static int32_t MusicVoice = -1;
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
static bool MusicPaused;
|
|
|
|
static bool SoundPaused;
|
|
|
|
|
2019-08-09 09:28:42 +00:00
|
|
|
static std::atomic<uint32_t> dnum, dq[DQSIZE];
|
|
|
|
static mutex_t m_callback;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2019-08-07 22:44:20 +00:00
|
|
|
static inline void S_SetProperties(assvoice_t *snd, int const owner, int const voice, int const dist, int const clock)
|
|
|
|
{
|
|
|
|
snd->owner = owner;
|
|
|
|
snd->id = voice;
|
|
|
|
snd->dist = dist;
|
|
|
|
snd->clock = clock;
|
|
|
|
}
|
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_SoundStartup(void)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2019-10-19 23:47:54 +00:00
|
|
|
#ifdef _WIN32
|
2018-10-16 06:08:50 +00:00
|
|
|
void *initdata = (void *) win_gethwnd(); // used for DirectSound
|
|
|
|
#else
|
|
|
|
void *initdata = NULL;
|
2009-07-27 05:33:12 +00:00
|
|
|
#endif
|
2009-07-09 02:29:48 +00:00
|
|
|
|
Patch from Hendricks266 and whatever changes happened to be in my tree. I hope they work ;)
"The most noticeable change is the addition of the "includedefault" CON and DEF command, which will attempt to include eduke.con (or nam.con, or ww2gi.con), then game.con, or duke3d.def, or nam.def, or ww2gi.def. This is useful for TCs like my add-ons, where for my pseudo-mutators I currently say "include EDUKE.CON", but I also have to juggle this terrible order of paths, so that I can have an EDUKE.CON file in my HRP which says "include GAME.CON" to allow the mainline game to actually run, but also allow DukePlus to load its EDUKE.CON file (since it uses that and not an -x switch), and also allow any custom EDUKE.CON files in the root to be used."
git-svn-id: https://svn.eduke32.com/eduke32@1909 1a8010ca-5511-0410-912e-c29ae57300e0
2011-06-19 00:11:52 +00:00
|
|
|
initprintf("Initializing sound... ");
|
2009-08-06 10:12:13 +00:00
|
|
|
|
2019-10-24 18:28:46 +00:00
|
|
|
int status = FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata);
|
2019-10-24 05:47:24 +00:00
|
|
|
if (status != FX_Ok)
|
2006-11-15 01:16:55 +00:00
|
|
|
{
|
2019-10-24 05:47:24 +00:00
|
|
|
initprintf("failed! %s\n", FX_ErrorString(status));
|
2011-01-23 04:59:04 +00:00
|
|
|
return;
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2019-10-22 15:47:24 +00:00
|
|
|
initprintf("%d voices, %d channels, 16-bit %d Hz\n", *snd_numvoices, *snd_numchannels, *snd_mixrate);
|
Patch from Hendricks266 and whatever changes happened to be in my tree. I hope they work ;)
"The most noticeable change is the addition of the "includedefault" CON and DEF command, which will attempt to include eduke.con (or nam.con, or ww2gi.con), then game.con, or duke3d.def, or nam.def, or ww2gi.def. This is useful for TCs like my add-ons, where for my pseudo-mutators I currently say "include EDUKE.CON", but I also have to juggle this terrible order of paths, so that I can have an EDUKE.CON file in my HRP which says "include GAME.CON" to allow the mainline game to actually run, but also allow DukePlus to load its EDUKE.CON file (since it uses that and not an -x switch), and also allow any custom EDUKE.CON files in the root to be used."
git-svn-id: https://svn.eduke32.com/eduke32@1909 1a8010ca-5511-0410-912e-c29ae57300e0
2011-06-19 00:11:52 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
for (int i = 0; i <= g_highestSoundIdx; ++i)
|
2010-08-02 08:13:51 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto & voice : g_sounds[i].voices)
|
2010-08-02 08:13:51 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
g_sounds[i].num = 0;
|
2019-08-07 22:44:20 +00:00
|
|
|
S_SetProperties(&voice, -1, 0, UINT16_MAX, 0);
|
2010-08-02 08:13:51 +00:00
|
|
|
}
|
|
|
|
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2010-08-02 08:13:51 +00:00
|
|
|
g_soundlocks[i] = 199;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2010-08-02 08:13:51 +00:00
|
|
|
}
|
|
|
|
|
2018-11-18 18:08:14 +00:00
|
|
|
cacheAllSounds();
|
2018-04-02 22:00:11 +00:00
|
|
|
|
2019-10-22 00:01:05 +00:00
|
|
|
snd_fxvolume.Callback();
|
|
|
|
S_MusicVolume(mus_volume);
|
2014-02-01 16:19:58 +00:00
|
|
|
|
2019-10-22 00:01:05 +00:00
|
|
|
snd_reversestereo.Callback();
|
2010-03-01 09:09:26 +00:00
|
|
|
FX_SetCallBack(S_Callback);
|
2019-01-12 00:21:58 +00:00
|
|
|
FX_SetPrintf(OSD_Printf);
|
2019-08-09 09:28:42 +00:00
|
|
|
mutex_init(&m_callback);
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_SoundShutdown(void)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2009-07-27 05:33:12 +00:00
|
|
|
if (MusicVoice >= 0)
|
|
|
|
S_MusicShutdown();
|
|
|
|
|
2019-10-24 05:47:24 +00:00
|
|
|
int status = FX_Shutdown();
|
|
|
|
if (status != FX_Ok)
|
2006-11-15 01:16:55 +00:00
|
|
|
{
|
2019-10-24 05:47:24 +00:00
|
|
|
Bsprintf(tempbuf, "S_SoundShutdown(): error: %s", FX_ErrorString(status));
|
2008-11-20 14:06:36 +00:00
|
|
|
G_GameExit(tempbuf);
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_MusicStartup(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-10-24 05:47:11 +00:00
|
|
|
initprintf("Initializing MIDI driver... ");
|
2009-07-09 02:29:48 +00:00
|
|
|
|
2019-10-24 05:47:24 +00:00
|
|
|
int status;
|
2019-10-24 18:28:46 +00:00
|
|
|
if ((status = MUSIC_Init(MusicDevice)) == MUSIC_Ok)
|
2019-10-24 05:47:29 +00:00
|
|
|
{
|
2019-10-24 18:28:46 +00:00
|
|
|
if (MusicDevice == ASS_AutoDetect)
|
|
|
|
MusicDevice = MIDI_GetDevice();
|
2019-10-24 05:47:29 +00:00
|
|
|
}
|
|
|
|
else if ((status = MUSIC_Init(ASS_AutoDetect)) == MUSIC_Ok)
|
|
|
|
{
|
2019-10-24 18:28:46 +00:00
|
|
|
MusicDevice = MIDI_GetDevice();
|
2019-10-24 05:47:29 +00:00
|
|
|
}
|
|
|
|
else
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-10-24 05:47:24 +00:00
|
|
|
initprintf("S_MusicStartup(): failed initializing: %s\n", MUSIC_ErrorString(status));
|
2019-10-24 05:47:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-10-19 23:48:20 +00:00
|
|
|
|
2019-10-24 05:47:15 +00:00
|
|
|
MUSIC_SetVolume(mus_volume);
|
2019-10-20 02:28:05 +00:00
|
|
|
auto const fil = kopen4load("d3dtimbr.tmb", 0);
|
|
|
|
|
|
|
|
if (fil != buildvfs_kfd_invalid)
|
2019-10-19 23:48:20 +00:00
|
|
|
{
|
|
|
|
int l = kfilelength(fil);
|
|
|
|
auto tmb = (uint8_t *)Xmalloc(l);
|
|
|
|
kread(fil, tmb, l);
|
2019-10-19 23:48:44 +00:00
|
|
|
AL_RegisterTimbreBank(tmb);
|
2019-10-19 23:48:20 +00:00
|
|
|
Xfree(tmb);
|
|
|
|
kclose(fil);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_MusicShutdown(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-07-27 05:33:12 +00:00
|
|
|
S_StopMusic();
|
|
|
|
|
2019-10-24 05:47:24 +00:00
|
|
|
int status = MUSIC_Shutdown();
|
|
|
|
if (status != MUSIC_Ok)
|
|
|
|
initprintf("S_MusicShutdown(): %s\n", MUSIC_ErrorString(status));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
void S_PauseMusic(bool paused)
|
2009-07-27 05:33:12 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if (MusicPaused == paused || (MusicIsWaveform && MusicVoice < 0))
|
2009-07-27 05:33:12 +00:00
|
|
|
return;
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
MusicPaused = paused;
|
2010-03-01 09:09:26 +00:00
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
if (MusicIsWaveform)
|
2009-07-31 11:45:29 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
FX_PauseVoice(MusicVoice, paused);
|
2010-03-01 09:09:26 +00:00
|
|
|
return;
|
2009-07-31 11:45:29 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (paused)
|
2010-03-01 09:09:26 +00:00
|
|
|
MUSIC_Pause();
|
|
|
|
else
|
|
|
|
MUSIC_Continue();
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
void S_PauseSounds(bool paused)
|
2016-02-02 06:39:22 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if (SoundPaused == paused)
|
2016-02-02 06:39:22 +00:00
|
|
|
return;
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
SoundPaused = paused;
|
2016-02-02 06:39:22 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
for (int i = 0; i <= g_highestSoundIdx; ++i)
|
2016-02-02 06:39:22 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto & voice : g_sounds[i].voices)
|
|
|
|
if (voice.id > 0)
|
|
|
|
FX_PauseVoice(voice.id, paused);
|
2016-02-02 06:39:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
void S_MusicVolume(int32_t volume)
|
|
|
|
{
|
|
|
|
if (MusicIsWaveform && MusicVoice >= 0)
|
|
|
|
FX_SetPan(MusicVoice, volume, volume, volume);
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
MUSIC_SetVolume(volume);
|
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2014-09-07 18:10:09 +00:00
|
|
|
void S_RestartMusic(void)
|
|
|
|
{
|
|
|
|
if (ud.recstat != 2 && g_player[myconnectindex].ps->gm&MODE_GAME)
|
|
|
|
{
|
2018-01-29 11:13:43 +00:00
|
|
|
S_PlayLevelMusicOrNothing(g_musicIndex);
|
2014-09-07 18:10:09 +00:00
|
|
|
}
|
2018-01-29 11:13:43 +00:00
|
|
|
else if (G_GetLogoFlags() & LOGO_PLAYMUSIC)
|
2014-09-07 18:10:14 +00:00
|
|
|
{
|
2018-01-29 11:13:43 +00:00
|
|
|
S_PlaySpecialMusicOrNothing(MUS_INTRO);
|
2014-09-07 18:10:14 +00:00
|
|
|
}
|
2014-09-07 18:10:09 +00:00
|
|
|
}
|
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_MenuSound(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-04-06 01:43:08 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
2018-10-25 23:32:29 +00:00
|
|
|
static int SoundNum;
|
|
|
|
int const menusnds[] = {
|
2015-02-11 05:22:00 +00:00
|
|
|
LASERTRIP_EXPLODE, DUKE_GRUNT, DUKE_LAND_HURT, CHAINGUN_FIRE, SQUISHED, KICK_HIT,
|
|
|
|
PISTOL_RICOCHET, PISTOL_BODYHIT, PISTOL_FIRE, SHOTGUN_FIRE, BOS1_WALK, RPG_EXPLODE,
|
|
|
|
PIPEBOMB_BOUNCE, PIPEBOMB_EXPLODE, NITEVISION_ONOFF, RPG_SHOOT, SELECT_WEAPON,
|
2007-08-25 01:05:00 +00:00
|
|
|
};
|
2019-08-07 22:44:12 +00:00
|
|
|
int s = VM_OnEventWithReturn(EVENT_OPENMENUSOUND, g_player[screenpeek].ps->i, screenpeek, FURY ? -1 : menusnds[SoundNum++ % ARRAY_SIZE(menusnds)]);
|
2018-04-06 01:43:08 +00:00
|
|
|
#else
|
2018-10-25 23:32:29 +00:00
|
|
|
int s = VM_OnEventWithReturn(EVENT_OPENMENUSOUND, g_player[screenpeek].ps->i, screenpeek, -1);
|
2018-04-06 01:43:08 +00:00
|
|
|
#endif
|
2017-11-29 07:29:37 +00:00
|
|
|
if (s != -1)
|
|
|
|
S_PlaySound(s);
|
2008-04-01 09:06:29 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
static int S_PlayMusic(const char *fn)
|
2009-07-27 05:33:12 +00:00
|
|
|
{
|
2019-10-28 21:19:50 +00:00
|
|
|
if (!MusicEnabled())
|
2018-02-25 01:18:32 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (fn == NULL)
|
2018-01-29 11:13:43 +00:00
|
|
|
return 1;
|
2014-12-28 22:12:40 +00:00
|
|
|
|
2019-10-20 21:37:07 +00:00
|
|
|
auto fp = S_OpenAudio(fn, 0, 1);
|
|
|
|
if (!fp.isOpen())
|
2009-08-09 05:32:17 +00:00
|
|
|
{
|
2012-03-26 05:05:57 +00:00
|
|
|
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn);
|
2018-01-29 11:13:43 +00:00
|
|
|
return 2;
|
2009-08-09 05:32:17 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2019-10-20 21:37:07 +00:00
|
|
|
int32_t MusicLen = fp.GetLength();
|
2009-08-09 05:32:17 +00:00
|
|
|
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(MusicLen < 4))
|
2009-08-09 05:32:17 +00:00
|
|
|
{
|
2014-02-02 15:56:11 +00:00
|
|
|
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn);
|
2018-01-29 11:13:43 +00:00
|
|
|
return 3;
|
2014-02-02 15:56:11 +00:00
|
|
|
}
|
|
|
|
|
2018-01-29 11:13:43 +00:00
|
|
|
char * MyMusicPtr = (char *)Xaligned_alloc(16, MusicLen);
|
2019-10-20 21:37:07 +00:00
|
|
|
int MyMusicSize = fp.Read(MyMusicPtr, MusicLen);
|
2014-02-02 15:56:11 +00:00
|
|
|
|
2018-01-29 11:13:43 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(MyMusicSize != MusicLen))
|
2014-02-02 15:56:11 +00:00
|
|
|
{
|
|
|
|
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n",
|
2018-01-29 11:13:43 +00:00
|
|
|
MyMusicSize, fn, MusicLen);
|
|
|
|
ALIGNED_FREE_AND_NULL(MyMusicPtr);
|
|
|
|
return 4;
|
2009-08-09 05:32:17 +00:00
|
|
|
}
|
|
|
|
|
2018-01-29 11:13:43 +00:00
|
|
|
if (!Bmemcmp(MyMusicPtr, "MThd", 4))
|
2009-07-27 05:33:12 +00:00
|
|
|
{
|
2019-10-19 23:47:29 +00:00
|
|
|
int32_t retval = MUSIC_PlaySong(MyMusicPtr, MyMusicSize, MUSIC_LoopSong, fn);
|
2018-01-29 11:13:43 +00:00
|
|
|
|
|
|
|
if (retval != MUSIC_Ok)
|
|
|
|
{
|
|
|
|
ALIGNED_FREE_AND_NULL(MyMusicPtr);
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MusicIsWaveform && MusicVoice >= 0)
|
|
|
|
{
|
|
|
|
FX_StopSound(MusicVoice);
|
|
|
|
MusicVoice = -1;
|
|
|
|
}
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
MusicIsWaveform = 0;
|
2018-01-29 11:13:43 +00:00
|
|
|
ALIGNED_FREE_AND_NULL(MusicPtr);
|
2018-04-02 22:00:11 +00:00
|
|
|
MusicPtr = MyMusicPtr;
|
2018-01-29 11:13:43 +00:00
|
|
|
g_musicSize = MyMusicSize;
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-22 00:01:05 +00:00
|
|
|
int MyMusicVoice = FX_Play(MyMusicPtr, MusicLen, 0, 0, 0, mus_volume, mus_volume, mus_volume,
|
2018-10-25 23:32:50 +00:00
|
|
|
FX_MUSIC_PRIORITY, 1.f, MUSIC_ID);
|
2018-01-29 11:13:43 +00:00
|
|
|
|
|
|
|
if (MyMusicVoice <= FX_Ok)
|
|
|
|
{
|
|
|
|
ALIGNED_FREE_AND_NULL(MyMusicPtr);
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MusicIsWaveform && MusicVoice >= 0)
|
|
|
|
FX_StopSound(MusicVoice);
|
|
|
|
|
|
|
|
MUSIC_StopSong();
|
|
|
|
|
2018-04-02 22:00:11 +00:00
|
|
|
MusicVoice = MyMusicVoice;
|
2018-01-29 11:13:43 +00:00
|
|
|
MusicIsWaveform = 1;
|
|
|
|
ALIGNED_FREE_AND_NULL(MusicPtr);
|
2018-04-02 22:00:11 +00:00
|
|
|
MusicPtr = MyMusicPtr;
|
2018-01-29 11:13:43 +00:00
|
|
|
g_musicSize = MyMusicSize;
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
2014-02-02 15:56:11 +00:00
|
|
|
|
2015-01-25 12:17:59 +00:00
|
|
|
return 0;
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
|
|
|
|
2018-01-29 11:13:49 +00:00
|
|
|
static void S_SetMusicIndex(unsigned int m)
|
|
|
|
{
|
|
|
|
g_musicIndex = m;
|
|
|
|
ud.music_episode = m / MAXLEVELS;
|
|
|
|
ud.music_level = m % MAXLEVELS;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
bool S_TryPlayLevelMusic(unsigned int m)
|
2018-01-29 11:13:43 +00:00
|
|
|
{
|
2018-02-26 20:20:00 +00:00
|
|
|
ud.returnvar[0] = m / MAXLEVELS;
|
|
|
|
ud.returnvar[1] = m % MAXLEVELS;
|
2018-10-25 23:32:29 +00:00
|
|
|
|
2018-01-29 11:14:08 +00:00
|
|
|
int retval = VM_OnEvent(EVENT_PLAYLEVELMUSICSLOT, g_player[myconnectindex].ps->i, myconnectindex);
|
|
|
|
|
|
|
|
if (retval < 0)
|
2018-10-25 23:32:29 +00:00
|
|
|
return false;
|
2018-01-29 11:14:08 +00:00
|
|
|
|
2018-01-29 11:13:43 +00:00
|
|
|
char const * musicfn = g_mapInfo[m].musicfn;
|
2018-10-25 23:32:29 +00:00
|
|
|
|
2018-01-29 11:13:43 +00:00
|
|
|
if (musicfn != NULL)
|
|
|
|
{
|
|
|
|
if (!S_PlayMusic(musicfn))
|
|
|
|
{
|
2018-01-29 11:13:49 +00:00
|
|
|
S_SetMusicIndex(m);
|
2018-10-25 23:32:29 +00:00
|
|
|
return false;
|
2018-01-29 11:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
return true;
|
2018-01-29 11:13:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void S_PlayLevelMusicOrNothing(unsigned int m)
|
|
|
|
{
|
|
|
|
if (S_TryPlayLevelMusic(m))
|
|
|
|
{
|
|
|
|
S_StopMusic();
|
2018-01-29 11:13:49 +00:00
|
|
|
S_SetMusicIndex(m);
|
2018-01-29 11:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int S_TryPlaySpecialMusic(unsigned int m)
|
|
|
|
{
|
|
|
|
char const * musicfn = g_mapInfo[m].musicfn;
|
|
|
|
if (musicfn != NULL)
|
|
|
|
{
|
|
|
|
if (!S_PlayMusic(musicfn))
|
|
|
|
{
|
2018-01-29 11:13:49 +00:00
|
|
|
S_SetMusicIndex(m);
|
2018-01-29 11:13:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void S_PlaySpecialMusicOrNothing(unsigned int m)
|
|
|
|
{
|
|
|
|
if (S_TryPlaySpecialMusic(m))
|
|
|
|
{
|
|
|
|
S_StopMusic();
|
2018-01-29 11:13:49 +00:00
|
|
|
S_SetMusicIndex(m);
|
2018-01-29 11:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-29 11:14:08 +00:00
|
|
|
void S_ContinueLevelMusic(void)
|
|
|
|
{
|
|
|
|
VM_OnEvent(EVENT_CONTINUELEVELMUSICSLOT, g_player[myconnectindex].ps->i, myconnectindex);
|
|
|
|
}
|
|
|
|
|
2015-01-17 00:28:49 +00:00
|
|
|
int32_t S_GetMusicPosition(void)
|
|
|
|
{
|
|
|
|
int32_t position = 0;
|
|
|
|
|
|
|
|
if (MusicIsWaveform)
|
|
|
|
FX_GetPosition(MusicVoice, &position);
|
|
|
|
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void S_SetMusicPosition(int32_t position)
|
|
|
|
{
|
|
|
|
if (MusicIsWaveform)
|
|
|
|
FX_SetPosition(MusicVoice, position);
|
|
|
|
}
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
void S_StopMusic(void)
|
|
|
|
{
|
2009-08-09 05:32:17 +00:00
|
|
|
MusicPaused = 0;
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
if (MusicIsWaveform && MusicVoice >= 0)
|
|
|
|
{
|
|
|
|
FX_StopSound(MusicVoice);
|
|
|
|
MusicVoice = -1;
|
2009-08-09 05:32:17 +00:00
|
|
|
MusicIsWaveform = 0;
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
2009-07-27 10:46:42 +00:00
|
|
|
|
|
|
|
MUSIC_StopSong();
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
ALIGNED_FREE_AND_NULL(MusicPtr);
|
2014-02-02 15:56:11 +00:00
|
|
|
g_musicSize = 0;
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
void S_Cleanup(void)
|
|
|
|
{
|
2019-08-07 22:44:29 +00:00
|
|
|
static uint32_t ldnum = 0;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2019-01-12 00:21:58 +00:00
|
|
|
while (ldnum < dnum)
|
2010-06-22 21:50:01 +00:00
|
|
|
{
|
2018-04-21 06:04:56 +00:00
|
|
|
uint32_t num = dq[ldnum++ & (DQSIZE - 1)];
|
2010-06-22 21:50:01 +00:00
|
|
|
|
|
|
|
// negative index is RTS playback
|
|
|
|
if ((int32_t)num < 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-10-30 19:48:46 +00:00
|
|
|
// num + (MAXSOUNDS*MAXSOUNDINSTANCES) is a sound played globally
|
|
|
|
// for which there was no open slot to keep track of the voice
|
|
|
|
if (num >= (MAXSOUNDS*MAXSOUNDINSTANCES))
|
2011-05-28 14:15:41 +00:00
|
|
|
{
|
2019-08-07 22:43:53 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-10-25 23:32:29 +00:00
|
|
|
--g_soundlocks[num-(MAXSOUNDS*MAXSOUNDINSTANCES)];
|
2019-08-07 22:43:53 +00:00
|
|
|
#endif
|
2011-05-28 14:15:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
int const voiceindex = num & (MAXSOUNDINSTANCES - 1);
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
num = (num - voiceindex) / MAXSOUNDINSTANCES;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
auto &snd = g_sounds[num];
|
2019-08-07 22:44:29 +00:00
|
|
|
auto &voice = snd.voices[voiceindex];
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int const spriteNum = voice.owner;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(snd.num > MAXSOUNDINSTANCES))
|
|
|
|
OSD_Printf(OSD_ERROR "S_Cleanup(): num exceeds MAXSOUNDINSTANCES! g_sounds[%d].num %d wtf?\n", num, snd.num);
|
2019-08-07 22:44:29 +00:00
|
|
|
else if (snd.num > 0)
|
2018-10-25 23:32:29 +00:00
|
|
|
--snd.num;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
// MUSICANDSFX uses t_data[0] to control restarting the sound
|
|
|
|
// CLEAR_SOUND_T0
|
2018-05-04 22:42:37 +00:00
|
|
|
if (spriteNum != -1 && S_IsAmbientSFX(spriteNum) && sector[SECT(spriteNum)].lotag < 3) // ST_2_UNDERWATER
|
|
|
|
actor[spriteNum].t_data[0] = 0;
|
2015-02-11 05:22:00 +00:00
|
|
|
|
2019-08-07 22:44:20 +00:00
|
|
|
S_SetProperties(&voice, -1, 0, UINT16_MAX, 0);
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2019-08-07 22:43:53 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-10-25 23:32:29 +00:00
|
|
|
--g_soundlocks[num];
|
2019-08-07 22:43:53 +00:00
|
|
|
#endif
|
2010-06-22 21:50:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
// returns number of bytes read
|
2018-10-25 23:32:29 +00:00
|
|
|
int32_t S_LoadSound(int num)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if ((unsigned)num > (unsigned)g_highestSoundIdx || EDUKE32_PREDICT_FALSE(g_sounds[num].filename == NULL))
|
2008-01-26 03:59:34 +00:00
|
|
|
return 0;
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
auto &snd = g_sounds[num];
|
|
|
|
|
2019-10-20 21:37:07 +00:00
|
|
|
auto fp = S_OpenAudio(snd.filename, g_loadFromGroupOnly, 0);
|
2018-04-02 22:00:11 +00:00
|
|
|
|
2019-10-20 21:37:07 +00:00
|
|
|
if (!fp.isOpen())
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
OSD_Printf(OSDTEXT_RED "Sound %s(#%d) not found!\n", snd.filename, num);
|
2015-11-25 12:08:04 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-10-20 21:37:07 +00:00
|
|
|
int32_t l = fp.GetLength();
|
2019-08-01 07:10:16 +00:00
|
|
|
g_soundlocks[num] = 255;
|
2018-10-25 23:32:29 +00:00
|
|
|
snd.siz = l;
|
2019-09-22 21:15:46 +00:00
|
|
|
cacheAllocateBlock((intptr_t *)&snd.ptr, l, &g_soundlocks[num]);
|
2019-10-20 21:37:07 +00:00
|
|
|
l = fp.Read(snd.ptr, l);
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
return l;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-11-18 18:08:14 +00:00
|
|
|
void cacheAllSounds(void)
|
2018-04-02 22:00:11 +00:00
|
|
|
{
|
2019-08-07 22:44:29 +00:00
|
|
|
for (int i=0, j=0; i <= g_highestSoundIdx; ++i)
|
|
|
|
{
|
2018-04-02 22:00:11 +00:00
|
|
|
if (g_sounds[i].ptr == 0)
|
|
|
|
{
|
|
|
|
j++;
|
|
|
|
if ((j&7) == 0)
|
2019-10-19 23:41:40 +00:00
|
|
|
gameHandleEvents();
|
2018-04-02 22:00:11 +00:00
|
|
|
|
|
|
|
S_LoadSound(i);
|
|
|
|
}
|
2019-08-07 22:44:29 +00:00
|
|
|
}
|
2018-04-02 22:00:11 +00:00
|
|
|
}
|
2012-08-13 18:25:48 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
static inline int S_GetPitch(int num)
|
2012-08-13 18:25:48 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
auto const &snd = g_sounds[num];
|
|
|
|
int const range = klabs(snd.pe - snd.ps);
|
|
|
|
|
|
|
|
return (range == 0) ? snd.ps : min(snd.ps, snd.pe) + rand() % range;
|
2012-08-13 18:25:48 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
static int S_TakeSlot(int soundNum)
|
2012-08-13 18:25:48 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
S_Cleanup();
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
uint16_t dist = 0;
|
|
|
|
uint16_t clock = 0;
|
|
|
|
|
|
|
|
int bestslot = 0;
|
|
|
|
int slot = 0;
|
2012-08-13 18:25:48 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
auto &snd = g_sounds[soundNum];
|
|
|
|
|
|
|
|
while (slot < MAXSOUNDINSTANCES && snd.voices[slot].id > 0)
|
2012-10-08 07:07:59 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
auto &voice = snd.voices[slot];
|
|
|
|
|
|
|
|
if (voice.dist > dist || (voice.dist == dist && voice.clock > clock))
|
2012-10-08 07:07:59 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
clock = voice.clock;
|
|
|
|
dist = voice.dist;
|
|
|
|
|
|
|
|
bestslot = slot;
|
2012-10-08 07:07:59 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
slot++;
|
2012-10-08 07:07:59 +00:00
|
|
|
}
|
2012-08-13 18:25:48 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (slot != MAXSOUNDINSTANCES)
|
|
|
|
return slot;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (FX_SoundActive(snd.voices[bestslot].id))
|
|
|
|
FX_StopSound(snd.voices[bestslot].id);
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2019-08-09 09:28:42 +00:00
|
|
|
mutex_lock(&m_callback);
|
|
|
|
unative_t const ldnum = dnum;
|
|
|
|
dq[ldnum & (DQSIZE-1)] = (soundNum * MAXSOUNDINSTANCES) + bestslot;
|
|
|
|
dnum++;
|
|
|
|
mutex_unlock(&m_callback);
|
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
S_Cleanup();
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
return bestslot;
|
2012-10-08 07:07:59 +00:00
|
|
|
}
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
static int S_GetSlot(int soundNum)
|
2012-10-08 07:07:59 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
int slot = 0;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
while (slot < MAXSOUNDINSTANCES && g_sounds[soundNum].voices[slot].id > 0)
|
|
|
|
slot++;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
return slot == MAXSOUNDINSTANCES ? S_TakeSlot(soundNum) : slot;
|
2012-08-13 18:25:48 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
static inline int S_GetAngle(int ang, const vec3_t *cam, const vec3_t *pos)
|
2012-08-13 18:25:53 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
return (2048 + ang - getangle(cam->x - pos->x, cam->y - pos->y)) & 2047;
|
2012-08-13 18:25:53 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, int angle,
|
|
|
|
const vec3_t *cam, const vec3_t *pos, int *distPtr, int *angPtr)
|
2012-08-13 18:25:51 +00:00
|
|
|
{
|
2019-08-07 22:44:29 +00:00
|
|
|
int sndang = 0, sndist = 0, explosion = 0;
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == screenpeek)
|
2012-08-13 18:25:53 +00:00
|
|
|
goto sound_further_processing;
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
sndang = S_GetAngle(angle, cam, pos);
|
2014-10-25 03:29:38 +00:00
|
|
|
sndist = FindDistance3D(cam->x-pos->x, cam->y-pos->y, (cam->z-pos->z));
|
2012-08-13 18:25:53 +00:00
|
|
|
|
2014-01-12 14:04:51 +00:00
|
|
|
#ifdef SPLITSCREEN_MOD_HACKS
|
2012-08-22 22:51:38 +00:00
|
|
|
if (g_fakeMultiMode==2)
|
2012-08-13 18:25:51 +00:00
|
|
|
{
|
2012-08-13 18:25:53 +00:00
|
|
|
// HACK for splitscreen mod: take the min of sound distances
|
|
|
|
// to 1st and 2nd player.
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == 1)
|
2012-08-13 18:25:53 +00:00
|
|
|
{
|
|
|
|
sndist = sndang = 0;
|
|
|
|
goto sound_further_processing;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const vec3_t *cam2 = &g_player[1].ps->pos;
|
2014-10-25 03:29:38 +00:00
|
|
|
int32_t sndist2 = FindDistance3D(cam2->x-pos->x, cam2->y-pos->y, (cam2->z-pos->z));
|
2012-08-13 18:25:53 +00:00
|
|
|
|
|
|
|
if (sndist2 < sndist)
|
|
|
|
{
|
|
|
|
cam = cam2;
|
2018-10-25 23:32:29 +00:00
|
|
|
sectNum = g_player[1].ps->cursectnum;
|
|
|
|
angle = g_player[1].ps->ang;
|
2012-08-13 18:25:53 +00:00
|
|
|
|
|
|
|
sndist = sndist2;
|
2018-10-25 23:32:29 +00:00
|
|
|
sndang = S_GetAngle(angle, cam, pos);
|
2012-08-13 18:25:53 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-13 18:25:51 +00:00
|
|
|
}
|
2014-01-12 14:04:51 +00:00
|
|
|
#endif
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2019-08-07 22:44:25 +00:00
|
|
|
if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) != SF_GLOBAL && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag&0xff) < 9) // ST_9_SLIDING_ST_DOOR
|
2018-10-25 23:32:29 +00:00
|
|
|
sndist = divscale14(sndist, SHT(spriteNum)+1);
|
2012-08-13 18:25:53 +00:00
|
|
|
|
|
|
|
sound_further_processing:
|
2018-10-25 23:32:29 +00:00
|
|
|
sndist += g_sounds[soundNum].vo;
|
2012-08-13 18:25:51 +00:00
|
|
|
if (sndist < 0)
|
|
|
|
sndist = 0;
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
|
|
|
if (!FURY && sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX
|
2018-10-25 23:32:29 +00:00
|
|
|
&& !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum)))
|
2012-08-13 18:25:51 +00:00
|
|
|
sndist += sndist>>5;
|
2019-08-07 22:44:29 +00:00
|
|
|
#else
|
|
|
|
UNREFERENCED_PARAMETER(sectNum);
|
|
|
|
#endif
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2019-08-07 22:44:25 +00:00
|
|
|
if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == (SF_GLOBAL|SF_DTAG))
|
|
|
|
{
|
2019-08-07 22:44:29 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
2019-08-07 22:44:25 +00:00
|
|
|
boost:
|
2019-08-07 22:44:29 +00:00
|
|
|
#endif
|
2019-08-29 19:00:42 +00:00
|
|
|
int const sdist = g_sounds[soundNum].vo > 0 ? g_sounds[soundNum].vo : 6144;
|
|
|
|
|
2019-08-07 22:44:25 +00:00
|
|
|
explosion = true;
|
2019-08-29 19:00:42 +00:00
|
|
|
|
|
|
|
if (sndist > sdist)
|
|
|
|
sndist = sdist;
|
2019-08-07 22:44:25 +00:00
|
|
|
}
|
2019-08-09 10:06:59 +00:00
|
|
|
|
2018-04-06 01:43:08 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
2019-08-10 13:03:31 +00:00
|
|
|
else if (!FURY)
|
2018-10-25 23:32:29 +00:00
|
|
|
{
|
2019-08-07 22:44:12 +00:00
|
|
|
switch (DYNAMICSOUNDMAP(soundNum))
|
|
|
|
{
|
|
|
|
case PIPEBOMB_EXPLODE__STATIC:
|
|
|
|
case LASERTRIP_EXPLODE__STATIC:
|
|
|
|
case RPG_EXPLODE__STATIC:
|
2019-08-07 22:44:25 +00:00
|
|
|
goto boost;
|
2019-08-07 22:44:12 +00:00
|
|
|
}
|
2012-08-13 18:25:51 +00:00
|
|
|
}
|
2018-04-06 01:43:08 +00:00
|
|
|
#endif
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2019-08-07 22:44:25 +00:00
|
|
|
if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL || sndist < ((255-LOUDESTVOLUME) << 6))
|
2018-10-25 23:32:29 +00:00
|
|
|
sndist = ((255-LOUDESTVOLUME) << 6);
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
*distPtr = sndist;
|
|
|
|
*angPtr = sndang;
|
2012-08-13 18:25:51 +00:00
|
|
|
|
|
|
|
return explosion;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
int32_t j = VM_OnEventWithReturn(EVENT_SOUND, spriteNum, screenpeek, num);
|
2014-06-23 02:24:10 +00:00
|
|
|
|
2019-10-28 21:19:50 +00:00
|
|
|
if ((j == -1 && num != -1) || !SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn)
|
2014-06-23 02:24:10 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-04-02 22:00:11 +00:00
|
|
|
int const sndNum = j;
|
2018-10-25 23:32:29 +00:00
|
|
|
sound_t & snd = g_sounds[sndNum];
|
2012-05-17 17:33:29 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned) sndNum > (unsigned) g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL))
|
|
|
|
{
|
|
|
|
OSD_Printf("WARNING: invalid sound #%d\n", num);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-07-08 00:41:25 +00:00
|
|
|
auto const pPlayer = g_player[myconnectindex].ps;
|
2015-02-11 05:22:00 +00:00
|
|
|
|
2019-10-27 12:40:24 +00:00
|
|
|
if (((snd.m & SF_ADULT) && adult_lockout) || (unsigned)spriteNum >= MAXSPRITES || (pPlayer->gm & MODE_MENU) || !FX_VoiceAvailable(snd.pr)
|
2018-05-04 22:42:37 +00:00
|
|
|
|| (pPlayer->timebeforeexit > 0 && pPlayer->timebeforeexit <= GAMETICSPERSEC * 3))
|
2013-03-31 18:58:17 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
// Duke talk
|
|
|
|
if (snd.m & SF_TALK)
|
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if ((g_netServer || ud.multimode > 1) && PN(spriteNum) == APLAYER && P_Get(spriteNum) != screenpeek) // other player sound
|
2018-05-04 22:42:37 +00:00
|
|
|
{
|
2019-10-22 00:01:05 +00:00
|
|
|
if ((snd_speech & 4) != 4)
|
2018-05-04 22:42:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2019-10-22 00:01:05 +00:00
|
|
|
else if ((snd_speech & 1) != 1)
|
2018-05-04 22:42:37 +00:00
|
|
|
return -1;
|
2015-02-11 05:22:00 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
// don't play if any Duke talk sounds are already playing
|
|
|
|
for (j = 0; j <= g_highestSoundIdx; ++j)
|
|
|
|
if ((g_sounds[j].m & SF_TALK) && g_sounds[j].num > 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2019-08-07 22:44:25 +00:00
|
|
|
else if ((snd.m & (SF_DTAG|SF_GLOBAL)) == SF_DTAG) // Duke-Tag sound
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-05-04 22:42:37 +00:00
|
|
|
int const voice = S_PlaySound(sndNum);
|
|
|
|
|
|
|
|
if (voice <= FX_Ok)
|
2010-07-05 04:37:28 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-06-23 02:24:10 +00:00
|
|
|
j = 0;
|
2018-10-25 23:32:29 +00:00
|
|
|
while (j < MAXSOUNDINSTANCES && snd.voices[j].id != voice)
|
2010-06-22 21:50:01 +00:00
|
|
|
j++;
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
#ifdef DEBUGGINGAIDS
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(j >= MAXSOUNDINSTANCES))
|
2010-06-22 21:50:01 +00:00
|
|
|
{
|
|
|
|
OSD_Printf(OSD_ERROR "%s %d: WTF?\n", __FILE__, __LINE__);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-05-04 22:42:37 +00:00
|
|
|
#endif
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
snd.voices[j].owner = spriteNum;
|
2010-07-05 04:37:28 +00:00
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
return voice;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int32_t sndist, sndang;
|
|
|
|
int const explosionp = S_CalcDistAndAng(spriteNum, sndNum, CAMERA(sect), fix16_to_int(CAMERA(q16ang)), &CAMERA(pos), pos, &sndist, &sndang);
|
|
|
|
int pitch = S_GetPitch(sndNum);
|
|
|
|
auto const pOther = g_player[screenpeek].ps;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-01-12 14:04:51 +00:00
|
|
|
#ifdef SPLITSCREEN_MOD_HACKS
|
2012-08-22 22:51:38 +00:00
|
|
|
if (g_fakeMultiMode==2)
|
2012-08-22 22:50:32 +00:00
|
|
|
{
|
|
|
|
// splitscreen HACK
|
2018-10-25 23:32:29 +00:00
|
|
|
if (g_player[1].ps->i == spriteNum)
|
2018-05-04 22:42:37 +00:00
|
|
|
pOther = g_player[1].ps;
|
2018-04-02 22:00:11 +00:00
|
|
|
}
|
2014-01-12 14:04:51 +00:00
|
|
|
#endif
|
2012-08-22 22:50:32 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (pOther->sound_pitch)
|
|
|
|
pitch += pOther->sound_pitch;
|
2012-08-13 18:25:51 +00:00
|
|
|
|
|
|
|
if (explosionp)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-05-04 22:42:37 +00:00
|
|
|
if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER)
|
2006-11-16 03:02:42 +00:00
|
|
|
pitch -= 1024;
|
2012-08-13 18:25:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if (sndist > 32767 && PN(spriteNum) != MUSICANDSFX && (snd.m & (SF_LOOP|SF_MSFX)) == 0)
|
2011-03-04 08:50:58 +00:00
|
|
|
return -1;
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER
|
2018-04-02 22:00:11 +00:00
|
|
|
&& (snd.m & SF_TALK) == 0)
|
2006-11-16 03:02:42 +00:00
|
|
|
pitch = -768;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (snd.num > 0 && PN(spriteNum) != MUSICANDSFX)
|
|
|
|
S_StopEnvSound(sndNum, spriteNum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-05-04 22:42:37 +00:00
|
|
|
if (++g_soundlocks[sndNum] < 200)
|
2018-04-02 22:00:11 +00:00
|
|
|
g_soundlocks[sndNum] = 200;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2018-04-02 22:00:11 +00:00
|
|
|
|
|
|
|
int const sndSlot = S_GetSlot(sndNum);
|
|
|
|
|
|
|
|
if (sndSlot >= MAXSOUNDINSTANCES)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-04-02 22:00:11 +00:00
|
|
|
g_soundlocks[sndNum]--;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2018-04-02 22:00:11 +00:00
|
|
|
return -1;
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
int const repeatp = (snd.m & SF_LOOP);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-02 22:00:11 +00:00
|
|
|
if (repeatp && (snd.m & SF_ONEINST_INTERNAL) && snd.num > 0)
|
2010-03-01 09:09:26 +00:00
|
|
|
{
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-04-02 22:00:11 +00:00
|
|
|
g_soundlocks[sndNum]--;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2010-03-01 09:09:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2019-07-24 01:37:32 +00:00
|
|
|
int const voice = FX_Play3D(snd.ptr, snd.siz, repeatp ? FX_LOOP : FX_ONESHOT, pitch, sndang >> 4, sndist >> 6,
|
2018-10-25 23:32:29 +00:00
|
|
|
snd.pr, snd.volume, (sndNum * MAXSOUNDINSTANCES) + sndSlot);
|
2010-03-01 09:09:26 +00:00
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
if (voice <= FX_Ok)
|
2010-03-01 09:09:26 +00:00
|
|
|
{
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-04-02 22:00:11 +00:00
|
|
|
g_soundlocks[sndNum]--;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2010-07-03 08:53:57 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2010-03-01 09:09:26 +00:00
|
|
|
|
2018-04-02 22:00:11 +00:00
|
|
|
snd.num++;
|
2019-08-07 22:44:20 +00:00
|
|
|
|
|
|
|
S_SetProperties(&snd.voices[sndSlot], spriteNum, voice, sndist >> 6, 0);
|
2013-03-31 18:58:17 +00:00
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
return voice;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int S_PlaySound(int num)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
int sndnum = VM_OnEventWithReturn(EVENT_SOUND, g_player[screenpeek].ps->i, screenpeek, num);
|
2014-06-23 02:24:10 +00:00
|
|
|
|
2019-10-28 21:19:50 +00:00
|
|
|
if ((sndnum == -1 && num != -1) || !SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn)
|
2014-06-23 02:24:10 +00:00
|
|
|
return -1;
|
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
num = sndnum;
|
2012-05-17 17:33:29 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
sound_t & snd = g_sounds[num];
|
2012-01-10 23:44:49 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL))
|
2007-08-15 03:05:14 +00:00
|
|
|
{
|
2007-08-25 01:05:00 +00:00
|
|
|
OSD_Printf("WARNING: invalid sound #%d\n",num);
|
2009-07-15 01:26:38 +00:00
|
|
|
return -1;
|
2007-08-15 03:05:14 +00:00
|
|
|
}
|
|
|
|
|
2019-10-27 12:40:24 +00:00
|
|
|
if ((!(snd_speech & 1) && (snd.m & SF_TALK)) || ((snd.m & SF_ADULT) && adult_lockout) || !FX_VoiceAvailable(snd.pr))
|
2015-02-11 05:22:00 +00:00
|
|
|
return -1;
|
2012-01-10 23:44:49 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int const pitch = S_GetPitch(num);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2018-05-04 22:42:37 +00:00
|
|
|
if (++g_soundlocks[num] < 200)
|
2018-04-02 22:00:11 +00:00
|
|
|
g_soundlocks[num] = 200;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
sndnum = S_GetSlot(num);
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (sndnum >= MAXSOUNDINSTANCES)
|
2012-10-08 07:07:59 +00:00
|
|
|
{
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2012-10-08 07:07:59 +00:00
|
|
|
g_soundlocks[num]--;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2012-10-08 07:07:59 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2010-08-02 08:13:51 +00:00
|
|
|
|
2018-10-25 23:32:50 +00:00
|
|
|
int const voice = (snd.m & SF_LOOP) ? FX_Play(snd.ptr, snd.siz, 0, -1, pitch, LOUDESTVOLUME, LOUDESTVOLUME,
|
|
|
|
LOUDESTVOLUME, snd.siz, snd.volume, (num * MAXSOUNDINSTANCES) + sndnum)
|
|
|
|
: FX_Play3D(snd.ptr, snd.siz, FX_ONESHOT, pitch, 0, 255 - LOUDESTVOLUME, snd.pr, snd.volume,
|
2018-10-25 23:32:29 +00:00
|
|
|
(num * MAXSOUNDINSTANCES) + sndnum);
|
2010-03-01 09:09:26 +00:00
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
if (voice <= FX_Ok)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-08-01 07:10:16 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2010-03-01 09:09:26 +00:00
|
|
|
g_soundlocks[num]--;
|
2019-08-01 07:10:16 +00:00
|
|
|
#endif
|
2010-03-01 09:09:26 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
snd.num++;
|
2019-08-07 22:44:29 +00:00
|
|
|
S_SetProperties(&snd.voices[sndnum], -1, voice, 255-LOUDESTVOLUME, 0);
|
2018-05-04 22:42:37 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
return voice;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
int A_PlaySound(int soundNum, int spriteNum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-08-07 22:44:29 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx))
|
|
|
|
return -1;
|
2012-05-14 18:12:27 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
return (unsigned)spriteNum >= MAXSPRITES ? S_PlaySound(soundNum) :
|
2019-08-13 14:44:00 +00:00
|
|
|
S_PlaySound3D(soundNum, spriteNum, &sprite[spriteNum].pos);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-08-09 11:00:34 +00:00
|
|
|
void S_StopEnvSound(int sndNum, int sprNum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-08-09 11:00:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)sndNum > (unsigned)g_highestSoundIdx) || g_sounds[sndNum].num <= 0)
|
2010-03-01 09:09:26 +00:00
|
|
|
return;
|
|
|
|
|
2019-08-09 11:00:34 +00:00
|
|
|
int j;
|
2015-02-11 05:22:00 +00:00
|
|
|
|
2019-08-09 11:00:34 +00:00
|
|
|
do
|
2010-06-26 08:51:42 +00:00
|
|
|
{
|
2019-08-09 11:00:34 +00:00
|
|
|
for (j=0; j<MAXSOUNDINSTANCES; ++j)
|
2019-08-07 22:44:29 +00:00
|
|
|
{
|
2019-08-09 11:00:34 +00:00
|
|
|
S_Cleanup();
|
|
|
|
|
|
|
|
auto &voice = g_sounds[sndNum].voices[j];
|
|
|
|
|
|
|
|
if ((sprNum == -1 && voice.id > FX_Ok) || (sprNum != -1 && voice.owner == sprNum))
|
|
|
|
{
|
2018-05-04 22:42:37 +00:00
|
|
|
#ifdef DEBUGGINGAIDS
|
2019-08-09 11:00:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(sprNum >= 0 && voice.id <= FX_Ok))
|
|
|
|
initprintf(OSD_ERROR "S_StopEnvSound(): bad voice %d for sound ID %d index %d!\n", voice.id, sndNum, j);
|
|
|
|
else
|
2018-05-04 22:42:37 +00:00
|
|
|
#endif
|
2019-08-09 11:00:34 +00:00
|
|
|
if (voice.id > FX_Ok)
|
2012-10-14 22:09:16 +00:00
|
|
|
{
|
2019-08-09 11:00:34 +00:00
|
|
|
if (FX_SoundActive(voice.id))
|
|
|
|
FX_StopSound(voice.id);
|
|
|
|
break;
|
2012-10-14 22:09:16 +00:00
|
|
|
}
|
2010-05-02 23:27:30 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-15 01:26:38 +00:00
|
|
|
}
|
2019-08-09 11:00:34 +00:00
|
|
|
while (j < MAXSOUNDINSTANCES);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2017-01-05 05:29:25 +00:00
|
|
|
// Do not remove this or make it inline.
|
|
|
|
void S_StopAllSounds(void)
|
|
|
|
{
|
|
|
|
FX_StopAllSounds();
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset)
|
2011-11-03 23:08:54 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if ((unsigned)soundNum > (unsigned)g_highestSoundIdx || g_sounds[soundNum].num <= 0)
|
2011-11-03 23:08:54 +00:00
|
|
|
return;
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto &voice : g_sounds[soundNum].voices)
|
2011-11-03 23:08:54 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if ((spriteNum == -1 && voice.id > FX_Ok) || (spriteNum != -1 && voice.owner == spriteNum))
|
2011-11-03 23:08:54 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(spriteNum >= 0 && voice.id <= FX_Ok))
|
|
|
|
initprintf(OSD_ERROR "S_ChangeSoundPitch(): bad voice %d for sound ID %d!\n", voice.id, soundNum);
|
|
|
|
else if (voice.id > FX_Ok && FX_SoundActive(voice.id))
|
|
|
|
FX_SetPitch(voice.id, pitchoffset);
|
2011-11-03 23:08:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-02 23:27:30 +00:00
|
|
|
void S_Update(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2010-07-05 04:37:28 +00:00
|
|
|
if ((g_player[myconnectindex].ps->gm & (MODE_GAME|MODE_DEMO)) == 0)
|
|
|
|
return;
|
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
g_numEnvSoundsPlaying = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
const vec3_t *c;
|
|
|
|
int32_t ca,cs;
|
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
if (ud.camerasprite == -1)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-07-06 17:54:38 +00:00
|
|
|
if (ud.overhead_on != 2)
|
|
|
|
{
|
|
|
|
c = &CAMERA(pos);
|
|
|
|
cs = CAMERA(sect);
|
|
|
|
ca = fix16_to_int(CAMERA(q16ang));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto pPlayer = g_player[screenpeek].ps;
|
|
|
|
c = &pPlayer->pos;
|
|
|
|
cs = pPlayer->cursectnum;
|
|
|
|
ca = fix16_to_int(pPlayer->q16ang);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-13 14:44:00 +00:00
|
|
|
c = &sprite[ud.camerasprite].pos;
|
2006-04-13 20:47:06 +00:00
|
|
|
cs = sprite[ud.camerasprite].sectnum;
|
|
|
|
ca = sprite[ud.camerasprite].ang;
|
|
|
|
}
|
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
int sndnum = 0;
|
|
|
|
int const highest = g_highestSoundIdx;
|
2009-07-24 02:31:34 +00:00
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
do
|
2009-07-24 02:31:34 +00:00
|
|
|
{
|
2018-05-04 22:42:37 +00:00
|
|
|
if (g_sounds[sndnum].num == 0)
|
2018-04-21 06:04:39 +00:00
|
|
|
continue;
|
|
|
|
|
2019-01-12 00:21:58 +00:00
|
|
|
S_Cleanup();
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto &voice : g_sounds[sndnum].voices)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
int const spriteNum = voice.owner;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if ((unsigned)spriteNum >= MAXSPRITES || voice.id <= FX_Ok || !FX_SoundActive(voice.id))
|
2010-06-22 21:50:01 +00:00
|
|
|
continue;
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
int sndist, sndang;
|
2010-01-23 22:12:02 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
S_CalcDistAndAng(spriteNum, sndnum, cs, ca, c, (const vec3_t *)&sprite[spriteNum], &sndist, &sndang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
if (S_IsAmbientSFX(spriteNum))
|
2008-11-20 14:06:36 +00:00
|
|
|
g_numEnvSoundsPlaying++;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-03-31 18:58:17 +00:00
|
|
|
// AMBIENT_SOUND
|
2018-10-25 23:32:50 +00:00
|
|
|
FX_Pan3D(voice.id, sndang >> 4, sndist >> 6);
|
2018-10-25 23:32:29 +00:00
|
|
|
voice.dist = sndist >> 6;
|
|
|
|
voice.clock++;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2018-10-25 23:32:29 +00:00
|
|
|
} while (++sndnum <= highest);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-01-13 23:26:50 +00:00
|
|
|
// S_Callback() can be called from either the audio thread when a sound ends, or the main thread
|
|
|
|
// when playing back a new sound needs an existing sound to be stopped first
|
2019-09-19 18:22:09 +00:00
|
|
|
void S_Callback(intptr_t num)
|
2010-01-05 21:53:14 +00:00
|
|
|
{
|
2019-09-21 11:02:17 +00:00
|
|
|
if ((int32_t)num == MUSIC_ID)
|
2010-01-05 21:53:14 +00:00
|
|
|
return;
|
|
|
|
|
2019-08-09 09:28:42 +00:00
|
|
|
mutex_lock(&m_callback);
|
|
|
|
unative_t const ldnum = dnum;
|
2019-09-21 11:02:17 +00:00
|
|
|
dq[ldnum & (DQSIZE - 1)] = (uint32_t)num;
|
2019-08-09 09:28:42 +00:00
|
|
|
dnum++;
|
|
|
|
mutex_unlock(&m_callback);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_ClearSoundLocks(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-05-03 04:44:36 +00:00
|
|
|
#ifdef CACHING_DOESNT_SUCK
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i;
|
2018-04-02 22:00:11 +00:00
|
|
|
int32_t const msp = g_highestSoundIdx;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-05-04 22:42:37 +00:00
|
|
|
for (native_t i = 0; i <= msp; ++i)
|
2009-07-12 01:55:34 +00:00
|
|
|
if (g_soundlocks[i] >= 200)
|
|
|
|
g_soundlocks[i] = 199;
|
2018-05-03 04:44:36 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
int A_CheckSoundPlaying(int spriteNum, int soundNum)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return 0;
|
2009-07-15 01:26:38 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
if (g_sounds[soundNum].num > 0 && spriteNum >= 0)
|
2009-07-15 01:26:38 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto &voice : g_sounds[soundNum].voices)
|
|
|
|
if (voice.owner == spriteNum)
|
2009-07-15 01:26:38 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
return (spriteNum == -1) ? (g_sounds[soundNum].num != 0) : 0;
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|
|
|
|
|
2013-01-02 22:33:32 +00:00
|
|
|
// Check if actor <i> is playing any sound.
|
2019-08-07 22:44:29 +00:00
|
|
|
int A_CheckAnySoundPlaying(int spriteNum)
|
2013-01-02 22:33:32 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
int const msp = g_highestSoundIdx;
|
2013-01-02 22:33:32 +00:00
|
|
|
|
2018-10-25 23:32:29 +00:00
|
|
|
for (int j = 0; j <= msp; ++j)
|
2013-01-02 22:33:32 +00:00
|
|
|
{
|
2018-10-25 23:32:29 +00:00
|
|
|
for (auto &voice : g_sounds[j].voices)
|
|
|
|
if (voice.owner == spriteNum)
|
2013-01-02 22:33:32 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-08-07 22:44:29 +00:00
|
|
|
int S_CheckSoundPlaying(int soundNum)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2018-12-15 01:39:25 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return false;
|
|
|
|
return (g_sounds[soundNum].num != 0);
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|
2019-09-21 20:53:00 +00:00
|
|
|
END_DUKE_NS
|