0

I'm trying to add background music to my WPF program. I also want additional sounds to happen "over" the background music. I tried using a SoundPlayer however, this could only play one piece of audio at once.

I am now trying to use MediaPlayer but I cannot get any audio to play. Here is my code:

In my ShellViewModel I start the background music:

Sounds.StartBackgroundMusic()

In my sounds class I have the following:

private static MediaPlayer _backgroundMusic = new MediaPlayer();

public static void StartBackgroundMusic()
{
    _backgroundMusic.Open(new Uri("pack://application:,,,/Assets/Sounds/backgroundmusic.wav"));
    _backgroundMusic.MediaEnded += new EventHandler (BackgroundMusic_Ended);
    _backgroundMusic.Play();
}

private static void BackgroundMusic_Ended(object sender, EventArgs e)
{
    _backgroundMusic.Position = TimeSpan.Zero;
    _backgroundMusic.Play();
}

Since I want the background music to loop continuously, I used the answer in this question to add the BackgroundMusic_Ended event. Can someone please help shed some light on why my audio isn't playing?

I.T Delinquent
  • 2,305
  • 2
  • 16
  • 33

2 Answers2

0

I tried to reproduce the problem but it worked as expected.

I created a new WPF application in Visual Studio and used the following code in MainWindow.xaml.cs:

using System;
using System.Windows;
using System.Windows.Media;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        private static MediaPlayer _backgroundMusic = new MediaPlayer();

        public MainWindow()
        {
            InitializeComponent();

            StartBackgroundMusic();
        }

        public static void StartBackgroundMusic()
        {
            _backgroundMusic.Open(new Uri(@"C:\<path-to-sound-file>\music.wav"));
            _backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
            _backgroundMusic.Play();
        }

        private static void BackgroundMusic_Ended(object sender, EventArgs e)
        {
            _backgroundMusic.Position = TimeSpan.Zero;
            _backgroundMusic.Play();
        }
    }
}

Did you try to use a "regular" file path to load a sound file instead of "pack://..."? When I used the wrong path I didn't get any sound and there was no error message or exception.

Marius
  • 1,529
  • 6
  • 21
  • I haven't tried using a system path as I can only really use an application path. This is for a WPF form that I want people just to be able to run on any computer without messing around with creating temporary files and such :) – I.T Delinquent Nov 25 '19 at 09:33
  • Do you know how I could use the application path? – I.T Delinquent Nov 25 '19 at 09:33
  • Can you try in your development environment to use a system path to an audio file? I think it is a good idea to try to confirm that this is the issue on your system. As for the application path maybe this SO question can help you: https://stackoverflow.com/questions/3123870/find-the-location-of-my-applications-executable-in-wpf-c-or-vb-net – Marius Nov 25 '19 at 13:32
  • The system file is working perfectly in development. Is there any way to use an embedded resource with MediaPlayer or do I need to temp store the wav file to disk? – I.T Delinquent Dec 10 '19 at 11:14
  • According to [this question](https://stackoverflow.com/questions/15145209/how-to-play-a-wpf-sound-file-resource) Media Player does not support embedded resources. The second answer provides a solution to read the WAV file from a stream. – Marius Dec 13 '19 at 10:59
0

Since I couldn't use MediaPlayer to play embedded resources and SoundPlayer can only play one sound at a time, I used a combination of them and saved the embedded background music resource to disk so that MediaPlayer could play it. I make a blog about it here

Heres what I did:

I set up my SoundPlayer as this was the simplest one of the two. I created a new SoundPlayer object using the embedded resource

private static readonly SoundPlayer _soundOne = new SoundPlayer(WPF.Properties.Resources.soundOne);

Now the MediaPlayer. I make sure that my audio file is set as an Embedded Resource under the Build Actions in the file’s properties in Visual Studio. Now that we have done this, we can create the method for saving the embedded WAV file to the %temp% location on disk:

public static void SaveMusicToDisk(){
    //This sets up a new temporary file in the %temp% location called "backgroundmusic.wav"
    using (FileStream fileStream = File.Create(Path.GetTempPath() + "backgroundmusic.wav")){

        //This them looks into the assembly and finds the embedded resource
        //inside the WPF project, under the assets folder
        //under the sounds folder called backgroundmusic.wav
        //PLEASE NOTE: this will be different to you
        Assembly.GetExecutingAssembly().GetManifestResourceStream("WPF.Assets.Sounds.backgroundmusic.wav").CopyTo(fileStream);
    }
}

We play this by creating a new MediaPlayer object and using the temp file location to play the audio:

//Create a new MediaPlayer object
private static readonly MediaPlayer _backgroundMusic = new MediaPlayer();

public static void StartBackgroundMusic(){
    //Open the temp WAV file saved in the temp location and called "backgroundmusic.wav"
    _backgroundMusic.Open(new Uri(Path.Combine(Path.GetTempPath(), "backgroundmusic.wav")));
    //Add an event handler for when the media has ended, this way
    //the music can be played on a loop
    _backgroundMusic.MediaEnded += new EventHandler(BackgroundMusic_Ended);
    //Start the music playing
    _backgroundMusic.Play();
}

My BackgroundMusic_Ended method looks like this and just makes sure that the music is always restarted once it has finished:

private static void BackgroundMusic_Ended(object sender, EventArgs e){
    //Set the music back to the beginning
    _backgroundMusic.Position = TimeSpan.Zro;
    //Play the music
    _backgroundMusic.Play();
}

Then I just had to worry about disposing of the objects and cleaning up the temp file when the program is closing.

I.T Delinquent
  • 2,305
  • 2
  • 16
  • 33