Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

MP3 Helper Class

4.80/5 (9 votes)
23 Jul 2010CPOL2 min read 41.6K   2.8K  
An MP3 helper class to help you play MP3 files and embedded resources' streams
MP3Helper.jpg

Introduction

To many .NET developers, it's always been an issue playing MP3 files in your application, whether embedded or as a separate system file.

According to MSDN, you can launch or embed WMP10 (using the WMP10SDK) in your application and then tell it to play the file through that, or you could use the DirectX SDK to play audio via DirectX in your application.

In this article, we're going to discuss playing MP3 using winmm.dll.

Background

Performance Issues When Loading Winmm.dll

According to Microsoft, when your Windows 2000-based computer loads the Winmm.dll file into memory, you may experience a delay. This delay may occur at different times, depending on how the Winmm.dll file is loaded.

If a program loads the Winmm.dll file by using an import library “like the way it is managed in this article”, Winmm.dll is loaded when the program starts. In this case, you may experience a delay when you start the program. Performance can be significantly affected if the program is started many times by using a batch file, so DON'T.

If a program loads the Winmm.dll file by using LoadLibrary, Winmm.dll is loaded only when the program needs to use it and that, my friends, is the better way to do it. For simplicity, we're discussing the more basic and slower method but you can always refer to the article Late binding on native DLLs with C# for the more efficient method.

Using the Code

The Helper class is a simple class with a couple of useful public static methods to control the playing file... Again, this class is very simple and to the point, so if you feel like adding some extra functions or attributes like a Boolean flag or an enumerator to tell you about the current state of a file/stream “for example, being currently played, paused or stopped”, go ahead and add it.

C#
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace QSoft
{
    class MP3Helper
    {
        [DllImport("winmm.dll")]
        private static extern long mciSendString(string strCommand,
            System.Text.StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback);
        
        public static void Play(string MP3_FileName,bool Repeat)
        {
            mciSendString("open \"" + MP3_FileName + "\" type mpegvideo alias MediaFile",
                null, 0, IntPtr.Zero);
            mciSendString("play MediaFile" + (Repeat ? " repeat" :String.Empty), null,
                0, IntPtr.Zero);
        }
        public static void Play(byte[] MP3_EmbeddedResource, bool Repeat)
        {
            extractResource(MP3_EmbeddedResource, Path.GetTempPath() + "resource.tmp");
            mciSendString("open \"" + Path.GetTempPath() + "resource.tmp" + 
                "\" type mpegvideo alias MediaFile", null, 0, IntPtr.Zero);
            mciSendString("play MediaFile" + (Repeat ? " repeat" : String.Empty),
                null, 0, IntPtr.Zero);
        }

        public static void Pause()
        {
            mciSendString("stop MediaFile", null, 0, IntPtr.Zero);
        }

        public static void Stop()
        {
            mciSendString("close MediaFile", null, 0, IntPtr.Zero);
        }

        private static void extractResource(byte[] res,string filePath)
        {
            FileStream fs;
            BinaryWriter bw;

            if (!File.Exists(filePath))
            {
                fs = new FileStream(filePath, FileMode.OpenOrCreate);
                bw = new BinaryWriter(fs);

                foreach (byte b in res)
                    bw.Write(b);

                bw.Close();
                fs.Close();
            }
        }
    }
} 

Playing a system file is straightforward, all you need to do is specify the name of the system. We call it using the overloaded Play method.

C#
QSoft.MP3Helper.Play(txtAudioFile.Text, true); 
C#
public static void Play(string MP3_FileName,bool Repeat)
{
     mciSendString("open \"" + MP3_FileName + "\" type mpegvideo alias MediaFile",
         null, 0, IntPtr.Zero);
     mciSendString("play MediaFile" + (Repeat ? " repeat" :String.Empty), null,
         0, IntPtr.Zero);
}

However, playing an embedded resource file is a bit tricky, in that, you will first extract it to a temporary file and then read it as a simple system file.

