2015-12-14 47 views
3

我试图在释放按钮时立即停止声音,但会发生什么情况是该文件已完全播放。 我不想突然停止声音,因为它发生在sp.Stop()。 有没有办法做到这一点?如何使用SoundPlayer淡出一个.wav文件的音频,而不是立即停止它?

private void button1_MouseDown(object sender, MouseEventArgs e) 
{ 
    if(sender == mk) 
    { 
     if(e.Button == MouseButtons.Left) 
     { 
      SoundPlayer sp = new SoundPlayer(); 

      sp.SoundLocation = (@"C:\my path\sound.wav"); 
      sp.Play(); 
     } 
    } 
} 

private void button1_MouseUp(object sender, MouseEventArgs e) 
{ 
    if(sender == mk) 
    { 
     if(e.Button == MouseButtons.Left) 
     { /*some code here (without sp.Stop())*/ } 
    } 
} 
+3

你的意思是说,当你“停止”你想让它淡出的声音或类似的东西吗? – test

+0

答案很可能是线程:) – UnholySheep

+0

@test是的。做一个简单的音乐作曲家,并停止像停止()听起来很糟糕 –

回答

2

我解释你的问题如下:

如何退出使用SoundPlayer .wav文件的音频而不是立即停止呢?

简单的答案是,你不能单独使用SoundPlayer。您需要使用winmm.dll库中的两个apis。

如果你对WPF感到满意,那么使用带有DoubleAnimationMediaElement的音量属性可能是更好的方法。有关这方面的信息,请参阅this问题。

但是,如果你真的想使用WinForms,下面是一个应该工作的实现。

注意有关Form1

  • 两个按钮,命名为startButtonstopButton
  • 定时器命名timer1,我用它来使声音渐渐消失

这里是代码即可获得此工作:

using System; 
using System.Media; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 

    public partial class Form1 : Form 
    { 

     [DllImport("winmm.dll", EntryPoint = "waveOutGetVolume")] 
     private static extern int WaveOutGetVolume(IntPtr hwo, out uint dwVolume); 

     [DllImport("winmm.dll", EntryPoint="waveOutSetVolume")] 
     private static extern int WaveOutSetVolume(IntPtr hwo, uint dwVolume); 

     private SoundPlayer player = new SoundPlayer(); 

     // a crude delta time field 
     private float totalElapsedTime; 

     // tweak this value to determine how quickly you want the fade to happen 
     private const float Velocity = 0.001f; 

     public Form1() 
     { 
      this.InitializeComponent(); 

      // i was using 100 milliseconds as my "frame rate" 
      this.timer1.Interval = 100; 
      this.stopButton.Enabled = false; 
     } 

     private void startButton_Click(object sender, EventArgs e) 
     { 
      // sets the audio device volume to the max. 
      // this is not the computer's volume so it won't 
      // blast out your ear drums by doing this unless you 
      // have the computer volume super high - which is not this 
      // code's fault 
      WaveOutSetVolume(IntPtr.Zero, uint.MaxValue); 

      this.startButton.Enabled = false; 
      this.stopButton.Enabled = true; 

      this.totalElapsedTime = 0f; 
      this.player.SoundLocation = @"Music File.wav"; 
      this.player.Load(); 
      this.player.Play(); 
     } 

     private void stopButton_Click(object sender, EventArgs e) 
     { 
      // being the stop 
      this.timer1.Start(); 
      this.stopButton.Enabled = false; 
     } 

     private void timer1_Tick(object sender, EventArgs e) 
     { 
      // amount to interpolate (value between 0 and 1 inclusive) 
      float amount = Math.Min(1f, this.totalElapsedTime * Velocity); 

      // the new channel volume after a lerp 
      float lerped = Lerp(ushort.MaxValue, 0, amount); 

      // each channel's volume is actually represented as a ushort 
      ushort channelVolume = (ushort)lerped; 

      // the new volume for all the channels 
      uint volume = (uint)channelVolume | ((uint)channelVolume << 16); 

      // sets the volume 
      WaveOutSetVolume(IntPtr.Zero, volume); 

      // checks if the interpolation is finished 
      if (amount >= 1f) 
      { 
       // stop the timer 
       this.timer1.Stop(); 

       // stop the player 
       this.player.Stop(); 

       // stop is complete so let user start again 
       this.startButton.Enabled = true; 
      } 

      // add the elapsed milliseconds (very crude delta time) 
      this.totalElapsedTime += this.timer1.Interval; 
     } 

     public static float Lerp(float value1, float value2, float amount) 
     { 
      // does a linear interpolation 
      return (value1 + ((value2 - value1) * amount)); 
     } 

    } 

} 

希望这应该是不言自明的。我认为大多数人会认为这是一种粗糙的“游戏循环”方式,但它似乎运作良好。值得注意的是,调整渐变发生的速度是Velocity的常数。

该代码设置为淡出1秒以上。通过查看timer1.IntervalVelocity可以很容易地得出结论。 1000毫秒后(10个计时器滴答),然后1000 * 0.001 = 1导致停止代码完成。

更改timer1.Interval的唯一原因是使更多的“淡化”发生。当前设置在停止之前会有10个音量消失。

+0

哇。哇哇!你摇滚!我设法将它们分配给实际事件,所以现在它的工作方式是如何工作的。非常感谢! –

相关问题