2015-12-14 3 views
3

Я пытаюсь остановить звук, как только я отпущу кнопку, но происходит то, что файл воспроизводится полностью. Я не хочу резко останавливать звук, как это случилось с sp.Stop(). Есть ли способ сделать это?Как выпустить звук WAV-файла, используя SoundPlayer, вместо того, чтобы немедленно его остановить?

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 yep. делать простой музыкальный композитор и останавливаться, как Stop(), звучит ужасно –

ответ

2

Я интерпретации ваш вопрос:

Как исчезать аудио файла .wav с помощью SoundPlayer вместо останавливать его сразу?

Короткий ответ заключается в том, что вы не можете сделать это только с SoundPlayer. Вам понадобится использовать пару apis из библиотеки winmm.dll.

Если вам комфортно с WPF, то с помощью MediaElement с DoubleAnimation на его объемном ресурсе, вероятно, лучший способ сделать это. См. Вопрос this.

Однако, если вы действительно хотите использовать WinForms, следующая реализация будет работать.

Заметки о Form1:

  • Две кнопки, названные startButton и stopButton
  • Таймер имени 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)); 
     } 

    } 

} 

Надеюсь, это должно быть довольно понятным. Я думаю, что большинство людей признают это как грубый подход «game-loop-esqe», но, похоже, он работает хорошо. Следует отметить, что для настройки скорости, с которой происходит затухание, является константа.

Код настроен на постепенное исчезновение более 1 секунды. Это легко понять, посмотрев на timer1.Interval и Velocity. После 1000 миллисекунд (10 тиков таймера), то 1000 * 0,001 = 1, что приводит к завершению кода остановки.

Единственная причина для изменения timer1.Interval - это сделать больше «затухания». Текущая настройка делает 10 томов затухания перед остановкой.

+0

Ничего себе. Просто вау. Ты жжешь! Мне удалось присвоить их реальным событиям, так что теперь он работает так, как мне нужно, чтобы он работал. Большое спасибо! –