Reputation: 65
I'm trying to stop sound as soon as I release the button, but what happens is that file is played fully.
I don't want to stop the sound abruptly as it happened with sp.Stop()
.
Is there a way to do this?
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())*/ }
}
}
Upvotes: 3
Views: 2149
Reputation: 2639
I'm interpreting your question as:
How do I fade out the audio of a .wav file using
SoundPlayer
instead of stopping it immediately?
The short answer is that you can't do it with SoundPlayer
alone. You'll need the use of a couple apis from the winmm.dll
library.
If you are comfortable with WPF, then using a MediaElement
with a DoubleAnimation
on it's volume property is probably a better way to do this. See this question for information on that.
However if you really want to use WinForms, the following is an implementation that should work.
Notes about Form1
:
startButton
and stopButton
timer1
that I use to fade out the soundHere is the code to get this working:
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));
}
}
}
Hopefully this should be pretty self-explanatory. I think most people will recognize this as a crude "game-loop-esqe" approach, but it seems to work well. Of note here is that to tweak the speed at which the fade happens is the Velocity
constant.
The code is setup to fade out over 1 second. It's easy to figure that out by looking at the timer1.Interval
and the Velocity
. After 1000 milliseconds (10 timer ticks) then 1000 * 0.001 = 1 which causes the stop code to complete.
The only reason to change the timer1.Interval
is to make more "fades" occur. Current setup does 10 volume fades before stopping.
Upvotes: 3