Playing wav files in a XAML/C# Windows Store App using SharpDX

So you have some great wave files (.wav) to play in your Windows Store App on your WinRT device? But you got lost after a few google searches on how to do that and are not sure which of the following methods is the best?

optionsSo what are the options?

After trying out some things, it was a post by Morten Nielsen who showed the code that put me in the right direction and I created a wave player that preloads waves and uses a new voice for each time you play them. Even if it is already playing.

Download the demo project

Step 1: Install SharpDX

SharpDX is a managed DirectX API that supports Windows 8 Store apps. Use NuGet to add it to your project.

Step 2: Add WavePlayer to your Project

using System;
using System.Collections.Generic;
using SharpDX.IO;
using SharpDX.Multimedia;
using SharpDX.XAudio2;

namespace WavePlayerDX {
    public class WavePlayer : IDisposable {
        public bool IsSoundOn { get; set; }

        private readonly XAudio2 xAudio;
        readonly Dictionary<string, MyWave> sounds;

        public WavePlayer() {
            xAudio = new XAudio2();
            xAudio.StartEngine();
            var masteringVoice = new MasteringVoice(xAudio);
            masteringVoice.SetVolume(1);
            sounds = new Dictionary<string, MyWave>();
        }

        // Reads a sound and puts it in the dictionary
        public void AddWave(string key, string filepath) {
            var wave = new MyWave();

            var nativeFileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
            var soundStream = new SoundStream(nativeFileStream);
            var buffer = new AudioBuffer { Stream = soundStream, AudioBytes = (int)soundStream.Length, Flags = BufferFlags.EndOfStream };

            wave.Buffer = buffer;
            wave.DecodedPacketsInfo = soundStream.DecodedPacketsInfo;
            wave.WaveFormat = soundStream.Format;

            sounds.Add(key, wave);
        }

        // Plays the sound
        public void PlayWave(string key) {
            if (!sounds.ContainsKey(key)) return;
            var w = sounds[key];

            var sourceVoice = new SourceVoice(xAudio, w.WaveFormat);
            sourceVoice.SubmitSourceBuffer(w.Buffer, w.DecodedPacketsInfo);
            sourceVoice.Start();
        }

        public void Dispose() {
            xAudio.Dispose();
        }
    }

    public class MyWave {
        public AudioBuffer Buffer { get; set; }
        public uint[] DecodedPacketsInfo { get; set; }
        public WaveFormat WaveFormat { get; set; }
    }
}
private WavePlayer _wavePlayer = new WavePlayer();

void MainPage_Loaded(object sender, RoutedEventArgs e) {
     _wavePlayer.AddWave("spacy", "spacy.wav");
}

private void Button_Click_1(object sender, RoutedEventArgs e) {
     _wavePlayer.PlayWave("spacy");
}

And that’s all folks. Note that I only did minor tests and I am not sure if all the voice resources are disposed correctly. So use this code at your own risk!