Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2010 Grant Archibald
In this post I will provide an overview of the changes from the original wav media files, to wma files required by the Silverlight version.
The main sections are:
As Scott indicated in his first post Introducing BabySmash, he started using techniques that he already knew. As a result the laughs and giggles played when a key is pressed where included as embedded wav files. When moving to the Silverlight environment this approach require some modifications to optimise the download experience and cater for the differences of running cross platform within a browser.
The original audio files used by the WPF application where wav files as in made use of class called Win32Audio, which wrapped calls to the underlying Windows unmanaged win32 api’s.
public class Win32Audio { #region WIN32 Const Definitions public const UInt32 SND_ASYNC = 0x0001; public const UInt32 SND_LOOP = 0x0008; public const UInt32 SND_MEMORY = 0x0004; public const UInt32 SND_NOSTOP = 0x0010; #endregion // this is the overload we want to play embedded resource... public static Dictionary<string, string> cachedWavs = new Dictionary<string, string>(); public static object cachedWavsLock = new object(); [DllImport("winmm.dll")] public static extern bool PlaySound(byte[] data, IntPtr hMod, UInt32 dwFlags); [DllImport("winmm.dll", SetLastError = true)] private static extern bool PlaySound(string pszSound, IntPtr hmod, UInt32 fdwSound); public void PlayWavResource(string wav) { string s = GetWavResource(wav); PlaySound(s, IntPtr.Zero, SND_ASYNC); }
For the Silverlight version pinvokes to the underlying operating system are not allowed from both a security point and cross platform point of view. The answer was to implement a new class XamlAudio that makes use of the MediaElement class present in both WPF and Silverlight to play the audio files.
public class XamlAudio { private MediaElement player; readonly Queue<string> soundsToPlay = new Queue<string>(); private bool inPlay; private Dictionary<string, Stream> media = new Dictionary<string, Stream>(); //TODO Add lock and config value for sound queue limit public void PlayWavResourceYield(string s) { if (player == null) return; if (inPlay && soundsToPlay.Count < 5) { soundsToPlay.Enqueue(s); return; } PlaySound(s); }
The second major difference in the code is the shift from the use of embedded audio files, as indicated in my earlier post Silverlight BabySmash Performance – The Asynchronous Story, the Silverlight version asynchronously downloads the audio files on demand. As result the initial download size for the deployed application is smaller.
The encoding format was also a major difference, changing from the use of wav files to Window Media Audio files (*.wma). To convert the files I used Microsoft Expression Encoder.
The steps I used to convert the files where as follows:
From the the output folder I copied the converted wma files to the ClientBin folder of the web site so that they where easily accessible to the Silverlight application when using a WebClient asynchronous download request.
One interesting point from the comparison of the conversion is that for the small files with the same bit rate encoding the WMA files where larger. If further optimisation in terms of files size is required, then this is an area that could be further investigated to determine the exact encoding settings to trade-off audio quality against file size.
Comments [0] Friday, December 19, 2008 12:11:25 AM (GMT Standard Time, UTC+00:00) Related posts:Three Little Pigs – Silverlight E-BookMy Mix09 10k Contest Entry Is Live – Spin And WinSilverlight BabySmash Performance – The Asynchronous StoryBabySmash At PDCTracking Silverlight And Moonlight Enabled Browsers via Google AnalyticsBabySmash Silverlight Refactorings - Part 2 - Routed Events babysmash | silverlight