Benignly Designed Sound Manager

Showcase your games and demos, and discuss ongoing projects.

Benignly Designed Sound Manager

Postby vrld on Wed Oct 19, 2011 2:46 pm

Because the one thing I like about Flash/ActionScript3 is how they handle audio playback and seeing new lovers often have trouble understanding love's audio architecture, I sat down and tried to emulate the AS3 behavior. The result is the
Benignly Designed Sound Manager

BDSM overwrites love.audio.newSource, love.audio.play and love.audio.stop, so that one source can be played multiple times.

love.audio.newSource(what, how)
Returns a new bdsm source. The parameters are the same as for the old love.audio.newSource().

love.audio.play(source) and source:play()
Plays the source and returns a handle to the player. The player is the same as love.audio's Source object. In contrast to love.audio, you can safely ignore the handles.

love.audio.stop(source) and source:stop()
Stops all instances of source. If source is omitted, it will stop all the sources.

The source code is rather short: Warning: OLD CODE
Code: Select all
local newSource = love.audio.newSource
local stop = love.audio.stop

local function remove_stopped(sources)
   local remove = {}
   for _, s in pairs(sources) do
      remove[s] = true
   end
   for s, _ in pairs(remove) do
      sources[s] = nil
   end
end

function love.audio.newSource(what, how)
   return {
      play = function(self)
         remove_stopped(self.handles)

         local s = newSource(what, how)
         s:setLooping(self.looping)
         s:setPitch(self.pitch)
         s:setVolume(self.volume)

         self.handles[s] = s
         s:play()
         return s
      end,

      stop = function(self)
         for _, s in pairs(self.handles) do
            s:stop()
         end
         self.handles = {}
      end,

      setLooping = function(self, v) self.looping = not not v   end,
      setPitch   = function(self, v) self.pitch   = tonumber(v) end,
      setVolume  = function(self, v) self.volume  = tonumber(v) end,

      looping = false,
      pitch = 1,
      volume = 1,
      handles = {},
   }
end

function love.audio.play(what)
   assert(what.handles, "Can only play source objects.")
   return what:play()
end

function love.audio.stop(what)
   if what and what.stop then return what:stop() end
   stop()
end


Example code:
Code: Select all
require 'bdsm'

function love.load()
   music = love.audio.newSource('music.ogg', 'stream')
   music:setLooping(true) -- set default value for all players
   music:setVolume(.3)
   love.audio.play(music) -- the handle can be ignored

   woosh = love.audio.newSource('woosh.ogg', 'static')

   love.graphics.setFont(30)
end

function love.draw()
   love.graphics.print('Press a key!', 20,20)
end

function love.keypressed()
   local h = woosh:play() -- same as love.audio.play(woosh)
   h:setPitch(.5 + math.random() * 3) -- set pitch for individual players
end


Can you see yourself using this?
If not: why?
What can be improved?

Edit:
This is now on github: https://github.com/vrld/Stuff/tree/master/bdsm
Attachments
example.love
Simple example. Old version.
(2.09 MiB) Downloaded 110 times
Last edited by vrld on Mon Oct 24, 2011 4:48 pm, edited 1 time in total.
When I was a kid I used to pray every night for a new bicycle. Then I realised God doesn’t work that way, so I stole one and prayed for forgiveness.
hump Helper Utilities for Massive Productivity | HardonCollider Collision detection | Quickie Easy GUI Library
User avatar
vrld
Party member
 
Posts: 848
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany

Re: Benignly Designed Sound Manager

Postby Taehl on Wed Oct 19, 2011 3:05 pm

