Forest Logo
search
package_2

audiokit

By @biotoxin495

Roblox

Mirrored from Wally

AudioKit — 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

MethodDescription
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

MethodDescription
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

MethodDescription
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

MemberDescription
SoundRuntime Sound owned by the handle
CompletedSignal 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

PropertyTypeDescription
NamestringName of the generated root folder
DefaultFadeTimenumberDefault music transition duration
VolumestableInitial Master, SFX, and Music volumes
MutedtableInitial Master, SFX, and Music mute states
Sounds{ [string]: SoundDefinition }Named sound-effect definitions
Music{ [string]: MusicDefinition }Named music definitions
Preload`booleantable`

Sound and track properties

PropertyTypeDescription
SoundId`stringnumber`
VolumenumberBase volume
PlaybackSpeednumberBase playback speed
LoopedbooleanWhether playback loops
TimePositionnumberStarting playback position
WeightnumberRelative weight for weighted selection
Effects`{ EffectDefinitionSoundEffect }`
RollOffMinDistancenumberMinimum positional roll-off distance
RollOffMaxDistancenumberMaximum positional roll-off distance
RollOffModeEnum.RollOffModePositional roll-off curve
EmitterSizenumberPositional 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

ValueBehavior
RandomSelects any variant randomly
RandomNoRepeatAvoids immediately replaying the previous variant
RotateSelects variants sequentially
ShuffleSelects every variant once before reshuffling
WeightedUses each variant's Weight

Overflow behaviors

ValueBehavior
RejectRefuses the new playback
StopOldestStops the oldest playback before starting the new one
RestartOldestReplaces the oldest playback with the new one

Play options

OptionTypeDescription
ParentInstanceParent for the runtime sound
VolumeScalenumberPer-play volume multiplier
PlaybackSpeedScalenumberPer-play speed multiplier
LoopedbooleanOverrides looping
TimePositionnumberOverrides the starting position
FadeInTimenumberFade-in duration
IgnoreCooldownbooleanBypasses the cooldown
MaxInstancesnumberOverrides the concurrency limit
OverflowBehaviorOverflowBehaviorOverrides overflow handling
PlayWhenMutedbooleanAllows 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 Sound instances rather than an AudioPlayer and Wire backend.
  • Beat-, bar-, and BPM-synchronized transitions are not included.
  • Effects use legacy SoundEffect instances because the playback backend uses Sound.
  • 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

check_circle

Safe for commercial use

Automated license review — not legal advice.