Added A_SoundPitch and an optional pitch parameter to A_PlaySound and S_Sound.

- Note: Because sound channels are not in zscript, there's no way to modify a sound made by S_Sound.
This commit is contained in:
Major Cooke 2019-07-23 19:40:19 -05:00 committed by Christoph Oelckers
parent 9d66a5105a
commit 15eabfd055
10 changed files with 144 additions and 30 deletions

View file

@ -142,6 +142,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StopSound, NativeStopSound)
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundPitch, S_ChangeSoundPitch)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(channel);
PARAM_FLOAT(pitch);
S_ChangeSoundPitch(self, channel, pitch);
return 0;
}
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundVolume, S_ChangeSoundVolume) DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_SoundVolume, S_ChangeSoundVolume)
{ {
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);
@ -160,7 +169,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound)
PARAM_BOOL(looping); PARAM_BOOL(looping);
PARAM_FLOAT(attenuation); PARAM_FLOAT(attenuation);
PARAM_BOOL(local); PARAM_BOOL(local);
A_PlaySound(self, soundid, channel, volume, looping, attenuation, local); PARAM_FLOAT(pitch);
A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch);
return 0; return 0;
} }

View file

@ -158,6 +158,9 @@ public:
void ChannelVolume(FISoundChannel *, float) void ChannelVolume(FISoundChannel *, float)
{ {
} }
void ChannelPitch(FISoundChannel *, float)
{
}
// Streaming sounds. // Streaming sounds.
SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata)

View file

@ -39,6 +39,7 @@
#include "i_soundinternal.h" #include "i_soundinternal.h"
class FileReader; class FileReader;
struct FSoundChan;
enum ECodecType enum ECodecType
{ {
@ -130,6 +131,9 @@ public:
// Changes a channel's volume. // Changes a channel's volume.
virtual void ChannelVolume (FISoundChannel *chan, float volume) = 0; virtual void ChannelVolume (FISoundChannel *chan, float volume) = 0;
// Changes a channel's pitch.
virtual void ChannelPitch(FISoundChannel *chan, float volume) = 0;
// Marks a channel's start time without actually playing it. // Marks a channel's start time without actually playing it.
virtual void MarkStartTime (FISoundChannel *chan) = 0; virtual void MarkStartTime (FISoundChannel *chan) = 0;

View file

@ -109,6 +109,7 @@ struct FISoundChannel
float DistanceScale; float DistanceScale;
float DistanceSqr; float DistanceSqr;
bool ManualRolloff; bool ManualRolloff;
int ChanFlags;
}; };

View file

