Click here to Skip to main content
Click here to Skip to main content

Media Player Class

, 18 Nov 2010
Rate this:
Please Sign up or sign in to vote.
An advanced media player class using WindowsMediaPlayerClass. Supports cross-fading/fading.

Introduction

I little while ago, I found myself writing a media player, and consequently was looking for an easy way to play MP3, Wav, midi, and other file types as well. I came across the WindowsMediaPlayerClass. It can be found in the COM library WMP.dll. However, it provided no features for fading or cross-fading songs. So, I wrote a more advanced wrapper class for it that uses WindowsMediaPlayerClass objects to fade and cross-fade songs.

Using the code

To use my code, download the source files and add the Media Player.cs file to your existing/new project. Then you must add a reference to the COM library WMPLib. Its description is Windows Media Player, and the file name is wmp.dll. Finally, make sure the reference's attribute Embed Interop Types is set to false. This is necessary for VS2010, I am not sure about earlier versions.

The class uses two WindowsMediaPlayerClass objects to play files and to enable cross-fading. When you are using the class, it appears only as if there is one player though. With the exception of events, which I will describe later.

The code has five main methods: Play, Pause, Stop, Resume, and Fade. These are the only public methods. Play is fairly basic; if the player is paused, it resumes play. If the player is stopped, it plays the file specified. Depending on whether you have set fade to true, the player will either just use player one for playing without fading or cross-fading. However, if you want fading/cross-fading, the player alternates between the two internal players, fading them in and out as is relevant.

Pause simply pauses the current internal player. If a fade is specified, it starts the fade process. Stop does the same thing except it stops the internal player completely, making it lose its current position. Also, Stop will set the player state to stopped so the first subsequent call to Play will play the new specified file. The first call after Pause will make the player continue playing the current track from the last position. The first call to Play after Pause will call Resume, so Resume and Play can be used interchangeably. The final method Fade simply starts a fade from the current volume to a new specified volume.

The main code that is useful is Crossfade, which fades one song up and another down in a set period of time, thus creating a linear cross-fade effect. The code uses a timer ticking every 500 milliseconds to adjust the volumes of the two internal players by a small amount, specified before the cross-fade starts, each time a tick event occurs. The volume may be changed during a fade/cross-fade; however, a sudden jump in volume would be heard at the end of the fade/cross-fade if you do. It is advisable, therefore, not to change the volume during a fade/cross-fade.

The first chunk of code in CrossfadeTimer_Tick determines whether it is the start of a cross-fade. If it is, then it starts the new player at volume 0, ready to fade up. The code is as follows:

if (CrossfadeTotalRunTime <= 0)
{
    switch (StoppingPlayer)
    {
        case Players.Player1:
            PlayingPlayer = Players.Player2;
            Player2.volume = 0;
            Player2.URL = Player2Song;
            Player2.play();
            break;

        case Players.Player2:
            PlayingPlayer = Players.Player1;
            Player1.volume = 0;
            Player1.URL = Player1Song;
            Player1.play();
            break;
    }
}

The next chunk runs while the cross-fade is occurring. It adjusts the volume of both the stopping and playing players, fading the playing up and stopping down. This is the cross-fade.

else if(CrossfadeTotalRunTime < (CrossfadeTime * 1000))
{
    switch (PlayingPlayer)
    {
        case Players.Player1:
            {
                Player1.volume = (int)(CrossfadeVolumeAdjustment * 
                                 ((float)CrossfadeTotalRunTime / 1000));
                Player2.volume = (int)(Volume - (CrossfadeVolumeAdjustment * 
                                 (float)(CrossfadeTotalRunTime / 1000)));
            }
            break;

        case Players.Player2:
            {
                Player1.volume = (int)(Volume - (CrossfadeVolumeAdjustment * 
                                 ((float)CrossfadeTotalRunTime / 1000)));
                Player2.volume = (int)(CrossfadeVolumeAdjustment * 
                                 ((float)CrossfadeTotalRunTime / 1000));
            }
            break;
    }
}

The final chunk runs when the fade is over. It does not stop the stopping player, but lets it run till its media ends. Also, it makes sure the player's volume of the internal player is the same as the volume set by the user. This is the reason a change in volume during a fade/cross-fade will result in a sudden jump at the end of the fade. The final volume used is just set; if it is different, there is no smooth fade between the two volumes. To implement that, one would increase the apparent length of the cross-fade/fade, and would be harder to implement than not changing the volume in the first place.

else if (CrossfadeTotalRunTime >= (CrossfadeTime * 1000))
{
    CrossfadeTimer.Enabled = false;
    CrossfadeTimer.Stop();
    InCrossfade = false;

    switch (PlayingPlayer)
    {
        case Players.Player1:
            Player1.volume = Volume;
            Player2.volume = 0;
            break;

        case Players.Player2:
            Player2.volume = Volume;
            Player1.volume = 0;
            break;
    }
}

The final thing to note is that events such as media-end are fired even if externally you have only just called Play. This is because separate events are fired for each player, but externally, they appear as one player, which sounds confusing, but is useful because, if say, you are playing a playlist of cross-fading tracks, you will still get the media-end event even after the next track has started playing. This allows easier programming of play counts and similar song attributes.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Ed Nutting
Founder
United Kingdom United Kingdom
Hi there, so you're reading this? I probably ought to tell you something helpful then...
 
Okay well, I'm 17 from London, UK and I have been programming since I was 8 years old. You'll see from my profile I've dabbled in a lot of different areas and I do know what I'm talking about so as they say "gimme some respect yeah?" Smile | :) I've done GCSE's (got 7A*'s, 2A's and a B in French) and am now studying for my AS-Levels (Math, Further Maths, Physics and Chemistry). My main aim is to go to university to study electronic engineering and then work in robotics (preferably humanoid but most of the field is interesting).
 
Thanks for reading,
Edward Nutting
Follow on   Twitter

Comments and Discussions

 
QuestionCould you give me a VB.NET code PinmemberTinhiuvanoinho24-Jul-11 0:25 
GeneralMy vote of 5 PinmemberTinhiuvanoinho24-Jul-11 0:24 
GeneralI used the MediaPlayer control for my degree project PinmvpSacha Barber18-Nov-10 6:33 
RantThe appended zip has 0 KB :-( Pinmemberthelittleguy18-Nov-10 5:14 
AnswerRe: The appended zip has 0 KB :-( PinmemberEdMan19618-Nov-10 6:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 18 Nov 2010
Article Copyright 2010 by Ed Nutting
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid