Chapter 5. Playing Sound Effects and Music

In years past, programming sound and music for games was an enormous task. Custom sound code was usually too difficult to write due to the conflicting standards among the various sound cards in the industry. Today, that is no longer a problem. Now a single, dominant hardware maker sets the PC audio standard and a single, dominant sound library sets the software standard. While some may argue the point, I believe that Creative Labs had the sound card market wrapped up with their Sound Blaster line of products, but today most motherboards include very capable audio hardware. This chapter is a quick jaunt through the basic audio features of Visual C#, with an example program to show how to play sound effects and music files in Visual C#, including the versatile MP3 format.

Here’s what we’ll cover in this chapter:

  • Playing wave files

  • Playing wave resources

  • Referencing the Media Player

  • Playing MP3 and MIDI files

Programming Audio

Audio is always a fun subject to explore because sound effects and music can influence our emotions so dramatically. Could you imagine playing a game like Halo: Reach without audio? It would be a different experience entirely! What is a game without sound? Little more than a graphics demo, all but unplayable in my opinion (unless you’re playing late at night and don’t want anyone to know!). Sound is absolutely essential for the success of any game, in both the professional and indie market.

Even the simplest game needs some form of background music, or it is difficult for the player to remain interested. Remember this important rule of game development: Any game without sound and music is just a technology demo. It is absolutely essential that you spend some of your development time on a game working on the music and sound effects. In fact, it is probably a good idea to do so during development. As the game takes shape, so should the sounds and music. Background music should reflect what is going on in the game and can even be used to invoke the emotions of the player. Consider a scene in which a beloved game character dies. Upbeat music would spoil the mood, whereas dark and menacing background music would engender feelings of remorse and sorrow (and perhaps even anger).

Keep this in mind when working on sections of a game and try to have a different background sequence for different circumstances. Victory should be rewarded with upbeat music, while menacing or dangerous situations should be accompanied by low-beat, low-tempo songs that reinforce the natural emotions that arise in such a circumstance. Later in this chapter, under the heading, “Using Windows Media Player,” I’ll show you how to use Windows Media Player to play an MP3 file in your game projects.

Ambient sound is a term that I borrowed from ambient light, which you might already understand. Just look at a light bulb in a light fixture on the ceiling. The light emitted by the bulb pretty much fills the room (unless you are in a very large room). When light permeates a room, it is said to be ambient; that is, the light does not seem to have a source. Contrast this idea with directional light and you get the idea behind ambient sound. Ambient sound refers to sound that appears to have no direction or source. Ambient sound is emitted by speakers uniformly, without any positional effects. This is the most common type of sound generated by most games (at least most older games—the tendency with modern games is to use positional sound).

Loading and Playing Audio Files

We can load and play a wave file using the class called System.Media.SoundPlayer. This class has limited features but gets the job done for simple sound effects needs. First, we create an object:

System.Media.SoundPlayer audio;

By adding System.Media to the using list, we can refer to just SoundPlayer:

audio = new SoundPlayer();

There are two overloads of the SoundPlayer() constructor, one to specify the audio file and another to specify a System.IO.Stream for loading the file. So, one way to load an audio clip is to pass the filename to the constructor:

audio = new SoundPlayer("sound.wav");

An option is to just use the default constructor and instead load the audio file manually. The SoundPlayer.SoundLocation property is used to specify the filename. Once set, we can use SoundPlayer.Load() to load the file.

audio.SoundLocation = "sound.wav";
audio.Load();

In either case, trapping errors is a good idea since a bad filename will generate an exception. We can write a LoadSoundFile() function to trap errors and return a SoundPlayer object if loading succeeds.

Hint

If you have a very large wave file that may take a few seconds to load, use the SoundPlayer. LoadAsync() and SoundPlayer.IsLoadCompleted() methods to find out when loading has finished.

public SoundPlayer LoadSoundFile(string filename)
{
    SoundPlayer sound = null;
    try
    {
        sound = new SoundPlayer();
        sound.SoundLocation = filename;
        sound.Load();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error loading sound");
    }
    return sound;
}