I like it (I'm assuming it works fully, rather than testing it). About the only reason I could see myself using TEsound instead of this is for two features: Sound tags (so you can set the volume or pitch of many different sounds together, thus enabling things like a "sound effect volume" option) and being able to pass it a table of sounds and it'll choose one at random. Also, lovely name.
User avatar
Taehl
Dreaming in associative arrays
 
Posts: 1000
Joined: Mon Jan 11, 2010 5:07 am
Location: FL, USA

Re: Benignly Designed Sound Manager

Postby adnzzzzZ on Wed Oct 19, 2011 3:19 pm

I have been playing with sound synthesis using LÖVE and I have designed something very similar to what you have here (I think, maybe: https://github.com/adonaac/love/tree/master/ss). But for what I'm doing I still have some problems with emulating a buffer and/or pop/click noises at the end and start of sources (although I think this has to do with the way I'm handling the samples)...

Regardless, your solution to my problems look a lot better. I will use this soon and report on what I think of it. Thanks!
User avatar
adnzzzzZ
Party member
 
Posts: 224
Joined: Sun Dec 26, 2010 11:04 pm
Location: Porto Alegre, Brazil

Re: Benignly Designed Sound Manager

Postby Robin on Wed Oct 19, 2011 9:31 pm

Very interesting, I might want to use that (seems perfect for Jams, for example). The only thing is that I might want to distinguish between BDSM Sources and regular old Sources.
Help us help you: attach a .love.
User avatar
Robin
The Omniscient
 
Posts: 6242
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands

Re: Benignly Designed Sound Manager

Postby headchant on Wed Oct 19, 2011 9:36 pm

In combination with your proxy stuff this could extremely simplify the whole sound managing business.
Write Games.
User avatar
headchant
Party member
 
Posts: 103
Joined: Fri Sep 03, 2010 12:39 pm

Re: Benignly Designed Sound Manager

Postby T-Bone on Thu Oct 20, 2011 6:07 am

Great name. Will check it out.
User avatar
T-Bone
Inner party member
 
Posts: 1210
Joined: Thu Jun 09, 2011 9:03 am

Re: Benignly Designed Sound Manager

Postby kikito on Thu Oct 20, 2011 1:41 pm

I like this very much! (IMHO this is how LÖVE should handle all sound, I've already talked about this)

vrld wrote:What can be improved?


Only two things:
  • Put it on github (or some other public repo). Or put a link on the forum, if it's already there.
  • newSource creates a lot of functions nearly identical. Wouldn't it be possible to extract them to a metatable?
When I write def I mean function.
User avatar
kikito
Inner party member
 
Posts: 2789
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain

Re: Benignly Designed Sound Manager

Postby vrld on Mon Oct 24, 2011 4:46 pm

Late reply, but better late than never. Thanks for the feedback :)

Taehl wrote:two features: Sound tags (so you can set the volume or pitch of many different sounds together, thus enabling things like a "sound effect volume" option)
That is a great idea! Tags can be played/stopped/pitched/whatevered by using love.audio.tags.tagname.foo, e.g. love.audio.tags.effects.setPitch(0.6). Doing stuff on tags will act upon all sources and their playing instances in that tag. By default, all sources are members of the 'all' tag, so you can act on all sources via love.audio.tags.all.

Likewise, modifying a source's pitch, volume or looping behavior will effect all playing instances of that source. So be careful with that.

Taehl wrote:and being able to pass it a table of sounds and it'll choose one at random.
Not quite sure what that means: Playing a shuffled playlist, or just choosing a sound to play, i.e.:
Code: Select all
sounds = table.shuffle{'foo.ogg', 'bar.ogg', 'baz.ogg'} -- doesn't exist
source = love.audio.newSource(sounds[1])
souce:play()



adnzzzzZ wrote: But for what I'm doing I still have some problems with emulating a buffer and/or pop/click noises at the end and start of sources
Just to clarify: This lib has nothing to do with sound synthesis, and it will not remove the clicking sounds. These are caused by your sound not having zero crossings at the beginning and end. To get rid of them, make sure the last sample you write is 0.0, either by using an envelope, or by making the sound duration a multiple of the wavelength of your wave function. On a side note (haha, get it? :ehem:), you might be interested in Moan.


Robin wrote:The only thing is that I might want to distinguish between BDSM Sources and regular old Sources.
Doable, but hackish:
  • function isLoveSource(s) return type(s) == "userdata" and s:typeOf("Source") end
  • function isLoveSource(s) return s.instances ~= nil end
  • function isLoveSource(s) return love.tags.all[s] ~= nil end


Kikito wrote:Put it on github
Done: https://github.com/vrld/Stuff/
The name will probably change in the future, since there already is bdsm for LÖVE.

Kikito wrote:newSource creates a lot of functions nearly identical. Wouldn't it be possible to extract them to a metatable?
Good point. Also done.
Kikito wrote:Put it on github
When I was a kid I used to pray every night for a new bicycle. Then I realised God doesn’t work that way, so I stole one and prayed for forgiveness.
hump Helper Utilities for Massive Productivity | HardonCollider Collision detection | Quickie Easy GUI Library
User avatar
vrld
Party member
 
Posts: 848
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany

Re: Benignly Designed Sound Manager

Postby Taehl on Mon Oct 24, 2011 5:09 pm

Sounds tags are in? Awesome.

vrld wrote:
Taehl wrote:and being able to pass it a table of sounds and it'll choose one at random.
Not quite sure what that means: Playing a shuffled playlist, or just choosing a sound to play, i.e.:
Code: Select all
sounds = table.shuffle{'foo.ogg', 'bar.ogg', 'baz.ogg'} -- doesn't exist
source = love.audio.newSource(sounds[1])
souce:play()


Choosing a sound to play. What I enjoy doing are things like:
Code: Select all
-- in love.load or content.lua
sounds = {
   growl = {
      "sounds/growl01.ogg", "sounds/growl02.ogg", "sounds/growl03.ogg", "sounds/growl04.ogg", "sounds/growl05.ogg", "sounds/growl06.ogg", "sounds/growl07.ogg", "sounds/growl08.ogg",
   },
}


-- somewhere in my game's code
-- This plays one growl sound at random
TEsound.play(sounds.growl)

-- That's functionally equivalent to, but much nicer to type, than
TEsound.play(sounds.growl[math.random(#sounds.growl)])
-- or in this case,
love.audio.play(love.audio.newSource(sounds.growl[math.random(#sounds.growl)], "stream"))
Also worth mentioning is that if you loop a random sound like this in TEsound, it'll choose a different sound each time. So you could very easily play a random list of music, for example. Would that be possible in BDSM?

... I don't think you mentioned how to add tags to sounds in BDSM...
User avatar
Taehl
Dreaming in associative arrays
 
Posts: 1000
Joined: Mon Jan 11, 2010 5:07 am
Location: FL, USA

Re: Benignly Designed Sound Manager

Postby slime on Mon Oct 24, 2011 5:23 pm

Taehl wrote:Sounds tags are in? Awesome.

vrld wrote:
Taehl wrote:and being able to pass it a table of sounds and it'll choose one at random.
Not quite sure what that means: Playing a shuffled playlist, or just choosing a sound to play, i.e.:
Code: Select all
sounds = table.shuffle{'foo.ogg', 'bar.ogg', 'baz.ogg'} -- doesn't exist
source = love.audio.newSource(sounds[1])
souce:play()


Choosing a sound to play. What I enjoy doing are things like:
Code: Select all
-- in love.load or content.lua
sounds = {
   growl = {
      "sounds/growl01.ogg", "sounds/growl02.ogg", "sounds/growl03.ogg", "sounds/growl04.ogg", "sounds/growl05.ogg", "sounds/growl06.ogg", "sounds/growl07.ogg", "sounds/growl08.ogg",
   },
}


-- somewhere in my game's code
-- This plays one growl sound at random
TEsound.play(sounds.growl)

-- That's functionally equivalent to, but much nicer to type, than
TEsound.play(sounds.growl[math.random(#sounds.growl)])
-- or in this case,
love.audio.play(love.audio.newSource(sounds.growl[math.random(#sounds.growl)], "stream"))
Also worth mentioning is that if you loop a random sound like this in TEsound, it'll choose a different sound each time. So you could very easily play a random list of music, for example. Would that be possible in BDSM?

... I don't think you mentioned how to add tags to sounds in BDSM...

Is it really that hard to do the random stuff yourself? I don't see it being an essential part of a sound library. :P
User avatar
slime
Solid Snayke
 
Posts: 1930
Joined: Mon Aug 23, 2010 6:45 am
Location: Canada

Next

Return to Projects and Demos

Who is online

Users browsing this forum: No registered users and 7 guests