目录
一、课程设计内容:
根据老师的要求:选择课程项目代码中的某一项(文件并发下载、音乐播放器、百度ai人脸识别)进行分析与设计。
具体步骤:先分析项目的功能需求,然后再做详细的代码设计。
这三个项目中我最感兴趣的当然是音乐播放器了,毕竟我平时没事就会戴上耳机听歌,对于音乐播放器的设计与实现自然是更有兴趣的啦!那我们就从这个项目开始分析和设计吧。
二、总体设计概述:
由于这是Windows课程的最后一次设计,所以我们应该尽可能地将老师课上讲的知识运用到代码中,所以需要至少实现音乐播放器的基本功能,包括各种类型音频文件的播放,对播放的歌曲进行控制(点击播放、暂停播放、播放下一曲等),对音频文件播放的音量大小进行实时控制等,如果大家感兴趣的话还可以尝试实现点击收藏歌曲、清除播放列表等相关的功能,这次又增加了一个在线播放音乐的功能,大家看过我上一篇博客的就直接跳过基本功能,看这个新增的功能即可。
不过,这一次因为最近临近期末考试,小编实在没时间实现这些额外的功能需求了,就先用课上学到的知识和老师讲的例子来实现基本的各类格式的音频文件的播放功能和网络请求相关的在线播放音乐的功能,暂且把那些丰富的额外锦上添花的功能放到期末考试结束吧,毕竟我也得抓紧时间复习考试了,不然要挂了就玩完了
三、功能需求:
就像上面的概述所说,这次我们暂且先设计这样一个音乐播放器:
- 可以实现按音频文件的不同格式实现播放功能,并且在点击从本地选中的音频文件之后,能够在label组件中同步更新,展示出所选中歌曲的名字(不带音频格式的后缀)。
- 播放时也可以通过点击按钮实现暂停播放,这是播放除ogg格式音频文件的基本实现的功能。
- 对于ogg格式的音频文件我们单独为其添加需要实现的功能,主要有基本的加入播放列表的功能、点击播放的功能、暂停播放的功能等。
- 当选中的音乐播放时,可以通过专门的控件的滑动控制,实现播放音量大小的实时更新。
- 当点击在线播放按钮时,可以在后台播放指定URL地址的歌曲。
好了,功能需求我们已经非常清晰地了解之后,就开始设计具体的代码实现吧。
四、各个子功能设计的分析:
- 从本地选中歌曲添加到播放列表中:设置
openFileDialog1
的Filter
属性,使得用户只能选择.mp3
、.flac
和.wav
类型的文件;设置Multiselect
属性为true
,用户可以在对话框中一次选择多个文件,将每个文件的路径添加到ListBox
和localmusiclist
中。 - 当点击list中的歌曲时播放并显示歌名:通过
listBox1.SelectedIndex
获取ListBox
控件中当前选中项的索引。然后,它使用这个索引从localmusiclist
列表中检索对应的音乐文件路径,并将这个路径设置为axWindowsMediaPlayer1
的URL
属性。这样,Windows Media Player控件就知道要播放哪个音乐文件了。 - 调用自己写的音乐播放函数实现播放列表播放:主要注意同步实现label标签显示当前播放的音频的名称,对用户的使用体验更友好
- 控制音量:这个功能直接拖一个控制音量的组件即可
- 停止播放:调用组件的stop方法即可
- 播放下一曲:主要注意判断当前播放列表中是否还有可以播放的音频文件
- 播放ogg音频文件:ogg文件比较特殊,需要用到VorbisWaveReader和WaveOutEvent来读取ogg格式的音频,并通过调用相关方法实现播放ogg文件的功能
- 设计函数用来实现本地音乐的播放:这个函数主要用来判别是否是ogg之外格式的音频文件,这样就可以直接调用控件播放即可
- 点击按钮在线播放歌曲:将指定歌曲的URL地址传给player,然后调用axWindowsMediaPlayer2.Ctlcontrols.play(),即可实现在线播放音乐
五、 具体代码实现:
(1)从本地选中歌曲添加到播放列表中:
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) 当点击list中的歌曲时播放并显示歌名:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)//当点击list中的歌曲时播放并显示歌名
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL); //调用自己写的音乐播放函数实现播放列表播放
label1.Text =Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
(3) 调用自己写的音乐播放函数实现播放列表播放:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)//当点击list中的歌曲时播放并显示歌名
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL); //调用自己写的音乐播放函数实现播放列表播放
label1.Text =Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
(4)控制音量:
private void trackBar1_Scroll(object sender, EventArgs e) //控制音量
{
axWindowsMediaPlayer1.settings.volume=trackBar1.Value;
}
(5)停止播放:
private void button2_Click(object sender, EventArgs e) //停止播放
{
axWindowsMediaPlayer1.Ctlcontrols.stop();
}
(6) 播放下一曲:
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;
}
}
(7) 播放ogg音频文件:
private void button4_Click(object sender, EventArgs e)//播放ogg音频文件
{
string oggFilePath="";
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "播放音频|*.ogg";
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);
}
}
}
}
(8) 设计函数用来实现本地音乐的播放:
private void musicplay(string filename) //该函数用来实现本地音乐的播放
{
axWindowsMediaPlayer1.URL= filename;
string extension=Path.GetExtension(filename);
if (extension == ".ogg") { Console.WriteLine("这是ogg文件。"); }
else { axWindowsMediaPlayer1.Ctlcontrols.play();}
}
(9) 点击按钮在线播放歌曲:
private void button5_Click(object sender, EventArgs e) //在线播放指定URL资源的歌曲
{
string url = "https://webfs.hw.kugou.com/202406182126/9a7ab8f412961bd9e9159410b9d05152/v2/052c7104ae6b25e0cde8a018be473f3d/G204/M06/0F/03/bIcBAF5MnwqAA4sAAFY5o-3769U345.mp3";//张杰的《哭砂》
axWindowsMediaPlayer2.URL = url;
axWindowsMediaPlayer2.Ctlcontrols.play();
}
整体代码设计汇总如下:
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 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)//当点击list中的歌曲时播放并显示歌名
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL); //调用自己写的音乐播放函数实现播放列表播放
label1.Text =Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
private void trackBar1_Scroll(object sender, EventArgs e) //控制音量
{
axWindowsMediaPlayer1.settings.volume=trackBar1.Value;
}
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)//播放ogg音频文件
{
string oggFilePath="";
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "播放音频|*.ogg";
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);
}
}
}
}
private void button5_Click(object sender, EventArgs e) //在线播放指定URL资源的歌曲
{
string url = "https://webfs.hw.kugou.com/202406182126/9a7ab8f412961bd9e9159410b9d05152/v2/052c7104ae6b25e0cde8a018be473f3d/G204/M06/0F/03/bIcBAF5MnwqAA4sAAFY5o-3769U345.mp3";
axWindowsMediaPlayer2.URL = url;
axWindowsMediaPlayer2.Ctlcontrols.play();
}
}
}
六、完整代码如下:
using NAudio.Wave;
using NAudio.Vorbis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace WindowsMusic2
{
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 extension=Path.GetExtension(filename);
if (extension == ".ogg") { Console.WriteLine("这是ogg文件。"); }
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[] array = files;
foreach (string x in array)
{
listBox1.Items.Add(x);
localmusiclist.Add(x);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)//当点击list中的歌曲时播放并显示歌名
{
if (localmusiclist.Count > 0)
{
axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
musicplay(axWindowsMediaPlayer1.URL); //调用自己写的音乐播放函数实现播放列表播放
label1.Text =Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
}
}
private void trackBar1_Scroll(object sender, EventArgs e) //控制音量
{
axWindowsMediaPlayer1.settings.volume=trackBar1.Value;
}
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)//播放ogg音频文件
{
string oggFilePath="";
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "播放音频|*.ogg";
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);
}
}
}
}
private void button5_Click(object sender, EventArgs e) //在线播放指定URL资源的歌曲
{
string url = "https://webfs.hw.kugou.com/202406182126/9a7ab8f412961bd9e9159410b9d05152/v2/052c7104ae6b25e0cde8a018be473f3d/G204/M06/0F/03/bIcBAF5MnwqAA4sAAFY5o-3769U345.mp3";//张杰的哭砂》
axWindowsMediaPlayer2.URL = url;
axWindowsMediaPlayer2.Ctlcontrols.play();
}
}
}
七、代码中的一些注意点:
1、使用如NAudio、Bass.Net或CSCore等成熟的音频处理库。这些库提供了对音频文件解码、播放、控制(如暂停、停止、音量控制等)的强大支持。
2、实现适当的错误处理机制来捕获和处理音频播放过程中可能出现的异常,如文件不存在、文件损坏或解码错误,向用户提供友好的错误消息。
3、提供直观的UI控件,如播放/暂停按钮、停止按钮、音量滑块、播放进度条等。响应式UI,确保按钮和其他控件在点击时即时响应,避免延迟。
4、在播放ogg格式的音频文件时要注意,在Windows提供的包中有可以实现外部设备播放的功能,如这次实验中我们选择使用的就是其中的NAudio,通过这个包,我们可以调用其中的函数方法去实现具体的功能。
5、在线播放音乐必须要获取到歌曲的URL地址,这就有需要uu们在各大音乐网站上爬取指定歌曲的资源地址啦。
点击选择播放歌曲后运行界面如下:
八、总结:
总体来看,此次设计中,我们主要是运用了Windows窗体设计中的一些控件和相关的知识,实现了项目中音乐播放器基本的功能,这其中包括了选中本地文件夹中指定格式的音频文件,选中播放列表中的歌曲实现播放功能并在label标签中同步更新内容,显示当前播放的音乐的名字;对于ogg格式的音频文件我们做了单独的处理,进行了本地ogg格式的音频文件的选择,播放ogg格式的音频;此外,还实现了对音频播放音量大小的实时控制。最后,在这些基本功能实现的基础上,通过将指定歌曲的URL地址传给winform中的媒体播放控件axWindowsMediaPlayer,实现了在线播放,从而增加了在线播放歌曲的功能。
但在具体操作时还是遇到了一些问题,比如,在实现ogg格式的音频文件的播放时,我以为还按照播放MP3格式一样,调用设计好的音乐播放函数实现播放,只用把音频文件格式限定为ogg为扩展即可,事实上,这样是会出错的。当我这样写时虽然不报错,也没有编译问题,但就是运行时出错,根本无法按要求播放ogg格式的音频。后来,在网上搜索了一些方法,照着例子改了代码的关键点之后,终于运行成功,实现了ogg格式的音频播放功能。这也充分说明了写代码不能想当然,还是要实现了解相关背景和约束后再来设计实现才更有保证。不过,总结下来,还是要多学会自己亲自敲一遍才能清楚自己哪些地方的知识点还没有掌握,或者哪些知识点还不是很理解,对于开发者而言,上手实践当然最重要了,所以,就像我们老师说的,遇到一个在理论知识层面上看不懂的知识点时,就把它在代码中手写一遍,从代码中体会这个知识点的含义和应用。
好啦,总结完毕,希望这篇文章能帮到小伙伴们,与同志们共勉!