Skip to content
Home » Basics of .NET MAUI – Part 21 – Sound

Basics of .NET MAUI – Part 21 – Sound

Spread the love

A game without audio seems incomplete. We’re going to implement background music and sound effects in our app. To do that, we need a plugin.

Plugin.Maui.Audio

The plugin is called Plugin.Maui.Audio. Let’s install the NuGet package:

We have to register it in the dependency injection container, so go to the MauiProgram.cs file and add the following code:

Let’s create a view model that will handle sound in our app.

SoundViewModel

Create a new class in the ViewModels folder and name it SoundViewModel. We inject the AudioManager in the constructor:

Let’s also register the view model with the dependency service in the MauiProgram class:

To play sounds, we need… Well, sounds.

Sound Files

Before we move on, we have to add the sound files we need to the Raw folder inside the Resources folder. You will find these files on Github.

The sound files are contained in three folders:

In the Accidents folder we have sounds that will be associated with the accidents that may happen to the slugs. We’re going to implement them in the next part of the series.

In the Game folder there are sounds that will be used when a race begins, while the slugs are running and when the game is over. There’s also a file that will be used as background music.

In the Slugs Winning folder there are files that will be played when the slugs win a race. Each slug will use a different sound to express his joy after winning a race.

All sounds that I’m using for the project were downloaded from Zapsplat. I renamed them so that you can easily see what each file is going to be used for. In the table below you can see both the names that we are going to use in the project and the original ones.

So, in the Game folder we have the following sounds:

File Name in SlugraceOriginal Zapsplat File Name
Background Music.mp3music_zapsplat_game_music_kids_warm_soft_slow_chilled_piano_bass_warm_pads_vocal_ahs_022.mp3
Slugs Running.mp3zapsplat_animals_leach_or_worm_slimy_movement_squelch_003_10795.mp3
Game Over.mp3cartoon_success_fanfair.mp3
Go.mp3esm_8bit_explosion_medium_with_voice_bomb_boom_blast_cannon_retro_old_school_classic_cartoon.mp3

The Background Music.mp3 file is going to be used for the background music.

The Slugs Running.mp3 file will start playing when a race begins and loop until all slugs have finished the race.

The Game Over.mp3 file will play just once when the Game Over screen appears.

The Go.mp3 file will be played just once the moment a race starts.

In the Slugs Winning folder we have the following files:

File Name in SlugraceOriginal Zapsplat File Name
Speedster Win.mp3human-toddler-18-months-boy-single-laugh.mp3
Trusty Win.mp3human_baby_3_months_short_laugh.mp3
Iffy Win.mp3jessey_drake_vox_10month_baby_SMOOCH_really_excited_laugh_build_HEX_JD.mp3
Slowpoke Win.mp3zapsplat_human_boy_3_years_old_british_laugh_001.mp3

Each of these sounds will be played just once when the corresponding slug wins a race, so you will hear just one of them in each race.

Finally, in the Accidents folder we have the following files:

File Name in SlugraceOriginal Zapsplat File Name
Asleep.mp3zapsplat_human_man_elderly_snore_20087.mp3
Blind.mp3horror_eyes_gouged_out_001.mp3
Broken Leg.mp3zapsplat_horror_gore_bone_arm_leg_break_crunch_57125.mp3
Devoured.mp3fork_media_horror_monster_roar_growl_reverberant.mp3
Drown.mp3zapsplat_nature_water_bubble_rise_underwater_002_20093.mp3
Electroshock.mp3sound_design_effect_electricity_electric_arc.mp3
Grass.mp3zapsplat_animals_slug_eat_designed_001_42438.mp3
Heart Attack.mp3zapsplat_human_child_heartbeat_fast_26491.mp3
Overheat.mp3Blastwave_FX_AcidBurnSizzle_S011SF.3.mp3
Rubberizer.mp3zapsplat_foley_latext_glove_pull_stretch_squeak_006_12113.mp3
Shooting Eyes.mp3warfare_gunshot_rifle_exterior_001.mp3
Turning Back.mp3zapsplat_cartoon_voice_funny_gibberish_worried_scared_19920.mp3

Each of these sounds will be associated with one of the accidents. The names of the files are pretty self-explanatory. But, as mentioned above, we’re not going to use these sounds for now.

Playing Sounds

We have one audio manager, but we can have as many audio players as we need. We can create a separate audio player for each sound.

An audio player is an object that implements the IAudioPlayer interface. We use it to play the sound, stop it, check if it’s playing, set its volume, make it loop, and so on.

