After releasing a first demo of Duality I’m planning to approach creating a simple game using framework and editor myself. Since I’m not pretending most of the gaming community being deaf, the biggest thing still missing in Duality is any kind of sound. Until now.
I’ve recently finished porting and upgrading the sound system from Nullpunkt to Duality. It is based on OpenAL and supports loading, storing, playing and streaming of OggVorbis audio data. Just like Pixmaps / Textures, audio data is managed in two resource layers:
While AudioData resources store a plain block of compressed OggVorbis byte data, Sound resources represent that data actually being parameterized, unpacked, uploaded and ready-to-use. The idea behind this is that multiple Sound resources, all with different configuration (Volume, pitch, etc.) may link to the same AudioData resource and thus require only a single memory allocation instead of n for n different configurations. In later versions, it may also be imaginable to take a step further and enable Sound resources to contain multiple layers of timed and configured audio data in order to dynamically combine existing sound effects. If you are familiar with FMod, that’s a little like their Sound Events.
There are currently three ways to play a sound in Duality. The first is to access the SoundDevice instance and directly request playing a sound. It’s the most straightforward way and usually best for simple one-shot sound effects since it’s only a single line of source code.
It returns the reference to a SoundInstance in case you want to modify the playing sounds parameters, fade or stop it. It is also possible to play the sound assuming it is located relative to the listener inside a 3D environment. Here is a more detailed example:
ContentRef yourSoundRes = ContentProvider.RequestContent("Data/Your.Sound.res");</p> // Playing it looped SoundInstance playingSound = DualityApp.Sound.PlaySound(yourSoundRes); playingSound.Looped = true; // Playing it 3D at [500, 0, 0] DualityApp.Sound.PlaySound3D(yourSoundRes, new Vector3(500, 0, 0)); // Playing it 3D attached and offset to some object DualityApp.Sound.PlaySound3D(yourSoundRes, someGameObject, new Vector3(50, 0, 0));
A more component-oriented way to play sounds is adding a SoundEmitterComponent to the desired object. It lets you set up and configure any number of simultaneously playing sounds directly in the Duality editor. This is usually the best solution for looped or more “persistent” sounds that are produced by an objects activity or located somewhere in the game world. Sounds that are played via SoundEmitterComponent are assumed to be always 3D.
The third way of playing sounds in Duality is the budget-based music / ambient system. In order to support multiple background music and ambient layers that are dynamically faded in and out based on the ingame situation I’ve migrated the budget-based weighting system from Nullpunkt as well. It basically maintains a sorted list of active BudgetPad objects per category (currently just music and ambient), each with an assigned priority and weight consumption value. In each category, there is a total available budget of 1.0f and each BudgetPad, ordered by priority, consumes a portion of it. A BudgetPads sound can only play with a volume corresponding to the budget value that is available to this BudgetPad.
Simple example: In a game level, there is some background song that is always playing, except in situations that are dangerous for the player. When detecting such situation, instead of manually fading out the background song and fading in more aggressive music, you can just push the aggressive music layer onto the music stack and assign a high priority. While the dangerous music fades in, it consumes more and more budget until consuming all of it when fully faded in – thus leaving no more budget for the background song which will then still be running “mute”. As soon as the dangerous music is fading out, it will smoothly release the budget and leave it to the calm background. The cool thing about this way of handling it is that you don’t need to care about re-establishing previously active music – just push something onto the stack, and pop it later – or wait until it finished playing by itsself.