diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 12cd27676b..92d4bb74ff 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -179,7 +179,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound) PARAM_FLOAT(attenuation); PARAM_BOOL(local); PARAM_FLOAT(pitch); - A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch); + PARAM_FLOAT(startTime); + A_PlaySound(self, soundid, channel, volume, looping, attenuation, local, pitch, startTime); return 0; } @@ -192,7 +193,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_StartSound, A_StartSound) PARAM_FLOAT(volume); PARAM_FLOAT(attenuation); PARAM_FLOAT(pitch); - A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch); + PARAM_FLOAT(startTime); + A_StartSound(self, soundid, channel, flags, volume, attenuation, pitch, startTime); return 0; } diff --git a/src/sound/backend/i_sound.cpp b/src/sound/backend/i_sound.cpp index 2561634040..f1f0e3c87a 100644 --- a/src/sound/backend/i_sound.cpp +++ b/src/sound/backend/i_sound.cpp @@ -171,17 +171,17 @@ public: } // Starts a sound. - FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) + FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) { return NULL; } - FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) + FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) { return NULL; } // Marks a channel's start time without actually playing it. - void MarkStartTime (FISoundChannel *chan) + void MarkStartTime (FISoundChannel *chan, float startTime) { } diff --git a/src/sound/backend/i_sound.h b/src/sound/backend/i_sound.h index 0564f7857e..573159242d 100644 --- a/src/sound/backend/i_sound.h +++ b/src/sound/backend/i_sound.h @@ -109,8 +109,8 @@ public: virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; // Starts a sound. - virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0; - virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) = 0; + virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; + virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0; // Stops a sound channel. virtual void StopChannel (FISoundChannel *chan) = 0; @@ -122,7 +122,7 @@ public: virtual void ChannelPitch(FISoundChannel *chan, float volume) = 0; // Marks a channel's start time without actually playing it. - virtual void MarkStartTime (FISoundChannel *chan) = 0; + virtual void MarkStartTime (FISoundChannel *chan, float startTime = 0.f) = 0; // Returns position of sound on this channel, in samples. virtual unsigned int GetPosition(FISoundChannel *chan) = 0; diff --git a/src/sound/backend/oalsound.cpp b/src/sound/backend/oalsound.cpp index a2848a967a..c6c4af18e8 100644 --- a/src/sound/backend/oalsound.cpp +++ b/src/sound/backend/oalsound.cpp @@ -1167,7 +1167,7 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int return stream; } -FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) +FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime) { if(FreeSfx.Size() == 0) { @@ -1218,7 +1218,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_PITCH, PITCH(pitch)); if(!reuse_chan || reuse_chan->StartTime == 0) - alSourcef(source, AL_SEC_OFFSET, 0.f); + { + float st = (chanflags&SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f); + alSourcef(source, AL_SEC_OFFSET, st); + } else { if((chanflags&SNDF_ABSTIME)) @@ -1267,7 +1270,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, - int channum, int chanflags, FISoundChannel *reuse_chan) + int channum, int chanflags, FISoundChannel *reuse_chan, float startTime) { float dist_sqr = (float)(pos - listener->position).LengthSquared(); @@ -1411,7 +1414,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSourcef(source, AL_PITCH, PITCH(pitch)); if(!reuse_chan || reuse_chan->StartTime == 0) - alSourcef(source, AL_SEC_OFFSET, 0.f); + { + float st = (chanflags & SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f); + alSourcef(source, AL_SEC_OFFSET, st); + } else { if((chanflags&SNDF_ABSTIME)) @@ -1791,11 +1797,14 @@ bool OpenALSoundRenderer::IsValid() return Device != NULL; } -void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan) +void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan, float startTime) { // FIXME: Get current time (preferably from the audio clock, but the system // time will have to do) - chan->StartTime = std::chrono::steady_clock::now().time_since_epoch().count(); + using namespace std::chrono; + auto startTimeDuration = duration(startTime); + auto diff = steady_clock::now().time_since_epoch() - startTimeDuration; + chan->StartTime = static_cast(duration_cast(diff).count()); } float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) diff --git a/src/sound/backend/oalsound.h b/src/sound/backend/oalsound.h index 1d2f09fbae..952b8776e2 100644 --- a/src/sound/backend/oalsound.h +++ b/src/sound/backend/oalsound.h @@ -136,8 +136,8 @@ public: virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata); // Starts a sound. - virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan); - virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan); + virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime); + virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime); // Changes a channel's volume. virtual void ChannelVolume(FISoundChannel *chan, float volume); @@ -166,7 +166,7 @@ public: virtual void UpdateListener(SoundListener *); virtual void UpdateSounds(); - virtual void MarkStartTime(FISoundChannel*); + virtual void MarkStartTime(FISoundChannel*, float startTime); virtual float GetAudibility(FISoundChannel*); diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index bec5fff8ba..282bf15e3e 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -278,7 +278,7 @@ void S_InitData() // //========================================================================== -void S_SoundPitch(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch) +void S_SoundPitch(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch, float startTime) { soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch); } @@ -296,7 +296,8 @@ DEFINE_ACTION_FUNCTION(DObject, S_Sound) PARAM_FLOAT(volume); PARAM_FLOAT(attn); PARAM_FLOAT(pitch); - S_SoundPitch(channel & 7, EChanFlags::FromInt(channel & ~7), id, static_cast(volume), static_cast(attn), static_cast(pitch)); + PARAM_FLOAT(startTime); + S_SoundPitch(channel & 7, EChanFlags::FromInt(channel & ~7), id, static_cast(volume), static_cast(attn), static_cast(pitch), static_cast(startTime)); return 0; } @@ -309,7 +310,8 @@ DEFINE_ACTION_FUNCTION(DObject, S_StartSound) PARAM_FLOAT(volume); PARAM_FLOAT(attn); PARAM_FLOAT(pitch); - S_SoundPitch(channel, EChanFlags::FromInt(flags), id, static_cast(volume), static_cast(attn), static_cast(pitch)); + PARAM_FLOAT(startTime); + S_SoundPitch(channel, EChanFlags::FromInt(flags), id, static_cast(volume), static_cast(attn), static_cast(pitch), static_cast(startTime)); return 0; } @@ -365,10 +367,10 @@ static bool VerifyActorSound(AActor* ent, FSoundID& sound_id, int& channel, ECha // //========================================================================== -void S_SoundPitchActor(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch) +void S_SoundPitchActor(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch, float startTime) { if (VerifyActorSound(ent, sound_id, channel, flags)) - soundEngine->StartSound (SOURCE_Actor, ent, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch); + soundEngine->StartSound (SOURCE_Actor, ent, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch, startTime); } void S_Sound(AActor *ent, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation) @@ -443,7 +445,7 @@ void S_Sound (const sector_t *sec, int channel, EChanFlags flags, FSoundID sfxid // //========================================================================== -void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten, float pitch) +void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten, float pitch, float startTime = 0.f) { if (a == nullptr || a->Sector->Flags & SECF_SILENT || a->Level != primaryLevel) return; @@ -452,7 +454,7 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float { if (!(flags & CHANF_NOSTOP) || !S_IsActorPlayingSomething(a, chan, sid)) { - S_SoundPitchActor(a, chan, flags, sid, vol, atten, pitch); + S_SoundPitchActor(a, chan, flags, sid, vol, atten, pitch, startTime); } } else @@ -461,7 +463,7 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float { if (!(flags & CHANF_NOSTOP) || !soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, chan, sid)) { - S_SoundPitch(chan, flags, sid, vol, ATTN_NONE, pitch); + S_SoundPitch(chan, flags, sid, vol, ATTN_NONE, pitch, startTime); } } } @@ -469,19 +471,19 @@ void S_PlaySoundPitch(AActor *a, int chan, EChanFlags flags, FSoundID sid, float void S_PlaySound(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten) { - S_PlaySoundPitch(a, chan, flags, sid, vol, atten, 0.f); + S_PlaySoundPitch(a, chan, flags, sid, vol, atten, 0.f, 0.f); } -void A_StartSound(AActor *self, int soundid, int channel, int flags, double volume, double attenuation, double pitch) +void A_StartSound(AActor *self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime) { - S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, (float)pitch); + S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, (float)pitch, (float)startTime); } -void A_PlaySound(AActor* self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch) +void A_PlaySound(AActor* self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch, double startTime) { if (looping) channel |= CHANF_LOOP | CHANF_NOSTOP; if (local) channel |= CHANF_LOCAL; - A_StartSound(self, soundid, channel & 7, channel & ~7, volume, attenuation, pitch); + A_StartSound(self, soundid, channel & 7, channel & ~7, volume, attenuation, pitch, startTime); } diff --git a/src/sound/s_doomsound.h b/src/sound/s_doomsound.h index 5a1a8fa090..584700ef23 100644 --- a/src/sound/s_doomsound.h +++ b/src/sound/s_doomsound.h @@ -17,7 +17,7 @@ void S_PrecacheLevel(FLevelLocals* l); // Start sound for thing at void S_Sound(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); -void S_SoundPitch(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch); +void S_SoundPitch(int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch, float startTime = 0.f); void S_Sound (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); @@ -26,7 +26,7 @@ void S_Sound (const FPolyObj *poly, int channel, EChanFlags flags, FSoundID sfxi void S_Sound (const sector_t *sec, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); void S_Sound(FLevelLocals *Level, const DVector3 &pos, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation); -void S_SoundPitchActor (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch); +void S_SoundPitchActor (AActor *ent, int channel, EChanFlags flags, FSoundID sfxid, float volume, float attenuation, float pitch, float startTime = 0.f); // [Nash] Used by ACS and DECORATE void S_PlaySound(AActor *a, int chan, EChanFlags flags, FSoundID sid, float vol, float atten); @@ -56,8 +56,8 @@ void S_ChangeActorSoundPitch(AActor *actor, int channel, double pitch); // Stores/retrieves playing channel information in an archive. void S_SerializeSounds(FSerializer &arc); -void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch); -void A_StartSound(AActor* self, int soundid, int channel, int flags, double volume, double attenuation, double pitch); +void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch, double startTime = 0.); +void A_StartSound(AActor* self, int soundid, int channel, int flags, double volume, double attenuation, double pitch, double startTime = 0.); static void S_SetListener(AActor *listenactor); void S_SoundReset(); void S_ResumeSound(bool state); diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index 9c15c47b52..5979d320f9 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -368,7 +368,7 @@ FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &a FSoundChan *SoundEngine::StartSound(int type, const void *source, const FVector3 *pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, - FRolloffInfo *forcedrolloff, float spitch) + FRolloffInfo *forcedrolloff, float spitch, float startTime) { sfxinfo_t *sfx; EChanFlags chanflags = flags; @@ -568,11 +568,11 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, if (attenuation > 0 && type != SOURCE_None) { - chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); + chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL, startTime); } else { - chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL); + chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL, startTime); } } if (chan == NULL && (chanflags & CHANF_LOOP)) diff --git a/src/sound/s_soundinternal.h b/src/sound/s_soundinternal.h index 4dc978ed37..e3647b9c7c 100644 --- a/src/sound/s_soundinternal.h +++ b/src/sound/s_soundinternal.h @@ -301,7 +301,7 @@ public: void UpdateSounds(int time); FSoundChan* StartSound(int sourcetype, const void* source, - const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f); + const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f, float startTime = 0.0f); // Stops an origin-less sound from playing from this channel. void StopSoundID(int sound_id); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 55b90edcbe..d287211546 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1054,8 +1054,8 @@ class Actor : Thinker native 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 pufftype = "BulletPuff"); - deprecated("4.3") 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 clearscope void A_StartSound(sound whattoplay, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0); + deprecated("4.3") 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, double startTime = 0.0); + native clearscope void A_StartSound(sound whattoplay, int slot = CHAN_BODY, int flags = 0, double volume = 1.0, double attenuation = ATTN_NORM, double pitch = 0.0, double startTime = 0.0); 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_StartSound(whattoplay, CHAN_WEAPON); }