前段时间想用C#写一个音频播放器,找来找去找到一个音频开源库:CSCore,发现有挺多家网站采用了它的底层库,它支持的音频格式也挺全。
CSCore 是一个完全用 C# 编写的免费 .NET 音频库。 尽管它仍然是一个相当年轻的项目,但它提供了大量功能,例如播放或捕获音频、编码或解码许多不同的编解码器、效果等等。
CSCore 基于一个可扩展的架构,它允许您无需努力即可满足您的需求。 您可以构建音乐播放器、语音聊天、录音机等! 支持的平台:仅限 Windows、linux 和 mac 实验版(参见 https://github.com/filoe/cscore/tree/netstandard)。--摘自Github官网
参考了一下它的Demo,特此记录一下编写的过程。编写的时候可以参考它的在线文档。
首先打开Visual Studio,打开项目-管理NuGet程序包,搜索CSCore并安装;
支持.NET Framework 4.0及以上,在.NET Core中导入会提示不兼容,不过好像也可以正常用。
先封装一个MusicPlayer类
namespace AudioPlayer
{
///
/// 封装音频播放器
///
public class MusicPlayer : Component
{
private ISoundOut _soundOut;
private IWaveSource _waveSource;
public event EventHandler PlaybackStopped;
///
/// 获取播放器的播放状态
///
public PlaybackState PlaybackState
{
get
{
if (_soundOut != null)
return _soundOut.PlaybackState;
return PlaybackState.Stopped;
}
}
///
/// 目前播放音频的位置
///
public TimeSpan Position
{
get
{
if (_waveSource != null)
return _waveSource.GetPosition();
return TimeSpan.Zero;
}
set
{
if (_waveSource != null)
_waveSource.SetPosition(value);
}
}
///
/// 获取播放音频的长度
///
public TimeSpan Length
{
get
{
if (_waveSource != null)
return _waveSource.GetLength();
return TimeSpan.Zero;
}
}
///
/// 播放器的音量
///
public int Volume
{
get
{
if (_soundOut != null)
return Math.Min(100, Math.Max((int)(_soundOut.Volume * 100), 0));
return 100;
}
set
{
if (_soundOut != null)
{
_soundOut.Volume = Math.Min(1.0f, Math.Max(value / 100f, 0f));
}
}
}
///
/// 读取音频文件地址
///
///
public void Open(string filename)
{
CleanupPlayback();
_waveSource =
CodecFactory.Instance.GetCodec(filename)
.ToSampleSource()
.ToWaveSource();
_soundOut = new WaveOut() {Latency = 100};
_soundOut.Initialize(_waveSource);
if (PlaybackStopped != null) _soundOut.Stopped += PlaybackStopped;
}
///
/// 播放
///
public void Play()
{
if (_soundOut != null)
_soundOut.Play();
}
///
/// 暂停
///
public void Pause()
{
if (_soundOut != null)
_soundOut.Pause();
}
///
/// 停止
///
public void Stop()
{
if (_soundOut != null)
_soundOut.Stop();
}
///
/// 释放设备和音频资源
///
public void CleanupPlayback()
{
if (_soundOut != null)
{
_soundOut.Dispose();
_soundOut = null;
}
if (_waveSource != null)
{
_waveSource.Dispose();
_waveSource = null;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
CleanupPlayback();
}
}
}
然后在主页面中实例化这个类
private readonly MusicPlayer _musicPlayer = new MusicPlayer();
设置一个“打开文件”按钮,Filter中是CSCore支持的音频格式,filename是音频文件的路径
private void button_selectfile_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = CodecFactory.SupportedFilesFilterEn
};
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
filename = openFileDialog.FileName;
}
catch (Exception ex)
{
MessageBox.Show("Could not open file: " + ex.Message);
}
}
}
如果想要播放网络上的音频也可以在MusicPlayer类中这样编写
///
/// 读取音频文件地址
///
///
public void Open(Uri uri)
{
CleanupPlayback();
_waveSource =
CodecFactory.Instance.GetCodec(uri)
.ToSampleSource()
.ToWaveSource();
_soundOut = new WaveOut() {Latency = 100};
_soundOut.Initialize(_waveSource);
if (PlaybackStopped != null) _soundOut.Stopped += PlaybackStopped;
}
设置一个播放按钮,按下后变成暂停按钮
private void button_play_Click(object sender, EventArgs e)
{
if(_musicPlayer.PlaybackState != CSCore.SoundOut.PlaybackState.Playing)
{
if (!filename.Equals(String.Empty))
{
try
{
if (_musicPlayer.Length.TotalMilliseconds - _musicPlayer.Position.TotalMilliseconds <= 50) _musicPlayer.Position = new TimeSpan(0);
_musicPlayer.Play();
button_play.Text = "暂停";
}
catch (Exception ex)
{
MessageBox.Show("播放失败:" + ex.Message);
}
}
}
else
{
if (_musicPlayer.PlaybackState == CSCore.SoundOut.PlaybackState.Playing)
{
_musicPlayer.Pause();
button_play.Text = "播放";
}
}
}
设置一个停止按钮
private void button_stop_Click(object sender, EventArgs e)
{
musicStop();
}
///
/// 音乐停止时的操作
///
private void musicStop()
{
_musicPlayer.Stop();
_musicPlayer.Position = new TimeSpan(0);
button_play.Text = "播放";
}
至此把音频的播放、暂停和停止功能实现了
音量控制在WinForm中可以和trackbar进行绑定,在WPF中和slider绑定;我设置trackbar的最大值为20,而MusicPlay类音量变化范围:0-100;
private void trackbar_volume_Scroll(object sender, EventArgs e)
{
_musicPlayer.Volume = trackbar_volume.Value * 5;
}
进度控制也是如此,新建一个trackbar,最大值为100,MusicPlayer类的播放进度范围:音频长度,Potison属性是TimeSpan类型
private void trackBar1_Scroll(object sender, EventArgs e)
{
int timenow = Convert.ToInt32(((trackBar1.Value * _musicPlayer.Length.TotalMilliseconds) / 100));
System.TimeSpan timeSpan = new TimeSpan(
((timenow % (360000 * 60 * 24)) / (36000 * 60)),
((timenow % (360000 * 60)) / 360000),
(timenow % 360000) / 60000,
(timenow % 60000) / 1000,
(timenow % 1000));
_musicPlayer.Position = timeSpan;
}
在播放的时候可以新建一个timer,将MusicPlayer的播放进度在trackbar上显示
private void timer1_Tick(object sender, EventArgs e)
{
trackbar_volume.Value = _musicPlayer.Volume / 5;
trackBar1.Value = (_musicPlayer.Position.TotalMilliseconds > 0 ? Convert.ToInt32(((_musicPlayer.Position.TotalMilliseconds * 100) / _musicPlayer.Length.TotalMilliseconds)) : 0);
}
写的时候踩了很多坑,由于MusicPlayer类我是从它的Demo里抄来的,刚开始代码没怎么看;后来发现音频播放的时候音质很差,没有立体音,翻了代码才发现_waveSource被转成了单声道,所以音频都没有立体音了。也许还有其他更好的音频库可以使用,不过我感觉CSCore的代码还是很轻便的;CSCore还有很多功能,有兴趣的可以去Github上看看它的Demo和在线文档。