一、代码功能
1.程序应能够读取MP3文件,并播放其中的音频。
2.程序应能够播放ogg文件。
3. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。并且程序应具有良好的用户界面,方便用户进行操作。
二、代码功能
程序应具有良好的兼容性,能在不同版本的C#中正常运行,并使用WindowsMediaPlayer以及Nuget程序包中的Naudi.Vorbis控件。
三、代码思路
利用vs2022实现简单音乐器播放时,需要先创建一个新的项目,项目模板为C#环境下的Windows窗体应用(.NET Framework)。当项目创建成功后,可以得到一个空的窗体。
在进行代码编写之前,需要对窗体进行操作,操作步骤如下:
1、播放音乐需要使用到axWindowsMediaPlayer的COM组件,因此需要在左栏工具箱中找到Windows Media Player控件拖入窗体中。
2、从左栏的工具箱中找到ListBox控件并拖入窗体中,该控件主要显示歌曲列表。
如果对播放器有美观需求,则可选中该控件左击选择属性,可对该控件进行颜色字体等选择。
3、拖入四个Button控件,为后续播放器的四个功能选择歌曲,暂停,下一首和播放.ogg文件作准备,同样可以在该控件的属性中重命名控件。
4、拖入TrackBar控件,该控件用于改变播放音量的大小。
5、拖入Label控件,该控件用于显示当前播放歌曲的名称信息。
窗体设计如下图
代码实现
先定义一个名为Form1的Windows Forms类,该类继承自Form。构造函数中调用了InitializeComponent()方法,该方法由Visual Studio自动生成,用于初始化窗体上的控件。
public Form1()
{
InitializeComponent();
}
双击窗体控件可跳转到对应的代码设计。
这是一个事件处理方法,当axWindowsMediaPlayer1控件获得焦点时触发。但在这段代码中,方法体是空的,所以没有执行任何操作。
private void axWindowsMediaPlayer1_Enter(object sender, EventArgs e)
{
}
写一个方法musicplay用于播放音频文件。
private void musicplay(string filename)
{
axWindowsMediaPlayer1.URL = filename;
string extension = Path.GetExtension(filename);
if (extension == ".ogg")
{
Console.WriteLine("这是ogg文件。");
}
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
}
写一个方法将选择的音乐添加,当用户在openFileDialog1中选择文件并单击“确定”时,此方法应被触发。
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
定义了两个成员变量,一个字符串数组files和一个字符串列表localmusiclist。
使用button1_Click方法处理按钮的点击事件。当点击按钮时,它会显示一个文件对话框,让用户选择音频文件。当用户选择了一些文件后,则这些文件将被添加到files数组和localmusiclist列表中,并在listBox1控件中显示。
string[] files;
List<string> localmusiclist = new List<string> { };
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 label1_Click(object sender, EventArgs e)
{
}
滑动条控件,用于调整音量的大小,设置axWindowsMediaPlayer1的音量为trackBar1的当前值
,并且在属性中将其默认值调整为20。
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;
}
else { }
axWindowsMediaPlayer1.URL = localmusiclist[index];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
listBox1.SelectedIndex = index;
}
}
按钮控件,用于播放.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);
}
}
}
}
}
四、代码难点解析
在musicplay方法中,它设置axWindowsMediaPlayer1的URL属性为给定的文件名。然后,它检查文件的扩展名。如果扩展名是.ogg,它只会在控制台输出一条消息。对于MP3扩展名,它调用play()方法来播放音频。难点在于虽然这个方法处理了.ogg文件,但它并没有实际播放它们,只是输出了消息。因此需要使用NAudio或其他库来支持播放.ogg文件。
在按钮控件中进行播放.ogg的实现,创建一个OpenFileDialog
对象openFileDialog
,用于让用户从文件系统中选择一个文件。设置openFileDialog
的Filter
属性,仅允许用户选择以.ogg
为扩展名的文件。使用ShowDialog()方法显示文件选择对话框。如果用户点击了“确定”按钮(DialogResult.OK),则获取用户选择的文件的完整路径,并将其存储在oggFilePath字符串变量中。使用using语句块创建一个VorbisWaveReader对象VorbisReader。这个对象用于读Ogg Vorbis格式的音频数据。在这个using语句块内部,又使用using语句块创建了一个WaveOutEvent对象outputDevice。WaveOutEvent是NAudio库中的一个类,用于通过系统的音频输出设备播放音频。
调用outputDevice.Init(VorbisReader)初始化输出设备,使其准备播放从VorbisReader读取的音频数据。调用outputDevice.Play()开始播放音频。使用一个while循环和Thread.Sleep(1000)来等待音频播放完成。
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);
}
}
}
}
}
在设计按钮控件下一首时,为了能够时音乐能够循环切换axWindowsMediaPlayer1到下一首音乐,需要获取当前选中项的下一个索引。如果下一个索引超出了localmusiclist的范围,则重置为0(即第一首音乐)。否则,设置axWindowsMediaPlayer1的URL为下一首音乐,并更新相关UI元素。
private void button3_Click(object sender, EventArgs e)
{
if (localmusiclist.Count > 0)
{
int index = listBox1.SelectedIndex + 1;
if (index >= localmusiclist.Count())
{
index = 0;
}
else { }
axWindowsMediaPlayer1.URL = localmusiclist[index];
musicplay(axWindowsMediaPlayer1.URL);
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
listBox1.SelectedIndex = index;
}
}
五、代码实现
using NAudio;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Un4seen.Bass;
using NAudio.Vorbis;
namespace Windowsmusic2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void axWindowsMediaPlayer1_Enter(object sender, EventArgs e)
{
}
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 openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
string[] files;
List<string> localmusiclist = new List<string> { };
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 label1_Click(object sender, EventArgs e)
{
}
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;
}
else { }
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();
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);
}
}
}
}
}
}
}