-
-
Notifications
You must be signed in to change notification settings - Fork 20.6k
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
Add beat and bar getters to AudioStreamPlayer[2D/3D] #81542
base: master
Are you sure you want to change the base?
Conversation
c7b9d76
to
d3d5f57
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And in all three AudioStreamPlayer* classes, you need to reset prev_beat
and prev_bar
inside play()
and stop()
Alternatively to the if (current_bar >= 0)
suggestion, you can cache a variant of beat_loop
(temp variable calculated in _mix_internal
in ogg vorbis and mp3), just without the has_loop
-check, and expose it to the AudioStreamPlayer* classes (and cache it there).
Thanks for the reviews! This is of course an edge case, but pausing music is relatively common when you e.g. go into a pause menu or inventory screen in the middle of the game, so it's worth considering imo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, you need to reset them in
And the very same if-clause in AudioStreamPlayer3D and AudioStreamPlayer.
Plus in case NOTIFICATION_PREDELETE
:
And you must still reset it in stop()
because of stream_playbacks.clear();
-> this prevents the code referenced above to be executed.
This way pausing should be no issue.
It seems you overlooked that: |
Yes, thanks! |
67a2681
to
ab4179e
Compare
Looking quite good : ) Last thing I can think of is that you should move all 3 lines with |
Thanks, applying that.
Is there a way to conditionally disable these error messages? Otherwise I guess I need a method for internal use on Edit: I'll just call |
I thought the same, but it looks like you cannot reach the necessary stream class from the players. That's why I made that suggestion: #81542 (review) |
I can reach the class. |
ab4179e
to
fac7efa
Compare
Indeed, I completely missed that and only saw |
fac7efa
to
9d2e26a
Compare
@AThousandShips @MJacred do you think this is ready to be merged, or do I need to make further changes? Thanks ✨ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than this it looks good style wise
48400bb
to
d2b6124
Compare
Applied the changes and squashed the commits again 👍 |
Considering that this seems to be a complete pr with no remaining notes, will this be merged for 4.2? |
I was told that 4.2 is entering a feature freeze, so this will likely only get merged for 4.3 sadly. |
@lemilonkh: This needs to be approved first. Could you please check as well @ellenhp? (The code looked good to me at least). If she's unavailable, we can ping Juan afterwards, as it's not about audio containers. |
I'm a bit out of the loop with beat/bar stuff and dynamic audio. I made some proposals that made sense to me but Juan wasn't as convinced and I think we ended up going a different way. I haven't kept up with progress. The only things I'll note here are:
Others may be better at reviewing for style than me and I think Juan should review this for audio. |
@reduz could you maybe give this PR a review? I've heard from multiple people who would like to use the functionality in official builds to make e.g. rhythm games or music visualizations, so I think it would be nice if it could make it in for 4.3. |
d2b6124
to
5f41a54
Compare
5f41a54
to
683eb3a
Compare
Based on the feedback from @reduz on Twitter I removed the signals from this PR, since they were basically also polling (just with a sugar coated interface), which can be done in GDScript if required. The previous state of the PR is preserved on the beat-helpers-signals branch in case anyone needs it. I'd say the PR is ready for a review ✨ |
@reduz any chance to take a look a this PR? |
This is scheduled for 4.3 but it is far from requiring a proper assessment and it cannot be in the incoming version. Is there any progress on this PR? It should be moved to 4.4 just to be sure. |
From my end it does what it needs to do, but I agree it makes sense to move it to 4.4. Let me know if there are any required changes, as this already went through the review process back when I originally made it, it was just never picked up by a core reviewer that could approve it... |
Implements godotengine/godot-proposals#6166.
Video demo
BeatTools.mp4
API
It adds the following functions and signals:
AudioStreamPlayer.get_current_beat() -> int
AudioStreamPlayer.get_current_bar() -> int
AudioStreamPlayer.get_beat_progress() -> float
in range [0,1]AudioStreamPlayer.get_bar_progress() -> float
in range [0,1]- SignalAudioStreamPlayback.beat_changed(beat: int)
- SignalAudioStreamPlayback.bar_changed(bar: int)
Edit: Signals were removed, see below.
This allows syncing gameplay or visual effects to the BPM (beats per minute) of music.
It is implemented for MP3 and OGG Vorbis streams (since those are the only ones that have BPM information attached, although it could be implemented for WAV if desired and the bpm/ bar_beats fields are added to that).
This works for
AudioStreamPlayer
,AudioStreamPlayer2D
andAudioStreamPlayer3D
.Test project
BeatToolsTestProject_v2.zipUpdate: New version that uses the signals on
AudioStreamPlayer
and adds tweens for label colors when the signals are triggered to demonstrate their usage.BeatToolsTestProject_v3.zip
This project contains two music files in ogg and mp3 formats with different BPM (to test both implementations and show that it syncs correctly to different speeds).
The contained music files are CC0 licensed and can be found here.
If desired, I can polish this project a bit and add it to the godot-demo-projects repository/ Godot Asset Library, so that we can show a working reference implementation for the BPM features.
Outstanding work
Ideally the events fromAudioStreamPlayback
would be exposed onAudioStreamPlayer
as well (I have defined them there too, but haven't found a good way to re-emit a signal emitted byAudioStreamPlayback
fromAudioStreamPlayer
, sinceAudioStreamPlayback
doesn't have a reference to the player and the player can have multiple playback instances. If someone has an idea how this signal could be exposed, please let me know and I'll adjust the implementation. Otherwise I will remove the signal definitions from AudioStreamPlayer[2D/3D].Another option would be to emit the signals from the AudioStream instead, which the AudioStreamPlayback has a reference to and could call a method on. This is slightly less elegant to work with in GDScript than signals emitted on the AudioStreamPlayer, since the stream might be changed and then the signals need to be reconnected from code. It also means that you can't connect the signal from the editor UI on the node as usual. It's much nicer than having to connect to signals on the AudioStreamPlayback object though, since that changes often (e.g. when seeking it seems) and isn't available until you play the stream (see the test project for this being tricky to work around).Another issue is that the signals are emitted from the audio thread, so you have to usecall_deferred
orset_deferred
to interact with UI or other nodes from a function connected to one of the signals (as seen in the example code). Is there a way to emit the signal on the main thread instead?Update: The signals are now emitted from
AudioStreamPlayer[2D/3D]
directly, so the GDScript interface is much nicer to use now. Thanks for the feedback and help in getting this to work! ✨