@ -1870,6 +1870,20 @@ void OpenALSoundRenderer::ChannelVolume(FISoundChannel *chan, float volume)
alSourcef(source, AL_GAIN, SfxVolume * volume); alSourcef(source, AL_GAIN, SfxVolume * volume);
} }
void OpenALSoundRenderer::ChannelPitch(FISoundChannel *chan, float pitch)
{
if (chan == NULL || chan->SysChannel == NULL)
return;
alDeferUpdatesSOFT();
ALuint source = GET_PTRID(chan->SysChannel);
if (WasInWater && !(chan->ChanFlags & CHAN_UI))
alSourcef(source, AL_PITCH, MAX(pitch, 0.0001f)*PITCH_MULT);
else
alSourcef(source, AL_PITCH, MAX(pitch, 0.0001f));
}
void OpenALSoundRenderer::FreeSource(ALuint source) void OpenALSoundRenderer::FreeSource(ALuint source)
{ {
alSourceRewind(source); alSourceRewind(source);
@ -2138,20 +2152,33 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f);
// Apply the updated filters on the sources // Apply the updated filters on the sources
for(uint32_t i = 0;i < ReverbSfx.Size();++i) FSoundChan *schan = Channels;
while (schan)
{ {
alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); ALuint source = GET_PTRID(schan->SysChannel);
alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); if (source && !(schan->ChanFlags & CHAN_UI))
{
alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]);
alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]);
}
schan = schan->NextChan;
} }
} }
for(uint32_t i = 0;i < ReverbSfx.Size();++i) FSoundChan *schan = Channels;
alSourcef(ReverbSfx[i], AL_PITCH, PITCH_MULT); while (schan)
{
ALuint source = GET_PTRID(schan->SysChannel);
if (source && !(schan->ChanFlags & CHAN_UI))
alSourcef(source, AL_PITCH, schan->Pitch / 128.0f * PITCH_MULT);
schan = schan->NextChan;
}
getALError(); getALError();
} }
} }
else if(WasInWater) else if(WasInWater)
{ {
WasInWater = false; WasInWater = false;
if(EnvSlot != 0) if(EnvSlot != 0)
@ -2162,15 +2189,28 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 1.f); alFilterf(EnvFilters[0], AL_LOWPASS_GAINHF, 1.f);
alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f);
alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f);
for(uint32_t i = 0;i < ReverbSfx.Size();++i)
FSoundChan *schan = Channels;
while (schan)
{ {
alSourcei(ReverbSfx[i], AL_DIRECT_FILTER, EnvFilters[0]); ALuint source = GET_PTRID(schan->SysChannel);
alSource3i(ReverbSfx[i], AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); if (source && !(schan->ChanFlags & CHAN_UI))
{
alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]);
alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]);
}
schan = schan->NextChan;
} }
} }
for(uint32_t i = 0;i < ReverbSfx.Size();++i) FSoundChan *schan = Channels;
alSourcef(ReverbSfx[i], AL_PITCH, 1.f); while (schan)
{
ALuint source = GET_PTRID(schan->SysChannel);
if (source && !(schan->ChanFlags & CHAN_UI))
alSourcef(source, AL_PITCH, schan->Pitch / 128.0f);
schan = schan->NextChan;
}
getALError(); getALError();
} }
} }

View file

@ -144,6 +144,9 @@ public:
// Changes a channel's volume. // Changes a channel's volume.
virtual void ChannelVolume(FISoundChannel *chan, float volume); virtual void ChannelVolume(FISoundChannel *chan, float volume);
// Changes a channel's pitch.
virtual void ChannelPitch(FISoundChannel *chan, float pitch);
// Stops a sound channel. // Stops a sound channel.
virtual void StopChannel(FISoundChannel *chan); virtual void StopChannel(FISoundChannel *chan);

View file

