Is it possible to play 2 sounds back to back using SoundPlayer?

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-08 03:32:51

问题


I'm looking for a way to play multiples sound back to back asynchronously.

I actually have :

jouerSon("_" + nbre1);
jouerSon(operateur);
jouerSon("_" + nbre2);
jouerSon("equal");

public void jouerSon(String son)
{
    System.Media.SoundPlayer player = new SoundPlayer();
    player.Stream = Properties.Resources.ResourceManager.GetStream(son);
    // player.LoadAsync();
    player.Play();
    //Thread.Sleep(500);
    //player.Stop();
 }

I'd like to play the first sound, then when it's over the second one etc all while the program is still responsive.

I managed to play each sound one after another but only using a synchronous play, which prevent the user from doing anything until all sound are played.

And if I try using with an asynchronous play, only the last sound is played instead of each one.

I've looked around for a solution, but can't seem to find any. Could someone help me?


回答1:


Play them on a different thread:

    private void button1_Click(object sender, EventArgs e)
    {
        // ...
        jouerSon(new String[] { "_" + nbre1, operateur, "_" + nbre2, "equal" });
        // ...
    }

    public void jouerSon(String[] sons)
    {
        Task t = new Task(() =>
        {
            System.Media.SoundPlayer player = new System.Media.SoundPlayer();
            foreach (String son in sons)
            {
                player.Stream = Properties.Resources.ResourceManager.GetStream(son);
                player.PlaySync();
            }    
        });
        t.Start();
    }

Or possibly something more specifically tailored, like this:

    private void button1_Click(object sender, EventArgs e)
    {
        // ...
        jouerSon(nbre1, operateur, nbre2);
        // ...
    }

    public void jouerSon(string nbre1, string operateur, string nbre2)
    {
        Task t = new Task(() =>
        {
            System.Media.SoundPlayer player = new System.Media.SoundPlayer();
            player.Stream = Properties.Resources.ResourceManager.GetStream("_" + nbre1);
            player.PlaySync();
            player.Stream = Properties.Resources.ResourceManager.GetStream(operateur);
            player.PlaySync();
            player.Stream = Properties.Resources.ResourceManager.GetStream("_" + nbre2);
            player.PlaySync();
            player.Stream = Properties.Resources.ResourceManager.GetStream("equal");
            player.PlaySync();
        });
        t.Start();
    }



回答2:


OK, as promised, here is some sample code for how to use Windows Media Player. But now that I look at it, I can see that it is quite a bit more complicated than I thought - maybe too complicated?

This program can be used to play a sound file 1 time, or 2 times, or n times, or an indeterminate number of times, until the calling program calls the StopPlayer() method. It should be fairly easy to modify it to play first one sound file and then another one.

using WMPLib;

using System;


namespace Merlinia.CommonClasses
{
   /// <summary>
   /// This class provides a very simple wrapper layer for the Microsoft Windows Media Player.
   /// 
   /// Remember to call Dispose() when the player is no longer needed. (Actually, this may not be 
   /// necessary.)
   /// </summary>
   public class MMediaPlayer : IDisposable
   {
      #region Private variables

      // Reference to an Interop object for the COM object that interfaces with Microsoft Windows 
      //  Media Player
      private readonly WindowsMediaPlayer _windowsMediaPlayer = null;

      // Number of repeats left, negative = keep looping
      private int _repeatCount = -1;

      // Part of the IDisposable pattern
      private bool _isDisposed = false;

      #endregion Private variables


      #region Constructor

      /// <summary>
      /// Constructor.
      /// </summary>
      public MMediaPlayer()
      {
         try
         {
            // Instantiate the Windows Media Player Interop object 
            _windowsMediaPlayer = new WindowsMediaPlayer();

            // Hook up a couple of event handlers
            _windowsMediaPlayer.MediaError += WindowsMediaPlayer_MediaError;
            _windowsMediaPlayer.PlayStateChange += WindowsMediaPlayer_PlayStateChange;
         }
         catch (Exception e)
         {
            _cLog.Error(0x3ad3a52u, e);
         }
      }

