一.功能说明
1. 程序应能够读取MP3,ogg文件,并播放其中的音频。
2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
3. 程序应具有良好的用户界面,方便用户进行操作。
4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行
二.winform窗体控件设计

通过button控件我们设计“播放ogg文件”“选择歌曲”“停止播放”和“下一首”这四个功能模块,listbox模块的右侧由一个竖着的进度条来控制音量,listbox用于显示我们的音乐播放列表,open file dialog1用于获取音乐文件,同时利用Windows自带的控件axWindowsMediaPlayer控件来实现音乐的播放功能,同时它也具有音乐播放器基本的暂停播放音量调节的作用。
三.代码实现
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using NVorbis.Contracts;
这些 using 声明导入了 NAudio 库中所需的命名空间,以便在代码中直接使用 NAudio 提供的类和接口。
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[] arry = files;
foreach (string x in arry)
{
listBox1.Items.Add(x);
localmusicList.Add(x);
}
}
}
这段代码实现的功能是当用户点击按钮1时,会弹出一个文件选择对话框,用户可以选择一个或多个音频文件。选择完成后,选中的文件会被添加到一个列表框中,并且它们的路径会被存储在 localmusicList 列表中。同时,之前选择的文件列表和路径数组都会被清空,以便存储新的选择。
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (localmusicList.Count > 0)
{
int selectedIndex = listBox1.SelectedIndex;
if (selectedIndex >= 0)
{
string selectedFile = localmusicList[selectedIndex];
if (!selectedFile.EndsWith(".ogg"))
{
axWindowsMediaPlayer1.URL = selectedFile;
musicplay(axWindowsMediaPlayer1.URL);
label1.Text = Path.GetFileNameWithoutExtension(selectedFile);
}
}
}
}
这段代码是一个事件处理方法,当列表框中的选项被选中时触发。它的功能是根据用户在列表框中选择的音乐文件,自动播放选中的音乐,并在标签中显示当前播放的音乐文件名(不包括扩展名)。
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}
这个方法是当用户滚动滑动条时触发的事件处理方法。它的作用是将滑动条的当前值设置为 Windows Media Player 控件 axWindowsMediaPlayer1 的音量值。
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;
}
}
这个方法是当用户点击按钮3时触发的事件处理方法。它的功能是播放列表中的下一首音乐。
具体地说,该方法首先检查当前播放列表中是否有音乐文件(即 localmusicList.Count > 0)。如果有音乐文件,则执行以下操作:
-
计算下一首音乐的索引:通过
listBox1.SelectedIndex + 1获取当前选中音乐的下一个索引位置。 -
检查下一首音乐的索引是否超出了列表的范围:如果
index大于等于localmusicList的长度,说明已经到达了列表的末尾,因此将index设置为 0,即播放列表的第一首音乐。 -
将下一首音乐的路径赋给 Windows Media Player 控件
axWindowsMediaPlayer1的URL属性,以播放该音乐。 -
调用
musicplay方法,将下一首音乐的路径作为参数传递给它,以实现音乐的播放功能。 -
更新标签
label1,将当前播放的音乐文件名(不包括扩展名)显示在标签上。 -
将列表框中的选中项设置为下一首音乐的索引,以确保列表框中显示正确的当前播放音乐。
这样,用户点击按钮3时,就可以顺序播放列表中的音乐文件,并在界面上显示当前播放的音乐文件名。
private void button5_Click(object sender, EventArgs e)
{
OpenFileDialog openFiledialog = new OpenFileDialog();
openFiledialog.Filter = "打开音频|*.ogg";
string oggFilePath = "";
if (openFiledialog.ShowDialog() == DialogResult.OK)
{
oggFilePath = openFiledialog.FileName;
listBox1.Items.Add(oggFilePath); // 将选择的ogg文件路径添加到列表框
localmusicList.Add(oggFilePath); // 将选择的ogg文件路径添加到列表
Task.Run(() =>
{
using (var vorbis = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbis);
outputDevice.Play();
// 等待播放结束,而不是使用Thread.Sleep进行轮询
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(100); // 减少轮询频率以降低CPU使用率
}
}
}
});
}
}
这个方法是当用户点击按钮5时触发的事件处理方法。它的功能是打开一个文件选择对话框,让用户选择一个 .ogg 格式的音频文件,并播放该音频文件。
具体的实现步骤如下:
-
创建一个
OpenFileDialog对象openFiledialog,用于打开文件选择对话框。 -
设置文件选择对话框的过滤器,只显示
.ogg格式的音频文件。 -
声明一个字符串变量
oggFilePath,用于存储选中的.ogg文件的路径。 -
使用
ShowDialog()方法显示文件选择对话框,并等待用户选择文件。如果用户点击了对话框中的 "确定" 按钮,则ShowDialog()方法返回DialogResult.OK,执行以下操作;否则,方法直接返回,不执行后续操作。 -
获取用户选择的
.ogg文件的完整路径,并将其赋值给oggFilePath变量。 -
将选中的
.ogg文件路径添加到列表框listBox1中,以便用户可以在列表框中看到选中的音频文件。 -
将选中的
.ogg文件路径添加到localmusicList列表中,以便在后续的播放列表中使用。 -
使用
Task.Run()创建一个异步任务,用于在后台播放选中的.ogg音频文件。在异步任务中,首先使用VorbisWaveReader类读取选中的.ogg文件,然后使用WaveOutEvent类初始化音频输出设备,并开始播放音频文件。 -
使用
while循环等待音频播放结束,而不是使用Thread.Sleep进行轮询。在循环中,不断检查音频输出设备的播放状态,直到播放状态变为非播放状态时退出循环。
总的来说,这个方法实现了打开文件选择对话框,选择并播放 .ogg 格式的音频文件,并将选中的文件路径添加到列表框和播放列表中的功能
完整代码
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using NVorbis.Contracts;
namespace 音乐播放
{
public partial class Form1 : Form
{
string[] files;
List<string> localmusicList = new List<string> { };
public Form1()
{
InitializeComponent();
}
private void musicplay(string filename)
{
axWindowsMediaPlayer1.URL = filename;
string extention = Path.GetExtension(filename);
if (extention == ".ogg")
{
Console.WriteLine("这是ogg文件");
listBox1.Items.Add(filename); // 将选中的ogg文件路径添加到列表框
localmusicList.Add(filename);
}
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
}
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[] arry = files;
foreach (string x in arry)
{
listBox1.Items.Add(x);
localmusicList.Add(x);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (localmusicList.Count > 0)
{
int selectedIndex = listBox1.SelectedIndex;
if (selectedIndex >= 0)
{
string selectedFile = localmusicList[selectedIndex];
if (!selectedFile.EndsWith(".ogg"))
{
axWindowsMediaPlayer1.URL = selectedFile;
musicplay(axWindowsMediaPlayer1.URL);
label1.Text = Path.GetFileNameWithoutExtension(selectedFile);
}
}
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}
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 button5_Click(object sender, EventArgs e)
{
OpenFileDialog openFiledialog = new OpenFileDialog();
openFiledialog.Filter = "打开音频|*.ogg";
string oggFilePath = "";
if (openFiledialog.ShowDialog() == DialogResult.OK)
{
oggFilePath = openFiledialog.FileName;
listBox1.Items.Add(oggFilePath); // 将选择的ogg文件路径添加到列表框
localmusicList.Add(oggFilePath); // 将选择的ogg文件路径添加到列表
Task.Run(() =>
{
using (var vorbis = new VorbisWaveReader(oggFilePath))
{
using (var outputDevice = new WaveOutEvent())
{
outputDevice.Init(vorbis);
outputDevice.Play();
// 等待播放结束,而不是使用Thread.Sleep进行轮询
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(100); // 减少轮询频率以降低CPU使用率
}
}
}
});
}
}
}
}
四,代码分析
这段代码实现了一个简单的音乐播放器应用程序。其中的难点在于以下几个方面:
-
多线程处理音频播放: 在按钮5的点击事件处理方法中,使用了
Task.Run()方法创建了一个异步任务,用于播放.ogg格式的音频文件。这涉及到多线程编程,需要确保在异步任务中正确地初始化音频播放设备,并且需要处理音频播放的状态。 -
文件格式处理: 在
musicplay方法中,针对不同的音频文件格式(如.ogg)做了不同的处理。这需要对不同的音频文件格式有一定的了解,以便正确地调用相应的播放方法或处理方法。 -
用户界面交互: 对话框的使用、列表框的更新、滑动条的操作等涉及用户界面的交互操作,需要确保界面的响应性和用户体验。
-
异常处理: 对异常情况的处理,如文件打开失败、音频播放失败等,需要进行合适的处理以保证程序的稳定性和可靠性。
-
异步编程理解: 对于
Task.Run()方法创建的异步任务,以及异步播放音频时的状态处理,可能需要对异步编程有一定的理解。 -
-
gitee的clone地址:

1589

被折叠的 条评论
为什么被折叠?



