- use backend pitch features for Duke instead of replicating them on the game side.

This commit is contained in:
Christoph Oelckers 2023-01-15 13:18:54 +01:00
parent 8859712a7b
commit f1c3a6548f
3 changed files with 41 additions and 66 deletions

View file

@ -60,7 +60,7 @@ enum SICommands
SI_Limit,
SI_Singular,
SI_PitchSet,
SI_DukePitchRange,
SI_PitchSetDuke,
SI_DukeFlags,
};
@ -93,7 +93,7 @@ static const char *SICommandStrings[] =
"$limit",
"$singular",
"$pitchset",
"$dukepitchrange",
"$pitchsetduke",
"$dukeflags",
NULL
};
@ -315,6 +315,26 @@ static void S_AddSNDINFO (int lump)
}
break;
case SI_PitchSetDuke: {
// $pitchset <logical name> <pitch amount as float> [range maximum]
// Same as above, but uses Duke's value range of 1200 units per octave.
FSoundID sfx;
sc.MustGetString();
sfx = soundEngine->FindSoundTentative(sc.String);
sc.MustGetFloat();
auto sfxp = soundEngine->GetWritableSfx(sfx);
sfxp->DefPitch = (float)pow(2, sc.Float / 1200.);
if (sc.CheckFloat())
{
sfxp->DefPitchMax = (float)pow(2, sc.Float / 1200.);
}
else
{
sfxp->DefPitchMax = 0;
}
break;
}
case SI_ConReserve: {
// $conreserve <logical name> <resource id>
@ -328,34 +348,6 @@ static void S_AddSNDINFO (int lump)
break;
}
case SI_DukePitchRange: {
// dukesound <logical name> <lower> <upper>
// Sets a pitch range for the sound.
sc.MustGetString();
auto sfxid = soundEngine->FindSoundTentative(sc.String, DEFAULT_LIMIT);
sc.MustGetNumber();
int minpitch = sc.Number;
sc.MustGetNumber();
int maxpitch = sc.Number;
if (isDukeEngine())
{
auto sfx = soundEngine->GetWritableSfx(sfxid);
if (sfx->UserData.Size() < Duke3d::kMaxUserData)
{
sfx->UserData.Resize(Duke3d::kMaxUserData);
memset(sfx->UserData.Data(), 0, Duke3d::kMaxUserData * sizeof(int));
}
sfx->UserData[Duke3d::kPitchStart] = clamp<int>(minpitch, INT16_MIN, INT16_MAX);
sfx->UserData[Duke3d::kPitchEnd] = clamp<int>(maxpitch, INT16_MIN, INT16_MAX);
}
else
{
sc.ScriptMessage("'$dukepitchrange' is not available in the current game and will be ignored");
}
break;
}
case SI_DukeFlags: {
static const char* dukeflags[] = { "LOOP", "MSFX", "TALK", "GLOBAL", nullptr};

View file

@ -174,19 +174,6 @@ void S_CacheAllSounds(void)
//
//==========================================================================
static inline int S_GetPitch(FSoundID soundid)
{
auto const* snd = soundEngine->GetUserData(soundid);
if (!snd) return 0;
int const range = abs(snd[kPitchEnd] - snd[kPitchStart]);
return (range == 0) ? snd[kPitchStart] : min(snd[kPitchStart], snd[kPitchEnd]) + rand() % range;
}
float S_ConvertPitch(int lpitch)
{
return powf(2, lpitch / 1200.f); // I hope I got this right that ASS uses a linear scale where 1200 is a full octave.
}
int S_GetUserFlags(FSoundID soundid)
{
if (!soundEngine->isValidSoundId(soundid)) return 0;
@ -234,9 +221,6 @@ int S_DefineSound(unsigned index, const char *filename, int minpitch, int maxpit
// Set everything to 0 to have default handling.
sfx->UserData.Resize(kMaxUserData);
auto& sndinf = sfx->UserData;
sndinf[kPitchStart] = 0;
sndinf[kPitchEnd] = 0;
sndinf[kPriority] = 0; // Raze's sound engine does not use this.
sndinf[kVolAdjust] = 0;
sndinf[kWorldTourMapping] = 0;
sndinf[kFlags] = 0;
@ -261,13 +245,14 @@ int S_DefineSound(unsigned index, const char *filename, int minpitch, int maxpit
fn.Substitute(".ogg", ".voc");
sfx->lumpnum = S_LookupSound(fn);
}
sndinf[kPitchStart] = clamp<int>(minpitch, INT16_MIN, INT16_MAX);
sndinf[kPitchEnd] = clamp<int>(maxpitch, INT16_MIN, INT16_MAX);
sndinf[kPriority] = priority & 255;
if (minpitch != 0 || maxpitch != 0)
{
sfx->DefPitch = (float)pow(2, clamp<int>(minpitch, INT16_MIN, INT16_MAX) / 1200.);
sfx->DefPitchMax = (float)pow(2, clamp<int>(maxpitch, INT16_MIN, INT16_MAX) / 1200.);
}
sndinf[kVolAdjust] = clamp<int>(distance, INT16_MIN, INT16_MAX);
sndinf[kWorldTourMapping] = 0;
sfx->Volume = volume;
//sfx->NearLimit = index == TELEPORTER + 1? 6 : 0; // the teleporter sound cannot be unlimited due to how it gets used.
sfx->bTentative = false;
return 0;
}
@ -499,25 +484,20 @@ int S_PlaySound3D(FSoundID soundid, DDukeActor* actor, const DVector3& pos, int
S_GetCamera(&campos, nullptr, &camsect);
GetPositionInfo(actor, soundid, camsect, campos, pos, &sndist, &sndpos);
int pitch = S_GetPitch(soundid);
auto sfx = soundEngine->GetSfx(soundid);
bool explosion = ((userflags & (SF_GLOBAL | SF_DTAG)) == (SF_GLOBAL | SF_DTAG)) ||
((sfx->ResourceId == PIPEBOMB_EXPLODE || sfx->ResourceId == LASERTRIP_EXPLODE || sfx->ResourceId == RPG_EXPLODE));
bool underwater = ps[screenpeek].insector() && ps[screenpeek].cursector->lotag == ST_2_UNDERWATER;
if (explosion)
{
if (underwater)
pitch -= 1024;
}
else
float pitch = 0;
if (!explosion)
{
if (sndist > 32767 && !issoundcontroller(actor) && (userflags & (SF_LOOP | SF_MSFX)) == 0)
return -1;
if (underwater && (userflags & SF_TALK) == 0)
pitch = -768;
pitch = 0.64f;
}
bool is_playing = soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, soundid);
@ -541,8 +521,16 @@ int S_PlaySound3D(FSoundID soundid, DDukeActor* actor, const DVector3& pos, int
if (userflags & SF_LOOP) flags |= CHANF_LOOP;
float vol = attenuation == ATTN_NONE ? 0.8f : 1.f;
if (currentCommentarySound != NO_SOUND) vol *= 0.25f;
auto chan = soundEngine->StartSound(SOURCE_Actor, actor, &sndpos, CHAN_AUTO, flags, soundid, vol, attenuation, nullptr, S_ConvertPitch(pitch));
if (chan) chan->UserData = (currentCommentarySound != NO_SOUND);
auto chan = soundEngine->StartSound(SOURCE_Actor, actor, &sndpos, CHAN_AUTO, flags, soundid, vol, attenuation, nullptr, pitch);
if (chan)
{
if (explosion && underwater)
{
pitch = chan->Pitch? chan->Pitch * (0.55 / 128) : 0.55; // todo: fix pitch storage in backend.
soundEngine->SetPitch(chan, pitch);
}
chan->UserData = (currentCommentarySound != NO_SOUND);
}
return chan ? 0 : -1;
}
@ -562,11 +550,9 @@ int S_PlaySound(FSoundID soundid, int channel, EChanFlags flags, float vol)
if ((!(snd_speech & 1) && (userflags & SF_TALK)))
return -1;
int const pitch = S_GetPitch(soundid);
if (userflags & SF_LOOP) flags |= CHANF_LOOP;
if (currentCommentarySound != NO_SOUND) vol *= 0.25f;
auto chan = soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, soundid, vol, ATTN_NONE, nullptr, S_ConvertPitch(pitch));
auto chan = soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, soundid, vol, ATTN_NONE, nullptr);
if (chan) chan->UserData = (currentCommentarySound != NO_SOUND);
return chan ? 0 : -1;
}

View file

@ -26,10 +26,7 @@ enum {
enum esound_t
{
kPitchStart,
kPitchEnd,
kVolAdjust,
kPriority,
kFlags,
kWorldTourMapping,
kMaxUserData