c#实现音乐的“vip播放功能”

文章目录

  • 前言
  • 1. c#窗体
  • [2. 功能](#2. 功能)
  • [3. 具体实现](#3. 具体实现)
    • [3.1 添加文件](#3.1 添加文件)
    • [3.2 音乐播放](#3.2 音乐播放)
    • [3.3 其他功能](#3.3 其他功能)
  • [4. 整体代码和窗口](#4. 整体代码和窗口)
  • [5. 依赖的第三方库](#5. 依赖的第三方库)

前言

最近在QQ音乐里重温周杰伦的歌,觉得好听到耳朵怀孕,兴起想要下载下来反复听,发现QQ音乐VIP歌曲下载下来的格式居然不是MP3格式,是ogg。OMG!ogg是什么鬼,都不能直接听,顿感失落,思来想去决定自己实现一个QQ音乐的播放功能,搞定这ogg

1. c#窗体

C#窗体是事件驱动的,在窗体中,可以通过定义和处理特定事件来触发相应的操作。例如,当用户点击按钮时,可以在对应的按钮的Click事件处理程序中执行相应的代码。这意味着窗体的行为是由事件的发生而触发的,而不是通过连续的轮询或主动调用来完成的。这种事件驱动的方式使得窗体在等待用户输入和响应用户操作时更加高效。
我们就选用c#窗体来做音乐播放器的界面。

2. 功能

  1. 程序应能够读取MP3文件,并播放其中的音频。

  2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。

  3. 程序应具有良好的用户界面,方便用户进行操作。

  4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
    此功能可以使用WindowsMediaPlayer控件

  5. 程序应能够播放ogg文件。

  6. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。

  7. 程序应具有良好的用户界面,方便用户进行操作。

  8. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
    此功能可以使用Nuget程序包中的Naudi.Vorbis控件

3. 具体实现

3.1 添加文件

音乐播放器少不了的就是音乐文件列表,在c#listBox控件便可以完成此工作,他能显示一行一行的文本信息,可以用来作为我们的音乐文件列表。

我们再添加button1控件,用于添加我们的音乐文件于列表中。

csharp 复制代码
private void button1_Click(object sender, EventArgs e)
{
    OpenFileDialog openFileDialog1 = new OpenFileDialog(); //这个是文件选择框的对象
    //筛选文件后缀
    openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
    //设置一次添加多个文件
    openFileDialog1.Multiselect = true;
    if(openFileDialog1.ShowDialog() == DialogResult.OK)  //这个会打开文件选择框
    {
        string[] files = openFileDialog1.FileNames;
        foreach(string x in files)
        {
            listBox1.Items.Add(x); //向listBox1控件里添加音乐文件名
            localmusiclist.Add(x); //localmusiclist,是一个全局的对象,用于存储已选音乐
        }
    }
}

3.2 音乐播放

Windows Media Player控件用于播放常见的音乐文件格式,如.mp3.wav.flac等等,所以我们添加它播放常见的音乐格式文件

但如果要播放.ogg格式音乐,那我们就需要引入第三方库了,分别是NAudioNAudio.vorbis

csharp 复制代码
private void musicplay(string filename)
{
    //获取filename的后缀名
    string extension = Path.GetExtension(filename).ToLower();
    //如果oggReader和outputDevice不为空,说明正在播放或播放过ogg文件,此时要再播放新选择的文件就要先释放旧的
    if (oggReader != null && outputDevice != null)
    {
        oggReader.Dispose();
        oggReader = null;
        outputDevice.Dispose(); 
        outputDevice = null;
    }
    axWindowsMediaPlayer1.Ctlcontrols.stop();
    try //捕获可能的错误
    {
        if (extension == ".ogg")
        {
            oggReader = new VorbisWaveReader(filename); //对ogg文件进行解析
            outputDevice = new WaveOutEvent();
            outputDevice.Init(oggReader); // 初始化解析后的ogg文件
            outputDevice.Play();
        }
        else
        {
            axWindowsMediaPlayer1.URL = filename;
            axWindowsMediaPlayer1.Ctlcontrols.play();
        }
    }
}

其中outputDeviceoggReader都要设置为全局的,因为如果是局部对象的话,出了作用域会自动被释放,导致音乐播放截然而止。所以我们将其设置为全局的,只有再次进行播放时才将他释放,再播放新选择的音乐。

此时窗口是这样的:

要想完成音乐播放,还需要最后一步,就是完善运行时 点击listBox1里的内容 就播放对应音乐的功能。

csharp 复制代码
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if(localmusiclist.Count > 0)
    {
        index = listBox1.SelectedIndex; //index为全局索引,用于标识正在播放哪个的音乐
        musicplay(localmusiclist[index]);
    }
}

至此,大功告成,我们已经完成了最重要的音乐播放,后续只需要完善其他功能即可

3.3 其他功能

label控件,用于显示正在播放的音乐的音乐名,添加此控件后,只需要在musicplay函数的最开始加上此代码即可:

csharp 复制代码
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);

停止播放

csharp 复制代码
private void button2_Click(object sender, EventArgs e)
{
    axWindowsMediaPlayer1.Ctlcontrols.stop();
    outputDevice.Stop();
}

下一曲

csharp 复制代码
private void button3_Click(object sender, EventArgs e)
{
    if(localmusiclist.Count > 0) 
    {
        index = (index+1)% localmusiclist.Count;
        musicplay(localmusiclist[index]);
    }
}

滑动音轨TrackBar控件

csharp 复制代码
private void trackBar1_Scroll(object sender, EventArgs e) //音轨控件
{
    axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
    outputDevice.Volume = trackBar1.Value;
}

4. 整体代码和窗口

csharp 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using System.Threading;

namespace music1
{
    public partial class Form1 : Form
    {
        VorbisWaveReader oggReader = null;  //定义此对象,用于解析.ogg文件格式
        WaveOutEvent outputDevice = null;  //定义此对象,用于播放.ogg音频
        List<string> localmusiclist  = new List<string>(); //添加的所有音频文件
        int index = -1; //当前播放的音频文件索引
        public Form1()
        {
            InitializeComponent();
        }

        private void musicplay(string filename)
        {
        	//修改label控件所显示的音乐文件名
            label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
            //获取filename的后缀名
            string extension = Path.GetExtension(filename).ToLower();
            //如果oggReader和outputDevice不为空,说明正在播放或播放过ogg文件,此时要再播放新选择的文件就要先释放旧的
            if (oggReader != null && outputDevice != null)
            {
                oggReader.Dispose();
                oggReader = null;
                outputDevice.Dispose(); 
                outputDevice = null;
            }
            axWindowsMediaPlayer1.Ctlcontrols.stop();
            try //捕获可能的错误
            {
                if (extension == ".ogg")
                {
                    oggReader = new VorbisWaveReader(filename); //对ogg文件进行解析
                    outputDevice = new WaveOutEvent();
                    outputDevice.Init(oggReader); // 初始化解析后的ogg文件
                    outputDevice.Play();
                }
                else
                {
                    axWindowsMediaPlayer1.URL = filename;
                    axWindowsMediaPlayer1.Ctlcontrols.play();
                }
            }
            catch (FileNotFoundException ex) //文件找不到的错误
            {
                MessageBox.Show("File not found: " + ex.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred: " + ex.Message);
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            //筛选文件后缀
            openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
            //设置一次添加多个文件
            openFileDialog1.Multiselect = true;
            if(openFileDialog1.ShowDialog() == DialogResult.OK)  
            {
                string[] files = openFileDialog1.FileNames;
                foreach(string x in files)
                {
                    listBox1.Items.Add(x); //向listBox1控件里添加音乐文件名
                    localmusiclist.Add(x); 
                }
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(localmusiclist.Count > 0)
            {
                index = listBox1.SelectedIndex;
                musicplay(localmusiclist[index]);
                label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
            }
        }
        private void trackBar1_Scroll(object sender, EventArgs e) //音轨控件
        {
            axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
            outputDevice.Volume = trackBar1.Value;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.Ctlcontrols.stop();
            outputDevice.Stop();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if(localmusiclist.Count > 0) 
            {
                index = (index+1)% localmusiclist.Count;
                musicplay(localmusiclist[index]);
            }
        }
    }
}

控件窗口

运行窗口

5. 依赖的第三方库


相关推荐
神奇夜光杯4 分钟前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue7 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
plmm烟酒僧8 分钟前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
测试界的酸菜鱼20 分钟前
Python 大数据展示屏实例
大数据·开发语言·python
晨曦_子画29 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
Black_Friend37 分钟前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
希言JY1 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
残月只会敲键盘1 小时前
php代码审计--常见函数整理
开发语言·php
xianwu5431 小时前
反向代理模块
linux·开发语言·网络·git
ktkiko111 小时前
Java中的远程方法调用——RPC详解
java·开发语言·rpc