@ -132,7 +132,7 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, co
static void CalcSectorSoundOrg(const DVector3 &listenpos, const sector_t *sec, int channum, FVector3 &res); static void CalcSectorSoundOrg(const DVector3 &listenpos, const sector_t *sec, int channum, FVector3 &res);
static void CalcPolyobjSoundOrg(const DVector3 &listenpos, const FPolyObj *poly, FVector3 &res); static void CalcPolyobjSoundOrg(const DVector3 &listenpos, const FPolyObj *poly, FVector3 &res);
static FSoundChan *S_StartSound(AActor *mover, const sector_t *sec, const FPolyObj *poly, static FSoundChan *S_StartSound(AActor *mover, const sector_t *sec, const FPolyObj *poly,
const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo *rolloff); const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo *rolloff, float spitch);
static void S_SetListener(SoundListener &listener, AActor *listenactor); static void S_SetListener(SoundListener &listener, AActor *listenactor);
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -929,7 +929,7 @@ static void CalcPolyobjSoundOrg(const DVector3 &listenpos, const FPolyObj *poly,
static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyObj *poly, static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyObj *poly,
const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation,
FRolloffInfo *forcedrolloff=NULL) FRolloffInfo *forcedrolloff=NULL, float spitch = 0.0f)
{ {
sfxinfo_t *sfx; sfxinfo_t *sfx;
int chanflags; int chanflags;
@ -1235,6 +1235,10 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO
default: break; default: break;
} }
} }
if (spitch > 0.0)
S_SetPitch(chan, spitch);
return chan; return chan;
} }
@ -1318,9 +1322,14 @@ void S_RestartSound(FSoundChan *chan)
// //
//========================================================================== //==========================================================================
void S_Sound (int channel, FSoundID sound_id, float volume, float attenuation) void S_SoundPitch(int channel, FSoundID sound_id, float volume, float attenuation, float pitch)
{ {
S_StartSound (NULL, NULL, NULL, NULL, channel, sound_id, volume, attenuation); S_StartSound(NULL, NULL, NULL, NULL, channel, sound_id, volume, attenuation, 0, pitch);
}
void S_Sound(int channel, FSoundID sound_id, float volume, float attenuation)
{
S_StartSound (NULL, NULL, NULL, NULL, channel, sound_id, volume, attenuation, 0, 0.f);
} }
DEFINE_ACTION_FUNCTION(DObject, S_Sound) DEFINE_ACTION_FUNCTION(DObject, S_Sound)
@ -1330,7 +1339,8 @@ DEFINE_ACTION_FUNCTION(DObject, S_Sound)
PARAM_INT(channel); PARAM_INT(channel);
PARAM_FLOAT(volume); PARAM_FLOAT(volume);
PARAM_FLOAT(attn); PARAM_FLOAT(attn);
S_Sound(channel, id, static_cast<float>(volume), static_cast<float>(attn)); PARAM_FLOAT(pitch);
S_SoundPitch(channel, id, static_cast<float>(volume), static_cast<float>(attn), static_cast<float>(pitch));
return 0; return 0;
} }
@ -1339,14 +1349,17 @@ DEFINE_ACTION_FUNCTION(DObject, S_Sound)
// S_Sound - An actor is source // S_Sound - An actor is source
// //
//========================================================================== //==========================================================================
void S_SoundPitchActor(AActor *ent, int channel, FSoundID sound_id, float volume, float attenuation, float pitch)
void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, float attenuation)
{ {
if (ent == nullptr || ent->Sector->Flags & SECF_SILENT || ent->Level != primaryLevel) if (ent == nullptr || ent->Sector->Flags & SECF_SILENT || ent->Level != primaryLevel)
return; return;
S_StartSound (ent, nullptr, nullptr, nullptr, channel, sound_id, volume, attenuation); S_StartSound (ent, nullptr, nullptr, nullptr, channel, sound_id, volume, attenuation, 0, pitch);
} }
void S_Sound(AActor *ent, int channel, FSoundID sound_id, float volume, float attenuation)
{
S_SoundPitchActor(ent, channel, sound_id, volume, attenuation, 0.f);
}
//========================================================================== //==========================================================================
// //
// S_SoundMinMaxDist - An actor is source // S_SoundMinMaxDist - An actor is source
@ -1414,38 +1427,43 @@ void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, fl
// //
//========================================================================== //==========================================================================
void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local) void S_PlaySoundPitch(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local, float pitch)
{ {
if (a == nullptr || a->Sector->Flags & SECF_SILENT || a->Level != primaryLevel) if (a == nullptr || a->Sector->Flags & SECF_SILENT || a->Level != primaryLevel)
return; return;
if (!local) if (!local)
{ {
S_Sound(a, chan, sid, vol, atten); S_SoundPitchActor(a, chan, sid, vol, atten, pitch);
} }
else else
{ {
if (a->CheckLocalView()) if (a->CheckLocalView())
{ {
S_Sound(chan, sid, vol, ATTN_NONE); S_SoundPitch(chan, sid, vol, ATTN_NONE, pitch);
} }
} }
} }
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local) void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local)
{
S_PlaySoundPitch(a, chan, sid, vol, atten, local, 0.f);
}
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch)
{ {
if (!looping) if (!looping)
{ {
if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid)) if (!(channel & CHAN_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid))
{ {
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local); S_PlaySoundPitch(self, channel, soundid, (float)volume, (float)attenuation, local, (float)pitch);
} }
} }
else else
{ {
if (!S_IsActorPlayingSomething(self, channel & 7, soundid)) if (!S_IsActorPlayingSomething(self, channel & 7, soundid))
{ {
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local); S_PlaySoundPitch(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local, (float)pitch);
} }
} }
} }
@ -1843,6 +1861,33 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double dvolume)
return; return;
} }
//==========================================================================
//
// S_ChangeSoundPitch
//
//==========================================================================
void S_ChangeSoundPitch(AActor *actor, int channel, double pitch)
{
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
{
if (chan->SourceType == SOURCE_Actor &&
chan->Actor == actor &&
chan->EntChannel == channel)
{
S_SetPitch(chan, (float)pitch);
return;
}
}
return;
}
void S_SetPitch(FSoundChan *chan, float pitch)
{
GSnd->ChannelPitch(chan, MAX(0.0001f, pitch));
chan->Pitch = MAX(1, int(float(NORM_PITCH) * pitch));
}
//========================================================================== //==========================================================================
// //
// S_GetSoundPlayingInfo // S_GetSoundPlayingInfo

