mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-02 09:02:18 +00:00
f103e33300
All Duke script code has been changed to use strings as sound names now, just like GZDoom these will be looked up at compile time. Original Duke sound indices still exist but are now being managed as resource IDs, not sound engine indices anymore.
285 lines
8.1 KiB
C++
285 lines
8.1 KiB
C++
/*
|
|
** s_advsound.cpp
|
|
** Routines for managing SNDINFO lumps and ambient sounds
|
|
** Thid is a stripped down version only handling the music related settings.
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 1998-2008 Randy Heit
|
|
** All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
**
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
*/
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
#include "c_dispatch.h"
|
|
#include "filesystem.h"
|
|
#include "v_text.h"
|
|
#include "s_music.h"
|
|
#include "sc_man.h"
|
|
#include "s_soundinternal.h"
|
|
#include <zmusic.h>
|
|
|
|
#include "raze_music.h"
|
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
enum SICommands
|
|
{
|
|
SI_MusicVolume,
|
|
SI_MidiDevice,
|
|
SI_MusicAlias,
|
|
SI_ConReserve,
|
|
SI_Alias
|
|
};
|
|
|
|
|
|
// This specifies whether Timidity or Windows playback is preferred for a certain song (only useful for Windows.)
|
|
extern MusicAliasMap MusicAliases;
|
|
extern MidiDeviceMap MidiDevices;
|
|
extern MusicVolumeMap MusicVolumes;
|
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
|
|
extern bool IsFloat (const char *str);
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
static void S_AddSNDINFO (int lumpnum);
|
|
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
static const char *SICommandStrings[] =
|
|
{
|
|
"$musicvolume",
|
|
"$mididevice",
|
|
"$musicalias",
|
|
"$conreserve",
|
|
"$alias",
|
|
NULL
|
|
};
|
|
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
//==========================================================================
|
|
//
|
|
// S_ReserveSoundSlot
|
|
//
|
|
// Reserves an empty sound slot and assigns it a resource ID and a name
|
|
//
|
|
//==========================================================================
|
|
|
|
FSoundID S_ReserveSoundSlot(const char* logicalname, int slotnum, int limit = 6)
|
|
{
|
|
auto& S_sfx = soundEngine->GetSounds();
|
|
|
|
auto sfxid = soundEngine->FindSoundNoHash(logicalname);
|
|
|
|
if (soundEngine->isValidSoundId(sfxid))
|
|
{ // If the sound has already been defined, change the old definition
|
|
sfxinfo_t* sfx = soundEngine->GetWritableSfx(sfxid);
|
|
|
|
if (sfx->ResourceId != -1)
|
|
{
|
|
// If the name was reseved before, delete that mapping.
|
|
soundEngine->RemoveResourceID(sfx->ResourceId);
|
|
}
|
|
if (sfx->bRandomHeader)
|
|
{
|
|
FRandomSoundList* rnd = soundEngine->ResolveRandomSound(sfx);
|
|
rnd->Choices.Reset();
|
|
rnd->Owner = NO_SOUND;
|
|
}
|
|
sfx->ResourceId = slotnum;
|
|
sfx->lumpnum = sfx_empty;
|
|
sfx->bRandomHeader = false;
|
|
sfx->link = sfxinfo_t::NO_LINK;
|
|
sfx->bTentative = true;
|
|
if (sfx->NearLimit == -1)
|
|
{
|
|
sfx->NearLimit = 2;
|
|
sfx->LimitRange = 256 * 256;
|
|
}
|
|
//sfx->PitchMask = CurrentPitchMask;
|
|
}
|
|
else
|
|
{ // Otherwise, create a new definition.
|
|
sfxid = soundEngine->AddSoundLump(logicalname, sfx_empty, 0, slotnum, limit);
|
|
}
|
|
|
|
return sfxid;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// S_ParseSndInfo
|
|
//
|
|
// Parses all loaded SNDINFO lumps.
|
|
// Also registers Blood SFX files and Strife's voices.
|
|
//==========================================================================
|
|
|
|
void S_ParseSndInfo ()
|
|
{
|
|
int lump, lastlump = 0;
|
|
|
|
while ((lump = fileSystem.FindLumpFullName("engine/mussetting.txt", &lastlump)) >= 0)
|
|
{
|
|
S_AddSNDINFO (lump);
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// S_AddSNDINFO
|
|
//
|
|
// Reads a SNDINFO and does what it says.
|
|
//
|
|
//==========================================================================
|
|
|
|
static void S_AddSNDINFO (int lump)
|
|
{
|
|
bool skipToEndIf;
|
|
TArray<uint32_t> list;
|
|
|
|
FScanner sc(lump);
|
|
skipToEndIf = false;
|
|
|
|
while (sc.GetString ())
|
|
{
|
|
if (skipToEndIf)
|
|
{
|
|
if (sc.Compare ("$endif"))
|
|
{
|
|
skipToEndIf = false;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (sc.String[0] == '$')
|
|
{ // Got a command
|
|
switch (sc.MatchString (SICommandStrings))
|
|
{
|
|
case SI_MusicVolume: {
|
|
sc.MustGetString();
|
|
FName musname (sc.String);
|
|
sc.MustGetFloat();
|
|
MusicVolumes[musname] = (float)sc.Float;
|
|
}
|
|
break;
|
|
|
|
case SI_MusicAlias: {
|
|
sc.MustGetString();
|
|
int mlump = fileSystem.FindFile(sc.String);
|
|
if (mlump < 0)
|
|
mlump = fileSystem.FindFile(FStringf("music/%s", sc.String));
|
|
if (mlump >= 0)
|
|
{
|
|
// do not set the alias if a later WAD defines its own music of this name
|
|
int file = fileSystem.GetFileContainer(mlump);
|
|
int sndifile = fileSystem.GetFileContainer(sc.LumpNum);
|
|
if (file > sndifile)
|
|
{
|
|
sc.MustGetString();
|
|
continue;
|
|
}
|
|
}
|
|
FName alias = sc.String;
|
|
sc.MustGetString();
|
|
FName mapped = sc.String;
|
|
|
|
// only set the alias if the lump it maps to exists.
|
|
if (mapped == NAME_None || fileSystem.FindFile(sc.String) >= 0)
|
|
{
|
|
MusicAliases[alias] = mapped;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SI_MidiDevice: {
|
|
sc.MustGetString();
|
|
FName nm = sc.String;
|
|
FScanner::SavedPos save = sc.SavePos();
|
|
|
|
sc.SetCMode(true);
|
|
sc.MustGetString();
|
|
MidiDeviceSetting devset;
|
|
// Important: This needs to handle all the devices not present in ZMusic Lite to be able to load configs made for GZDoom.
|
|
// Also let the library handle the fallback so this can adjust automatically if the feature set gets extended.
|
|
if (sc.Compare("timidity")) devset.device = MDEV_TIMIDITY;
|
|
else if (sc.Compare("fmod") || sc.Compare("sndsys")) devset.device = MDEV_SNDSYS;
|
|
else if (sc.Compare("standard")) devset.device = MDEV_STANDARD;
|
|
else if (sc.Compare("opl")) devset.device = MDEV_OPL;
|
|
else if (sc.Compare("default")) devset.device = MDEV_DEFAULT;
|
|
else if (sc.Compare("fluidsynth")) devset.device = MDEV_FLUIDSYNTH;
|
|
else if (sc.Compare("gus")) devset.device = MDEV_GUS;
|
|
else if (sc.Compare("wildmidi")) devset.device = MDEV_WILDMIDI;
|
|
else if (sc.Compare("adl")) devset.device = MDEV_ADL;
|
|
else if (sc.Compare("opn")) devset.device = MDEV_OPN;
|
|
else sc.ScriptError("Unknown MIDI device %s\n", sc.String);
|
|
if (sc.CheckString(","))
|
|
{
|
|
sc.SetCMode(false);
|
|
sc.MustGetString();
|
|
devset.args = sc.String;
|
|
}
|
|
else
|
|
{
|
|
// This does not really do what one might expect, because the next token has already been parsed and can be a '$'.
|
|
// So in order to continue parsing without C-Mode, we need to reset and parse the last token again.
|
|
sc.SetCMode(false);
|
|
sc.RestorePos(save);
|
|
sc.MustGetString();
|
|
}
|
|
MidiDevices[nm] = devset;
|
|
}
|
|
break;
|
|
|
|
case SI_ConReserve: {
|
|
sc.MustGetNumber();
|
|
int num = sc.Number;
|
|
sc.MustGetStringName("=");
|
|
sc.MustGetString();
|
|
FString name = sc.String;
|
|
int limit = 6;
|
|
if (sc.CheckString(","))
|
|
{
|
|
sc.MustGetNumber();
|
|
limit = sc.Number;
|
|
}
|
|
S_ReserveSoundSlot(name, num, limit);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|