C#实现简单音乐文件解析播放——Windows程序设计作业2
1. 作业内容
编写一个C#程序,要求实现常见音乐文件的播放功能,具体要求如下:
1). 播放MP3文件: 程序应能够读取MP3文件,并播放其中的音频。
2). 播放OGG文件: 应能够播放ogg文件。
3). 用户界面: 一个简单的窗口,包含播放和暂停按钮以及文件选择功能。
4). 异常处理: 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
5). 兼容性: 确保代码在多个C#版本上均可运行。
2. 设计思路分析与难点
2.1 架构选择
考虑到需求中的界面友好和跨版本兼容性,我们可以选择选择Windows Forms作为开发平台,Windows Forms提供了一个简单而强大的方法来创建桌面应用程序,并且与C#高度兼容,在开发过程,我们选择.NETFramework 4.8.0进行程序设计。
2.2 设计思路
1). 界面设计: 使用Windows Forms工具箱中的控件如按钮、标签和文件对话框构建用户界面。
2). 功能编码: 使用OpenFileDialog允许用户选择音频文件。 根据文件扩展名调用相应的播放器对象进行播放。 播放控制,包括开始、暂停和停止。
3). 异常处理: 捕获并响应各种可能的运行时错误,如文件读取失败、文件格式不支持等,为用户提供清晰的错误信息。
2.3 难点分析
1). 文件格式支持: 处理多种音频格式(MP3,OGG等)要求使用不同的库,这可能导致代码复杂度增加。
2). 异常处理: 音频文件的播放中可能遇到多种异常情况,如文件损坏、编解码器不支持等。
3. 窗体设计
按照需求和功能分析,实现窗体如下:

其中,各控件实现功能如下:
Label:展示当前播放的歌曲。
ListBox:展示选择的歌曲列表。
AxWindowsMediaPlayer:用于播放常规格式音乐(ogg无法用此播放)。
OpenFileDialog:用于选择音乐文件。
Button:用于选择歌曲文件、停止播放、下一曲的功能实现。
TrackBarl:用于音量控制。
4. 代码实现
4.0 类成员变量定义
List<string> localmusiclist = new List<string> { };
private WaveOutEvent waveOut = new WaveOutEvent();
private VorbisWaveReader currentVorbisReader;
在类中,我们需要定义类成员变量,localmusiclist在音乐播放应用中用来追踪和管理用户加载的音乐文件集合,waveOut用于播放ogg文件,currentVorbisReader为当前使用的ogg文件实例。
4.1 文件选择功能
函数定义:
private void button1_Click(object sender, EventArgs e)
{//功能实现见下方
}
具体实现:
string[] files = { };openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
//同时打开多个文件
openFileDialog1.Multiselect = true;
在这部分,我们采用button和openFileDialog控件来实现文件的选择,Filter用于筛选文件类型,使得用户只能选择音乐文件,不能选择其他文件导致后续功能无法实现报错,同时初始化一个files文件存放音乐文件的文件名。
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){listBox1.Items.Add(file);localmusiclist.Add(file);}
}
这里我们对选择的文件进行处理,首先,将所有变量清空,防止有残留影响后续程序执行,之后,将文件名添加到ListBox中,显示出来用于选择音乐,同时,利用localmusiclist变量存储文件名,并且作为类成员变量进行传输,方便后续对音乐的操作。
openFileDialog1.ShowDialog() == DialogResult.OK
其中,if条件判断openFileDialog是否接收到文件,不然不执行后续程序。
4.2 音乐选择功能
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]);}
}
在ListBox控件中,存在一个事件监听SelectedIndexChanged,利用该事件,我们可以去获取用户切换列表,SelectedIndex是获取目前列表中选择的序号,通过该序号和之前的localmusiclist,我们可以获取到音乐信息并且进行传参调用函数,进行后续的音乐播放。

同时,将Label的内容设置为音乐文件的信息并展示。

4.3 音乐选择功能
函数定义:
private void musicplay(string filename)
{//功能实现见下方
}
具体实现:
string extension = Path.GetExtension(filename).ToLower();
首先,获取当前文件名的后缀信息,判断文件类型。
if (extension == ".ogg")
{if (currentVorbisReader != null){// 确保先停止当前播放再释放资源if (waveOut.PlaybackState != PlaybackState.Stopped){waveOut.Stop();}currentVorbisReader.Dispose();}currentVorbisReader = new VorbisWaveReader(filename);waveOut.Init(currentVorbisReader);waveOut.Play();
}
针对不同的文件类型,采用不同的处理方式:若是ogg文件,调用NAudio第三方库总的Vorbis和Wave类来实现播放音乐。
在播放新的音乐时,先检测当前是否有正在进行播放或者是暂停播放的ogg音乐,先进行处理再播放当前歌曲,可以防止同时初始化两次WaveOut产生播放异常。
else
{axWindowsMediaPlayer1.URL = filename;axWindowsMediaPlayer1.Ctlcontrols.play();
}
若是其他类型的文件,使用C#原生库中的WindowsMediaPlayer控件实现播放。
4.4 暂停播放
private void button2_Click(object sender, EventArgs e)
{if (waveOut.PlaybackState == PlaybackState.Playing){waveOut.Pause(); // 暂停播放OGG}axWindowsMediaPlayer1.Ctlcontrols.stop(); // 停止其他格式的播放
}
音乐暂停功能也需要先区分类型,如果waveOut的播放状态为正在播放,调用函数暂停音乐,否则就是调用WindowsMediaPlayer的暂停函数。
4.5 播放下一首&&循环播放
函数定义:
private void button3_Click(object sender, EventArgs e)
{//功能实现见下方
}
具体实现:
if(localmusiclist.Count > 0)
{//记录下一首音乐的索引int index = (listBox1.SelectedIndex + 1);axWindowsMediaPlayer1.URL = localmusiclist[index];musicplay(axWindowsMediaPlayer1.URL);label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);listBox1.SelectedIndex = index;
}
这里采用索引来得到下一首音乐URL,再进行播放,同时更改Label的信息显示与SelectedIndex的当前索引。
if (index >= localmusiclist.Count())
{index = 0;
}
在索引大于当前音乐列表的时候,将Index重置为零,从而实现循环播放功能。
4.6 音量控制
private void trackBar1_Scroll(object sender, EventArgs e)
{axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}
直接将WindowsMediaPlayer的属性和TrackBar设置的值进行关联即可实现音乐播放事的音乐控制了。
5. 完整代码
代码仓库:hmcy-zbx的windows课程设计作业
6. 总结&改进思路
本次作业旨在通过导入第三方库辅助自己的程序设计与学习更复杂的控件使用和控件之间的联系,通过本次作业,我对于C#的控件使用掌握的更加深入了。
尽管当前程序能实现较多的音乐文件格式播放,但是不能够实现最新的音乐文件解析,例如:ape文件与aac文件。
并且,缺少高级音频功能的设置,例如增加音频效果处理(如均衡器、声音增强等)和支持音频流的直接下载和播放。
相关文章:
C#实现简单音乐文件解析播放——Windows程序设计作业2
1. 作业内容 编写一个C#程序,要求实现常见音乐文件的播放功能,具体要求如下: 1). 播放MP3文件: 程序应能够读取MP3文件,并播放其中的音频。 2). 播放OGG文件: 应能够播放ogg文件。 …...
Python数据爬取超简单入门
## 什么是网络爬虫? 网络爬虫是一种自动浏览器程序,能够自动地从互联网获取数据。爬虫的主要任务是访问网页,分析网页内容,然后提取所需的信息。爬虫广泛应用于数据收集、数据分析、网页内容监控等领域。 ## 爬虫的基本步骤 1.…...
Dreamweaver 2021 for Mac 激活版:网页设计工具
在追求卓越的网页设计道路上,Dreamweaver 2021 for Mac无疑是您的梦幻之选。这款专为Mac用户打造的网页设计工具,集强大的功能与出色的用户体验于一身。 Dreamweaver 2021支持多种网页标准和技术,让您能够轻松创建符合现代网页设计的作品。其…...
【Git】Git学习-15:分支简介和基本操作
学习视频链接:【GeekHour】一小时Git教程_哔哩哔哩_bilibili编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 git bran…...
浏览器提示网站“不安全”原因及解决方法
是否经常会遇到访问的网站被浏览器提示访问不安全?那么,浏览器提示网站不安全通常有哪些原因又该如何处理这种不安全提醒,以下总结了几个原因及相应的处理办法: 一、网站管理者原因排查及处理办法: 1、网站没有部署S…...
Jmeter详细学习思路和教程
目录 1、JMeter环境准备 1.1、介绍 1.2、与LoadRunner比较 1.3、前提条件 1.4、安装配置 2、JMeter脚本 2.1、测试计划 2.2、线程组 2.3、Sampler 2.4、HTTP请求 2.5、查看结果树 2.6、HTTP Cookie管理器 2.7、HTTP信息头管理器 2.8、响应断言 2.9、参数化 3、JM…...
钉钉开放平台创建企业内部H5微应用或者小程序
前言: 在当今企业数字化转型的浪潮中,创建企业内部H5微应用或小程序已成为提升工作效率和促进内部沟通的重要举措。发话不多说本文将介绍如何利用钉钉平台快速创建这些应用,让企业内部的工作更加便捷高效。 步骤 1.在浏览器打开链接…...
Linux中每当执行‘mount’命令(或其他命令)时,自动激活执行脚本:输入密码,才可以执行mount
要实现这个功能,可以通过创建一个自定义的mount命令的包装器(wrapper)来完成。这个包装器脚本会首先提示用户输入密码,如果密码正确,则执行实际的mount命令。以下是创建这样一个包装器的步骤: 创建一个名为…...
【网络协议】----IPv6协议报文、地址分类
【网络协议】----IPv6协议简介 【网络协议】----IPv6协议简介IPv6特点IPv4 和 IPv6报文结构IPv6报文格式-拓展报头 IPv6地址分类IPv6地址表示IPv6单播地址可聚合全球单播地址链路本地地址唯一本地地址特殊地址补充 接口标识(主机位)生成方法通过EUI-64规…...
Llama改进之——SwiGLU激活函数
引言 今天介绍LLAMA模型引入的关于激活函数的改进——SwiGLU1,该激活函数取得了不错的效果,得到了广泛地应用。 SwiGLU是GLU的一种变体,其中包含了GLU和Swish激活函数。 GLU GLU(Gated Linear Units,门控线性单元)2引入了两个不同的线性层…...
在数据分析中所需要运用到的概率论知识
数据分析 前言一、总体二、样本三、统计抽样抽取的基本准则 四、随机抽样抽签法随机数法 五、分层抽样六、整群抽样七、系统抽样八、统计参数常用的分布函数参数 九、样本统计量十、样本均值和样本方差十一、描述样本集中位置的统计量样本均值样本中位数样本众数 十二、描述样本…...
韩顺平0基础学Java——第6天
p87-p109 运算符(第四章) 四种进制 二进制用0b或0B开头 十进制略 八进制用0开头 十六进制0x或0X开头,其中的A—F不区分大小写 10转2:将这个数不断除以2,直到商为0,然后把每步得到的余数倒过来&#…...
react18子组件设置接收默认值和值类型验证
父组件传值 import ChildCom from ./components/ChildCom export default function Person {return(<div><ChildCom name"alan-ben" age{18} score{[98, 97, 100]} /></div>) } 子组件接收并验证类型 import React from react import PropTypes…...
Java 高级面试问题及答案(二)
Java高级面试问题及答案 1. 在Java中,什么是强引用、软引用、弱引用和虚引用,它们有什么区别? 答案: 在Java中,引用类型决定了对象的生命周期,主要有以下四种: 强引用:最常见的引…...
数据统计:词频统计、词表生成、排序及计数、词云图生成
文章目录 📚输入及输出📚代码实现 📚输入及输出 输入:读取一个input.txt,其中包含单词及其对应的TED打卡号。 输出 output.txt:包含按频率降序排列的每个单词及其计数(这里直接用于后续的词云…...
W801学习笔记二十四:NES模拟器游戏
之前已经实现了NES模拟器玩游戏。W801学习笔记九:HLK-W801制作学习机/NES游戏机(模拟器) 现在要在新版本掌机中移植过来。 1、把NES文件都拷贝到SD卡中。 这回不会受内存大小限制了。我这里拷贝了4个,还可以拷贝更多。 2、应用初始化中,加载…...
ECMAScript 6简介
ECMAScript 6简介 发布日期目标ECMAScript 和 JavaScript 的关系ES6 与 ECMAScript 2015 的关系 ESx标准 命名规则 ECMAScript 的历史 1. ECMAScript 6简介 1.1. 发布日期 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已…...
第1个数据库:编号,文本,时间,
写一个数据库 编号 文本 时间1 第一个文本 有100万条数据 -- 创建一个名为texts的表格来存储数据 CREATE TABLE texts ( id INTEGER PRIMARY KEY, text TEXT, time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- 插入数据INSERT INTO texts (text) VALUES (第一个文…...
线性数据结构-手写链表-LinkList
为什么需要手写实现数据结构? 其实技术的本身就是基础的积累和搭建的过程,基础扎实 地基平稳 万丈高楼才会久战不衰,做技术能一通百,百通千就不怕有再难得技术了。 一:链表的分类 主要有单向,双向和循环链表…...
快手客户端一二面+美团前端一面+腾讯企业微信开发客户端一面
快手一面结志 1、自我介绍 2、对称加密非对称加密 3、TCP/UDP 4、在学校有什么课程是强项,说了过去几次面试中面到的C的语言基础知识 5、问C、Java中兴趣在哪里 6、问到项目,自己做的还是跟着学校老师做的,同样问到兴趣在哪里 7、LRU …...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
