This article is compatible with the latest version of Silverlight.
Introduction
This article is part 4 of my article series, Simulating rain in Silverlight. After I added wind effect in the previous article, now I add some “color” in the whole scene. Besides the sound effect, I also put in some visuals to control the wind speed. You can choose between three different rates that will alter the angle of the rain drops. To better react when changing the speed I had to do some minor changes in the simulation algorithm. You are free to download and play with the code from the link below.
It may seem very unfamiliar to you to have sound in your Silverlight application, but it, actually, is not that hard. Silverlight provides you with tools for handling sounds and videos in code and XAML. How? Just in a few seconds...
First, here is a demo:
View live demo
As you might see, you can choose between three different speeds that affect respectively the angle of the rain. Obviously, the stronger the wind is, the bigger the angle is. In nature, having summer rain with 40 kilometers per hour, results in approximately 10 degrees of inclination of the rain. Respectively, 60 km/h yields 30 degrees and 80 km/h – 60 degrees. Again, it depends on the intensity and rain density, but we can use this rule for orientation marks in our simulation.
You can download the source from the following link:
Download source code
How to add sound in your application?
Rain and wind simulation is not complete without any sound effects.
The MediaElement class is the key. It allows you to play a number of audio and video formats. For a complete list of supported files, read here.
The first thing you need to do is to find (or create the sounds) you are to use. There are a bundle of websites on the net offering free sound effects in any audio format. For example, check these out: http://www.partnersinrhyme.com/soundfx/Weather.shtml and http://www.shockwave-sound.com/.
My rain simulation uses two audio files – one for the rain and one for the wind. You need to add the files in the project and change the build action to Resource to ensure the media file gets copied in the ClientBin folder.
I declare my media elements in the XAML that control the both effects:
<
MediaElement
x:Name
=
"WindSound"
Source
=
"wind.mp3"
AutoPlay
=
"False"
></
MediaElement
>
<
MediaElement
x:Name
=
"RainSound"
Source
=
"rain.mp3"
AutoPlay
=
"False"
></
MediaElement
>
I set AutoPlay=”False” to prevent the media element from playing as soon as the app starts. I control this on my own:
private
void
WindSound_MediaOpened(
object
sender, System.Windows.RoutedEventArgs e)
{
this
.windMarker.Time = TimeSpan.FromMilliseconds(
this
.WindSound.NaturalDuration.TimeSpan.TotalMilliseconds - 1000);
this
.WindSound.Markers.Add(
this
.windMarker);
this
.WindSound.Volume = 0.3;
this
.WindSound.Play();
}
To loop the audio, I use markers. Markers are marks in the audio/video that you can jump to when needed. I create a marker one second before the end of the media file and I use it to mark the end of the file and loop the media. The alternative, to handle the media ended event, is not the best choice here since the sound is getting silent and silent in the very end:
private
void
WindSound_MarkerReached(
object
sender, TimelineMarkerRoutedEventArgs e)
{
this
.WindSound.Stop();
this
.WindSound.Play();
}
To change the rain angle on the fly, I must abstract the rain in maximum rate. The improvement that I make here is in the way I initialize the rain and all it dependencies. The drop settings are constructed in the rain constructor, so is the slice and the fall distance.
Having all this in mind, we have this method:
public
void
ChangeAngle(
int
angle)
{
int
fallDistance = (
int
)((
double
)
this
.Height / Math.Cos(Math.PI * angle / 180));
this
.FallDistance = fallDistance;
this
.Angle = angle;
this
.Slice = (
int
)(
this
.Height * Math.Tan(Math.PI * angle / 180));
this
.sliceCoef = (
this
.FallDistance * Math.Sin(Math.PI * angle / 180)) /
this
.Width;
this
.DropSettings =
new
DropSettings(0, fallDistance, Constants.ANIMATION_DURATION);
}
It changes not only the angle, but every aspect of the rain that depends on the angle.
Now, it’s easy to change the wind speed:
// Speed changed handler
private
void
SpeedSelector_SelectionChanged(
object
sender, SelectionChangedEventArgs e)
{
this
.HideArrows();
switch
(
this
.SpeedSelector.SelectedIndex)
{
case
0:
{
// Light rain
this
.light1.Visibility =
this
.light2.Visibility =
this
.light3.Visibility = System.Windows.Visibility.Visible;
this
.rain.ChangeAngle(
this
.lightAngle);
this
.WindSound.Volume = 0.3;
break
;
}
case
1:
{
// Medium rain
this
.medium1.Visibility =
this
.medium2.Visibility =
this
.medium3.Visibility = System.Windows.Visibility.Visible;
this
.rain.ChangeAngle(
this
.mediumAngle);
this
.WindSound.Volume = 0.6;
break
;
}
case
2:
{
// Rough rain
this
.rough1.Visibility =
this
.rough2.Visibility =
this
.rough3.Visibility = System.Windows.Visibility.Visible;
this
.rain.ChangeAngle(
this
.roughAngle);
this
.WindSound.Volume = 0.9;
break
;
}
}
}
Of course, changing the wind speed affects the Volume property of the media file. That’s how you volume up or down an audio.
Conclusion
In this article I add sound effects to my rain simulation. Moreover, I build some visuals to change the wind speed. I strongly encourage you to use MediaElement when dealing with media files. It provides you with all you could need. Or solid base for all you could ever need!
Feel free to ask or comment!