4

I am creating a WP7 application that requires various sound effects to be played (on button press) over looped background music. The background music is initiated by pressing Button 1 and loops fine. When I press button3 (triggers a sound effect), the sound effect overlays on the background music fine on first press. However, when I press button3 again, the background music stops. I cannot figure out why this might be happening!? I have pasted the relevant portions of code below. Would appreciate any help.

public partial class MainPage : PhoneApplicationPage
{
    SoundEffect soundEffect;
    Stream soundfile;

    // Constructor
    public MainPage()
    {
        InitializeComponent();
    }



    static protected void LoopClip(SoundEffect soundEffect)
    {
        {
        SoundEffectInstance instance = soundEffect.CreateInstance();
        instance.IsLooped = true;
        FrameworkDispatcher.Update();
        instance.Play();
        }
    }

    public void PlaySound(string soundFile)
    {
        using (var stream = TitleContainer.OpenStream(soundFile))
        {

            var effect = SoundEffect.FromStream(stream);
            effect.Play();
        }
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        soundfile = TitleContainer.OpenStream("BackgroundMusic.wav");
        soundEffect = SoundEffect.FromStream(soundfile);  
        LoopClip(soundEffect);
    }


    private void button3_Click(object sender, RoutedEventArgs e)
    {
        PlaySound("sound3.wav");
    }

}

}

sv77
  • 67
  • 1
  • 4

2 Answers2

4

This should work if you are always working with Instances so change your code to this and it should clear up the problem:

public partial class MainPage : PhoneApplicationPage
{   

    SoundEffectInstance loopedSound = null;

    // Constructor
    public MainPage()
    {
        InitializeComponent();
    }

    static protected void LoopClip(SoundEffect soundEffect)
    {
        loopedSound = soundEffect.CreateInstance();
        loopedSound.IsLooped = true;
        loopedSound.Play();
    }

    public void PlaySound(string soundFile)
    {
        SoundEffect sound = SoundEffect.FromStream(Application.GetResourceStream(new Uri(soundFile, UriKind.Relative)).Stream);
        SoundEffectInstance instance = sound.CreateInstance();
        instance.Play();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        SoundEffect sound = SoundEffect.FromStream(Application.GetResourceStream(new Uri(@"BackgroundMusic.wav", UriKind.Relative)).Stream); 
        LoopClip(sound);
    }


    private void button3_Click(object sender, RoutedEventArgs e)
    {
        PlaySound("sound3.wav");
    }

}

The above example assumes your sound files are set with Build Action = Content and are in the top level directory.

theChrisKent
  • 15,029
  • 3
  • 61
  • 62
  • Thank you so much! Unfortunately, I just tried your code and I am having the same original issue -- background music stops after button3 is clicked more than 2 times (first click of button3 works fine..) – sv77 Apr 21 '11 at 20:49
  • @sv77 you are right. I ran my code and duplicated your issue. I have updated my code and it should now work for you. The key is to keep the looped soundeffectinstance around in it's own variable. – theChrisKent Apr 21 '11 at 21:00
0

You will need to play each sound from a separate thread.

What seems to be happening here is that the different Play method calls are interfering with each other since they are in the same thread.

Try just putting the background music in a separate thread and see if that solves the problem you mention in the question. If so, split the others out as well.

Philip Hanson
  • 1,847
  • 2
  • 15
  • 24
  • Thank you. Could you please give me some more details on how to start a new thread? I have not done it before and can't seem to get it to compile. [Thread backgroundThread = new Thread(new ThreadStart (LoopClip))]; – sv77 Apr 21 '11 at 17:47
  • From the code in your comment, you should instead be using `Thread backgroundThread = new Thread(new ParameterizedThreadStart(LoopClip))` or something similar, and pass in the argument (`soundEffect`) using the facilities provided by `ParameterizedThreadStart`. – Philip Hanson Apr 21 '11 at 19:13
  • Still having problems: "No overload for LoopClip matches delegate." I was able to use ThreadStart to call a nonparametized function that then called LoopClip. However, I still had the same original issue when the program ran.. Should I be creating a new Thread in button1_Click or somewhere else? – sv77 Apr 21 '11 at 20:19