Playing MP3s and WMAs using the .Net Compact Framework

I've been working on a new project called Klaxon: it's a G-Sensor enabled alarm clock for Windows Mobile phones. One of the features is that it can allow playback of MP3s and WMAs. I initially wrote the application in .NET 3.5 assuming that the new System.Media.SoundPlayer class would support those audio formats. But, they don't! I ended up writing my own class that handles all the Sound related PInvokes:

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace WindowsMobile.Utilities
{
    public class SoundPlayer : IDisposable
    {
        [DllImport("aygshell.dll")]
        static extern uint SndOpen(string pszSoundFile, ref IntPtr phSound);

        [DllImport("aygshell.dll")]
        static extern uint SndPlayAsync(IntPtr hSound, uint dwFlags);

        [DllImport("aygshell.dll")]
        static extern uint SndClose(IntPtr hSound);

        [DllImport("aygshell.dll")]
        static extern uint SndStop(int SoundScope, IntPtr hSound);

        [DllImport("aygshell.dll")]
        static extern uint SndPlaySync(string pszSoundFile, uint dwFlags);

        const int SND_SCOPE_PROCESS = 0x1;


        string mySoundLocation = string.Empty;

        public string SoundLocation
        {
            get { return mySoundLocation; }
            set { mySoundLocation = value; }
        }

        IntPtr mySound = IntPtr.Zero;
        Thread myThread = null;
        public void PlayLooping()
        {
            myThread = new Thread(() =>
            {
                while (true)
                {
                    SndPlaySync(mySoundLocation, 0);
                }
            }
            );
            myThread.Start();
        }

        public void Play()
        {
            SndOpen(mySoundLocation, ref mySound);
            SndPlayAsync(mySound, 0);
        }

        public void Stop()
        {
            if (myThread != null)
            {
                SndStop(SND_SCOPE_PROCESS, IntPtr.Zero);
                myThread.Abort();
                myThread = null;
            }
            if (mySound != IntPtr.Zero)
            {
                SndStop(SND_SCOPE_PROCESS, IntPtr.Zero);
                SndClose(mySound);
                mySound = IntPtr.Zero;
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Stop();
        }

        #endregion
    }
}

It should work just like System.Media.SoundPlayer.

8 comments:

Thymos said...

Thank you very much, works great - good job.

Ryan said...

I can't seem to get the sound file working. I've added the class to my project but no sound is coming out of the mobile device?

i'm using:

SoundPlayer sound = new SoundPlayer();
sound.SoundLocation = @"Program Files\MyApp\audio.mp3";
sound.play();

Anonymous said...

hello,

Do you know if this could work with .net CF2?

Thanks;

Anonymous said...

Hi,
Very useful class, it works on my HD with WM6.5 and .net CF 3.5

But one question ?
In class there are methods to play() and stop() music (thread). There is a possibility to "pause" music / thread ?
Thanks in advance
Fabrizio

Zsolti said...

Simply, clean, short. Everything a beginner in c# would need. Thanks a lot for this class!

marfali bro said...

i did used the same class above ..and used:
SoundPlayer sound = newSoundPlayer();
sound.SoundLocation = @"Program Files\MyApp\1.mp3";
sound.play();
bt this doesn't return any sounds, however it returns no error too. whats wrong with this..plz reply me back, its urgent!

Md.Maniruzzaman (Monir) said...
This comment has been removed by the author.
Anonymous said...

thx for the code

@ryan, try using @"\Program Files\MyApp\audio.mp3";

.. with a backslash in fron of program files ;-)