Using Audio Resources

We can play an audio file that has been added to the project as a resource by using Properties.Resources to get the audio file resource as a SoundPlayer object. We can use SoundPlayer to play waves loaded from a file or a resource, so there’s some flexibility there. One great advantage to using a resource file is that your game’s asset files are compiled into the executable and are no longer exposed so that the user can access them. Let me show you how to add a resource file to the project.

First, open the Project menu and choose Add New Item. Choose the list of General items, and then Resources File, as shown in Figure 5.1.

Adding a resource file to the project.

Figure 5.1. Adding a resource file to the project.

Next, double-click the Resource1.resx file to open the project’s resources. Open the drop-down list of resource types and choose Audio, as shown in Figure 5.2.

Selecting the Audio resources list.

Figure 5.2. Selecting the Audio resources list.

Next, you can use the Add Resource drop-down list and choose a wave file to load, or you can just drag a wave file from Windows Explorer into the resource file asset pane, as shown in Figure 5.3.

The foom.wav file has been added to the project as a resource.

Figure 5.3. The foom.wav file has been added to the project as a resource.

To play an audio file from a resource, we can use Properties.Resources to access the resource object directly in our code.

SoundPlayer audio = new SoundPlayer();
audio.Stream = Properties.Resources.foom;

Tip

If you are using Visual C# 2010, you will not be able to load an audio clip as a resource like this section suggested. Instead, just use the default resource or load an audio clip from a file instead.

Built-In System Sounds

The System.Media namespace contains a class called SystemSounds. By using this class, we gain access to the built-in system sounds that can be played directly without any preparation. Here is a list of the system sounds available:

  • SystemSounds.Asterisk

  • SystemSounds.Beep

  • SystemSounds.Exclamation

  • SystemSounds.Hand

  • SystemSounds.Question

These system sound objects can be played directly in code using the Play() method with no other loading or preparation needed.

The Audio Playback Demo Program

The Audio Playback demo program demonstrates how to load audio files into memory and play them using System.Media.SoundPlayer, as well as how to play the built-in system sounds. To demonstrate how sounds are automatically mixed, the program actually loads up another sound file as well. There are several buttons on the form; each plays one of the sound clips. There is not much to this program other than the simple form. There are ten buttons to the form, simply called button1, button2, etc., as shown in Figure 5.4.

The Audio demo program demonstrates how to play audio files.

Figure 5.4. The Audio demo program demonstrates how to play audio files.

using System;
using System.Media;
using System.Reflection;
using System.IO;
using System.Windows.Forms;

namespace Audio_Playback_Demo
{
    public partial class Form1 : Form
    {
        System.Media.SoundPlayer[] audio;

        public SoundPlayer LoadSoundFile(string filename)
        {
            SoundPlayer sound = null;
            try
            {
                sound = new SoundPlayer();
                sound.SoundLocation = filename;
                sound.Load();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error loading sound");
            }
            return sound;
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            audio = new SoundPlayer[5];

            //load audio using constructor
            audio[0] = new SoundPlayer("launch1.wav");

            //load audio using Load method
            audio[1] = new SoundPlayer();
            audio[1].SoundLocation = "launch2.wav";
            audio[1].Load();

            //load audio from wave file
            audio[2] = LoadSoundFile("missed1.wav");
            audio[3] = LoadSoundFile("laser.wav");

            //load audio from resource
            audio[4] = new SoundPlayer();
            audio[4].Stream = Properties.Resources.foom;
        }
        private void button_Click(object sender, EventArgs e)
        {
            Button button = (Button)sender;
            if (button.Text == "Asterisk")
            {
                SystemSounds.Asterisk.Play();
            }
            else if (button.Text == "Beep")
            {
                SystemSounds.Beep.Play();
            }
            else if (button.Text == "Exclamation")
            {
                SystemSounds.Exclamation.Play();
            }
            else if (button.Text == "Hand")
            {
                SystemSounds.Hand.Play();
            }
            else if (button.Text == "Question")
            {
                SystemSounds.Question.Play();
            }
            else if (button.Text == "Launch1")
            {
                audio[0].Play();
            }
            else if (button.Text == "Launch2")
            {
                audio[1].Play();
            }
            else if (button.Text == "Missed1")
            {
                audio[2].Play();
            }
            else if (button.Text == "Laser")
            {
                audio[3].Play();
            }
            else if (button.Text == "Foom")
            {
                audio[4].Play();
            }
        }
    }
}