View file

@ -179,7 +179,6 @@ struct FSoundChan : public FISoundChannel
FSoundID SoundID; // Sound ID of playing sound. FSoundID SoundID; // Sound ID of playing sound.
FSoundID OrgID; // Sound ID of sound used to start this channel. FSoundID OrgID; // Sound ID of sound used to start this channel.
float Volume; float Volume;
int ChanFlags;
int16_t Pitch; // Pitch variation. int16_t Pitch; // Pitch variation.
uint8_t EntChannel; // Actor's sound channel. uint8_t EntChannel; // Actor's sound channel.
int8_t Priority; int8_t Priority;
@ -231,8 +230,12 @@ void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, f
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation);
void S_Sound(FLevelLocals *Level, const DVector3 &pos, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound(FLevelLocals *Level, const DVector3 &pos, int channel, FSoundID sfxid, float volume, float attenuation);
void S_SoundPitch (int channel, FSoundID sfxid, float volume, float attenuation, float pitch);
void S_SoundPitchActor (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation, float pitch);
// [Nash] Used by ACS and DECORATE // [Nash] Used by ACS and DECORATE
void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local); void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local);
void S_PlaySoundPitch(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local, float pitch);
// sound channels // sound channels
// channel 0 never willingly overrides // channel 0 never willingly overrides
@ -310,6 +313,10 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id);
// Change a playing sound's volume // Change a playing sound's volume
void S_ChangeSoundVolume(AActor *actor, int channel, double volume); void S_ChangeSoundVolume(AActor *actor, int channel, double volume);
// Change a playing sound's pitch
void S_ChangeSoundPitch(AActor *actor, int channel, double pitch);
void S_SetPitch(FSoundChan *chan, float dpitch);
// Moves all sounds from one mobj to another // Moves all sounds from one mobj to another
void S_RelinkSound (AActor *from, AActor *to); void S_RelinkSound (AActor *from, AActor *to);
@ -372,7 +379,7 @@ sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
unsigned int S_GetMSLength(FSoundID sound); unsigned int S_GetMSLength(FSoundID sound);
void S_ParseMusInfo(); void S_ParseMusInfo();
bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time); bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time);
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local); void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch);
// [RH] Prints sound debug info to the screen. // [RH] Prints sound debug info to the screen.
// Modelled after Hexen's noise cheat. // Modelled after Hexen's noise cheat.

View file

@ -1052,8 +1052,9 @@ class Actor : Thinker native
deprecated("2.3") native void A_BulletAttack(); deprecated("2.3") native void A_BulletAttack();
native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff"); native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
native clearscope void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false); native clearscope void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false, double pitch = 0.0);
native void A_SoundVolume(int slot, double volume); native void A_SoundVolume(int slot, double volume);
native void A_SoundPitch(int slot, double pitch);
deprecated("2.3") void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); } deprecated("2.3") void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); }
native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was... native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
deprecated("2.3") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0); deprecated("2.3") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);

View file

@ -442,7 +442,7 @@ class Object native
{ {
return level.PickPlayerStart(pnum, flags); return level.PickPlayerStart(pnum, flags);
} }
native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0);
native static void S_PauseSound (bool notmusic, bool notsfx); native static void S_PauseSound (bool notmusic, bool notsfx);
native static void S_ResumeSound (bool notsfx); native static void S_ResumeSound (bool notsfx);
native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false); native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false);