Tutorial: Positional Audio

This tutorial teaches you how to position audio in 3D with Quorum.

3D Sound: Positional Audio

Quorum audio objects have the ability to be set in a position in a virtual 3D space. 3D space is often represented in math and other applications with 3D (x, y, z) coordinate system. An example of a 3D coordinate system is below.

This is an image of the coordinate system with x, y, and z axes.

Quorum uses a virtual 3D coordinate system very much like this one to set sounds in 3D space. Audio objects have x, y, and z-coordinates that can be set through the SetX, SetY, and SetZ actions. These three actions each take a single number parameter that represents the value of that coordinate. Audio objects also have corresponding GetX, GetY, and GetZ actions that return the requested coordinate.

Using positional audio can allow us to do some cool things in our programs. For example, we can use an audio object in a game, set its initial position, and then update its position in the game update loop. An example is below.

use Libraries.Game.Game
use Libraries.Sound.Audio

class Main is Game
   Audio audio

   action Main
       StartGame()
   end

   action CreateGame
       audio:Load("Sounds/Firework.ogg")

       // give the audio some initial coordinates
       audio:SetX(-1)
       audio:SetY(-1)
       audio:SetZ(-1)

       audio:Play()
   end

   action Update(number seconds)
       // calculate the new x, y, and z coordinates based off the current coordinates.
      //In this example, the x, y, and z coordinates are increased by 0.25 every second.
       number newX = audio:GetX() + 0.30 * seconds
       number newY = audio:GetY() + 0.30 * seconds
       number newZ = audio:GetZ() + 0.30 * seconds

       // using the newly calculated coordinates, update the position of the object
       audio:SetX(newX)
       audio:SetY(newY)
       audio:SetZ(newZ)
   end
end

Audio3D

The Quorum game engine also supports Audio3D objects, which inherit from the Item3D class and the Audio class. An Audio3D object can be moved, positioned, and rotated just like a Model in 3-space, and it can use all of the Audio actions. We can add Audio3D objects directly to our models so that the positional audio will be calculated for us. Our Audio3D objects share the same coordinate system as all other Item3D objects and can exist on the same Layer .

Doppler Shift

Audio3D objects have their Doppler shift (the change in pitch based on listener position, for more information, see here) calculated and enabled by default. At any time we can disable Doppler by calling the Audio3D DisableDoppler() action. Once it has been disabled, the Audio3D action EnableDoppler() will turn it back on. We should remember that these actions can only be called on an instantiated Audio3D object. For example:

audio:DisableDoppler()
audio:EnableDoppler()

Listener Position and Direction

Recall this from our Camera

tutorial: A camera object has both a position and a direction that it uses to display a scene. Our Audio3D objects have a similar feature called a listener. That listener has a position and a direction that it uses to represent a scene. The default listener position is at (0, 0, 0), with the direction (0, 0, 1). Both of these can be changed to track the movement of a player in the game. The actions that we use to change the position are Audio3D actions that should be called on our audio object. Below is an example of how we can call these actions on our Audio3D object:
audio:SetListenerPosition(0, 1, -1)
audio:SetListenerDirection(0, -1, 1)

We can also represent our position and direction as a Vector3.

Below is an example of a program that adds a sound to a moving box. The default settings for Doppler (on) and Listener are used, but we can try any of the code fragments from the two previous sections to understand how Doppler and Listener position/direction affect our game.

use Libraries.Game.Game
use Libraries.Game.Graphics.Model
use Libraries.Game.Graphics.Color
use Libraries.Game.Audio3D

class Main is Game
   Audio3D audio
   Model model

   action Main
       StartGame()
   end

   action CreateGame
       Color color
       model:LoadBox(0.5, 0.5, 0.5, color:Green())
       Add(model)
       audio:Load("Sounds/Robot.ogg")
       audio:EnableLooping()
       //adds the audio to the model so position is automatically calculated
       model:Add(audio)

       model:SetX(-5)

       audio:Play()
   end

   action Update(number seconds)
       //Moves the model a small amount in each frame
       model:Move(0.025, 0, 0)

   end
end

Common Problems

When I run my program, I get an error telling me that the file extension is unsupported.

Quorum can only play audio files in the ".wav" or ".ogg" formats. Ensure that the audio file is one of these formats. If it is not, there are many free programs available that will convert the file to one of these formats.

When I run my program, I get an error telling me that I can't play audio before it is loaded.

In order to play an audio object, a file must be loaded to it. Ensure that a file is loaded to the audio object before calling its Play action.

I have called SetBalance/SetPitch/Rotate on my audio object, but it did not have any effect.

The SetBalance, SetPitch, and Rotate actions only work on mono sounds. Ensure that the sound is not stereo. If it is, there are many free programs available that will convert sound files from stereo to mono.

I have called SetX/SetY/SetZ on my audio object, but it did not have any effect.

The SetX, SetY, and SetZ actions only work on mono sounds. Ensure that the sound is not stereo. If it is, there are many free programs available that will convert sound files from stereo to mono.

Next Tutorial

In the next tutorial, we will discuss Playing Longer Audio: Streaming, which describes how to play audio files Quorum.