The extractResource does the extracting by taking your music file as a byte array as its first argument and the fully qualified name of destination temporary file.

C#
private static void extractResource(byte[] res,string filePath)
{
    FileStream fs;
    BinaryWriter bw;

    if (!File.Exists(filePath))
    {
        fs = new FileStream(filePath, FileMode.OpenOrCreate);
        bw = new BinaryWriter(fs);

        foreach (byte b in res)
            bw.Write(b);

        bw.Close();
        fs.Close();
    }
}  

And we call it using the overloaded Play method:

C#
QSoft.MP3Helper.Play(Properties.Resources.YourMp3File, true); 
C#
public static void Play(byte[] MP3_EmbeddedResource, bool Repeat)
{
    extractResource(MP3_EmbeddedResource, Path.GetTempPath() + "resource.tmp");
    mciSendString("open \"" + Path.GetTempPath() + "resource.tmp" + 
                "\" type mpegvideo alias MediaFile", null, 0, IntPtr.Zero);
    mciSendString("play MediaFile" + (Repeat ? " repeat" : String.Empty),
    null, 0, IntPtr.Zero);
}

To stop and pause the file, we use MP3Helper .Stop() and MP3Helper.Pause respectively.

C#
public static void Pause()
{
    mciSendString("stop MediaFile", null, 0, IntPtr.Zero);
}

public static void Stop()
{
    mciSendString("close MediaFile", null, 0, IntPtr.Zero);
} 

The implementing form code uses the traditional button disabling technique to prevent playing an already playing file “feel free to add your boolean flag/enumerator state for better checks”.

C#
using System;
using System.Windows.Forms;
using System.IO;

namespace MP3Helper
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            if(rdSystemFile.Checked)
                if (txtAudioFile.Text.Length > 0 && File.Exists(txtAudioFile.Text))
                {
                    QSoft.MP3Helper.Play(txtAudioFile.Text, true);
                    btnPlay.Enabled = false;
                    btnPause.Enabled = true;
                    btnStop.Enabled = true;
                }
            if (rdResourceFile.Checked)
            {
                QSoft.MP3Helper.Play(Properties.Resources.Shakira___Waka_Waka, true);
                btnPlay.Enabled = false;
                btnPause.Enabled = true;
                btnStop.Enabled = true;
            }
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            QSoft.MP3Helper.Pause();
            btnPlay.Text = "Resume";
            btnPlay.Enabled = true;
            btnPause.Enabled = false;
            btnStop.Enabled = true;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            QSoft.MP3Helper.Stop();
            btnPlay.Text = "Play";
            btnPlay.Enabled = true;
            btnPause.Enabled = false;
            btnStop.Enabled = false;
        }

        private void lnkBrowse_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            openFileDialog1.Filter = 
                "mp3 files|*.mp3|wave files|*.wav|rm files|*.rm|All files|*.*";
            openFileDialog1.ShowDialog();
            txtAudioFile.Text = openFileDialog1.FileName;
        }

        private void rdResourceFile_CheckedChanged(object sender, EventArgs e)
        {
            if (rdResourceFile.Checked)
            {
                lnkBrowse.Enabled = false;
                txtAudioFile.Enabled = false;

                QSoft.MP3Helper.Stop();
                btnPlay.Text = "Play";
                btnPlay.Enabled = true;
                btnPause.Enabled = false;
                btnStop.Enabled = false;
            }
        }

        private void rdSystemFile_CheckedChanged(object sender, EventArgs e)
        {
            if (rdSystemFile.Checked)
            {
                lnkBrowse.Enabled = true;
                txtAudioFile.Enabled = true;

                //Stopping resource
                QSoft.MP3Helper.Stop();
                btnPlay.Text = "Play";
                btnPlay.Enabled = true;
                btnPause.Enabled = false;
                btnStop.Enabled = false;
            }
        }
    }
}

History

  • 23rd July, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)