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
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
2014-11-24 08:19:50 +00:00
|
|
|
#ifndef __STDC_FORMAT_MACROS
|
2012-11-05 02:49:08 +00:00
|
|
|
#define __STDC_FORMAT_MACROS
|
2014-11-24 08:19:50 +00:00
|
|
|
#endif
|
2014-07-10 09:01:48 +00:00
|
|
|
#ifndef __STDC_LIMIT_MACROS
|
2012-11-05 02:49:08 +00:00
|
|
|
#define __STDC_LIMIT_MACROS
|
2014-07-10 09:01:48 +00:00
|
|
|
#endif
|
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()
|
2010-07-19 15:14:00 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
#define DQSIZE 128
|
|
|
|
|
2014-02-02 15:56:11 +00:00
|
|
|
int32_t g_numEnvSoundsPlaying, g_maxSoundPos = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
static int32_t MusicIsWaveform = 0;
|
2015-02-11 05:22:00 +00:00
|
|
|
static char *MusicPtr = NULL;
|
2009-07-27 05:33:12 +00:00
|
|
|
static int32_t MusicVoice = -1;
|
|
|
|
static int32_t MusicPaused = 0;
|
2016-02-02 06:39:22 +00:00
|
|
|
static int32_t SoundPaused = 0;
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
static mutex_t s_mutex;
|
2015-02-11 05:22:00 +00:00
|
|
|
static volatile uint32_t dq[DQSIZE], dnum = 0;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2008-11-20 14:06:36 +00:00
|
|
|
void S_SoundStartup(void)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
void *initdata = NULL;
|
2006-04-16 03:42:36 +00:00
|
|
|
|
2013-10-07 10:05:03 +00:00
|
|
|
#ifdef MIXERTYPEWIN
|
2012-11-25 04:26:37 +00:00
|
|
|
initdata = (void *) win_gethwnd(); // used for DirectSound
|
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
|
|
|
|
2016-08-27 01:39:38 +00:00
|
|
|
if (FX_Init(ud.config.NumVoices, ud.config.NumChannels, ud.config.MixRate, initdata) != FX_Ok)
|
2006-11-15 01:16:55 +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("failed! %s\n", FX_ErrorString(FX_Error));
|
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
|
|
|
|
2012-03-10 21:21:42 +00:00
|
|
|
initprintf("%d voices, %d channels, %d-bit %d Hz\n", ud.config.NumVoices, ud.config.NumChannels,
|
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
|
|
|
ud.config.NumBits, ud.config.MixRate);
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<g_maxSoundPos; ++i)
|
2010-08-02 08:13:51 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j = 0; j<MAXSOUNDINSTANCES; ++j)
|
2010-08-02 08:13:51 +00:00
|
|
|
{
|
|
|
|
g_sounds[i].num = 0;
|
|
|
|
g_sounds[i].SoundOwner[j].voice = 0;
|
2012-03-10 21:22:44 +00:00
|
|
|
g_sounds[i].SoundOwner[j].ow = -1;
|
2012-10-08 07:07:59 +00:00
|
|
|
g_sounds[i].SoundOwner[j].sndist = UINT32_MAX;
|
|
|
|
g_sounds[i].SoundOwner[j].clock = 0;
|
2010-08-02 08:13:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_soundlocks[i] = 199;
|
|
|
|
}
|
|
|
|
|
2013-08-06 23:53:55 +00:00
|
|
|
FX_SetVolume(ud.config.MasterVolume);
|
2014-02-01 16:19:58 +00:00
|
|
|
S_MusicVolume(MASTER_VOLUME(ud.config.MusicVolume));
|
|
|
|
|
2009-08-06 10:12:13 +00:00
|
|
|
FX_SetReverseStereo(ud.config.ReverseStereo);
|
2010-03-01 09:09:26 +00:00
|
|
|
FX_SetCallBack(S_Callback);
|
2010-06-22 21:50:01 +00:00
|
|
|
FX_SetPrintf(initprintf);
|
|
|
|
mutex_init(&s_mutex);
|
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();
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
if (FX_Shutdown() != FX_Ok)
|
2006-11-15 01:16:55 +00:00
|
|
|
{
|
2010-03-01 09:09:26 +00:00
|
|
|
Bsprintf(tempbuf, "S_SoundShutdown(): error: %s", FX_ErrorString(FX_Error));
|
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
|
|
|
{
|
2009-07-09 02:29:48 +00:00
|
|
|
initprintf("Initializing music...\n");
|
|
|
|
|
2016-03-07 11:22:07 +00:00
|
|
|
if (MUSIC_Init(0, 0) == MUSIC_Ok || MUSIC_Init(1, 0) == MUSIC_Ok)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2013-08-06 23:53:55 +00:00
|
|
|
MUSIC_SetVolume(MASTER_VOLUME(ud.config.MusicVolume));
|
2010-03-01 09:09:26 +00:00
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2009-02-28 07:44:54 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
initprintf("S_MusicStartup(): failed initializing\n");
|
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();
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
if (MUSIC_Shutdown() != MUSIC_Ok)
|
2013-04-13 03:49:35 +00:00
|
|
|
initprintf("%s\n", MUSIC_ErrorString(MUSIC_ErrorCode));
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
void S_PauseMusic(int32_t onf)
|
|
|
|
{
|
|
|
|
if (MusicPaused == onf || (MusicIsWaveform && MusicVoice < 0))
|
|
|
|
return;
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
MusicPaused = onf;
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
if (MusicIsWaveform)
|
2009-07-31 11:45:29 +00:00
|
|
|
{
|
2010-03-01 09:09:26 +00:00
|
|
|
FX_PauseVoice(MusicVoice, onf);
|
|
|
|
return;
|
2009-07-31 11:45:29 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
if (onf)
|
|
|
|
MUSIC_Pause();
|
|
|
|
else
|
|
|
|
MUSIC_Continue();
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
|
|
|
|
2016-02-02 06:39:22 +00:00
|
|
|
void S_PauseSounds(int32_t onf)
|
|
|
|
{
|
|
|
|
if (SoundPaused == onf)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SoundPaused = onf;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<g_maxSoundPos; ++i)
|
2016-02-02 06:39:22 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j = 0; j<MAXSOUNDINSTANCES; ++j)
|
2016-02-02 06:39:22 +00:00
|
|
|
{
|
|
|
|
if (g_sounds[i].SoundOwner[j].voice > 0)
|
|
|
|
FX_PauseVoice(g_sounds[i].SoundOwner[j].voice, onf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2016-08-27 01:42:01 +00:00
|
|
|
if (g_mapInfo[g_musicIndex].musicfn != NULL)
|
|
|
|
S_PlayMusic(g_mapInfo[g_musicIndex].musicfn);
|
2014-09-07 18:10:09 +00:00
|
|
|
}
|
2016-08-27 01:42:01 +00:00
|
|
|
else if (g_mapInfo[MUS_INTRO].musicfn != 0 && (G_GetLogoFlags() & LOGO_PLAYMUSIC))
|
2014-09-07 18:10:14 +00:00
|
|
|
{
|
2015-04-24 00:10:00 +00:00
|
|
|
g_musicIndex = MUS_INTRO;
|
2016-08-27 01:42:01 +00:00
|
|
|
S_PlayMusic(g_mapInfo[MUS_INTRO].musicfn);
|
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
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
static int32_t SoundNum;
|
|
|
|
int32_t const menusnds[] = {
|
|
|
|
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
|
|
|
};
|
2014-03-22 09:25:15 +00:00
|
|
|
S_PlaySound(menusnds[SoundNum++ % ARRAY_SIZE(menusnds)]);
|
2008-04-01 09:06:29 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
2015-01-25 12:17:59 +00:00
|
|
|
int32_t S_PlayMusic(const char *fn)
|
2009-07-27 05:33:12 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
if (!ud.config.MusicToggle || fn == NULL)
|
2014-12-28 22:12:40 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-11-25 12:08:10 +00:00
|
|
|
int32_t fp = S_OpenAudio(fn, 0, 1);
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(fp < 0))
|
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);
|
2009-08-09 05:32:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
|
|
|
|
S_StopMusic();
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t MusicLen = kfilelength(fp);
|
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);
|
|
|
|
kclose(fp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
ALIGNED_FREE_AND_NULL(MusicPtr); // in case the following allocation was never freed
|
|
|
|
MusicPtr = (char *)Xaligned_alloc(16, MusicLen);
|
2014-02-02 15:56:11 +00:00
|
|
|
g_musicSize = kread(fp, (char *)MusicPtr, MusicLen);
|
|
|
|
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(g_musicSize != MusicLen))
|
2014-02-02 15:56:11 +00:00
|
|
|
{
|
|
|
|
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n",
|
|
|
|
g_musicSize, fn, MusicLen);
|
2009-08-09 05:32:17 +00:00
|
|
|
kclose(fp);
|
|
|
|
g_musicSize = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-27 05:33:12 +00:00
|
|
|
kclose(fp);
|
|
|
|
|
2009-07-27 10:46:42 +00:00
|
|
|
if (!Bmemcmp(MusicPtr, "MThd", 4))
|
2009-07-27 05:33:12 +00:00
|
|
|
{
|
|
|
|
MUSIC_PlaySong(MusicPtr, MUSIC_LoopSong);
|
|
|
|
MusicIsWaveform = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t const mvol = MASTER_VOLUME(ud.config.MusicVolume);
|
2016-08-27 01:39:38 +00:00
|
|
|
MusicVoice = FX_Play(MusicPtr, MusicLen, 0, 0,
|
2013-03-31 18:58:17 +00:00
|
|
|
0, mvol, mvol, mvol,
|
|
|
|
FX_MUSIC_PRIORITY, MUSIC_ID);
|
|
|
|
if (MusicVoice > FX_Ok)
|
2009-08-09 05:32:17 +00:00
|
|
|
MusicIsWaveform = 1;
|
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
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
static uint32_t ldq[DQSIZE];
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
// process from our own local copy of the delete queue so we don't hold the lock long
|
2010-06-22 21:50:01 +00:00
|
|
|
mutex_lock(&s_mutex);
|
|
|
|
|
2016-01-11 05:05:38 +00:00
|
|
|
uint32_t ldnum = dnum;
|
|
|
|
|
|
|
|
if (!ldnum)
|
2010-06-22 21:50:01 +00:00
|
|
|
{
|
|
|
|
mutex_unlock(&s_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dnum = 0;
|
|
|
|
|
2016-01-11 05:05:38 +00:00
|
|
|
for (uint32_t i = 0; i < ldnum; i++)
|
|
|
|
ldq[i] = dq[i];
|
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
mutex_unlock(&s_mutex);
|
|
|
|
|
2016-01-11 05:05:38 +00:00
|
|
|
ldnum--;
|
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
do
|
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
uint32_t num = ldq[ldnum];
|
2010-06-22 21:50:01 +00:00
|
|
|
|
|
|
|
// negative index is RTS playback
|
|
|
|
if ((int32_t)num < 0)
|
|
|
|
{
|
2010-08-02 08:13:51 +00:00
|
|
|
if (rts_lumplockbyte[-(int32_t)num] >= 200)
|
|
|
|
rts_lumplockbyte[-(int32_t)num]--;
|
2010-06-22 21:50:01 +00:00
|
|
|
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
|
|
|
{
|
2011-10-30 19:48:46 +00:00
|
|
|
g_soundlocks[num-(MAXSOUNDS*MAXSOUNDINSTANCES)]--;
|
2011-05-28 14:15:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t j = num & (MAXSOUNDINSTANCES-1);
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
num = (num - j) / MAXSOUNDINSTANCES;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t i = g_sounds[num].SoundOwner[j].ow;
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(g_sounds[num].num > MAXSOUNDINSTANCES))
|
|
|
|
OSD_Printf(OSD_ERROR "S_Cleanup(): num exceeds MAXSOUNDINSTANCES! g_sounds[%d].num %d wtf?\n", num, g_sounds[num].num);
|
2010-06-22 21:50:01 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (g_sounds[num].num > 0)
|
|
|
|
g_sounds[num].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
|
|
|
|
if (i != -1 && S_IsAmbientSFX(i) && sector[sprite[i].sectnum].lotag < 3) // ST_2_UNDERWATER
|
|
|
|
actor[i].t_data[0] = 0;
|
|
|
|
|
|
|
|
g_sounds[num].SoundOwner[j].ow = -1;
|
|
|
|
g_sounds[num].SoundOwner[j].voice = 0;
|
|
|
|
g_sounds[num].SoundOwner[j].sndist = UINT32_MAX;
|
|
|
|
g_sounds[num].SoundOwner[j].clock = 0;
|
2010-06-22 21:50:01 +00:00
|
|
|
|
|
|
|
g_soundlocks[num]--;
|
|
|
|
}
|
2015-02-11 05:22:00 +00:00
|
|
|
while (ldnum--);
|
2010-06-22 21:50:01 +00:00
|
|
|
}
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
// returns number of bytes read
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t S_LoadSound(uint32_t num)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (num > (unsigned)g_maxSoundPos || !ud.config.SoundToggle ) return 0;
|
2010-08-02 08:13:51 +00:00
|
|
|
|
2015-01-25 12:17:59 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(g_sounds[num].filename == NULL))
|
2008-01-26 03:59:34 +00:00
|
|
|
{
|
2008-07-27 01:22:17 +00:00
|
|
|
OSD_Printf(OSD_ERROR "Sound (#%d) not defined!\n",num);
|
2008-01-26 03:59:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-11-25 12:08:10 +00:00
|
|
|
int32_t fp = S_OpenAudio(g_sounds[num].filename, g_loadFromGroupOnly, 0);
|
2015-11-25 12:08:04 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(fp == -1))
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-11-25 12:08:04 +00:00
|
|
|
OSD_Printf(OSDTEXT_RED "Sound %s(#%d) not found!\n",g_sounds[num].filename,num);
|
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t l = kfilelength(fp);
|
2009-07-12 01:55:34 +00:00
|
|
|
g_soundlocks[num] = 200;
|
2015-02-11 05:22:00 +00:00
|
|
|
g_sounds[num].soundsiz = l;
|
2010-03-01 09:09:26 +00:00
|
|
|
allocache((intptr_t *)&g_sounds[num].ptr, l, (char *)&g_soundlocks[num]);
|
2012-03-13 20:07:40 +00:00
|
|
|
l = kread(fp, g_sounds[num].ptr, l);
|
2006-11-14 21:35:50 +00:00
|
|
|
kclose(fp);
|
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
|
|
|
}
|
|
|
|
|
2012-08-13 18:25:48 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
static inline int32_t S_GetPitch(int32_t num)
|
2012-08-13 18:25:48 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t const range = klabs(g_sounds[num].pe - g_sounds[num].ps);
|
|
|
|
return (range == 0) ? g_sounds[num].ps : min(g_sounds[num].ps, g_sounds[num].pe) + rand() % range;
|
2012-08-13 18:25:48 +00:00
|
|
|
}
|
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
static int32_t S_TakeSlot(int32_t num)
|
2012-08-13 18:25:48 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
S_Cleanup();
|
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
uint32_t dist = 0, clock = UINT32_MAX;
|
|
|
|
int32_t i = 0, j = 0;
|
2012-08-13 18:25:48 +00:00
|
|
|
|
|
|
|
while (j < MAXSOUNDINSTANCES && g_sounds[num].SoundOwner[j].voice > 0)
|
2012-10-08 07:07:59 +00:00
|
|
|
{
|
|
|
|
if (g_sounds[num].SoundOwner[j].sndist > dist ||
|
|
|
|
(g_sounds[num].SoundOwner[j].sndist == dist && g_sounds[num].SoundOwner[j].clock < clock))
|
|
|
|
{
|
|
|
|
clock = g_sounds[num].SoundOwner[j].clock;
|
|
|
|
dist = g_sounds[num].SoundOwner[j].sndist;
|
|
|
|
i = j;
|
|
|
|
}
|
|
|
|
|
2012-08-13 18:25:48 +00:00
|
|
|
j++;
|
2012-10-08 07:07:59 +00:00
|
|
|
}
|
2012-08-13 18:25:48 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
if (j != MAXSOUNDINSTANCES)
|
|
|
|
return j;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
if (FX_SoundActive(g_sounds[num].SoundOwner[i].voice))
|
|
|
|
FX_StopSound(g_sounds[num].SoundOwner[i].voice);
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
mutex_lock(&s_mutex);
|
|
|
|
dq[dnum++] = (num * MAXSOUNDINSTANCES) + i;
|
|
|
|
mutex_unlock(&s_mutex);
|
|
|
|
S_Cleanup();
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
return i;
|
|
|
|
}
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
static int32_t S_GetSlot(int32_t num)
|
|
|
|
{
|
|
|
|
int32_t j = 0;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
while (j < MAXSOUNDINSTANCES && g_sounds[num].SoundOwner[j].voice > 0)
|
|
|
|
j++;
|
2012-10-08 07:07:17 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
return j == MAXSOUNDINSTANCES ? S_TakeSlot(num) : j;
|
2012-08-13 18:25:48 +00:00
|
|
|
}
|
|
|
|
|
2012-10-08 07:07:17 +00:00
|
|
|
static inline int32_t S_GetAngle(int32_t camang, const vec3_t *cam, const vec3_t *pos)
|
2012-08-13 18:25:53 +00:00
|
|
|
{
|
2012-10-08 07:07:59 +00:00
|
|
|
return (2048 + camang - getangle(cam->x-pos->x, cam->y-pos->y))&2047;
|
2012-08-13 18:25:53 +00:00
|
|
|
}
|
|
|
|
|
2012-08-13 18:25:51 +00:00
|
|
|
static int32_t S_CalcDistAndAng(int32_t i, int32_t num, int32_t camsect, int32_t camang,
|
|
|
|
const vec3_t *cam, const vec3_t *pos,
|
|
|
|
int32_t *sndistptr, int32_t *sndangptr)
|
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t sndang = 0, sndist = 0;
|
2012-08-13 18:25:51 +00:00
|
|
|
int32_t explosion = 0;
|
|
|
|
|
2016-08-27 01:40:35 +00:00
|
|
|
if (PN(i) == APLAYER && P_Get(i) == screenpeek)
|
2012-08-13 18:25:53 +00:00
|
|
|
goto sound_further_processing;
|
|
|
|
|
2012-10-08 07:07:17 +00:00
|
|
|
sndang = S_GetAngle(camang, 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
|
|
|
|
2016-08-27 01:40:35 +00:00
|
|
|
if (PN(i) == APLAYER && P_Get(i) == 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;
|
|
|
|
camsect = g_player[1].ps->cursectnum;
|
|
|
|
camang = g_player[1].ps->ang;
|
|
|
|
|
|
|
|
sndist = sndist2;
|
2012-10-08 07:07:17 +00:00
|
|
|
sndang = S_GetAngle(camang, 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
|
|
|
|
2016-08-27 01:40:35 +00:00
|
|
|
if ((g_sounds[num].m & SF_GLOBAL) == 0 && S_IsAmbientSFX(i) && (sector[SECT(i)].lotag&0xff) < 9) // ST_9_SLIDING_ST_DOOR
|
|
|
|
sndist = divscale14(sndist, SHT(i)+1);
|
2012-08-13 18:25:53 +00:00
|
|
|
|
|
|
|
sound_further_processing:
|
2012-08-13 18:25:51 +00:00
|
|
|
sndist += g_sounds[num].vo;
|
|
|
|
if (sndist < 0)
|
|
|
|
sndist = 0;
|
|
|
|
|
2016-08-27 01:40:35 +00:00
|
|
|
if (camsect > -1 && sndist && PN(i) != MUSICANDSFX &&
|
|
|
|
!cansee(cam->x,cam->y,cam->z-(24<<8),camsect, SX(i),SY(i),SZ(i)-(24<<8),SECT(i)))
|
2012-08-13 18:25:51 +00:00
|
|
|
sndist += sndist>>5;
|
|
|
|
|
2013-06-01 06:55:30 +00:00
|
|
|
switch (DYNAMICSOUNDMAP(num))
|
2012-08-13 18:25:51 +00:00
|
|
|
{
|
2013-06-01 06:55:30 +00:00
|
|
|
case PIPEBOMB_EXPLODE__STATIC:
|
|
|
|
case LASERTRIP_EXPLODE__STATIC:
|
|
|
|
case RPG_EXPLODE__STATIC:
|
2012-08-13 18:25:51 +00:00
|
|
|
explosion = 1;
|
|
|
|
if (sndist > 6144)
|
|
|
|
sndist = 6144;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-09-08 20:18:56 +00:00
|
|
|
if ((g_sounds[num].m & SF_GLOBAL) || sndist < ((255-LOUDESTVOLUME)<<6))
|
2012-08-13 18:25:51 +00:00
|
|
|
sndist = ((255-LOUDESTVOLUME)<<6);
|
|
|
|
|
|
|
|
*sndistptr = sndist;
|
|
|
|
*sndangptr = sndang;
|
|
|
|
|
|
|
|
return explosion;
|
|
|
|
}
|
|
|
|
|
2009-08-06 10:12:13 +00:00
|
|
|
int32_t S_PlaySound3D(int32_t num, int32_t i, const vec3_t *pos)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t j = VM_OnEventWithReturn(EVENT_SOUND, i, screenpeek, num);
|
2014-06-23 02:24:10 +00:00
|
|
|
|
|
|
|
if (j == -1 && num != -1) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
num = j;
|
2012-05-17 17:33:29 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
const DukePlayer_t *const myps = g_player[myconnectindex].ps;
|
|
|
|
|
|
|
|
if ((unsigned)num > (unsigned)g_maxSoundPos || ((g_sounds[num].m & SF_ADULT) && ud.lockout) ||
|
|
|
|
!ud.config.SoundToggle || (unsigned)i >= MAXSPRITES || !FX_VoiceAvailable(g_sounds[num].pr) ||
|
|
|
|
(myps->timebeforeexit > 0 && myps->timebeforeexit <= GAMETICSPERSEC * 3) || (myps->gm & MODE_MENU))
|
2013-03-31 18:58:17 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t voice;
|
|
|
|
|
2013-09-08 20:18:56 +00:00
|
|
|
if (g_sounds[num].m & SF_DTAG) // Duke-Tag sound
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2010-07-05 04:37:28 +00:00
|
|
|
if ((voice = S_PlaySound(num)) <= FX_Ok)
|
|
|
|
return -1;
|
|
|
|
|
2014-06-23 02:24:10 +00:00
|
|
|
j = 0;
|
2010-07-05 04:37:28 +00:00
|
|
|
while (j < MAXSOUNDINSTANCES && g_sounds[num].SoundOwner[j].voice != voice)
|
2010-06-22 21:50:01 +00:00
|
|
|
j++;
|
2010-01-05 21:53:14 +00:00
|
|
|
|
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;
|
|
|
|
}
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2012-03-10 21:22:44 +00:00
|
|
|
g_sounds[num].SoundOwner[j].ow = i;
|
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
|
|
|
}
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
// Duke talk
|
2013-09-08 20:18:56 +00:00
|
|
|
if (g_sounds[num].m & SF_TALK)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-08-27 01:40:35 +00:00
|
|
|
if ((g_netServer || ud.multimode > 1) && PN(i) == APLAYER && P_Get(i) != screenpeek) // other player sound
|
2008-07-28 21:23:10 +00:00
|
|
|
{
|
|
|
|
if (!(ud.config.VoiceToggle&4))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (!(ud.config.VoiceToggle&1))
|
2006-04-16 03:42:36 +00:00
|
|
|
return -1;
|
2010-03-01 09:09:26 +00:00
|
|
|
|
|
|
|
// don't play if any Duke talk sounds are already playing
|
2015-02-11 05:22:00 +00:00
|
|
|
for (j=0; j<g_maxSoundPos; ++j)
|
2013-09-08 20:18:56 +00:00
|
|
|
if ((g_sounds[j].m & SF_TALK) && g_sounds[j].num > 0)
|
2010-03-01 09:09:26 +00:00
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t sndist, sndang;
|
|
|
|
int32_t explosionp = S_CalcDistAndAng(i, num, CAMERA(sect), CAMERA(ang), &CAMERA(pos), pos, &sndist, &sndang);
|
|
|
|
int32_t pitch = S_GetPitch(num);
|
|
|
|
const DukePlayer_t *peekps = 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
|
|
|
|
if (g_player[1].ps->i == i)
|
|
|
|
peekps = g_player[1].ps;
|
|
|
|
}
|
2014-01-12 14:04:51 +00:00
|
|
|
#endif
|
2012-08-22 22:50:32 +00:00
|
|
|
|
2012-08-13 18:25:51 +00:00
|
|
|
if (peekps->sound_pitch)
|
|
|
|
pitch += peekps->sound_pitch;
|
|
|
|
|
|
|
|
if (explosionp)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-10-14 20:41:21 +00:00
|
|
|
if (peekps->cursectnum > -1 && sector[peekps->cursectnum].lotag == ST_2_UNDERWATER)
|
2006-11-16 03:02:42 +00:00
|
|
|
pitch -= 1024;
|
2012-08-13 18:25:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-27 01:40:35 +00:00
|
|
|
if (sndist > 32767 && PN(i) != MUSICANDSFX && (g_sounds[num].m & (SF_LOOP|SF_MSFX)) == 0)
|
2011-03-04 08:50:58 +00:00
|
|
|
return -1;
|
2012-08-13 18:25:51 +00:00
|
|
|
|
2013-09-08 20:18:56 +00:00
|
|
|
if (peekps->cursectnum > -1 && sector[peekps->cursectnum].lotag == ST_2_UNDERWATER
|
|
|
|
&& (g_sounds[num].m & SF_TALK) == 0)
|
2006-11-16 03:02:42 +00:00
|
|
|
pitch = -768;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-08-27 01:40:35 +00:00
|
|
|
if (g_sounds[num].num > 0 && PN(i) != MUSICANDSFX)
|
2010-03-01 09:09:26 +00:00
|
|
|
S_StopEnvSound(num, i);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2007-09-11 05:26:38 +00:00
|
|
|
if (g_sounds[num].ptr == 0)
|
2006-11-15 01:16:55 +00:00
|
|
|
{
|
2010-03-01 09:09:26 +00:00
|
|
|
if (S_LoadSound(num) == 0)
|
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2010-08-02 08:13:51 +00:00
|
|
|
else
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
if (g_soundlocks[num] < 200)
|
|
|
|
g_soundlocks[num] = 200;
|
|
|
|
else g_soundlocks[num]++;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
j = S_GetSlot(num);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
if (j >= MAXSOUNDINSTANCES)
|
|
|
|
{
|
|
|
|
g_soundlocks[num]--;
|
|
|
|
return -1;
|
|
|
|
}
|
2010-01-05 21:53:14 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
{
|
2013-09-08 20:18:56 +00:00
|
|
|
const int32_t repeatp = (g_sounds[num].m & SF_LOOP);
|
2013-03-31 18:58:17 +00:00
|
|
|
const int32_t ambsfxp = S_IsAmbientSFX(i);
|
|
|
|
|
2013-09-08 20:18:56 +00:00
|
|
|
if (repeatp && (g_sounds[num].m & SF_ONEINST_INTERNAL) && g_sounds[num].num > 0)
|
2010-06-22 21:50:01 +00:00
|
|
|
{
|
|
|
|
g_soundlocks[num]--;
|
|
|
|
return -1;
|
|
|
|
}
|
2014-02-02 15:56:11 +00:00
|
|
|
|
2013-03-31 18:58:17 +00:00
|
|
|
if (repeatp && !ambsfxp)
|
|
|
|
{
|
2016-08-27 01:39:38 +00:00
|
|
|
voice = FX_Play(g_sounds[num].ptr, g_sounds[num].soundsiz, 0, -1,
|
2013-08-06 23:53:55 +00:00
|
|
|
pitch, FX_VOLUME(sndist>>6), FX_VOLUME(sndist>>6), 0, // XXX: why is 'right' 0?
|
2013-03-31 18:58:17 +00:00
|
|
|
g_sounds[num].pr, (num * MAXSOUNDINSTANCES) + j);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Ambient MUSICANDSFX always start playing using the 3D routines!
|
2016-08-27 01:39:24 +00:00
|
|
|
voice = FX_Play3D(g_sounds[num].ptr, g_sounds[num].soundsiz,
|
2013-03-31 22:29:30 +00:00
|
|
|
repeatp ? FX_LOOP : FX_ONESHOT,
|
2013-08-06 23:53:55 +00:00
|
|
|
pitch, sndang>>4, FX_VOLUME(sndist>>6),
|
2013-03-31 18:58:17 +00:00
|
|
|
g_sounds[num].pr, (num * MAXSOUNDINSTANCES) + j);
|
|
|
|
}
|
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
|
|
|
{
|
2010-07-03 08:53:57 +00:00
|
|
|
g_soundlocks[num]--;
|
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2010-03-01 09:09:26 +00:00
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
g_sounds[num].num++;
|
2012-03-10 21:22:44 +00:00
|
|
|
g_sounds[num].SoundOwner[j].ow = i;
|
2010-07-03 08:53:57 +00:00
|
|
|
g_sounds[num].SoundOwner[j].voice = voice;
|
2012-10-08 07:07:59 +00:00
|
|
|
g_sounds[num].SoundOwner[j].sndist = sndist>>6;
|
|
|
|
g_sounds[num].SoundOwner[j].clock = totalclock;
|
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
|
|
|
}
|
|
|
|
|
2009-07-15 01:26:38 +00:00
|
|
|
int32_t S_PlaySound(int32_t num)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-13 18:25:48 +00:00
|
|
|
int32_t pitch;
|
2010-07-03 08:53:57 +00:00
|
|
|
int32_t voice, j;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-11-22 12:29:25 +00:00
|
|
|
j = VM_OnEventWithReturn(EVENT_SOUND, g_player[screenpeek].ps->i, screenpeek, num);
|
2014-06-23 02:24:10 +00:00
|
|
|
|
|
|
|
if (j == -1 && num != -1) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
num = j;
|
2012-05-17 17:33:29 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (!ud.config.SoundToggle) return -1;
|
2012-01-10 23:44:49 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_maxSoundPos || (g_sounds[num].filename == 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
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (!ud.config.SoundToggle || (!(ud.config.VoiceToggle & 1) && (g_sounds[num].m & SF_TALK)) ||
|
|
|
|
((g_sounds[num].m & SF_ADULT) && ud.lockout) || !FX_VoiceAvailable(g_sounds[num].pr))
|
|
|
|
return -1;
|
2012-01-10 23:44:49 +00:00
|
|
|
|
2012-10-08 07:07:17 +00:00
|
|
|
pitch = S_GetPitch(num);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (g_sounds[num].ptr == NULL && !S_LoadSound(num))
|
|
|
|
return -1;
|
2010-08-02 08:13:51 +00:00
|
|
|
else
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
|
|
|
if (g_soundlocks[num] < 200)
|
|
|
|
g_soundlocks[num] = 200;
|
|
|
|
else g_soundlocks[num]++;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
j = S_GetSlot(num);
|
2010-07-03 08:53:57 +00:00
|
|
|
|
2012-10-08 07:07:59 +00:00
|
|
|
if (j >= MAXSOUNDINSTANCES)
|
|
|
|
{
|
|
|
|
g_soundlocks[num]--;
|
|
|
|
return -1;
|
|
|
|
}
|
2010-08-02 08:13:51 +00:00
|
|
|
|
2013-09-08 20:18:56 +00:00
|
|
|
if (g_sounds[num].m & SF_LOOP)
|
2016-08-27 01:39:38 +00:00
|
|
|
voice = FX_Play(g_sounds[num].ptr, g_sounds[num].soundsiz, 0, -1,
|
2013-08-06 23:53:55 +00:00
|
|
|
pitch,FX_VOLUME(LOUDESTVOLUME), FX_VOLUME(LOUDESTVOLUME), FX_VOLUME(LOUDESTVOLUME),
|
2013-03-31 18:58:17 +00:00
|
|
|
g_sounds[num].soundsiz, (num * MAXSOUNDINSTANCES) + j);
|
|
|
|
else
|
2016-08-27 01:39:24 +00:00
|
|
|
voice = FX_Play3D(g_sounds[num].ptr, g_sounds[num].soundsiz, FX_ONESHOT,
|
2013-08-06 23:53:55 +00:00
|
|
|
pitch, 0, FX_VOLUME(255-LOUDESTVOLUME),
|
2013-03-31 18:58:17 +00:00
|
|
|
g_sounds[num].pr, (num * MAXSOUNDINSTANCES) + j);
|
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
|
|
|
{
|
2010-03-01 09:09:26 +00:00
|
|
|
g_soundlocks[num]--;
|
|
|
|
return -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
g_sounds[num].num++;
|
2012-03-10 21:22:44 +00:00
|
|
|
g_sounds[num].SoundOwner[j].ow = -1;
|
2010-07-03 08:53:57 +00:00
|
|
|
g_sounds[num].SoundOwner[j].voice = voice;
|
2012-10-08 07:07:59 +00:00
|
|
|
g_sounds[num].SoundOwner[j].sndist = 255-LOUDESTVOLUME;
|
|
|
|
g_sounds[num].SoundOwner[j].clock = totalclock;
|
2010-03-01 09:09:26 +00:00
|
|
|
return voice;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t A_PlaySound(uint32_t num, int32_t i)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_maxSoundPos)) return -1;
|
2012-05-14 18:12:27 +00:00
|
|
|
|
2016-06-05 04:46:28 +00:00
|
|
|
return (unsigned)i >= MAXSPRITES ? S_PlaySound(num) :
|
2012-05-16 00:45:10 +00:00
|
|
|
S_PlaySound3D(num, i, (vec3_t *)&sprite[i]);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
void S_StopEnvSound(int32_t num, int32_t i)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2010-06-26 08:51:42 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_maxSoundPos) || g_sounds[num].num <= 0)
|
2010-03-01 09:09:26 +00:00
|
|
|
return;
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t j;
|
|
|
|
|
2010-07-03 08:53:57 +00:00
|
|
|
do
|
2010-06-26 08:51:42 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
for (j=0; j<MAXSOUNDINSTANCES; ++j)
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
2012-03-10 21:22:44 +00:00
|
|
|
if ((i == -1 && g_sounds[num].SoundOwner[j].voice > FX_Ok) || (i != -1 && g_sounds[num].SoundOwner[j].ow == i))
|
2010-05-02 23:27:30 +00:00
|
|
|
{
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(i >= 0 && g_sounds[num].SoundOwner[j].voice <= FX_Ok))
|
2010-06-26 08:51:42 +00:00
|
|
|
initprintf(OSD_ERROR "S_StopEnvSound(): bad voice %d for sound ID %d index %d!\n", g_sounds[num].SoundOwner[j].voice, num, j);
|
2012-10-14 22:09:16 +00:00
|
|
|
else if (g_sounds[num].SoundOwner[j].voice > FX_Ok)
|
|
|
|
{
|
2010-06-26 08:51:42 +00:00
|
|
|
FX_StopSound(g_sounds[num].SoundOwner[j].voice);
|
2015-02-11 05:22:00 +00:00
|
|
|
S_Cleanup();
|
|
|
|
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
|
|
|
}
|
2015-02-11 05:22:00 +00:00
|
|
|
while (j < MAXSOUNDINSTANCES);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2011-11-03 23:08:54 +00:00
|
|
|
void S_ChangeSoundPitch(int32_t num, int32_t i, int32_t pitchoffset)
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((unsigned)num > (unsigned)g_maxSoundPos || g_sounds[num].num <= 0)
|
|
|
|
return;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<MAXSOUNDINSTANCES; ++j)
|
2011-11-03 23:08:54 +00:00
|
|
|
{
|
|
|
|
int32_t voice = g_sounds[num].SoundOwner[j].voice;
|
|
|
|
|
2012-03-10 21:22:44 +00:00
|
|
|
if ((i == -1 && voice > FX_Ok) || (i != -1 && g_sounds[num].SoundOwner[j].ow == i))
|
2011-11-03 23:08:54 +00:00
|
|
|
{
|
2014-10-29 17:05:46 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(i >= 0 && voice <= FX_Ok))
|
2016-08-27 01:41:33 +00:00
|
|
|
initprintf(OSD_ERROR "S_ChangeSoundPitch(): bad voice %d for sound ID %d index %zd!\n", voice, num, j);
|
2011-11-03 23:08:54 +00:00
|
|
|
else if (voice > FX_Ok && FX_SoundActive(voice))
|
|
|
|
FX_SetPitch(voice, pitchoffset);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-02 23:27:30 +00:00
|
|
|
void S_Update(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2010-06-22 21:50:01 +00:00
|
|
|
S_Cleanup();
|
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
|
|
|
{
|
2013-01-19 18:28:32 +00:00
|
|
|
c = &CAMERA(pos);
|
|
|
|
cs = CAMERA(sect);
|
|
|
|
ca = CAMERA(ang);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-01 09:09:26 +00:00
|
|
|
c = (vec3_t *)&sprite[ud.camerasprite];
|
2006-04-13 20:47:06 +00:00
|
|
|
cs = sprite[ud.camerasprite].sectnum;
|
|
|
|
ca = sprite[ud.camerasprite].ang;
|
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t num = g_maxSoundPos;
|
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
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t k=0; k<MAXSOUNDINSTANCES; ++k)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-08-13 18:25:48 +00:00
|
|
|
int32_t i = g_sounds[num].SoundOwner[k].ow;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
if ((unsigned)i >= MAXSPRITES || g_sounds[num].num == 0 || g_sounds[num].SoundOwner[k].voice <= FX_Ok ||
|
|
|
|
!FX_SoundActive(g_sounds[num].SoundOwner[k].voice))
|
2010-06-22 21:50:01 +00:00
|
|
|
continue;
|
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t sndist, sndang;
|
2010-01-23 22:12:02 +00:00
|
|
|
|
2012-08-13 18:25:51 +00:00
|
|
|
S_CalcDistAndAng(i, num, cs, ca, c, (const vec3_t *)&sprite[i], &sndist, &sndang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-03-31 18:58:17 +00:00
|
|
|
if (S_IsAmbientSFX(i))
|
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
|
2013-08-06 23:53:55 +00:00
|
|
|
FX_Pan3D(g_sounds[num].SoundOwner[k].voice, sndang>>4, FX_VOLUME(sndist>>6));
|
2012-10-08 07:07:59 +00:00
|
|
|
g_sounds[num].SoundOwner[k].sndist = sndist>>6;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2009-07-27 05:33:12 +00:00
|
|
|
}
|
2012-08-13 18:25:48 +00:00
|
|
|
while (num--);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2010-02-23 18:13:46 +00:00
|
|
|
void S_Callback(uint32_t num)
|
2010-01-05 21:53:14 +00:00
|
|
|
{
|
|
|
|
if ((int32_t)num == MUSIC_ID)
|
|
|
|
return;
|
|
|
|
|
2010-06-22 21:50:01 +00:00
|
|
|
mutex_lock(&s_mutex);
|
|
|
|
dq[dnum++] = num;
|
|
|
|
mutex_unlock(&s_mutex);
|
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
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i;
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t const msp = g_maxSoundPos;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:00 +00:00
|
|
|
for (i = 0; i < 11; ++i)
|
|
|
|
if (rts_lumplockbyte[i] >= 200)
|
|
|
|
rts_lumplockbyte[i] = 199;
|
|
|
|
|
|
|
|
for (i = 0; i < msp; ++i)
|
2009-07-12 01:55:34 +00:00
|
|
|
if (g_soundlocks[i] >= 200)
|
|
|
|
g_soundlocks[i] = 199;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t A_CheckSoundPlaying(int32_t i, int32_t num)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_maxSoundPos)) return 0;
|
2009-07-15 01:26:38 +00:00
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
if (g_sounds[num].num > 0 && i >= 0)
|
2009-07-15 01:26:38 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<MAXSOUNDINSTANCES; ++j)
|
2012-03-10 21:22:44 +00:00
|
|
|
if (g_sounds[num].SoundOwner[j].ow == i)
|
2009-07-15 01:26:38 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-03-01 09:09:26 +00:00
|
|
|
return (i == -1) ? g_sounds[num].num : 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.
|
|
|
|
int32_t A_CheckAnySoundPlaying(int32_t i)
|
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
int32_t const msp = g_maxSoundPos;
|
|
|
|
int32_t k;
|
2013-01-02 22:33:32 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<msp; ++j)
|
2013-01-02 22:33:32 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
for (k=0; k<MAXSOUNDINSTANCES; ++k)
|
2013-01-02 22:33:32 +00:00
|
|
|
if (g_sounds[j].SoundOwner[k].ow == i)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t S_CheckSoundPlaying(int32_t i, int32_t num)
|
2006-04-16 03:42:36 +00:00
|
|
|
{
|
2015-02-11 05:22:00 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_maxSoundPos)) return 0;
|
2015-04-18 21:37:13 +00:00
|
|
|
return (i == -1) ? (g_soundlocks[num] > 200) : g_sounds[num].num;
|
2006-04-16 03:42:36 +00:00
|
|
|
}
|