Skip to content
Snippets Groups Projects

Added Queues and BGM/BGS looping

Open Divided by Zer0 requested to merge dbyzer0/sound-manager:queuing into master

I wanted to create functionality to specify a number of tracks on my game to loop through as background music. I could do it externally in my own game, but I felt this functionality might be useful to other people.

Unfortunately due to the nature of the code and using the index of the children nodes, this was impossible to do with the current codebase. So I had to refactor things quite a bit. In the process I simplified the workflow and switched to some more simplified code.

  • I removed the index-based arrays
  • To discover playing tracks, I just check the existing children in runtime.
  • I class-named the Sounds.gd as SoundManagerAudioStreamPlayer. This avoids having to check if the node has a script.
  • I renamed sound_name to sound_path and added a new sound_name which stores the key the developer has given to this file in Audio_Files_Dictionary. This makes it more obvious what the variable stores.
  • Instead of having to keep track of children index, I am now using the sound.gd class directly. I have extended it to store more properties
  • Removed redundant self. pointers.
  • Added extra function get_all_playing_streams() which returns an Array of SoundManagerAudioStreamPlayer currently playing
  • Added extra function find_audiostream() which returns a SoundManagerAudioStreamPlayer which has that sound_name of sound_path
  • Added extra function get_sound_name_from_path() which returns the Audio_Files_Dictionary key which matches the sound_path provided
  • Added more static typing

On top of those I added 2 extra features

  • You can now queue sounds, and they will be played after the current sound ends, in a FIFO order.
    • Added functions queue_bgm and queue_bgs which handle this for these two types. I don't expect anyone will want to queue SE/ME types.
    • Queuing a sound when there's nothing in the queue already,will automatically start playing it.
    • Added function clear_queue() to empty the specified sound_type queue
  • Can now loop queues. A queue marked for looping will put any finished sound to the back of the queue.
    • Added function toggle_queue_repeat() which accepts a sound_type argument as string

PS: This includes the mp3 support, you you can skip that merge

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Divided by Zer0 mentioned in merge request !19 (closed)

    mentioned in merge request !19 (closed)

  • added 1 commit

    • 36c9f079 - Added queue_directory, queue_filelist, and stop_all

    Compare with previous version

  • Some more improvements:

    • Added function queue_directory()
    • Added function queue_filelist()
    • Added function stop_all()
    • extracted code from preload_audio_files_from_path and converted it into static func get_sound_files_in_dir() which can be used by externally from the SoundManager
    • converted is_import_file() and is_audio_file into static funcs as they don't have any dependency on the SoundManager instance.
  • added 1 commit

    • 868b4572 - fix for get_sound_files_in_dir to work with exports

    Compare with previous version

  • added 1 commit

    • e4ab78ad - Added fade-in/out and crossfade methods

    Compare with previous version

  • And some more features

    • Added functions fade_in_bgm() and fade_out_bgm() to graceful start/end music
    • Added function crossfade_queue() which will crossfade the current playing song, with the next one in the queue
    • queue_filelist() and queue_directory() now accept a boolean to initiate a crossfade

    These allow a game to gracefully change the looping background music between scenes gracefully.

    Edited by Divided by Zer0
  • Welp this is a lot of stuff haha Very impressive! I've actually wanted to add the queue feature for a while, but I read somewhere that in some new version of the engine they were adding AudioStreamPlaylists and I was waiting to see how they worked and what they were. But I'm more and more convinced they're going to pop up directly in Godot 4, so, yea, no reason not to make a self-made system at this point. I will have to review your code and test it before approving the merge (although I assume you're already testing it, but you know, just to be sure) so it'll take some more time. Still good job, though!

  • It's already being used in my game (Hypnagonia), so feel free to see how it works there, and naturally I expected no less than you double-checking my work :)

  • added 1 commit

    • 7a581842 - fix(sound) Fix logic error in find_audiostream()

    Compare with previous version

  • Ok, sorry for the wait (I had a really busy week). I took a quick look at the code and I like the new features, even though I feel like there's still room for improvement. But I'm not sure how atm, it's just a hunch. Switching to actually testing it, I started messing around with the official demo just to make sure the basic features weren't broken in the process. Unfortunately, I'm already finding a bug. If you try to play an audio (no preload, no preinstantiation, no queues, just playing an audio) then you stop it and you try to play it again, the engine throws this error. image
    Related to the method prepare_sound. It appears to only happen when you manually stop a sound: testing with a sound effect letting it naturally stop by itself didn't throw the same error.

    Edited by Celeste Privitera
  • Lemme take a look. That reminds me, this project could really benefit from some unit testing. Not very optimal to be manually testing the features like that. Would you be OK with me adding the GUT add-on to your demo project? I can then develop some starting tests and you can keep adding to them

  • Divided by Zer0 added 4 commits

    added 4 commits

    • 757e2a10 - fixes not clearing out the right path from Instantatiated Nodes
    • 76e8b8ad - fix trying to erase non-existing sound
    • 42d0d3c7 - fix for preinstantatiated nodes not setting sound_type
    • c56f8cff - fix for uninstantiate_nodes_from_list

    Compare with previous version

  • OK, I went through your demo and tried various combinations. Caught a bunch of issues and fixed them. I can't make the demo behave unexpectedly anymore, so I think it should be fine now.

  • That reminds me, this project could really benefit from some unit testing. Not very optimal to be manually testing the features like that. Would you be OK with me adding the GUT add-on to your demo project?

    I usually go with prints because I find them more convenient, but I understand where you're coming from with this proposal. If you want to try, yes, it could be a good idea.

    I pulled the new version and tested again and it now works! Tomorrow (it's already evening here), I'll take a proper look at the changes and new additions!

  • I usually go with prints because I find them more convenient,

    Ye, plan is to have both. UT might be a good way to catch bugs automatically.

    If you want to try, yes, it could be a good idea.

    OK, I'll see what I can come up after this PR is merged.

  • Sooo...about this MR..?

  • added 1 commit

    • ae30641f - Added pause_streams() and unpause_streams()

    Compare with previous version

Please register or sign in to reply
Loading