用c#实现简单音乐播放器

一、功能需求

  1. 播放MP3文件:可播放MP3文件
  2. 播放OGG文件:可播放OGG文件
  3. 用户界面:一个简单的窗口,包含播放和暂停按钮及文件选择功能
  4. 异常处理:程序能处理可能处理可能出现的异常,如文件不存在、文件读取错误等
  5. 兼容性:确保代码能在多个c#版本上运行

二、设计思路分析

  • 架构选择

    考虑到需求中的界面友好和跨版本兼容性,我们可以选择选择Windows Forms作为开发平台,Windows Forms提供了一个简单而强大的方法来创建桌面应用程序,并且与C#高度兼容,在开发过程,我们选择.NETFramework 4.8.0进行程序设计。

  • 设计思路

    1. 界面设计: 使用Windows Forms工具箱中的控件如按钮、标签和文件对话框构建用户界面。
    2. 功能编码: 使用OpenFileDialog允许用户选择音频文件。 根据文件扩展名调用相应的播放器对象进行播放。 播放控制,包括开始、暂停和停止。
    3. 异常处理: 捕获并响应各种可能的运行时错误,如文件读取失败、文件格式不支持等,为用户提供清晰的错误信息。
  • 难点分析

    1. 文件格式支持: 处理多种音频格式(MP3,OGG等)要求使用不同的库,这可能导致代码复杂度增加。
    2. 异常处理: 音频文件的播放中可能遇到多种异常情况,如文件损坏、编解码器不支持等。

三、窗体设计

按照需求设计窗体,并进行一定的美化

  • Label:展示当前播放的歌曲
  • Listbox:展示歌曲列表
  • AxWindowsMediaPlayer:播放常规音乐
  • Button:选择歌曲文件、停止播放、下一曲
  • TraceBarl:用于音量控制

