Skip to main content
Version: 1.0.0-preview.45

Audio

Guide Source Code

Go to the Audio guide project to see the source code for a fully working example of this guide.

Can you imagine playing Super Mario Bros. without the jump sound effect? How about playing Metroid with no music and no weapon sound effects? Audio is a great way to add some life to your game. Whether it is background music or sound effects, Velaptor has you covered.

Check out some of this audio! They might bring back memories. 😉

Mario Jump

Metroid Ice Beam

Metroid Brinstar Music

Step 1: Project setup​

Create a basic Velaptor application.

Refer To Guide

For more info, refer to the Quick Start guide.
You only need the OnLoad(), OnUnload(), and OnUpdate() methods.

Step 2: Create class fields​

Create the required class fields that will be used to read keyboard input, store the previous keyboard state for each loop iteration, and load the music audio content.

public class Game : Window
{
private IContentManager contentManager;
private IAppInput<KeyboardState> keyboard;
private IAudio? music;
private KeyboardState prevKeyState;
...
}

Step 3: Setup window​

Let's set up our window to a smaller size, create an object to detect keyboard input, and create the content manager to load the audio content.

Create a Game() constructor and add the following code:

public Game()
{
Title = "Sounds";
Width = 1210;
Height = 600;

this.keyboard = HardwareFactory.GetKeyboard();
this.contentManager = ContentManager.Create();
}

Step 4: Load and unload the content​

Before we delve into the code for loading the audio content, it's crucial to add the audio file to the project as content so it can be loaded. Once that's finished, we can add code to the OnLoad() method. This code will enable us to load the audio content and create a keyboard input object. By utilizing the keyboard, we'll be able to easily control the audio playback.

Supported Audio Formats

Currently, the supported audio formats are .mp3 and .ogg.

4.1: Get audio content​

You can provide whatever audio file you want, but if you don't have one, you can download one of these from the audio guide project, or from the mini audio players on this page.

4.2: Setup file as content​

We need to add the audio file to the project into a particular directory and then set the file to be copied to the build output. This will be the default location where Velaptor looks for audio content.

Refer To Guide

For more info, refer to the Adding Content guide.

4.3: Load the content​

Now that we’ve added the audio file to the project, we can write some code to load the audio content. Add the following code to the OnLoad() method to load the sound. All that is required is the name of the audio content and the type of audio buffer to use.

protected override void OnLoad()
{
this.music = this.contentManager.LoadAudio("brinstar-music", AudioBuffer.Stream);

base.OnLoad();
}
Content name

Remember, the name of the audio file without its extension will be the name of the content.
Example: 'brinstar-music.ogg' will become 'brinstar-music'.

What is an audio buffer? An audio buffer is just a container that holds the audio data. When you hear "audio buffer", think of "audio data". There are two types of audio buffers, each with its use cases.

The two types of audio buffers are:

  1. AudioBuffer.Full - This buffer type means that ALL of the audio data will be loaded into memory.
  2. AudioBuffer.Stream - This buffer type means that ONLY a small portion of the audio data will be loaded into memory at a time.

Using AudioBuffer.Full is better for short audio clips such as sound effects, while AudioBuffer.Stream is better for longer audio clips such as music. You can use either buffer type for short or long audio content, but the buffer type you choose will affect your game's memory usage and performance.

If you want to save memory, use AudioBuffer.Stream. This will directly affect the performance of loading content. If you want better performance with quick response time when changing audio playback—such as pausing, playing, rewinding, and fast-forwarding—use AudioBuffer.Full.

4.4: Unload the content​

We also need to unload the audio content when the window is closed. Add the following code to the OnUnload() method.

Create the OnUnload() method and add the following code to unload the audio content.

protected override void OnUnload()
{
this.contentManager.Unload(this.music);
base.OnUnload();
}

Step 5: Displaying sound info​

We have an audio file to play, but we also need some information, such as the current playback time, whether it's playing or paused, and some basic instructions for the user on how to control the audio. Since we are going to be using the keyboard to control the sound, it makes sense to tell the user which keyboard keys are used to stop, play, and perform other sound-related operations.

Note

To keep things simple, we'll display the information in the window's title bar. You could display the information in the window itself by rendering text.

