Skip to content

Instantly share code, notes, and snippets.

@1bardesign
Last active November 14, 2018 02:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1bardesign/6f9353bb6488a367ab2aeb72b999df39 to your computer and use it in GitHub Desktop.
Save 1bardesign/6f9353bb6488a367ab2aeb72b999df39 to your computer and use it in GitHub Desktop.
will not work out of the box, as it relies on my class() impl and table.foreach, but should be fairly readable as a jumping off point!
--[[
audio manager
]]
--sound source wrapper
local sound = class()
--
function sound:new(source, volume, set)
return self:init({
source = source,
set = set,
volume = volume,
})
end
--stop the sound
function sound:stop()
self.set:remove(self)
end
--todo: volume/etc controls?
--soundset - a collection of same-audio sources that can be
-- played/triggered as needed and managed as a single unit.
local soundset = class()
--create a soundset
function soundset:new(manager, path, source_count, source_type)
local r = self:init({
manager = manager,
path = path,
source_count = source_count,
sounds = {},
sources = {},
})
for i = 1,source_count do
table.insert(r.sources, love.audio.newSource(path, source_type))
end
return r
end
--update this set (stop sounds as needed)
function soundset:update()
table.foreach(self.sounds, function(sound)
--clean up stopped sounds
if not sound.source:isPlaying() then
sound:stop()
end
end)
end
--play a sound
function soundset:play(loop, reset, volume)
if #self.sources == 0 then
if reset then
--shift the oldest sound and recurse
local sound = table.remove(self.sounds, 1)
if sound then
self:remove(sound)
return self:play(loop, reset, volume)
end
else
--could not play
return nil
end
end
local source = table.remove(self.sources)
--setup source params
source:setVolume(volume * self.manager.volume)
source:setLooping(loop)
--start it
love.audio.play(source)
--init the sound
local sound = sound:new(source, volume, self)
--push to sound queue
table.insert(self.sounds, sound)
--done!
return sound
end
function soundset:remove(sound)
--stop the sound
love.audio.stop(sound.source)
--recycle the source
table.insert(self.sources, sound.source)
sound.source = nil
--remove the sound object
table.remove_value(self.sounds, sound)
end
--the actual audio manager class
local audio = class()
--create a new audio manager
function audio:new()
return self:init({
sets = {},
volume = 1.0,
})
end
--update the audio manager
function audio:update()
table.foreach(self.sets, soundset.update)
end
--add a sound set
function audio:add_set(name, sound_path, source_count, source_type)
if not self.sets[name] then
if sound_path == "" then
error("missing sound set "..name)
end
self.sets[name] = soundset:new(self, sound_path, source_count, source_type)
end
return self.sets[name]
end
--play a sound set by name, returning the sound
function audio:play(name, args)
--(args here are default to catch unloaded sounds)
local set = self:add_set(name, "", 1, "static")
args = args or {}
default(args, "loop", false)
default(args, "reset", true)
default(args, "volume", 1.0)
return set:play(args.loop, args.reset, args.volume)
end
--stop all sounds playing for a given set name
function audio:stop(name)
if name == nil then
for k,v in pairs(self.sets) do
self:stop(k)
end
end
if self.sets[name] ~= nil then
local sounds = self.sets[name].sounds
while #sounds > 0 do
sounds[1]:stop() --(handles remove itself)
end
end
end
--volume handling
--get the current master volume
function audio:get_volume()
return self.volume
end
--set the current master volume
function audio:set_volume(volume)
--limit
volume = math.clamp(volume, 0, 1)
--(avoid setting everything if no change)
if self.volume == volume then
return
end
--update volume for manager and all soundsets
self.volume = volume
for name, set in pairs(self.sets) do
--update active sounds volume
table.foreach(set.sounds, function(sound)
sound.source:setVolume(sound.volume * volume)
end)
--update inactive sounds volume (maybe not needed)
table.foreach(set.sources, function(source)
source:setVolume(volume)
end)
end
end
return audio
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment