目录
0 作业内容
要求1:
1. 程序应能够读取MP3文件,并播放其中的音频。
2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
3. 程序应具有良好的用户界面,方便用户进行操作。
4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
提示:此功能可以使用WindowsMediaPlayer控件
要求2:
1. 程序应能够播放ogg文件。
2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
3. 程序应具有良好的用户界面,方便用户进行操作。
4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
提示:此功能可以使用Nuget程序包中的Naudi.Vorbis控件
1 窗体设置
1.1 创建项目
选择Windows窗体应用(.NET Framework)创建有Windows窗体界面的项目
1.2 窗体设计
1.2.1 加载COM组件
ToolTip->选择项->COM 组件->Windows Media Player如下图:
1.2.2 添加控件
a.Label:显示当前播放。
b.Listbox:显示选择播放的音乐列表。
c.Trackbar:调节音量。
d.WindowsMediaPlayer:播放常规音乐格式(ogg格式无法用此播放)。
e.openFileDialog:用于选择音乐文件。
f.button1:用于“选择歌曲”
button2:用于“停止播放”
button3:用于“播放下一首”
button4:用于“播放ogg”
注意:在NuGet程序包中安装NAudio.Vorbis如图,才能播放ogg文件。
2 代码实现
2.0 类成员变量定义
string[] files;
List<string> localmusiclist = new List<string> { };
private WaveOutEvent waveOut = new WaveOutEvent();
private VorbisWaveReader currentVorbisReader;
定义一个字符串,用于储存音频文件名称。
localmusiclist
在音乐播放应用中用来追踪和管理用户加载的音乐文件集合。
waveOut
用来播放ogg
文件。
currentVorbisReader
为当前使用的ogg
文件实例。
2.1 Button1—选择歌曲
这个控件用来选择.mp3 .flac .wav这三个类型的音乐文件,因此添加条件用来过滤其余文件。
openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav";
在选择文件时,我们有时需要选择多个文件,因此需要补充代码。
openFileDialog1.Multiselect = true;
清空localmusiclist和listBox1中的项目,同时检查files是否为空,不为空则清空。
利用foreach循环遍历数组中的所有元素,并分别存入listBox1和localmuasiclist列表中;为避免foreach会直接修改files,创建一个新的数组array用于存放多个音频文件。
可以选取多个音频传给files变量。
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav";
openFileDialog1.Multiselect = true;
if(openFileDialog1.ShowDialog()==DialogResult.OK)
{
localmusiclist.Clear();
listBox1.Items.Clear();
if(files!=null)
{
Array.Clear(files, 0, files.Length);
}
files = openFileDialog1.FileNames;
string[] array = files;
foreach(string x in array)
{
listBox1.Items.Add(x);
localmusiclist.Add(x);
}
}
}
2.2 Button2—停止播放
使用 axWindowsMediaPlayer控件中的Ctlcontrols来停止播放。
private void button2_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.Ctlcontrols.stop();
}
2.3 Button3— 播放下一首
如果音频文件数量大于0,则先将文件列表的索引+1,获取下一个音频文件。
int index = (listBox1.SelectedIndex + 1);
当索引超出音频文件的数量,将索引置0。
if (index >= localmusiclist.Count()) { index=0; }
将新的索引对应的对应的音频文件赋值 axWindowsMediaPlayer1控件的URL,调用musicplay方法。
private void button3_Click(object sender, EventArgs e)
{
if(localmusiclist.Count>0)
{
int index = (listBox1.SelectedIndex + 1);
if (index >= localmusiclist.Count()) { index=0; }
axWindowsMediaPlayer1.URL = localmusiclist[index];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text= Path.GetFileNameWithoutExtension(localmusiclist[index]);
listBox1.SelectedIndex = index;
}
}
2.4 Button4— 播放ogg
private void button4_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "打开音频|*.ogg";
string oggFilePath = "";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
oggFilePath = openFileDialog.FileName;
}
using (var vorbisReader = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbisReader);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
}
using (var vorbisStream = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbisStream);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
}
}
2.5 Trackbar—调节音量
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume= trackBar1.Value;
}
2.6 Listbox—显示选择播放的音乐列表
开始播放音频之后,label1需要显示当前播放音频文件的名称。
此时可以根据当前正在播放的音频文件的文件路径,获取扩展名以外的音频文件名,赋值给label1的文本Text。
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
利用ListBox控件中的SelectedIndexChanged获取用户切换列表,SelectedIndex是获取目前列表中选择的序号,通过该序号和之前的localmusiclist,获取到音乐信息并且进行传参调用函数,进行音乐播放。
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text=Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
2.7 musicplay
private void musicplay(string filename)
{
axWindowsMediaPlayer1.URL = filename;
string extension = Path.GetExtension(filename);
if (extension == ".ogg") { Console.WriteLine("这是ogg文件。"); }
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
}
3 完整代码
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using AxWMPLib;
namespace MediaPlayer
{
public partial class Form1 : Form
{
string[] files;
List<string> localmusiclist = new List<string> { };
private WaveOutEvent waveOut = new WaveOutEvent();
private VorbisWaveReader currentVorbisReader;
public Form1()
{
InitializeComponent();
}
private void musicplay(string filename)
{
axWindowsMediaPlayer1.URL = filename;
string extension = Path.GetExtension(filename);
if (extension == ".ogg") { Console.WriteLine("这是ogg文件。"); }
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav";
openFileDialog1.Multiselect = true;
if(openFileDialog1.ShowDialog()==DialogResult.OK)
{
localmusiclist.Clear();
listBox1.Items.Clear();
if(files!=null)
{
Array.Clear(files, 0, files.Length);
}
files = openFileDialog1.FileNames;
string[] array = files;
foreach(string x in array)
{
listBox1.Items.Add(x);
localmusiclist.Add(x);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
private void button2_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.Ctlcontrols.stop();
}
private void button3_Click(object sender, EventArgs e)
{
if(localmusiclist.Count>0)
{
int index = (listBox1.SelectedIndex + 1);
if (index >= localmusiclist.Count()) { index=0; }
axWindowsMediaPlayer1.URL = localmusiclist[index];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text= Path.GetFileNameWithoutExtension(localmusiclist[index]);
listBox1.SelectedIndex = index;
}
}
private void button4_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog1.Filter = "打开音频|*.ogg";
string oggFilepath = "";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
oggFilepath = openFileDialog1.FileName;
}
using (var vorbisReader = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbisReader);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
}
using (var vorbisStream = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbisStream);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
}
}
}
}
4 代码分析
4.1 基本思路
首先确定本次实验需要播放.mp3和.ogg文件,并且需要实现基本音乐播放器的功能,包括选择音频文件、停止播放、调整音量、播放下一首等。
届时可开始进行窗体设计,界面干净整洁便于用户使用。
4.2 难点分析
a. 文件格式: 处理多种音频格式(MP3
,OGG
等)要求使用不同的库,需要额外下载并安装第三方库,导致代码复杂度增加。
b. 异常处理: 音频文件的播放中可能遇到多种异常情况,如文件损坏、编解码器不支持等。
c.下一曲循环播放:下一曲不能仅仅只是索引加1,还需要考虑到现实生活中,列表的循环播放。
d.选取多个音频文件:需要借助list列表来存储多个音频文件,以此来实现多个音频文件的选取,并利用索引来确定当前播放的音乐文件。
5 小结
本次实验的主要目标是编写一个C#程序,该程序能够播放MP3和OGG两种音乐文件格式。
5.1 MP3文件播放实现
在实现MP3文件播放功能时,我使用了Windows Media Player控件。首先在Windows窗体应用程序中添加了一个Media Player控件,并编写了相应的代码来加载和播放MP3文件,同时添加了异常处理逻辑,以捕获并处理文件不存在或读取错误等异常情况。
5.2 OGG文件播放实现
对于OGG文件的播放,我使用了NuGet程序包中的Naudi.Vorbis控件,OGG是一种开源的音频压缩格式,而Naudi.Vorbis控件提供了对OGG文件的支持。首先通过NuGet安装Naudi.Vorbis控件,并将其集成到我的C#项目中;然后编写代码来加载和播放OGG文件。
5.3 用户界面设计
为了提供良好的用户界面,在窗体上需要添加必要的控件,如按钮用于控制播放、暂停和停止等操作,以及一个文本框用于显示当前播放的音频文件名。
通过本次实验,我成功实现了MP3和OGG两种音频文件的播放功能,并处理了可能出现的异常情况,同时也提高了对C#窗体应用程序开发的理解。此外,我还了解了Windows Media Player控件和Naudi.Vorbis控件的使用方法,为今后的项目开发提供了更多的可能性。