Repository navigation
Functions Reference
These functions are the absolute basic standard ones that would be used in any project to hook the system into the flow of your game.
This should generally be run once per frame, i.e. in the Step event of a global controller object or something like that. This is where the state of all your audio will update. Internally, all timing and updates are based on the actual play states of the sound files and on deltatime / milliseconds, not frames.
This should generally be run in a Room End event or equivalent "Level End" event in your game. This cleans up audio players, ends their associated sounds, and frees up the associated memory. Audio that is marked "persistent" like music or background ambience will continue to play unless you explicitly set the clearPersistent flag to TRUE ie. with bard_audio_clear(true);
This updates the position of the audio listener to the specified x,y,(z) location. "Where" audio seems to be coming from will based on the spatial relationship between this "listener" position and the 3D position of playing sounds. Generally speaking, you'll want to run this function every frame and simply place the listener at the center of the camera view.
In the script bard_audio_system you'll find a global variable definition for global.listener_distance among other values - this is the default distance the listener is positioned away from the screen. The further it is, the less sounds will appear to pan left and right of the listener. Audio sounds most natural when the listener position reflects where the actual player's head is relative to the game screen. The _view_zoom_scale input scales this distance, such that if your game camera is zoomed in (thus scaling the view by some amount less than 1), the listener will be placed closer to the screen, making audio sound louder and closer. Or if the view is zoomed out (thus scaling the view by some amount greater than 1), the listener will be farther and audio will be quieter and more distant.
Run this in a Draw GUI event to display information on the state of the audio system including currently playing sounds, their input volumes, emitter positions, beat timing, etc.
These functions are for playing, getting data from, and updating global audio state and sounds, ie. music and ambiences. You do not need to use these if you would rather have your music and ambience state controlled your own way. They are essentially just interfaces for class_audio_playstack() instances called global.music_system and global.ambience_system. For the audio assets themselves you will need to provide string names of containers which you previously defined in the Audio Editor.
This sets the currently playing background music to the specified container. The "tier" can be any integer value 0 or greater (generally 0 - 3). In place of the container name, you can say 0 to mean "silent" or -1 to mean "empty/no instruction."
By assigning music a higher "tier," it will remember music playing on a lower tier and be able to return to it later. For example, if you are exploring an overworld area with its own background music on tier 0, you could enter combat and begin playing battle music on tier 1. Then when combat is over, set the tier 1 music to -1, thus allowing the overworld music to resume. If you want to enter a cutscene that is temporarily silent, you could set the tier 1 music to 0, and then -1 when you want the regular music to resume. Playing a non-looping container on a higher tier will also automatically resume the lower-tier music when the higher-tier song ends, like if you want to play a short jingle for finding an item.
This lets you set the current musical key to one you defined in the bard_audio_system_music_keys script. The current music key only really matters if you use container_play_note().
Return the string name of the container that is currently playing from the music system. It will return 0 if it is currently set to be silent, or -1 if there is no instruction found.
Returns the "tier" of the currently playing music audio. (An integer).
Pauses the currently playing music and prevents any updates until unpaused.
Unpauses the music system.
Return the current playtime of the current music container, in seconds.
Return the current playtime of the current music container, in beats. Beats are measured based on the "starting beat" and BPM you set for the music in the Audio Editor, or is set to 120BPM if none was provided. This counts progress through the song in terms of beats, so if you are halfway through the 1st beat of the song, this will return 0.5.
Returns the BPM of the currently playing song. This also factors in the current pitch setting on the music, so if it is slowed down or sped up then you'll see what the BPM effectively currently is.
This sets the playtime of the currently playing music to the provided time in seconds. This simply sets the playtime on the audio asset itself, so if you are playing a looping song that had a head intro, this won't revert the song back into its head.
This goes through all the audio layers in the currently playing song and sets them all to be at the same play position if they are sufficiently out of sync. This is a hack to correct music layers which can drift out of sync after a very long time. At one point Game Maker implemented audio_sync_groups to correct issues with this, but sync_groups have had their own issues int he past so by default we don't make use of them. If you are experiencing audio drift, you can try running this function every few minutes to correct it.
This works just like music_set() but for ambience instead. There are fewer interfaces for getting ambience data since you generally don't do a lot of effects with ambience.
These scripts are all named tersely and differently from everything else because it felt cool (sorry). They all grab data off the current highest tier music in the global.music_system, so they rely on you playing audio through the above systems to function. If you understand the inner workings well enough you can recreate them easily enough on your own system though.
Return TRUE or FALSE if the currently playing music hit a new beat on the current frame. This state updates each time you run bard_audio_update(), and on a new beat will be TRUE for exactly 1 cycle and will then reset to false the next time bard_audio_update() is run. The frequency of beatEvents updates correctly if you change the pitch of the audio.
Like above, but will return TRUE on half-beats as well as on the beats themselves.
Like above, but will return TRUE only if the new beat also started off a new measure. Measures are counted based on how many beats per measure you set for he playing container in the Audio Editor. A typical 4/4 song will have a new "measure event" every 4 beats, whereas a 3/4 walts would be on every 3 beats, a 6/4 punk jam would be on every 6 beats, etc...
This returns the length of 1 beat in milliseconds. It can be used to time visual effects; for example, draw_circle(x,y,10+(5 * sin(pi * current_time/beatMS())),true) would draw a circle that expands and retracts in time with the current background music.
These functions are for playing and managing containers which you've defined in the Audio Editor. These are probably the functions you'll be making the most use of, for playing any conceivable sound in your game.
Plays the named container. The name should be provided as a string (ie. "music_area_1") and would be the name of a container you previously defined in the Audio Editor. This returns an integer ID for the sound you just played, which you can use to manipulate the playing audio instance.
If the container is a 3D sound, it will only play as a 3D-positioned sound if the playing object has objSpatialObject as a parent. 3D audio in this system is always associated with a playing object. It will always be positioned at, and move along with, the original playing object, so that for ex. if you have 2 enemy characters on screen who are both moving around and screaming constantly, you will hear each of their individual screams moving with the character as they move around.
Like above, but this creates a new object called objLocationSound which holds the playing audio. This returns the instance id of the newly created objLocationSound so that you can move the object to reposition the sound if you so please. objLocationSound objects are destroyed in bard_audio_update() if and when their associated container stops playing.
Nearly identical to container_play(), but it will only play the container if the provided playID is not -1. The intended use is as a shorthand for checking every frame if a sound needs to played, ie. in the Step Event of a scrollbar you might say if (dragging){ dragging_sound_id = container_play_instance("drag_sfx",dragging_sound_id);}. This would ensure that a dragging sound starts playing anytime the object is in the dragging state. This is a very pedantic alternate function to exist, but I like to use it a lot, so I thought you would too.
This plays the named container, pitched to a musical note using the integer noteID input, based on the current music key set by set_music_key(). 0 is the "root" note, 1 is the next one up, etc. So if the key is set to C major and you want to play note 0, that's a C. This function assumes that the source sound file is pitched to be a C note, and simply re-pitches it to match the provided key/note.
You can also supply a fractional value for the noteID and it will give you its best approximation of what that is using the nearest adjacent integer pitches (we used this to create a theremin instrument in Chicory).
Stops the playing container. If any stopping effects have been defined in the Audio Editor, those will be respected, ie. the sound might delay for a moment before stopping, fade out, or play a tail sound. However, at the exact moment container_stop() is called, the container will from then on be treated as if it is NOT playing by container_is_playing(). If a playID is supplied, only that playing instance of the container will stop.
If the playID is something other than -1, that instance of the container will be stopped. The function always returns -1. This is meant to be used in conjunction with container_play_instance(). For example, on a scrollbar object, you could say in its step event if (!dragging){dragging_sound = container_stop_instance("drag_sfx",dragging_sound);} and this would ensure that when the scroll bar is not being dragged, any associated dragging sounds it might be playing are also stopped.
This stops the named container, ignoring any stop effects. The container then immediately clears itself from memory. Note that if the container has any component sounds which are not looping, this will allow those sounds to play out. Non-looping sounds CAN be cut off by using container_stop(), bu the purpose of this function is mostly to free up the memory. (I never used it, idk).
Stops all playing containers with a container_stop_hard().
Returns TRUE if the named container is currently playing and FALSE if not. If the container has been stopped with container_stop() but is still playing some residual audio effects, this will return FALSE so as to correctly feedback that the container "has been stopped." This will also return FALSE if the container is paused, or doesn't exist at all.
Exactly like container_is_playing(), but will also return TRUE even if the container is paused, indicating that it currently is running in some form even if it is not currently emitting audio.
Pauses the named container and prevents updates until further notice.
Unpauses the named container.
Updates an already-playing container to set its pitch to the given noteID, as if it were played with container_play_note(). If a playID other than 01 is provided, it will update only that specific playing instance of the container.