From 5c7712daadbb49dd13388d7a2f7521fe8bf9b0ee Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:07:25 -0500 Subject: [PATCH 1/5] Add audio clip started and finished events to audio source --- Source/Engine/Audio/AudioSource.cpp | 15 ++++++++++++++- Source/Engine/Audio/AudioSource.h | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index cff89e7e1..c15084dc3 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -168,7 +168,7 @@ void AudioSource::Play() else { // Source was nt properly added to the Audio Backend - LOG(Warning, "Cannot play unitialized audio source."); + LOG(Warning, "Cannot play uninitialized audio source."); } } @@ -395,6 +395,9 @@ void AudioSource::Update() AudioBackend::Source::VelocityChanged(SourceID, _velocity); } + if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) + ClipStarted(); + // Reset starting to play value once time is greater than zero if (_startingToPlay && GetTime() > 0.0f) { @@ -416,6 +419,7 @@ void AudioSource::Update() { Stop(); } + ClipFinished(); } } @@ -486,6 +490,7 @@ void AudioSource::Update() { Stop(); } + ClipFinished(); } ASSERT(_streamingFirstChunk < clip->Buffers.Count()); @@ -583,3 +588,11 @@ void AudioSource::BeginPlay(SceneBeginData* data) SetTime(GetStartTime()); } } + +void AudioSource::EndPlay() +{ + Actor::EndPlay(); + + ClipStarted.UnbindAll(); + ClipFinished.UnbindAll(); +} diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index b83a2b408..4e05d1594 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -76,6 +76,16 @@ public: API_FIELD(Attributes="EditorOrder(10), DefaultValue(null), EditorDisplay(\"Audio Source\")") AssetReference Clip; + /// + /// Event fired when the audio clip starts. + /// + API_EVENT() Delegate<> ClipStarted; + + /// + /// Event fired when the audio clip finishes. + /// + API_EVENT() Delegate<> ClipFinished; + /// /// Gets the velocity of the source. Determines pitch in relation to AudioListener's position. Only relevant for spatial (3D) sources. /// @@ -326,4 +336,5 @@ protected: void OnDisable() override; void OnTransformChanged() override; void BeginPlay(SceneBeginData* data) override; + void EndPlay() override; }; From 0dc1e04c897606bd3ecb03b917ebef70b551b89e Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:07:49 -0500 Subject: [PATCH 2/5] Add slider to audio debug editor for selecting time. --- .../Dedicated/AudioSourceEditor.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs b/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs index 1ddc1c144..0b15773b8 100644 --- a/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/AudioSourceEditor.cs @@ -13,6 +13,8 @@ namespace FlaxEditor.CustomEditors.Dedicated public class AudioSourceEditor : ActorEditor { private Label _infoLabel; + private Slider _slider; + private AudioSource.States _slideStartState; /// public override void Initialize(LayoutElementsContainer layout) @@ -28,6 +30,13 @@ namespace FlaxEditor.CustomEditors.Dedicated _infoLabel = playbackGroup.Label(string.Empty).Label; _infoLabel.AutoHeight = true; + // Play back slider + var sliderElement = playbackGroup.CustomContainer(); + _slider = sliderElement.CustomControl; + _slider.ThumbSize = new Float2(_slider.ThumbSize.X * 0.5f, _slider.ThumbSize.Y); + _slider.SlidingStart += OnSlidingStart; + _slider.SlidingEnd += OnSlidingEnd; + var grid = playbackGroup.UniformGrid(); var gridControl = grid.CustomControl; gridControl.ClipChildren = false; @@ -40,6 +49,38 @@ namespace FlaxEditor.CustomEditors.Dedicated } } + private void OnSlidingEnd() + { + foreach (var value in Values) + { + if (value is AudioSource audioSource && audioSource.Clip) + { + switch (_slideStartState) + { + case AudioSource.States.Playing: + audioSource.Play(); + break; + case AudioSource.States.Paused: + case AudioSource.States.Stopped: + audioSource.Pause(); + break; + default: break; + } + } + } + } + + private void OnSlidingStart() + { + foreach (var value in Values) + { + if (value is AudioSource audioSource && audioSource.Clip) + { + _slideStartState = audioSource.State; + } + } + } + /// public override void Refresh() { @@ -51,7 +92,29 @@ namespace FlaxEditor.CustomEditors.Dedicated foreach (var value in Values) { if (value is AudioSource audioSource && audioSource.Clip) + { text += $"Time: {audioSource.Time:##0.0}s / {audioSource.Clip.Length:##0.0}s\n"; + _slider.Maximum = audioSource.Clip.Length; + _slider.Minimum = 0; + if (_slider.IsSliding) + { + if (audioSource.State != AudioSource.States.Playing) + { + // Play to move slider correctly + audioSource.Play(); + audioSource.Time = _slider.Value; + } + else + { + audioSource.Time = _slider.Value; + } + } + else + { + _slider.Value = audioSource.Time; + } + + } } _infoLabel.Text = text; } From 0e3a22faa0a0207f8b1acbb86de801dcbd430a2c Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:11:06 -0500 Subject: [PATCH 3/5] Fix spelling in comment. --- Source/Engine/Audio/AudioSource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index c15084dc3..e17fbca0b 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -167,7 +167,7 @@ void AudioSource::Play() } else { - // Source was nt properly added to the Audio Backend + // Source was not properly added to the Audio Backend LOG(Warning, "Cannot play uninitialized audio source."); } } From 6f15ef769065ec3ac868a23ecd9aacdd55c84e72 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 1 Aug 2025 15:15:54 -0500 Subject: [PATCH 4/5] Fix location of clip start call. --- Source/Engine/Audio/AudioSource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index e17fbca0b..069fa29a3 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -395,15 +395,15 @@ void AudioSource::Update() AudioBackend::Source::VelocityChanged(SourceID, _velocity); } - if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) - ClipStarted(); - // Reset starting to play value once time is greater than zero if (_startingToPlay && GetTime() > 0.0f) { _startingToPlay = false; } + if (Math::NearEqual(GetTime(), _startTime) && _isActuallyPlayingSth && _startingToPlay) + ClipStarted(); + if (!UseStreaming() && Math::NearEqual(GetTime(), 0.0f) && _isActuallyPlayingSth && !_startingToPlay) { int32 queuedBuffers; From 4ae3d57adc531e99cbe9174a07733b8d6035c0c2 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 22 Sep 2025 11:32:24 -0500 Subject: [PATCH 5/5] Resolve code suggestions --- Source/Engine/Audio/AudioSource.cpp | 8 -------- Source/Engine/Audio/AudioSource.h | 5 ++--- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index 069fa29a3..f16f95423 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -588,11 +588,3 @@ void AudioSource::BeginPlay(SceneBeginData* data) SetTime(GetStartTime()); } } - -void AudioSource::EndPlay() -{ - Actor::EndPlay(); - - ClipStarted.UnbindAll(); - ClipFinished.UnbindAll(); -} diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index 4e05d1594..9858d283a 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -79,12 +79,12 @@ public: /// /// Event fired when the audio clip starts. /// - API_EVENT() Delegate<> ClipStarted; + API_EVENT() Action ClipStarted; /// /// Event fired when the audio clip finishes. /// - API_EVENT() Delegate<> ClipFinished; + API_EVENT() Action ClipFinished; /// /// Gets the velocity of the source. Determines pitch in relation to AudioListener's position. Only relevant for spatial (3D) sources. @@ -336,5 +336,4 @@ protected: void OnDisable() override; void OnTransformChanged() override; void BeginPlay(SceneBeginData* data) override; - void EndPlay() override; };