Using Windows Media Player

What if you want to use a more advanced audio file, such as an MP3, for your game’s music? Although we don’t have a library available for this, there is an alternative that works quite well that I’ll introduce to you: the Windows Media Player control. You may be wondering: why would I want to use a Media Player control when we can already play audio files? Here’s the reason: for simple music playback, System.Media.SoundPlayer is preferred. But there is a drawback—limited options. Sure, you can play back an audio file, but that’s about all you can do. Beyond that, the features are pretty slim. The Media Player control, on the other hand, is full of features, as the Music Playback demo program demonstrates.

So how does this work? Visual C# has the ability to embed an object on a form, and this capability is called OLE (Object Linking and Embedding). You can, for instance, embed an Excel spreadsheet on a form, and it will be fully functional! There are some obvious licensing issues when you embed a whole application onto a form, and usually applications that do this sort of thing just assume that the software (such as Excel) has already been preinstalled on the end user’s PC. (The Excel control simply won’t work unless Excel is already installed.) But there are some Windows applications that are so common that we can pretty much count on them being available. One example is Windows Media Player, which is automatically installed on Windows systems today. Even if someone is still using an older version of Windows, odds are they have Windows Media Player installed because it is free.

Referencing the Media Player

I’ve included a project with this chapter called Music Playback demo, which shows how to use WMPLib and a class called WindowsMediaPlayerClass. This is not a normal .NET component, and not part of the .NET Framework, so we have to add it from the list of COM/ActiveX components (see the COM tab in the Add Reference dialog box). We need to add a reference to a COM component in order to use the Windows Media Player component. See Figure 5.5.

Adding a reference to the Windows Media Player control.

Figure 5.5. Adding a reference to the Windows Media Player control.

Definition

COM stands for Component Object Model, a technology created by Microsoft to make it easier to share useful software libraries.

Tip

If you see two items called “Windows Media Player” as shown in Figure 5.5, choose the one associated with wmp.dll (not msdxm.tlb).

When the Windows Media Player component is visible to the project, then an object can be created at runtime and used to play music. The COM library component is called WMPLib and can be added to the project with a using statement:

using WMPLib;

A media player object can then be created with the WindowsMediaPlayerClass class:

WindowsMediaPlayerClass player =
    new WindowsMediaPlayerClass();

Tip

Visual C# 2010 users will need to note another change to the architecture here. After adding WMPLib to the project (via wmp.dll), you must change the object’s “Embed Interop Type” property to False. It defaults to True, but that causes a compile error. Thanks to Joshua Smith for solving this extremely difficult problem!

Playing MP3 and MIDI Files

You can play any media file with the Windows Media Player component by setting its URL property equal to a filename (or a URL to a file on a website, for instance). This is deceptively simple, because there is really no “play” function at all. Once you set the URL property to a filename, playback will automatically start. Likewise, if you want to stop playback, set the URL to an empty string (“”). The control can support the same media file formats supported by the full-blown media player application, including MP3! Interestingly enough, you can specify a URL to an audio file on a remote website:

player.URL = "song.mp3";

To stop playback, just set the URL to an empty string:

player.URL = "";

I have included a generic MIDI file with the example but you may replace it with any MP3 file from your music collection!

Level Up!

This chapter was a quick overview of Visual C# audio support, giving you just enough information to add sound effects and music to your own games. By loading multiple sound files into memory and playing them at certain points in your game, you greatly enhance the gameplay experience. In a sense, you are the conductor of this orchestra by directing what happens in the source code. You also learned how to use the Windows Media Player component for advanced audio file support to make it possible to add music to a game. Just keep in mind that you cannot distribute copyrighted music.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.60.239