Start typing to search packages!
audiokit
By @biotoxin495
Roblox
Mirrored from WallyAudioKit — A config-driven audio manager for Roblox
AudioKit, a standalone audio manager for Roblox experiences.
AudioKit lets you define sound effects and music once, refer to them by logical name throughout your game, and control playback through one reusable API.
The module handles overlapping sound effects, variations, cooldowns, looping audio, playlists, crossfades, temporary music overrides, preloading, volume controls, and cleanup internally—with no external dependencies.
Quick example
AudioKit plays configured sounds by name through Play.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AudioKit = require(ReplicatedStorage.Packages.AudioKit)
local Audio = AudioKit.new({
Sounds = {
UIClick = {
SoundId = "rbxassetid://123456789",
Volume = 0.8,
},
},
})
Audio:Play("UIClick")
Audio definitions are available immediately. Preloading is optional and can be performed separately when needed.
🚀 Features
Config-driven audio
Keep sound effects, variations, playlists, default volumes, and preload selections in one configuration table. Definitions may be tables, asset ID strings, or numeric asset IDs.
local Audio = AudioKit.new({
Volumes = {
Master = 1,
SFX = 0.8,
Music = 0.4,
},
Sounds = {
Confirm = "rbxassetid://123456789",
},
Music = {
Main = "rbxassetid://987654321",
},
})
Sound variations
Multiple physical sounds can sit behind one logical name. AudioKit supports random, non-repeating random, rotating, shuffled, and weighted selection.
Sounds = {
Footstep = {
Variants = {
{ SoundId = "rbxassetid://111", Weight = 4 },
{ SoundId = "rbxassetid://222", Weight = 2 },
{ SoundId = "rbxassetid://333", Weight = 1 },
},
Selection = "Weighted",
},
}
Overlapping and looping playback
Every playback uses its own Sound clone, allowing the same effect to overlap without restarting an existing voice. Play returns a handle that can pause, resume, fade, retune, or stop that playback.
local engine = Audio:Play("Engine", {
Looped = true,
FadeInTime = 0.25,
})
if engine then
engine:SetVolume(0.65, 0.2)
engine:SetPlaybackSpeed(1.15)
engine:Stop(0.3)
end
Cooldowns and concurrency limits
Frequently triggered sounds can limit how often they start and how many instances may play simultaneously.
Sounds = {
Hover = {
SoundId = "rbxassetid://123",
Cooldown = 0.03,
MaxInstances = 2,
OverflowBehavior = "StopOldest",
},
}
Music playlists and crossfades
Music entries may contain multiple tracks. AudioKit advances through the playlist and overlaps outgoing and incoming tracks during crossfades.
Music = {
Main = {
Tracks = {
{ SoundId = "rbxassetid://111", Volume = 0.5 },
{ SoundId = "rbxassetid://222", Volume = 0.5 },
},
Selection = "Shuffle",
Repeat = true,
CrossfadeTime = 1.5,
},
}
Temporary music overrides
PushMusic temporarily places another music context above the current one. Stopping its token automatically restores the previous context, and overrides may be nested.
local shopMusic = Audio:PushMusic("Shop")
if shopMusic then
shopMusic:Stop()
end
Volume and mute controls
Master, sound-effect, and music levels can be adjusted independently without destroying active playback.
Audio:SetMasterVolume(0.8)
Audio:SetBusVolume("SFX", 0.6)
Audio:SetBusVolume("Music", 0.4)
Audio:SetBusMuted("Music", true)
Selective preloading
Preload the complete library, selected logical names, or the entries listed in the configuration.
local ok, err = Audio:PreloadAsync({
Sounds = { "UIClick", "Purchase" },
Music = { "Main" },
})
PreloadAsync yields until Roblox finishes the request, so run it in a separate task if the rest of startup should continue.
Positional audio and effects
Parent playback to a BasePart or Attachment for positional audio. Definitions may also configure roll-off properties and legacy Roblox SoundEffect instances.
Audio:PlayAt("Explosion", workspace.ExplosionPoint)
Fully typed, no dependencies
AudioKit uses strict Luau, ships with reusable exported types, and does not require Promise, Signal, Maid, Kernel, or another framework.
📖 Basic usage
Place AudioKit somewhere accessible to your client scripts, such as ReplicatedStorage.Packages, then require it from a LocalScript.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AudioKit = require(ReplicatedStorage.Packages.AudioKit)
local Audio = AudioKit.new({
DefaultFadeTime = 0.5,
Sounds = {
UIClick = "rbxassetid://123456789",
Explosion = {
SoundId = "rbxassetid://234567891",
Volume = 0.7,
},
},
Music = {
Main = {
Tracks = {
"rbxassetid://345678912",
"rbxassetid://456789123",
},
Selection = "Shuffle",
Repeat = true,
CrossfadeTime = 1.5,
},
},
})
Audio:Play("UIClick")
Audio:PlayMusic("Main")
Example: per-play options
local handle = Audio:Play("Explosion", {
Parent = workspace.ExplosionPoint,
VolumeScale = 0.8,
PlaybackSpeedScale = 1.05,
FadeInTime = 0.1,
})
Example: temporary one-shot music
Audio:PushMusic("CrateOpening", {
Repeat = false,
OnComplete = function(reason)
print("Crate music finished:", reason)
end,
})
⚙️ API
AudioKit.new(config, options?)
Creates an AudioKit instance and synchronously prepares its configured source sounds. Constructor options may override the generated folder's Name and Parent; it otherwise defaults to config.Name or AudioKit under SoundService.
Audio:Play(name, options?)
Plays a configured sound effect and returns a playback handle, or nil when the name is missing, the bus is muted, or cooldown/concurrency rules reject playback.
Audio:CreateSound(name, options?)
Creates and returns an unplayed Sound clone. The caller controls its parent and lifetime.
Audio:PlayAt(name, parent, options?)
Plays a sound parented to the supplied Instance, which is useful for positional playback.
Audio:PlayMusic(name, options?)
Sets the base music context and returns whether the configured entry was found. If a temporary override is active, the new base context begins when that override is removed.
Audio:PushMusic(name, options?)
Pushes a temporary music context and returns a token. Call token:Stop() or token:Destroy() to restore the context beneath it. token:IsActive() reports whether it remains on the stack.
Audio:StopMusic(fadeTime?)
Stops current music and clears the base context and all temporary overrides.
Audio:GetCurrentMusicName()
Returns the active logical music name, or nil when no context is selected.
Volume and mute methods
| Method | Description |
|---|---|
SetMasterVolume(volume) / GetMasterVolume() | Sets or returns the master volume |
SetBusVolume(bus, volume) / GetBusVolume(bus) | Sets or returns the "SFX" or "Music" volume |
SetMasterMuted(muted) / IsMasterMuted() | Sets or returns the master mute state |
SetBusMuted(bus, muted) / IsBusMuted(bus) | Sets or returns a bus mute state |
SetSFXEnabled(enabled) | Convenience setter for the SFX mute state |
SetMusicEnabled(enabled) | Convenience setter for the music mute state |
Preloading and inspection methods
| Method | Description |
|---|---|
PreloadAsync(selection?, onProgress?) | Preloads all or selected assets and returns ok, err |
PreloadConfiguredAsync(onProgress?) | Preloads the selection in config.Preload |
GetActivePlaybackCount(bus?) | Returns the number of live handles, optionally by bus |
GetDebugState() | Returns music, playback, volume, mute, and version state |
Cleanup methods
| Method | Description |
|---|---|
StopAllSFX(fadeTime?) | Stops all sound-effect playback |
StopAll(fadeTime?) | Stops all sound effects and music |
Destroy() | Stops playback, invalidates music tasks, and destroys generated instances |
Playback handle API
| Member | Description |
|---|---|
Sound | Runtime Sound owned by the handle |
Completed | Signal fired with the completion reason |
Play() | Starts the sound |
Pause() / Resume() | Pauses or resumes playback |
IsAlive() / IsPlaying() | Returns handle or playback state |
SetPlaybackSpeed(speed) | Updates playback speed |
SetVolume(scale, fadeTime?) | Updates per-play volume, optionally over time |
FadeTo(gain, fadeTime, callback?) | Fades gain and optionally invokes a callback |
Stop(fadeTime?) / Destroy() | Stops and cleans up playback |
Wait() | Yields until completion and returns the reason |
OnCompleted(callback) | Connects a completion callback |
The handle destroys its runtime Sound when playback finishes or the handle is destroyed.
Complete options reference
You normally only need to provide the properties you want to change. Omitted values use the module defaults.
Root configuration
| Property | Type | Description |
|---|---|---|
Name | string | Name of the generated root folder |
DefaultFadeTime | number | Default music transition duration |
Volumes | table | Initial Master, SFX, and Music volumes |
Muted | table | Initial Master, SFX, and Music mute states |
Sounds | { [string]: SoundDefinition } | Named sound-effect definitions |
Music | { [string]: MusicDefinition } | Named music definitions |
Preload | `boolean | table` |
Sound and track properties
| Property | Type | Description |
|---|---|---|
SoundId | `string | number` |
Volume | number | Base volume |
PlaybackSpeed | number | Base playback speed |
Looped | boolean | Whether playback loops |
TimePosition | number | Starting playback position |
Weight | number | Relative weight for weighted selection |
Effects | `{ EffectDefinition | SoundEffect }` |
RollOffMinDistance | number | Minimum positional roll-off distance |
RollOffMaxDistance | number | Maximum positional roll-off distance |
RollOffMode | Enum.RollOffMode | Positional roll-off curve |
EmitterSize | number | Positional emitter size |
Sound definitions also accept Variants, Selection, Cooldown, MaxInstances, and OverflowBehavior. Music definitions accept Tracks or Variants, plus Selection, Repeat, and CrossfadeTime.
Selection modes
| Value | Behavior |
|---|---|
Random | Selects any variant randomly |
RandomNoRepeat | Avoids immediately replaying the previous variant |
Rotate | Selects variants sequentially |
Shuffle | Selects every variant once before reshuffling |
Weighted | Uses each variant's Weight |
Overflow behaviors
| Value | Behavior |
|---|---|
Reject | Refuses the new playback |
StopOldest | Stops the oldest playback before starting the new one |
RestartOldest | Replaces the oldest playback with the new one |
Play options
| Option | Type | Description |
|---|---|---|
Parent | Instance | Parent for the runtime sound |
VolumeScale | number | Per-play volume multiplier |
PlaybackSpeedScale | number | Per-play speed multiplier |
Looped | boolean | Overrides looping |
TimePosition | number | Overrides the starting position |
FadeInTime | number | Fade-in duration |
IgnoreCooldown | boolean | Bypasses the cooldown |
MaxInstances | number | Overrides the concurrency limit |
OverflowBehavior | OverflowBehavior | Overrides overflow handling |
PlayWhenMuted | boolean | Allows creation while SFX is muted |
Music options additionally support FadeTime, Repeat, OnComplete, and OnStopped.
Complete example
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AudioKit = require(ReplicatedStorage.Packages.AudioKit)
local Audio = AudioKit.new({
Name = "GameAudio",
DefaultFadeTime = 0.5,
Volumes = { Master = 1, SFX = 0.8, Music = 0.4 },
Sounds = {
UIClick = "rbxassetid://123456789",
Footstep = {
Variants = {
"rbxassetid://111111111",
"rbxassetid://222222222",
"rbxassetid://333333333",
},
Selection = "RandomNoRepeat",
Cooldown = 0.05,
MaxInstances = 4,
OverflowBehavior = "StopOldest",
},
},
Music = {
Main = {
Tracks = {
{ SoundId = "rbxassetid://444444444", Volume = 0.5 },
{ SoundId = "rbxassetid://555555555", Volume = 0.5 },
},
Selection = "Shuffle",
Repeat = true,
CrossfadeTime = 1.5,
},
},
Preload = {
Sounds = { "UIClick", "Footstep" },
Music = { "Main" },
},
})
task.spawn(function()
Audio:PreloadConfiguredAsync()
end)
Audio:Play("UIClick")
Audio:PlayMusic("Main")
Legacy AudioController compatibility
AudioKit automatically converts the previous configuration shape containing SoundEffects, BackgroundMusic, AdditionalMusic, and legacy Sounds groups.
Compatibility methods include PlaySound, GetSoundInstance, PlaySoundVariant, StartLoopingSound, StopLoopingSound, PlaySpecialMusic, and StopSpecialMusic.
Game-specific methods such as StartShopMusic should remain in the consuming game's controller and call the generic AudioKit API internally.
Behavior
Each playback receives its own runtime Sound clone, so repeated effects can overlap. Source instances are created synchronously during AudioKit.new; preloading is a separate, optional operation.
Music overrides form a stack. The most recently pushed override plays until its token stops, then AudioKit restores the context beneath it. Crossfades use simultaneous outgoing and incoming sounds.
AudioKit is designed primarily for a local player's client-side audio context. It does not prescribe an options menu, persistence system, or server-authoritative replication model.
📝 Notes
- AudioKit currently uses Roblox
Soundinstances rather than anAudioPlayerandWirebackend. - Beat-, bar-, and BPM-synchronized transitions are not included.
- Effects use legacy
SoundEffectinstances because the playback backend usesSound. - Roblox audio ownership and experience permissions remain the consuming game's responsibility.
- Call
Audio:Destroy()when the audio context is no longer needed.
🛠️ Installation
Roblox Studio
Import AudioKitStandalone.rbxmx for a single-ModuleScript package, or AudioKit.rbxmx for the structured version with child modules.
ReplicatedStorage
└── Packages
└── AudioKit
Rojo
The included project maps AudioKit to ReplicatedStorage.Packages.AudioKit.
rojo serve default.project.json
Single ModuleScript
dist/AudioKit.lua contains the complete bundled module. Create a ModuleScript named AudioKit, paste the bundled source into it, and require it normally.
License
This project is released under the MIT License.
See LICENSE for details.
made with ❤️ by biotoxin495
Package Details
Install command (Click to copy)
Version
1.0.0
License
MIT
Safe for commercial use
Automated license review — not legal advice.