四、代码实现

  1. 头文件引入

    c# 复制代码
    using AxWMPLib;
    using NAudio.Vorbis;
    using NAudio.Wave;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection.Emit;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using static System.Windows.Forms.VisualStyles.VisualStyleElement;
  2. 类成员变量定义

    c# 复制代码
    List<string> localmusiclist = new List<string> { };
    private WaveOutEvent waveOut = new WaveOutEvent();
    private VorbisWaveReader currentVorbisReader;

    在类中,localmusiclist在音乐播放时用来追踪和管理用户加载的音乐文件集合,waveOut用于播放ogg文件,currentVorbisReader为当前播放ogg文件的状态

  3. 按钮控件

    • 歌曲文件选择

      c# 复制代码
      private void button1_Click(object sender, EventArgs e)
      {
          string[] files = { };
      
      
          openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
          //同时打开多个文件
          openFileDialog1.Multiselect = true;
      
          if (openFileDialog1.ShowDialog() == DialogResult.OK)
          {
              //清空原有列表
              listBox1.Items.Clear();
              localmusiclist.Clear();
      
              if (files != null)
              {
                  Array.Clear(files, 0, files.Length);
              }
      
              files = openFileDialog1.FileNames;
              string[] array = files;
              foreach (string file in array)
              {
                  string extension = Path.GetExtension(file).ToLower();
                  if (extension == ".mp3" || extension == ".flac" || extension == ".wav" || extension == ".ogg")
                  {
                      listBox1.Items.Add(file);
                      localmusiclist.Add(file);
                  }
                  else
                  {
                      MessageBox.Show($"不支持的文件格式:{file}", "文件错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                  }
              }
          }
      }

      这里我们通过Filter方法来限制用户选择的音乐文件,防止后续播放功能报错,并在选择文件之后将选择的音乐列表放置到ListBox中,同时逻辑判断删除已有的列表,并将歌曲播放列表放入localmusiclist中,再通过openFileDialog来判断文件是否读取成功。

    • 暂停播放按钮

      c# 复制代码
      private void button2_Click(object sender, EventArgs e)
      {
          if (waveOut.PlaybackState == PlaybackState.Playing)
          {
              waveOut.Pause(); // 暂停播放OGG
          }
      
          axWindowsMediaPlayer1.Ctlcontrols.stop(); // 停止其他格式的播放
      }

      if条件判断,如果在播放ogg就停止播放ogg,如果播放的是普通文件就停止普通播放器就行

    • 播放下一首按钮

      c# 复制代码
      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;
         }
      
      }

      判断Count是否大于0,以此来判断是否能执行下一首播放的逻辑,如果index大于localmusiclist的长度,就将index置0,以此来循环播放列表,在播放时调用musicplay函数来播放音乐,同时用Label来显示当前播放音乐的信息。

  4. 音乐选择控件

    c# 复制代码
    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]);
        }
    }

    当listBox1中的音乐选择发生改变时,会触发该事件函数,若localmusiclist.Count > 0,就用musicplay播放选择中的音乐,并更新label1的值

  5. 音乐播放函数

    c# 复制代码
    private void musicplay(string filename)
    {
        string extension = Path.GetExtension(filename).ToLower();
        try
        {
            if (extension == ".ogg")
            {
                if (currentVorbisReader != null)
                {
                    // 确保先停止当前播放再释放资源
                    if (waveOut.PlaybackState != PlaybackState.Stopped)
                    {
                        waveOut.Stop();
                    }
                    currentVorbisReader.Dispose();
                }
    
                currentVorbisReader = new VorbisWaveReader(filename);
                waveOut.Init(currentVorbisReader);
                waveOut.Play();
            }
            else
            {
                if (currentVorbisReader != null)
                {
                    // 确保先停止当前播放再释放资源
                    if (waveOut.PlaybackState != PlaybackState.Stopped)
                    {
                        waveOut.Stop();
                    }
                    currentVorbisReader.Dispose();
                }
                axWindowsMediaPlayer1.URL = filename;
                axWindowsMediaPlayer1.Ctlcontrols.play();
            }
        }
        catch (Exception ex) 
        {
            MessageBox.Show($"无法播放文件:{filename}\n\n错误信息:{ex.Message}", "播放错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    首先获取文件后缀名,然后判断后缀名是否为ogg,若为普通文件,则用c#自带的内置播放器即可完成播放,否则则需要下载安装NAudio的第三方库中的Vorbis和Wave类来实现播放音乐,在播放时要检查是否正在播放ogg音乐,若是则停止播放当前音乐再播放其他音乐,同时这里使用try捕获播放错误来防止读取文件产生的错误导致程序卡死。

  6. 音量控制组件

    c# 复制代码
    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
    }

    这里将axWindowsMediaPlayer1的按钮联动到traceBar1上,实现用traceBar1来控制音量。

五、完整代码

ini 复制代码
```c#
using AxWMPLib;
using NAudio.Vorbis;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace _4._23上课code
{
    public partial class Form1 : Form
    {
        List<string> localmusiclist = new List<string> { };
        private WaveOutEvent waveOut = new WaveOutEvent();
        private VorbisWaveReader currentVorbisReader;

        public Form1()
        {
            InitializeComponent();
        }

        private void musicplay(string filename)
        {
            string extension = Path.GetExtension(filename).ToLower();
            try
            {
                if (extension == ".ogg")
                {
                    if (currentVorbisReader != null)
                    {
                        // 确保先停止当前播放再释放资源
                        if (waveOut.PlaybackState != PlaybackState.Stopped)
                        {
                            waveOut.Stop();
                        }
                        currentVorbisReader.Dispose();
                    }

                    currentVorbisReader = new VorbisWaveReader(filename);
                    waveOut.Init(currentVorbisReader);
                    waveOut.Play();
                }
                else
                {
                    if (currentVorbisReader != null)
                    {
                        // 确保先停止当前播放再释放资源
                        if (waveOut.PlaybackState != PlaybackState.Stopped)
                        {
                            waveOut.Stop();
                        }
                        currentVorbisReader.Dispose();
                    }
                    axWindowsMediaPlayer1.URL = filename;
                    axWindowsMediaPlayer1.Ctlcontrols.play();
                }
            }
            catch (Exception ex) 
            {
                MessageBox.Show($"无法播放文件:{filename}\n\n错误信息:{ex.Message}", "播放错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private void axWindowsMediaPlayer1_Enter(object sender, EventArgs e)
        {

        }


        private void button1_Click(object sender, EventArgs e)
        {
            string[] files = { };


            openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
            //同时打开多个文件
            openFileDialog1.Multiselect = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                //清空原有列表
                listBox1.Items.Clear();
                localmusiclist.Clear();

                if (files != null)
                {
                    Array.Clear(files, 0, files.Length);
                }

                files = openFileDialog1.FileNames;
                string[] array = files;
                foreach (string file in array)
                {
                    string extension = Path.GetExtension(file).ToLower();
                    if (extension == ".mp3" || extension == ".flac" || extension == ".wav" || extension == ".ogg")
                    {
                        listBox1.Items.Add(file);
                        localmusiclist.Add(file);
                    }
                    else
                    {
                        MessageBox.Show($"不支持的文件格式:{file}", "文件错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
            }
        }


        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 trackBar1_Scroll(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (waveOut.PlaybackState == PlaybackState.Playing)
            {
                waveOut.Pause(); // 暂停播放OGG
            }

            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 Form1_Load(object sender, EventArgs e)
        {

        }

    }
}
```

六、总结&改进思路

通过本次作业,我得以运用第三方库来辅助我的程序设计,并学习了更复杂的控件使用以及控件之间的协作。这让我对C#的控件使用有了更深入的理解。 尽管当前程序能够播放多种音乐文件格式,但它无法解析最新的音乐文件格式,比如ape和aac文件。 此外,程序还缺少一些高级音频功能的设置,比如音频效果处理(如均衡器、声音增强等),以及支持音频流的直接下载和播放。

相关推荐
关键帧Keyframe5 天前
iOS 不用 libyuv 也能高效实现 RGB/YUV 数据转换丨音视频工业实战
音视频开发·视频编码·客户端
关键帧Keyframe6 天前
音视频面试题集锦第 7 期
音视频开发·视频编码·客户端
关键帧Keyframe6 天前
音视频面试题集锦第 8 期
ios·音视频开发·客户端
瑞英24 天前
Android热修
客户端
__water1 个月前
『网络游戏』服务器向客户端分发消息【21】
服务器·客户端
网络研究院1 个月前
Node.js 中的 WebSocket 底层实现
服务器·websocket·网络协议·node.js·客户端·底层·机制
大雪山掘金1 个月前
开屏广告框架的设计
ios·客户端
jyl_sh1 个月前
CMake教程:第一步:一个基本的起点
开发语言·c++·客户端·cmake
jyl_sh2 个月前
Windows Ribbon框架
windows·ribbon·c#·客户端
jyl_sh2 个月前
Ribbon布局和尺寸调整
ribbon·c#·wpf·客户端