Search Results

Monday, December 12, 2011

BGE Audaspace Python Tutorial

Hey. So today, we'll briefly go into using Audaspace, an audio library shipped with Blender distributions, with the game engine.


Audaspace is a standalone Python module, much like the mathutils library. While it's not a game engine specific library, it works with the BGE just fine, and is very versatile and useful. Some nice features are dynamic filtering, synth waveform playing (e.g. dynamically playing a square or sine wave), and fading sounds in and out.

The idea behind Audaspace is pretty simple. We have a device that we use to play sounds, which is like our sound card, and we have sounds. We first load up the sounds from the hard disk to create Factories, and then play those Factories using the default device.

Note that there's no packing sounds into the blend file if you use Audaspace, which is similar to the inability to pack textures in if you use the bge.texture module for loading textures.

So, let's take a look at the source code.

from bge import logic

import aud

cont = logic.getCurrentController()
obj = cont.owner

if not 'init' in obj:
    
    obj['init'] = 1
    logic.device = aud.device()
    soundpath = logic.expandPath('//theme.ogg')
    obj['sound'] = aud.Factory.file(soundpath)
    logic.device.play(obj['sound'])

So in the first line, we simply import the logic module. No surprise there. In the third, we import the Audaspace module. It's name is 'aud'. So, then, we see that a few lines down, we run some code only once. We store in a module variable (game-wide variable) a reference to the current audio Device that we'll be using to play sounds and songs.

    logic.device = aud.device()

Note, you could also make a new device using the aud.Device class to customize parameters, like which library you use to play sounds (SDL or OpenAL), and other features as well, but you can easily get the current and preconfigured device using the aud.device() function, like we did here. You usually want OpenAL because it allows you to use advanced features like dynamically adjusting the pitch of sounds. Simply using the aud.device() function defaults to Blender's User Preferences setting, which is set to OpenAL by default.

    soundpath = logic.expandPath('//theme.ogg')

Next, we expand a path out to our song that we want to play using a string. The string indicates the filename of the sound or song that we want to play. When using logic.expandPath, utilizing two forward slashes inthe string makes the string relative to the blend file. You would use this, for example, to navigate to the 'DungeonBGM.ogg' file in the Resources folder relative to your blend file or game executable like so:

    testpath = logic.expandPath('//Resources/DungeonBGM.ogg')

Which would read back as "Game Directory (where the blend file or BlenderPlayer is)/Resources/DungeonBGM.ogg". To be more efficient, you could even store out the path to the music or resources directory, and then simply specify the filename when you want to load it:

    resourcedir = logic.expandPath('//Resources/')
    bgmpath = resourcedir + 'DungeonBGM.ogg'

Okay, so after we specify the sound directory, we create a Factory to play a sound.

    obj['sound'] = aud.Factory.file(soundpath)

A Factory is just that - a Factory, or generator, for sounds to be played from. You could think of it like a cookie cutter - each Factory plays a specific sound, but you can use it several times to play a single sound several times, even in different ways.

Note that here, I'm loading sounds using the aud.Factory.file() method, which loads a Factory from a file. You can also just use aud.Factory() and have the same result of loading a Factory from a file - I'm not sure as to the reason that both methods seem to work and exist together, but only the aud.Factory.file() method is documented, so make of that what you will. :p

    logic.device.play(obj['sound'])

Finally, we play the sound via the Device. Be sure that you only play the sound on the frame that you need to play it, and no other times. In this example, the script only runs once, so the sound plays just once. So, don't hook up a sound to play whenever the player's got a key pressed, unless you want it to play many times in a second.

There's one last thing to consider, and that's Handles. Handles are like controls for sounds after they've begun playing. You can use Handles to change the volume, pitch, loop count, and other factors about how the sound plays. Each time you play a sound using an audio Device, it returns a Handle. Handles have their own properties, which is how you control how the sound is played back. Here's an example of making a sound loop indefinitely:

    handle = logic.device.play(logic.sounds['Explosion'])
    handle.loop_count = -1

As you can see, we assign a variable to the play() function of the sound device. This is the handle variable, and we access its loop_count variable to designate how many times the sound should loop. A value of -1 is indefinitely, a value of 0 is for no looping whatsoever, and a value greater than 0 will make the sound loop that many times.

From here, there are different ways you can expand this process. You can, for example, store a dictionary of sounds globally, along with your sound device, and play them when you need to:

    logic.device.play(logic.sounds['Explosion'])

Anyway, from this point, it's up to you. Have fun!

12 comments:

  1. Audaspace? Sounds cool! Thanks for the tutorials. Is this audaspace is something related to audacity? I just started learning python a while ago and for some reasons the progress is rather slow. So, since this is a python module, is it not possible to access this new feature using logic bricks only?

    ReplyDelete
  2. @Anonymous - No, Audaspace isn't related to Audacity. Unfortunately, there is no capability to access the Audaspace module through logic bricks - you have to use Python.

    ReplyDelete
  3. I see.
    Heheh... i thought there is audacity in blender, silly me. Still glad to see this new library in bge though.

    Thanks for the response, SolarLune. I'll keep in mind to look at this tutorial again when the time is coming for me to work with this library in bge.
    Thank you ; )

    ReplyDelete
  4. This was very, very helpful for me. Before I was just using the sound actuator but it doesn't act the same if you activate it with python vs logic bricks(the sound wouldn't play a second time unless it was finished playing it the first time), but now I can use audaspace instead:), Thanks again!

    ReplyDelete
  5. Hello is there a way to use audio from microphone input?

    ReplyDelete
    Replies
    1. Possibly. I don't think there's a built in way to use the microphone with Audaspace, but there should be other Python modules that will allow you to take microphone input.

      Delete
    2. Hello,
      SolarLune could you please suggest some other Python modules that I could possibly test for microphone input?
      Did the person who posted this find any sort of solution?
      Any help would be much appreciated!
      Thanks!

      Delete
    3. @Archana - I don't know of any off-hand - I would just try a Google search to turn some up. I'm not sure if the person who posted this found any solution. It wouldn't appear to be the case.

      Delete
  6. Hey Solar,
    thanks for this tutorial. You helped me a lot!
    BTW, this does not work for me:
    handle = logic.device.play(logic.sounds['Explosion'])
    I used instead:
    handle = logic.device.play(obj['Explosion'])
    You can't access the logic sound module for some reason.

    ReplyDelete
    Replies
    1. That example is an example of storing a global list of sounds that you've loaded in. You have to create the sounds dictionary and fill it with sounds, i.e.

      logic.sounds = {
      'Explosion':aud.Factory...
      }

      Delete
  7. Hey Lune, how would you go about creating a handle without actually playing the a sound?

    ReplyDelete
    Replies
    1. Yo, I haven't used the BGE in a long while, but if Audaspace automatically creates a handle when you play the sound, and you want to have the handle to customize before actually hearing it, you could play the sound and then immediately pause it.

      Delete