Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No "Finished" signal with looped audio #30737

Closed
JustYourAverageJosh opened this issue Jul 21, 2019 · 4 comments
Closed

No "Finished" signal with looped audio #30737

JustYourAverageJosh opened this issue Jul 21, 2019 · 4 comments

Comments

@JustYourAverageJosh
Copy link

Using 3.1.1

Audio that is set to loop does not send a "finished" signal when it restarts.
To get around this, I disabled loop, and loop through code (on the finished signal, play)
That is almost good enough, but I have found:
Manually looping like this causes the audio to have a slight delay before it restarts, so the looping audio is not seamless.
When set to automatically loop, there is no (observable) delay. However as I said, with automatic loop set I can't get the finished signal.

@henriiquecampos
Copy link
Contributor

They should totally emit a signal, but I think it should be a different one to avoid any compatibility break, something like signal looped

@hungrymonkey
Copy link
Contributor

hungrymonkey commented Sep 28, 2019

For fun, I decided to guess on how to implement this feature

Background: Godot implements scripting and audio on different threads. To avoid avoiding mixing on the main thread, Audioplayer::play() only sets flags in the Audioplayer itself and calls AudioStreamPlayback::play() which holds the state instance for static AudioStream resources. When the Audioplayer ends, Scenetree calls Audioplayer::_notification(int) to emit signals.

The Problem: AudioStreamPlayer::_mix_internal(bool) is managed by the audio thread and should not be emitting signals. Although AudioStreamPlayer mix creates AudioFrame to be generated into the audio buffer, the Class store mostly user settings rather than player state. AudioStreamPlayback::get_loop_count() can only provide count information but cannot discern when the playback happened.

Proposal: Implement play() flag setting in reverse.

  1. Add a signal looped to Audioplayer

    ADD_SIGNAL(MethodInfo("finished"));
    .

  2. Call AudioStreamPlayback::get_loop_count() in the beginning of _mix_internal() and call it again to the end to see if the player looped and set a flag for later processing

  3. In the NOTIFICATION_INTERNAL_PROCESS state, check the flag and `emit_signal("looped")

if (p_what == NOTIFICATION_INTERNAL_PROCESS) {

Like play, this loop will only emit signals in between frames like the rest of the engine.

@Xrayez
Copy link
Contributor

Xrayez commented Jan 5, 2020

Somewhat related discussion: #33579.

@KoBeWi
Copy link
Member

KoBeWi commented Oct 31, 2021

Closing in favor of the proposal: godotengine/godot-proposals#1641

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants