使用 C# 开发的音乐播放器项目

前言

  在日常生活中,音乐是我们不可或缺的一部分。作为程序员,我们可以利用自己的编程技能来开发一个简单的音乐播放器。这不仅可以满足我们日常的娱乐需求,同时也可以提高我们的编程水平。在这篇博客中,我将带大家一起探索如何使用 C# 来开发一个基本的音乐播放器。



一、摘要

  音乐播放器是一个很常见的应用程序,本文将详细介绍如何使用 C# 和 Windows Forms 开发一个音乐播放器应用程序,支持本地音乐文件的播放、音量调节、播放控制、在线音乐播放及下载等功能。该项目中我使用 了NAudio 库来处理音频文件,HttpClient 来获取在线音乐。


二、项目概述

这个音乐播放器包含以下主要功能:
1.支持播放本地音乐文件(包括 MP3、FLAC、WAV 等格式)。
2.支持在线音乐播放,可以通过网易云音乐 API 获取音乐链接并播放。
3.支持音乐下载功能,可以下载网易云音乐的音乐文件到本地。
4.提供基本的音量控制功能。
5.支持切换音乐和停止播放。
接下来让我们一步步来实现这个音乐播放器。

三、项目结构

我将项目分为以下几个部分:

1、用户界面设计

  在该项目中,我定义了一个 Form1 类,这个类作为应用程序的主窗体。在这个类的构造函数 public Form1() 中,我调用了 InitializeComponent() 方法,这个方法会自动生成窗体的各种控件,如按钮、列表框等。

  在窗体上我添加了如下控件:

openFileDialog1: 用于选择本地音乐文件
listBox1: 用于显示选择的本地音乐文件列表
axWindowsMediaPlayer1: 用于播放音乐
trackBar1: 用于控制音量
button1: 用于选择本地音乐文件
button2: 用于停止播放
button3: 用于播放下一首音乐
button4: 用于播放 OGG 格式的音乐
textBoxDownloadURL: 用于输入要下载的歌曲 ID
buttonDownload: 用于下载网络音乐
textBoxOnlineURL: 用于输入要播放的网络音乐 ID
buttonPlayOnline: 用于播放网络音乐

  这些控件的具体作用和实现将在后面的章节中介绍。

2、本地音乐播放功能

  在 button1_Click 方法中,我实现了本地音乐文件的选择和加载。当用户点击 button1 时,会弹出一个 openFileDialog1 对话框,用户可以选择多个音乐文件。选择完文件后,会将选择的文件路径添加到 localmusiclist 列表中,并将文件名显示在 listBox1 中。当用户在 listBox1 中选择一个文件时,会触发 listBox1_SelectedIndexChanged 方法。在这个方法中,我获取了选中文件的路径,并调用 musicplay 方法来播放音乐。musicplay 方法首先设置 axWindowsMediaPlayer1 的 URL 属性为选中文件的路径,然后检查文件的扩展名是否为 .ogg。如果是 OGG 格式,我们会在控制台输出提示信息,否则直接调用 axWindowsMediaPlayer1.Ctlcontrols.play() 方法播放音乐。
  此外,我还实现了音量控制功能。当用户拖动 trackBar1 时,会触发 trackBar1_Scroll 方法,在这个方法中我将 axWindowsMediaPlayer1 的音量设置为 trackBar1 的值。我还实现了停止播放的功能。当用户点击 button2 时,会触发 button2_Click 方法,在这个方法中我调用 axWindowsMediaPlayer1.Ctlcontrols.stop() 方法来停止播放。
  最后,当用户点击 button3 时,会触发 button3_Click 方法,在这个方法中我实现了播放下一首音乐的功能。获取 localmusiclist 列表中下一个文件的路径,设置 axWindowsMediaPlayer1 的 URL 属性,并调用 musicplay 方法来播放音乐。同时,还更新了 listBox1 中选中的项目。

3、在线音乐播放功能

  在 buttonPlayOnline_Click 事件处理器中,我实现了从网易云音乐播放在线音乐的功能。
  首先,我定义了一个名为 GetMusicUrlFromNetease 的异步方法,该方法使用 HttpClient 向网易云音乐的 API 发送请求,并获取指定歌曲的 URL。然后,我在 PlayOnlineMusic 方法中使用这个 URL 来播放音乐。使用 MediaFoundationReader 类读取音乐数据,并通过 WaveOutEvent 类播放音乐。为了避免内存泄漏,我在播放完成后删除了临时文件。

4、在线音乐下载功能

  在 buttonDownload_Click 事件处理器中,我实现了从网易云音乐下载音乐的功能。
  首先,我使用 GetValidFileName 方法生成一个合法的文件名。然后,需要确保下载目录 (C:\Music) 存在,并使用 DownloadMusicFile 异步方法下载音乐文件。在 DownloadMusicFile 方法中,我再次使用 GetMusicUrlFromNetease 方法获取音乐的 URL,并使用 HttpClient 下载音乐文件。最后将文件保存到指定的路径。
通过这个应用程序,用户可以轻松地播放本地音乐文件,也可以从网易云音乐下载和播放在线音乐。该应用程序使用了多种 .NET 库和 API,展示了如何利用 C# 和 .NET Framework 开发一个功能丰富的音乐播放器应用程序。


三、环境配置

1.安装Visual Studio

(确保版本支持Windows Forms应用程序)。

2.创建一个新的Windows Forms应用程序项目。

3.通过NuGet包管理器安装NAudio库

(用于OGG文件播放)。
在这里插入图片描述在这里插入图片描述

四、具体的功能设计和实现

1、引入必要的命名空间

首先,我们需要引入一些必要的命名空间:

using System.Net.Http;
using NAudio.Wave;
using NAudio.Vorbis;
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 Un4seen.Bass;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;

2、初始化组件

Form1 类的构造函数中初始化组件:

namespace WindowsMusic2
{
    public partial class Form1 : Form
    {
        string[] files;
        List<string> localmusiclist = new List<string> { };

        public Form1()
        {
            InitializeComponent();
        }
    }
}

3、播放音乐文件

我们创建一个 musicplay 方法,用于播放指定的音乐文件:

private void musicplay(string filename) 
{
    axWindowsMediaPlayer1.URL = filename;
    string extension = Path.GetExtension(filename);

    if (extension == ".ogg")
    {
        Console.WriteLine("这是ogg文件。");
    }
    else
    {
        axWindowsMediaPlayer1.Ctlcontrols.play();
    }
}

4、选择并加载本地音乐文件

通过按钮 button1 的点击事件,用户可以选择并加载多个本地音乐文件:

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;
        foreach (string x in files)
        {
            listBox1.Items.Add(x);
            localmusiclist.Add(x);
        }
    }
}

5、选择播放列表中的音乐

通过列表框 listBox1 的选择事件,用户可以选择播放列表中的音乐进行播放:

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]);
    }
}

6、音量调节

通过滑动条 trackBar1 的滚动事件,用户可以调节音量:

private void trackBar1_Scroll(object sender, EventArgs e)
{
    axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}

7、停止播放

通过按钮 button2 的点击事件,用户可以停止播放当前音乐:

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

8、播放下一首音乐

通过按钮 button3 的点击事件,用户可以播放下一首音乐:

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;
    }
}

9、播放 OGG 文件

通过按钮 button4 的点击事件,用户可以选择并播放 OGG 文件:

private void button4_Click(object sender, EventArgs e)
{
    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);
            }
        }
    }
}

10、获取网易云音乐的 URL

通过 HttpClient 获取网易云音乐的 URL:

private async Task<string> GetMusicUrlFromNetease(string songId)
{
    string apiEndpoint = $"https://music.163.com/api/song/enhance/player/url?ids=[{songId}]&br=320000";
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Add("Referer", "https://music.163.com");
        var response = await httpClient.GetAsync(apiEndpoint);
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();
        var json = JObject.Parse(content);
        return json["data"][0]["url"].ToString();
    }
}

11、播放在线音乐

通过按钮的点击事件,用户可以播放在线音乐:

private async void PlayOnlineMusic(string songId)
{
    try
    {
        string url = await GetMusicUrlFromNetease(songId);
        if (!string.IsNullOrEmpty(url))
        {
            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
                response.EnsureSuccessStatusCode();

                using (var stream = await response.Content.ReadAsStreamAsync())
                {
                    var tempFilePath = Path.GetTempFileName();
                    using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
                    {
                        await stream.CopyToAsync(fileStream);
                    }

                    using (var mediaFoundationReader = new MediaFoundationReader(tempFilePath))
                    {
                        using (var outputDevice = new WaveOutEvent())
                        {
                            outputDevice.Init(mediaFoundationReader);
                            outputDevice.Play();

                            while (outputDevice.PlaybackState == PlaybackState.Playing)
                            {
                                await Task.Delay(1000);
                            }
                        }
                    }
                    File.Delete(tempFilePath);
                }
            }
        }
        else
        {
            MessageBox.Show("无法获取音乐 URL。");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("播放在线音乐时出错:" + ex.Message);
    }
}

12、下载在线音乐文件

通过按钮的点击事件,用户可以下载在线音乐文件:

private async void buttonDownload_Click(object sender, EventArgs e)
{
    string songId = textBoxDownloadURL.Text;
    string saveFileName = GetValidFileName(songId) + ".mp3";
    string savePath = Path.Combine(@"C:\Music\", saveFileName);

    await DownloadMusicFile(songId, savePath);
}
辅助方法:获取合法文件名
private string GetValidFileName(string fileName)
{
    foreach (char c in Path.GetInvalidFileNameChars())
    {
        fileName = fileName.Replace(c, '_');
    }
    return fileName;
}

private async Task DownloadMusicFile(string songId, string savePath)
{
    try
    {
        string url = await GetMusicUrlFromNetease(songId);
        if (!string.IsNullOrEmpty(url))
        {
            string directory = Path.GetDirectoryName(savePath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    await response.Content.CopyToAsync(fs);
                }

                MessageBox.Show("下载完成!");
            }
        }
        else
        {
            MessageBox.Show("无法获取音乐 URL。");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("下载音乐文件时出错:" + ex.Message);
    }
}


13、界面设计

通过设计器添加以下控件:

  • 一个 OpenFileDialog 控件,用于选择本地音乐文件。
  • 一个 ListBox 控件,用于显示播放列表。
  • 一个 TrackBar 控件,用于调节音量。
  • 若干按钮(Button)控件,用于播放、暂停、停止、下一曲等操作。
  • 一个 AxWindowsMediaPlayer 控件,用于播放音乐。
  • 两个文本框(TextBox)控件,用于输入在线音乐的歌曲 ID 和下载路径。
  • 若干标签(Label)控件,用于显示歌曲信息。

五、源代码和运行结果

using System.Net.Http;
using NAudio.Wave;
using NAudio.Vorbis;
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 Un4seen.Bass;
using System.Xml.Linq;
using Newtonsoft.Json.Linq;

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)
        {
            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)
        {
            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 async Task<string> GetMusicUrlFromNetease(string songId)
        {
            string apiEndpoint = $"https://music.163.com/api/song/enhance/player/url?ids=[{songId}]&br=320000";
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Add("Referer", "https://music.163.com");
                var response = await httpClient.GetAsync(apiEndpoint);
                response.EnsureSuccessStatusCode();
                var content = await response.Content.ReadAsStringAsync();
                var json = JObject.Parse(content);
                return json["data"][0]["url"].ToString();
            }
        }

        private async void PlayOnlineMusic(string songId)
        {
            try
            {
                string url = await GetMusicUrlFromNetease(songId);
                if (!string.IsNullOrEmpty(url))
                {
                    using (var httpClient = new HttpClient())
                    {
                        var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
                        response.EnsureSuccessStatusCode();

                        using (var stream = await response.Content.ReadAsStreamAsync())
                        {
                            var tempFilePath = Path.GetTempFileName();
                            using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
                            {
                                await stream.CopyToAsync(fileStream);
                            }

                            using (var mediaFoundationReader = new MediaFoundationReader(tempFilePath))
                            {
                                using (var outputDevice = new WaveOutEvent())
                                {
                                    outputDevice.Init(mediaFoundationReader);
                                    outputDevice.Play();

                                    // 等待播放完成
                                    while (outputDevice.PlaybackState == PlaybackState.Playing)
                                    {
                                        await Task.Delay(1000);
                                    }
                                }
                            }
                            File.Delete(tempFilePath); // 删除临时文件
                        }
                    }
                }
                else
                {
                    MessageBox.Show("无法获取音乐 URL。");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("播放在线音乐时出错:" + ex.Message);
            }
        }

        private string GetValidFileName(string fileName)
        {
            foreach (char c in Path.GetInvalidFileNameChars())
            {
                fileName = fileName.Replace(c, '_');
            }
            return fileName;
        }

        private async Task DownloadMusicFile(string songId, string savePath)
        {
            try
            {
                string url = await GetMusicUrlFromNetease(songId);
                if (!string.IsNullOrEmpty(url))
                {
                    // 确保目录存在
                    string directory = Path.GetDirectoryName(savePath);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    using (var httpClient = new HttpClient())
                    {
                        var response = await httpClient.GetAsync(url);
                        response.EnsureSuccessStatusCode();

                        using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            await response.Content.CopyToAsync(fs);
                        }

                        MessageBox.Show("下载完成!");
                    }
                }
                else
                {
                    MessageBox.Show("无法获取音乐 URL。");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("下载音乐文件时出错:" + ex.Message);
            }
        }

        private async void buttonDownload_Click(object sender, EventArgs e)
        {
            string songId = textBoxDownloadURL.Text; // 使用文本框来输入歌曲ID
            string saveFileName = GetValidFileName(songId) + ".mp3"; // 获取合法的文件名
            string savePath = Path.Combine(@"C:\Music\", saveFileName); // 下载保存路径

            await DownloadMusicFile(songId, savePath);
        }

        private void buttonPlayOnline_Click(object sender, EventArgs e)
        {
            string songId = textBoxOnlineURL.Text; // 使用文本框来输入歌曲ID
            PlayOnlineMusic(songId);
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void buttonDownload_Click_1(object sender, EventArgs e)
        {

        }

        private void buttonPlayOnline_Click_1(object sender, EventArgs e)
        {

        }

        private void textBoxDownloadURL_TextChanged(object sender, EventArgs e)
        {

        }

        private void label6_Click(object sender, EventArgs e)
        {

        }
    }
}

播放本地音乐:

在线播放音乐:
在这里插入图片描述
下载音乐到本地:
在这里插入图片描述

在这里插入图片描述

六、结论

  本项目实现了本地音乐播放功能,用户可以选择多个音频文件并进行播放,控制音量大小。支持 OGG 文件的播放,扩展了系统的音频格式兼容性。实现了从网易云音乐 API 获取在线音乐的播放和下载功能。整体上满足了用户的基本音乐管理和播放需求,并通过使用 NAudio 库和网易云音乐 API 提高了系统的可扩展性。未来可以继续优化界面交互、增加更多音频格式支持等功能,提升用户体验。
  本文所涉及的代码可以在gitee上找到。

总结

  通过上述步骤,我们实现了一个简单的音乐播放器,支持本地音乐文件的播放、音量调节、播放控制、在线音乐播放及下载等功能。该程序可以作为音乐播放器开发的基础,通过进一步扩展,可以实现更多的功能。希望这篇文章对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值