Audio players are disposable objects. We should dispose of them after they’re done playing their sound. This way we’ll avoid memory leaks.

In our app we’ll create an audio player to handle the background music. We’ll name it just audioPlayer. We’ll also create a list of audio players for the sound effects. We’ll name the list effectPlayers. Each time a sound should be played, a new audio player will be created and added to that list. It will be disposed of when it’s done its job.

So, let’s add the audio players to the SoundViewModel. Let’s also create the methods to play the sounds:

We create an audio player for each sound. We pass a stream to the CreatePlayer method. To create a stream from a file we use the FileSystem.OpenAppPackageFileAsync method. We also set the Loop property of the player.

The Stop and Clean methods, among other things, dispose of the audio players. We’ll use the former in a minute. We use the Clean method inside the PlaySound method to dispose of any audio players that might still be there and clear the list.

The volume should be set to a value between 0 (silent) to 1 (full volume).

Background Music

Let’s create an instance of the SoundViewModel in the GameViewModel:

The background music should start playing in a loop the moment the game starts, so after we click the Ready button in the SettingsPage. So, let’s call the PlayBackgroundMusic method in the OnGameChanged method:

The background music will now play throughout the entire game. It will stop playing only when the game is over. During the short period of time after the last race and before the GameOverPage is shown, the sound should attenuate. Let’s create the Attenuate method in the SoundViewModel:

This method will gradually decrease the volume until we can’t hear anything.

Now, let’s call this method in the EndGame method in the GameViewModel. We’ll also call the Stop method we defined in the SoundViewModel to stop the background music if it is still playing for some reason and to dispose of the audio player:

If you now run the app, you’ll be able to hear the background music.

Sound Effects

We’re going to implement some sound effects in the game. There are going to be sounds associated with accidents that happen to the slugs, but we’ll take care of them in the next part of the series. For now, let’s add the other sound effects.

The first effect we want to implement is the sound that we hear when the game is over. Let’s play the sound in the EndGame method:

We’ll still hear the sound when the GameOverPage shows up.

The next two sound effects are the shot that should be heard when a race begins and the sound that can be heard while the slugs are running. The latter sound should be looped. We’ll implement them in the StartRace and RunRace methods:

We also call the Clean method in the RunRace method because we don’t want the running sound to continue in the next race.

Finally, we’ll add a victory sound for each slug. Each slug will rejoice in a different way when they win.

Let’s start by adding a WinSound property to the Slug model class:

Next, in the SettingsPage, where the slugs are created in the StartGame method, let’s assign the sound file names to this new property:

Let’s also add a WinSound property to the SlugViewModel:

Now, back in the GameViewModel, let’s revisit the OnGameChanged method and assign the sounds:

This victory joy sound should be played when we have a slug winner, so in the RunRace method:

Now play the game and wait until each of the slugs wins at least once so that you can hear all the different sounds.

If you like the sound effects, that’s great. These effects will be always turned on. If you really can’t stand them, just mute your device.

But you will be able to turn the background music on and off. There’s one button in the RacePage we haven’t talked about so far. Let’s have a look at it now.

The Sound Button

The Sound button in the RacePage, which is the one with a note image on it, has one simple job to do. It should toggle the background music on and off. Also, when clicked, the image on it should change.

We’ll create a command for this button in the GameViewModel. However, as we want to keep all the sound-related code in one place, which is the SoundViewModel, let’s start by adding some properties and a method there.

So, we’ll make some modifications in the SoundViewModel:

So, here we can see two new properties: Volume and Muted. The former is used for the background music. We also have a new method, MuteUnmute. As the name suggests, it will mute the background music if it’s on and turn it back on if it’s off.

As we have access to an instance of SoundViewModel in the GameViewModel, we can create properties and methods there that we’ll use for data binding. In particular, we’ll add a Muted property and a MuteUnmute method:

Now we can bind them in the RacePage XAML file. For simplicity’s sake, we’ll move most of the Sound button’s properties to a style. We’ll duplicate the Sound button. One will be visible when the background music is on, the other when it’s off. The image on either button will be different.

So, here’s the code:

Let’s run the app. When we leave the SettingsPage and enter the RacePage, the background music is on. The Sound button looks like before:

When you press the button, the music will be off and the other Sound button will be visible:

If you now decide the music wasn’t that bad, you can always unmute it.

In the next part of the series we’ll implement even more sound effects. They will be associated with accidents that can happen to the slugs. We’ll also see how to use popups to deliver a short message and offer some options to the user.


Spread the love

Leave a Reply