Commit 5d916bab authored by Dino Bollinger's avatar Dino Bollinger
Browse files

Duke3D: Add CON commands 'definesoundv', 'setactorsoundvolume' and 'setglobalsoundvolume'

'definesoundv <soundID> <file> <pitch_lower> <pitch_upper> <priority> <type> <distance> <volume>':
Variant of definesound, takes one extra argument which sets the global volume for all instances of this sound.
The second to last parameter specifies how far a sound is audible, like the original 'definesound' command.

'setactorsoundvolume <spriteID> <soundID> <newVolume>':
Like 'setactorsoundpitch', allows scripts to change the volume of currently active sounds,
which are addressed based on sprite and sound ID.

'setglobalsoundvolume <soundID> <newVolume>':
Alters the volume of all future instances of the corresponding sound ID.
However, it does not affect currently active sounds.

For all commands, <volume> ranges from 0 to 4096, where 1024 is the default volume set by 'definesound'.
parent a399f5b0
......@@ -120,6 +120,7 @@ static FORCE_INLINE int FX_SetPan(int handle, int vol, int left, int right)
return FX_CheckMVErr(MV_SetPan(handle, vol, left, right));
}
static FORCE_INLINE int FX_SetPitch(int handle, int pitchoffset) { return FX_CheckMVErr(MV_SetPitch(handle, pitchoffset)); }
static FORCE_INLINE int FX_SetVoiceVolume(int handle, fix16_t volume) { return FX_CheckMVErr(MV_SetVoiceVolumeWithoutChannels(handle, volume)); }
static FORCE_INLINE int FX_SetFrequency(int handle, int frequency) { return FX_CheckMVErr(MV_SetFrequency(handle, frequency)); }
static FORCE_INLINE int32_t FX_GetFrequency(int handle, int *frequency) { return FX_CheckMVErr(MV_GetFrequency(handle, frequency)); }
static FORCE_INLINE int FX_Pan3D(int handle, int angle, int distance)
......
......@@ -93,6 +93,7 @@ int MV_Kill(int handle);
int MV_VoicesPlaying(void);
int MV_VoiceAvailable(int priority);
int MV_SetPitch(int handle, int pitchoffset);
int MV_SetVoiceVolumeWithoutChannels(int handle, fix16_t volume);
int MV_SetFrequency(int handle, int frequency);
int MV_GetFrequency(int handle, int *frequency);
int MV_PauseVoice(int handle, int pause);
......
......@@ -614,6 +614,19 @@ void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, fix16_t v
MV_SetVoiceMixMode(voice);
}
int MV_SetVoiceVolumeWithoutChannels(int handle, fix16_t volume)
{
auto voice = MV_BeginService(handle);
if (voice == nullptr)
return MV_Error;
voice->volume = volume;
MV_EndService();
return MV_Ok;
}
int MV_PauseVoice(int handle, int pause)
{
auto voice = MV_BeginService(handle);
......
......@@ -194,6 +194,7 @@ static tokenmap_t const vm_keywords[] =
{ "definequote", CON_DEFINEQUOTE },
{ "defineskillname", CON_DEFINESKILLNAME },
{ "definesound", CON_DEFINESOUND },
{ "definesoundv", CON_DEFINESOUNDV },
{ "definevolumeflags", CON_DEFINEVOLUMEFLAGS },
{ "definevolumename", CON_DEFINEVOLUMENAME },
{ "defstate", CON_DEFSTATE },
......@@ -461,6 +462,7 @@ static tokenmap_t const vm_keywords[] =
{ "setactor", CON_SETACTOR },
{ "setactorangle", CON_SETACTORANGLE },
{ "setactorsoundpitch", CON_SETACTORSOUNDPITCH },
{ "setactorsoundvolume", CON_SETACTORSOUNDVOLUME },
{ "setactorvar", CON_SETACTORVAR },
{ "setarray", CON_SETARRAY },
{ "setarraysequence", CON_SETARRAYSEQUENCE },
......@@ -476,6 +478,7 @@ static tokenmap_t const vm_keywords[] =
{ "setplayervar", CON_SETPLAYERVAR },
{ "setprojectile", CON_SETPROJECTILE },
{ "setsector", CON_SETSECTOR },
{ "setsoundvolume", CON_SETSOUNDVOLUME },
{ "setsprite", CON_SETSPRITE },
{ "setthisprojectile", CON_SETTHISPROJECTILE },
{ "settiledata", CON_SETTILEDATA },
......@@ -3600,6 +3603,7 @@ DO_DEFSTATE:
case CON_QGETSYSSTR:
case CON_QSTRCAT:
case CON_QSTRCPY:
case CON_SETSOUNDVOLUME:
case CON_SPAWNCEILINGGLASS:
case CON_SPAWNWALLGLASS:
case CON_SPAWNWALLSTAINEDGLASS:
......@@ -4815,6 +4819,7 @@ repeatcase:
case CON_GETKEYNAME:
case CON_QSTRNCAT:
case CON_SETACTORSOUNDPITCH:
case CON_SETACTORSOUNDVOLUME:
C_GetManyVars(3);
continue;
......@@ -5631,6 +5636,7 @@ repeatcase:
continue;
case CON_DEFINESOUND:
case CON_DEFINESOUNDV:
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE);
......@@ -5705,7 +5711,22 @@ repeatcase:
g_sounds[k].vo = g_scriptPtr[-1];
g_scriptPtr -= 5;
g_sounds[k].volume = fix16_one;
if (tw == CON_DEFINESOUNDV)
{
C_GetNextValue(LABEL_DEFINE);
i = g_scriptPtr[-1];
if (EDUKE32_PREDICT_FALSE((unsigned) i > MAXSCRIPTSOUNDVOL))
{
initprintf("%s:%d provided sound volume exceeds limit of %d.\n", g_scriptFileName, g_lineNumber, MAXSCRIPTSOUNDVOL);
g_errorCnt++;
i = (int) (fix16_one >> 6);
}
g_sounds[k].volume = (fix16_t) (i << 6);
g_scriptPtr--;
}
else
g_sounds[k].volume = fix16_one;
if (k > g_highestSoundIdx)
g_highestSoundIdx = k;
......
......@@ -1231,11 +1231,13 @@ enum IterationTypes_t
TRANSFORM(CON_SECTSETINTERPOLATION) DELIMITER \
TRANSFORM(CON_SETACTORANGLE) DELIMITER \
TRANSFORM(CON_SETACTORSOUNDPITCH) DELIMITER \
TRANSFORM(CON_SETACTORSOUNDVOLUME) DELIMITER \
TRANSFORM(CON_SETASPECT) DELIMITER \
TRANSFORM(CON_SETGAMEPALETTE) DELIMITER \
TRANSFORM(CON_SETINPUT) DELIMITER \
TRANSFORM(CON_SETMUSICPOSITION) DELIMITER \
TRANSFORM(CON_SETPLAYERANGLE) DELIMITER \
TRANSFORM(CON_SETSOUNDVOLUME) DELIMITER \
TRANSFORM(CON_SETSPRITE) DELIMITER \
TRANSFORM(CON_SETTILEDATA) DELIMITER \
TRANSFORM(CON_SHOOT) DELIMITER \
......@@ -1308,6 +1310,7 @@ enum IterationTypes_t
TRANSFORM(CON_DEFINEQUOTE) DELIMITER \
TRANSFORM(CON_DEFINESKILLNAME) DELIMITER \
TRANSFORM(CON_DEFINESOUND) DELIMITER \
TRANSFORM(CON_DEFINESOUNDV) DELIMITER \
TRANSFORM(CON_DEFINEVOLUMEFLAGS) DELIMITER \
TRANSFORM(CON_DEFINEVOLUMENAME) DELIMITER \
TRANSFORM(CON_DEFSTATE) DELIMITER \
......
......@@ -3223,6 +3223,35 @@ badindex:
dispatch();
}
vInstruction(CON_SETACTORSOUNDVOLUME):
insptr++;
{
int const spriteNum = Gv_GetVar(*insptr++);
int const soundNum = Gv_GetVar(*insptr++);
int const newVolume = Gv_GetVar(*insptr++);
VM_ASSERT((unsigned)soundNum < MAXSOUNDS, "invalid sound %d\n", soundNum);
VM_ASSERT((unsigned)newVolume <= MAXSCRIPTSOUNDVOL, "volume %d exceeds limit of %d\n", newVolume, MAXSCRIPTSOUNDVOL);
S_ChangeSoundVolume(soundNum, spriteNum, (fix16_t) newVolume << 6);
dispatch();
}
vInstruction(CON_SETSOUNDVOLUME):
insptr++;
{
int const soundNum = Gv_GetVar(*insptr++);
int const newVolume = Gv_GetVar(*insptr++);
VM_ASSERT((unsigned)soundNum < MAXSOUNDS, "invalid sound %d\n", soundNum);
VM_ASSERT((unsigned)newVolume <= MAXSCRIPTSOUNDVOL, "volume %d exceeds limit of %d\n", newVolume, MAXSCRIPTSOUNDVOL);
g_sounds[soundNum].volume = (fix16_t) newVolume << 6;
dispatch();
}
vInstruction(CON_TIP):
insptr++;
vm.pPlayer->tipincs = GAMETICSPERSEC;
......
......@@ -920,6 +920,25 @@ void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset)
}
}
void S_ChangeSoundVolume(int soundNum, int spriteNum, fix16_t newVolume)
{
if ((unsigned)soundNum > (unsigned)g_highestSoundIdx || g_sounds[soundNum].num <= 0)
return;
for (auto &voice : g_sounds[soundNum].voices)
{
if ((spriteNum == -1 && voice.id > FX_Ok) || (spriteNum != -1 && voice.owner == spriteNum))
{
if (EDUKE32_PREDICT_FALSE(spriteNum >= 0 && voice.id <= FX_Ok))
initprintf(OSD_ERROR "S_ChangeSoundVolume(): bad voice %d for sound ID %d!\n", voice.id, soundNum);
else if (voice.id > FX_Ok && FX_SoundActive(voice.id))
FX_SetVoiceVolume(voice.id, newVolume);
break;
}
}
}
void S_Update(void)
{
if ((g_player[myconnectindex].ps->gm & (MODE_GAME|MODE_DEMO)) == 0)
......
......@@ -40,6 +40,7 @@ extern "C" {
#define LOUDESTVOLUME 111
#define MUSIC_ID -65536
#define MAXVOICES 128
#define MAXSCRIPTSOUNDVOL 4096
typedef struct
{
......@@ -93,6 +94,7 @@ void S_StopAllSounds(void);
void S_StopMusic(void);
void S_Update(void);
void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset);
void S_ChangeSoundVolume(int soundNum, int spriteNum, int newVolume);
int32_t S_GetMusicPosition(void);
void S_SetMusicPosition(int32_t position);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment