媒体播放器类






4.85/5 (6投票s)
一个使用 WindowsMediaPlayerClass 的高级媒体播放器类。支持交叉淡入/淡出。
引言
不久前,我发现自己在编写一个媒体播放器,因此也在寻找一种播放 MP3、Wav、midi 和其他文件类型的简单方法。我偶然发现了 WindowsMediaPlayerClass
。它可以在 COM 库 WMP.dll 中找到。但是,它没有提供淡入或交叉淡出歌曲的功能。因此,我为它编写了一个更高级的包装类,它使用 WindowsMediaPlayerClass
对象来淡入和交叉淡出歌曲。
使用代码
要使用我的代码,请下载源文件并将 *Media Player.cs* 文件添加到你现有的/新的项目中。然后你必须添加对 COM 库 WMPLib 的引用。它的描述是 Windows Media Player,文件名是 *wmp.dll*。最后,确保引用的属性*嵌入互操作类型*设置为 false。这对于 VS2010 是必要的,我不确定早期版本。
该类使用两个 WindowsMediaPlayerClass
对象来播放文件和启用交叉淡入。当您使用该类时,它看起来好像只有一个播放器。但事件除外,我稍后会介绍。
该代码有五个主要方法:Play
、Pause
、Stop
、Resume
和 Fade
。这些是唯一的公共方法。Play
相当基本;如果播放器暂停,它会恢复播放。如果播放器停止,它会播放指定的文件。根据您是否已将淡入设置为 true,播放器将仅使用播放器一进行播放,而无需淡入或交叉淡入。但是,如果您想要淡入/交叉淡入,播放器会在两个内部播放器之间交替,根据需要将它们淡入和淡出。
Pause
只是暂停当前的内部播放器。如果指定了淡出,它会启动淡出过程。Stop
执行相同的操作,只是它完全停止内部播放器,使其丢失当前位置。此外,Stop
会将播放器状态设置为已停止,因此后续对 Play
的第一次调用将播放新的指定文件。Pause
后的第一次调用将使播放器从上次位置继续播放当前曲目。Pause
后的第一次 Play
调用将调用 Resume
,因此 Resume
和 Play
可以互换使用。最终方法 Fade
只是开始从当前音量淡入到新的指定音量。
有用的主要代码是 Crossfade
,它在一个设定的时间内将一首歌曲淡入,将另一首歌曲淡出,从而产生线性交叉淡入效果。该代码使用一个每 500 毫秒滴答一次的计时器,以在每次发生滴答事件时,通过少量指定量调整两个内部播放器的音量。音量可能会在淡入/交叉淡入期间更改;但是,如果您这样做,在淡入/交叉淡入结束时会听到音量的突然跳跃。因此,建议不要在淡入/交叉淡入期间更改音量。
CrossfadeTimer_Tick
中的第一段代码确定这是否是交叉淡入的开始。如果是,则它以音量 0 启动新播放器,准备好淡入。代码如下
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;
}
}
下一段代码在交叉淡入发生时运行。它调整停止和播放播放器的音量,将播放淡入和停止淡出。这是交叉淡入。
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;
}
}
最后一段代码在淡入结束时运行。它不会停止停止的播放器,而是让它运行直到其媒体结束。此外,它确保内部播放器的播放器音量与用户设置的音量相同。这就是在淡入/交叉淡入期间更改音量会在淡入结束时导致突然跳跃的原因。使用的最终音量只是设置的;如果不同,则两个音量之间没有平滑的淡入淡出。为了实现这一点,人们会增加交叉淡入/淡入的明显长度,并且比从一开始就不更改音量更难实现。
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;
}
}
最后要注意的是,即使您只是在外部调用了 Play
,也会触发媒体结束等事件。这是因为每个播放器都会触发单独的事件,但在外部,它们看起来像一个播放器,这听起来令人困惑,但很有用,因为,例如,如果您正在播放交叉淡入曲目的播放列表,即使在下一首曲目开始播放后,您仍然会收到媒体结束事件。这允许更容易地编程播放计数和类似的歌曲属性。