5.1: Displaying audio state​

We'll create a method that displays the information we want in the title bar. Create the following UpdateTitle() method and add some code to get a string representing the current state of the audio file.

private void UpdateTitle()
{
string state;

if (this.music.IsStopped)
{
state = "Stopped";
}
else
{
state = this.music.IsPlaying ? "Playing" : "Paused";
}
}

5.2: Display time and instructions​

Now, add the following code below what you previously added. This code will get the minutes and seconds of the audio playback in the correct 2-digit format as well as the instructions for the user on how to play, pause, fast forward, and rewind the audio.

private void UpdateTitle()
{
...
var minutes = this.music.Position.Minutes;
var seconds = this.music.Position.Seconds;

var minStr = minutes <= 9 ? $"0{minutes}" : minutes.ToString();
var secStr = seconds <= 9 ? $"0{seconds}" : seconds.ToString();

var volume = $"Volume: {this.music.Volume}";
const string instructions = "Instructions: Space(play/pause) Esc(restart) Left(-5s) - Right(+5s) - Up(+vol) - Down(-vol)";

Title = $"{state} - {playTime} - {volume} | {instructions}";
}

Great! Now we have a method to update useful information about the audio as well as instructions for the user!

Step 6: Controlling the audio​

Refer To Guide

For more info, refer to the Keyboard Input guide.

We can put this all together so we can control the audio playback but first, we need to inspect the state of the keyboard to see which key is being pressed.

6.1: Keyboard state & key pressed​

To get the current state of the keyboard and to check if any key has been fully pressed, add the code below to the OnUpdate() method.

protected override void OnUpdate(FrameTime frameTime)
{
var currKeyState = this.keyboard.GetState();

bool IsPressed(KeyCode key)
{
return this.prevKeyState.IsKeyDown(key) && currKeyState.IsKeyUp(key);
}
}
Local Functions

This code snippet uses a local function to check whether or not a key is pressed, which is a new feature in C# 7.0. If you are not familiar with local functions, you can read more about them here.

// This is a local function
bool IsPressed(KeyCode key)
{
return this.prevKeyState.IsKeyDown(key) && currKeyState.IsKeyUp(key);
}

6.2: Audio control with keyboard​

This tutorial would be pretty useless if we didn't provide control over the audio for demo and learning purposes, right?😉
You can make that happen by adding the following code after the local function in the OnUpdate() method.

protected override void OnUpdate(FrameTime frameTime)
{
...
if (IsPressed(KeyCode.Space))
{
if (this.music.IsPaused or this.music.IsStopped)
{
this.music.Play();
}
else
{
this.music.Pause();
}
}
else if (IsPressed(KeyCode.Escape))
{
this.music.Stop();
}
else if (IsPressed(KeyCode.Left))
{
this.music.Rewind(5);
}
else if (IsPressed(KeyCode.Right))
{
this.music.FastForward(5);
}
else if (IsPressed(KeyCode.Up))
{
this.music.Volume += 10;
}
else if (IsPressed(KeyCode.Down))
{
this.music.Volume -= 10;
}
}

6.3: Finishing up​

Now, to finish things up, we’ll finalize our code by tracking the keyboard state from the previous frame and updating the window title. The significance of the previous keyboard state is that, without it, we cannot accurately determine if a key has been pressed.

To accomplish this, we must keep a record of the keyboard's state in the previous frame and compare it with the current state. This approach enables us to discern whether a key has moved from a pressed down position to a released up position.

To implement this, simply insert the following code snippet after the OnUpdate() method.

protected override void OnUpdate(FrameTime frameTime)
{
...
this.prevKeyState = currKeyState;

UpdateTitle();

base.OnUpdate(frameTime);
}

Step 7: Run it​

Run the game, and let's play some music! You should see the following window:

Example banner

As the instructions in the title bar state, do the following to test out your game:

  1. Press the space bar to play and pause the audio.
  2. Press the escape key to stop or restart the audio.
  3. Press the left arrow key to rewind 5 seconds.
  4. Press the right arrow key to fast forward 5 seconds.
  5. Press the up arrow key to increase the volume.
  6. Press the down arrow key to decrease the volume.

Not bad right?! Now you can add sound effects and/or music to your games!