      #endregion Constructor


      #region Public methods

      /// <summary>
      /// Method to start the media player playing a file.
      /// </summary>
      /// <param name="fileName">complete file name</param>
      /// <param name="repeatCount">zero = repeat indefinitely, else number of times to repeat</param>
      public void PlayMediaFile(string fileName, int repeatCount)
      {
         if (_windowsMediaPlayer == null)
            return;

         _repeatCount = --repeatCount;  // Zero -> -1, 1 -> zero, etc.

         if (_windowsMediaPlayer.playState == WMPPlayState.wmppsPlaying)
            _windowsMediaPlayer.controls.stop();  // Probably unnecessary

         _windowsMediaPlayer.URL = fileName;
         _windowsMediaPlayer.controls.play();
      }


      /// <summary>
      /// Method to stop the media player.
      /// </summary>
      public void StopPlayer()
      {
         if (_windowsMediaPlayer == null)
            return;

         _repeatCount = 0;
         _windowsMediaPlayer.controls.stop();
      }

      #endregion Public methods


      #region Private methods

      /// <summary>
      /// Event-handler method called by Windows Media Player when the media file can't be opened, 
      /// or some other error. This is logged, but otherwise ignored - the calling module is not 
      /// signaled in any way.
      /// </summary>
      private static void WindowsMediaPlayer_MediaError(object pMediaObject)
      {
         _cLog.Error(0x3ad1d3bu);
      }


      /// <summary>
      /// Event-handler method called by Windows Media Player when the "state" of the media player 
      /// changes. This is used to repeat the playing of the media for the specified number of 
      /// times, or maybe for an indeterminate number of times.
      /// </summary>
      private void WindowsMediaPlayer_PlayStateChange(int newState)
      {
         if ((WMPPlayState)newState == WMPPlayState.wmppsStopped)
         {
            if (_repeatCount != 0)
            {
               _repeatCount--;
               _windowsMediaPlayer.controls.play();
            }
         }
      }

      #endregion Private methods


      #region IDisposable stuff

      // This copied from here: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

      /// <summary>
      /// Method to implement IDisposable. Do not make this method virtual - a derived class should 
      /// not be able to override this method.
      /// </summary>
      public void Dispose()
      {
         // Call the following method
         Dispose(true);

         // This object will be cleaned up by the Dispose() method below. Therefore, we call 
         //  GC.SuppressFinalize to take this object off the finalization queue and prevent 
         //  finalization code for this object from executing a second time.
         GC.SuppressFinalize(this);
      }


      /// <summary>
      /// Dispose(bool disposing) executes in two distinct scenarios. If isDisposing equals true, 
      /// the method has been called directly or indirectly by a user's code. Managed and unmanaged 
      /// resources can be disposed. If isDisposing equals false, the method has been called by the 
      /// runtime from inside the finalizer and you should not reference other objects - only 
      /// unmanaged resources can be disposed.
      /// </summary>
      protected virtual void Dispose(bool isDisposing)
      {
         // Check to see if Dispose() has already been called
         if (!_isDisposed)
         {
            // If isDisposing equals true, dispose all managed and unmanaged resources
            if (isDisposing && _windowsMediaPlayer != null)
            {
               // Close the media player. (This may not be necessary?)
               _windowsMediaPlayer.close();
            }

            // Note disposing has been done
            _isDisposed = true;
         }
      }

      #endregion IDisposable stuff

   }
}

Ignore the statements that have to do with logging.

But for this to work you need an Interop dll for the COM object that interfaces with Windows Media Player. This is unfortunately a bit tricky if you've never done this before. Visual Studio is able to generate an Interop dll. Alternatively you can try to find one on the Internet. That's what I did in fact, I happened to find one here: http://grouplab.cpsc.ucalgary.ca/cookbook/index.php/VisualStudio/HowToUseWindowsMediaPlayerToPlayAudioAndVideo

Good luck, and you're welcome to ask if you try to do this and run into problems.



来源:https://stackoverflow.com/questions/27424538/is-it-possible-to-play-2-sounds-back-to-back-using-soundplayer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!