【毕业学位论文】(Word原稿)基于Java技术的音频播放软件的设计与实现-电子信息科学与技术_第1页
【毕业学位论文】(Word原稿)基于Java技术的音频播放软件的设计与实现-电子信息科学与技术_第2页
【毕业学位论文】(Word原稿)基于Java技术的音频播放软件的设计与实现-电子信息科学与技术_第3页
【毕业学位论文】(Word原稿)基于Java技术的音频播放软件的设计与实现-电子信息科学与技术_第4页
【毕业学位论文】(Word原稿)基于Java技术的音频播放软件的设计与实现-电子信息科学与技术_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 毕 业 设 计 基于 术的音频播放软件的设计与实现 李鸿青 200730800113 指导教师 戴占海 讲师 学院名称 理学院 专业名称 光信息科学与技术 论文提交日期 2011 年 4 月 论文答辩日期 年 月 答辩委员会主席 _ 评 阅 人 _ 2 摘 要 随着计算机系统的日趋复杂,人们逐渐感觉到旧有软件设计 体系的局限性。由此,对旧有软件设计体系的变革也应运而生。在面向过程的软件设计方法中,人们渐渐感受到将系统模块化这样的设计方法可以让系统更富有可用性、可伸缩性、可靠性、可维护性,从而在不断变化的需求中获得较为理想、较为适应的解决方案。但是这显然是不够的,因为由面向过程的程序设计语言所带来的局限性始终无法更大程度地解放人们的大脑,所以面向对象的编程语言开始诞生。 本文设计基于 E 平台,使用 构设计,以模块化为设计指导。 本文设计的 放器主要由以下几个模块组 成: ( 1) 插件系统 : 主要包括对于整个系统的初始化,加载播放核心,加载插件,插件管理等功能。 ( 2) 日志记录模块:使用成熟的 决方案。 线程池:用于多线程操作时避免线程初始化 /销毁等操作所带来的高资源消耗。 ( 3) 播放核心 : 使用 构,实现基本的播放控制逻辑,实现对 持的接口 。 ( 4) 控制台模块 : 简单的控制台程序,实现对播放器的控制,作为插件被插件系统加载。 ( 5) 块 : 简单的 面,实现对播放控制的可视操作,作为插件被插件系统加载 。 本文 基于 台 架设计并开发实现了音频播放软件的基本功能以及其插件系统。尽管这个音频播放软件还十分粗糙,还仅仅只是个原型。但这些不足以及没有实现的功能都可以通过延续本文的设计思路,设计相关的插件来完善。 关键词 频播放 面向对象 面向接口编程 插件系统 3 目 录 1 引言 . 5 软件开发的困难 . 5 复杂性是软件开发过程中所故有的特质 . 5 计算机表达能力的局限性 . 5 软件开发困难的解决方法 . 5 面向对象的编程方法 . 5 言 . 6 2 面向对象的软件开发 . 6 软件需求 . 6 可行性分析 . 7 系统概要设计 . 8 使用技术简介 . 9 采样音频 . 9 . 10 . 12 . 12 . 12 3 关键模块设计 . 13 插件系统 . 13 . 13 . 15 . 16 . 17 配置管理 器 . 18 日志记录系统 . 19 线程池 . 20 已实现插件 . 21 . 21 4 . 22 4 结论 . 22 致谢 . 24 参考文献 . 25 . 26 5 1 引言 软 件开发的困难 复杂性是软件开发过程中所故有的特质 1 在 70 年代,软件系统已经变得极其复杂,无论是开发还是维护都是一项成本高昂的工作。而随着软件系统的越来越庞大,其复杂度也以更大的比率增长着。 复杂度的提高,这就要求人们要有更好的管理方法、开发方法让软件开发变得更加可控。 计算机表达能力的局限性 软件系统的开发本身就是在将人类大脑中的虚拟印象表达出来。而计算机系统与人类的沟通途径就是通过各种各样的编程语言来实现。通过编程语言这样的媒介,人们可以把要实现的东西告诉计算机。这样计算 机才知道怎么去做。 这就引出了一个问题,编程语言这种媒介在人们与计算机之间的沟通桥梁是否有效,是否高效?这就是计算机表达能力的局限性。而随着时代在发展,计算机编程语言也在不断进步。从一开始的二进制指令到汇编语言、从汇编语言到面向过程的编程语言、再到面向对象的编程语言。这一切都是在降低沟通的消耗。 而另一方面,人类大脑的想象力、创新能力是无穷的,但是计算机系统的能力确实有限的。如何在有限的能力里将无穷的可能给创造出来,这也是一门科学。 软件开发困难的解决方法 软件开发的困难一方面是软件开发本身所具有 的复杂性。另一方面则是人们与计算机系统之间沟通工具的可用性及计算机系统本身能力的局限性。 而人们在面对这些问题的时候,很大程度上是通过改进编程语言与设计模式来解决的。而这种方式也可以归纳为:抽象。 将需要设计的系统进行抽象可以让人们在人脑有限的控制力中尽可能的管理更多的变化。抽象可以从复杂的事物中抽象出共性和特性,使得事物更容易被管理。另一方面,抽象出共性和特性意味着事物可以被模块化,以更合理的方式模块化,实现更低的耦合性。人们都知道,低耦合对于软件系统来说是十分有利的,这将使得软件变得可靠,且更容易维护。 面向对象的编程方法 2 面向对象程序设计( 一种起源于六十年代,发展已6 经将近三十年的程序设计思想。其自身理论已十分完善,并被多种面向对象程序设计语言( 下简称 现。 面向对象程序设计就是在对于事物进行抽象。在面向对象的世界里,一切皆是对象3。对象是对现实世界实体的模拟,由现实实体的过程或信息牲来定义。一个对象可被认为是一个把数据(属性)和程序(方法)封 装在一起的实体,这个程序产生该对象的动作或对它接受到的外界信号的反应。这些对象操作有时称为方法。 面向对象的程序设计可以比面向过程的程序设计更好的表达物理世界中的实体,从而以一种更加适宜人们思考方式的方法来实现程序 。 言 由 司于 1995 年 5 月推出的 序设计语言和 现的 览器(支持 示了 魅力:跨平台、动态的 算。从此, 广泛接受 并推动了 迅速发展,常用的浏览器现在均支持 。 一种简单的,面向对象的,分布式的,解释型的,健壮安全的,结构中立的,可移植的,性能优异、多线程的动态语言 5。 言提供类、接口和继承等原语。 掉了 C+中经常令人费解的多重继承,只支持类之间的单继承,而以接口这种更加符合 想的方式来替代多继承。 言全面支持动态绑定,而 C+ 语言只对虚函数使用动态绑定。另外,与其他编程语言不同的是, 言内置支持多线程,并且对网络的支持非常的完善 ,这使得类似分布式计算这样的场景在 言中更加容易实现 6。总之, 言是一个纯的面向对象程序设计语言。 2 面向对象的软件开发 本文利用面向对象的软件开发方法来设计开发一个简单的音频播放软件。 本音频播放系统采用 言作为开发编程语言。系统基于 用 为日志记录模块,实现了基本播放控制逻辑与一个基本的插件系统。 软件需求 7 每一个软件项目的开始都是因为需求。只有先确定了需求,才能在接下来的设计、实现阶段能够对系统有 个明确的认识。 7 本系统的需求如下。 表 1 音频播放系统需求列表 序号 输入 输出 实现优先级 1 音频文件 音乐 必须,最高 2 无 插件系统 必须,最高 3 歌词文件 歌词显示 必须,中 4 音频文件 歌词联网查找 必须,中 5 音频文件 列表管理 必须,中 6 音频流 音频控制与调整 必须,高 7 所有相关模块 日志系统 必须,高 8 多种音频文件 音乐 可选,中 9 无 皮肤系统 可选,中 10 歌词文件 歌词编辑 可选,中 11 音频文件 格式转换 可选,低 可行性分析 需求是项目开始的原动力,但这并不意味着项目便会开始。因为这涉及到项目是否具有可行性。可行性包含多个方面,而同时会有多个元素会影响到。比如说时间、经济允许度等等因素的影响。 首先从需求实现的技术可行性上来分析。表格 1 所列出来的绝大多数需求都可以通过 言所提供的 架来实现,所以从技术上来说是可行的。但对于需求8 所提及的多种音频格式支持这样的需求,则是无法完全实现。比如说微软的 式,因为微软将 式闭源,且当前尚未有人以纯 方式实现从 获得音频流 ,所以对 件的播放支持是不现实的。 其次,从时间可行性上面来分析。因为本项目只是作为毕业设计时的程序示例之用,且作者并没有很多的时间精力保持在该项目中,所以需求列表中优先级在“高”以下的大部分功能都需要删减。 8 系统概要设计 在可行性分析确定了项目所需要实现的功能后,就应当开始系统的设计阶段。 软件的模块化给软件开发带来了很多的好处,所以本系统也将以模块化的方式进行设计。其具体表现方式为:使用插件系统的方式现实各个功能模块。 本系统借鉴 插件概念,通过 现播放器自 己的插件系统。通过插件系统,可以使得除了播放核心之外的所有东西全面插件化。比如说歌词功能,开发者可以把歌词功能封装成一个插件,然后通过插件系统访问到播放核心等系统资源来实现歌词与播放同步的目的,同时也能很容易便改变歌词功能的具体实现。通过这种方式,我们可以大大降低系统的耦合度,也可以提高系统的定制灵活性。 而因为本系统的核心功能为音频播放和插件系统,所以抽象出来的实体就应当有代表播放核心的对象和代表插件系统的示例。在这里,其设计为类 类 图 1 系统核心类图 系统的核心类图如图 1 所示。通过该图我们可以看到系统主要分为几大模块:9 系统用例图则如图 2 所示。 图 2 系统用例图 使用技术简介 采样音频 对音频而言,信号就是一段声波。麦克风把原始信号转化为相关模拟电信号,然后换器把该模拟信号转化为一种采样的数字信号。图 3 为一小段时间的声音波形。 该图在纵轴上画出了声波的幅度,水平轴为时间。该模拟声波的 幅度在某个频率下等间隔的被测量,最后形成的离散采样点(图中的红色数据点)组成了数字音频信号。图中中间的水平线代表幅度为 0;线上的点为正值采样点,线下的为负值。数字信号逼近某个模拟信号的精度取决于其在时间上的分辨率(采样频率)和其量化标准(幅度上的分辨率,每个采样点用几位数字来表示)。作为一个例子, 存储的音频数据是每秒采样 44100 个点、用 16 位的数字来表示每个采样点的数值。 “采样音频”( 个术语在这里比较宽泛。一个声波可以按照一个离散间隔来采样但仍然保留其模拟信号的形式。 然而在 里,“采样音频”的意思就是“数字音频”( 特别需要注意的是,电脑上的采样音频来自于声音录制,但是相应的声音也可以由10 各种其他声音信号合成的(例如合成一个拨号电话的声音)。“采样音频”在这儿指的就是这种合成性的声音,而不是原始的声音信号。 图 3 音频采样信号 一个小巧的低层 持数字音频和 据的记录 /回放。在 之前, 一个 标准的 展 从 的 开始, 于 作系统、硬件平台)的特点,基于 括本文的程序)能够在任何实现了 更高版本的系统上运行,无须加装任何支持软件。 含在 中,分别用以处理数字音频 含在 义了第三方实现的扩展接口。 音频的输入和输出需要分别使用类 别代表了输入和输出的设备,它们都实现了 口。 口用来关闭 /打开设备、注册事件监听器,以及提供一些用来调整声音效果的对象,例如调整音量大小的对象。 系中起着一个工厂( 的作用,提供了一系列的静态方法,我们通过这些静态方法来获取 统默认配置的资源。它们之 间的关系如图 4 所示。 在处理输入音频时,对于来自各种音频输入端口的信号,例如麦克风、 放器、磁带播放器等,可以在它们到达 前,利用混频器控制输入混频,最后在11 程序中通过 得数字化的音频输入流。 图 4 类关系图 类似地,在处理输出音频时,混频器用来对一系列来自 数据进行混频处理,经处理后的信号可输出到各种输出端口,例如扬声器、耳机等。 如,我们可以从一个 件读取内容写入到后再通过扬声器输出。 音频数据 就是从 入或从 出的数据,必须符合音频格式的标准。音频数据的格式选项由 封装,主要选项包括:编码方式(可以是 冲编码调制)、 )、通道数量、取样率、帧速率等。 而播放音频数据的过程需要如下的 5 步。 ( 1)取得输出设备信息 2) 取得输出设备 3)打开输出设备 12 ( 4)开始播放 ; ( 5)循环读取 入源中的音频数据,对于读取到的数据 接写入 象即可播出声音了。 的 的是 单的说,就是一种服务提供规范。 在 言中 ,人们可以定义服务接口,即 后通过 言提供的服务加载机制加载所有符合这一服务接口的类来实现程序的扩展功能。打个比方,比如 言中的 ,在该包下定义了 口。该 口的作用即是实现字符集扩展功能。任何第三方的开发者均可以通过该 口实现自己的字符集扩展,从而支持任何新增的字符集。 同样的, 言在很多地方也用到了 架,比如输入方法框架 架 本处理库 等。 缩写,中文为 地调用。从 始, 准成为 台的一部分,它允许 码和其他语言写的代码进行交互。 开始是为了本地已编译语言,尤其是 C 和 C+而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。 是 缩写。 供一组 具类用于在运行期动态访问系统本地库( 不需要编写任何 码。开发人员只要在一个 口中描述目标 自动实现 口到 映射。 实现原理其实是通过 射机制获得描述的接口信息,再根据该接口信息动态编译出代理 样的功能。换句话说,其底层实现依旧是 出现是为了解决多变成语言共开发的问题。因为标准的 库可能不 支持你的程序所需的特性。或许你已经有了一个用其他语言写成的库或程序,而你希望在 序中使用它。又或者你可能就需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的 序中调用这些功能。而这些问题都涉及到如何在 言中使用其他编程语言。所以 出现可以说是必然的。 3 一个用于开发 用程序用户界面的开发工具包。它以抽象窗口工具包( 基础使跨平台应用程序可以使用任何可插拔的外观风格。 发人员只用很少的代码就可以利用 富、灵活的功能和模块化组件来创建优雅的用户界面。 工具包中所有的包都是以 为名称,例如 3 关键模块设计 插件系统 插件系统是一个全局的核心,所以这里将其设计为单例,采用工程模式获得其实例。 因为插件系统这一实例本身仅实现其作为一个插件系统所应当具有的功能:管理插件。所以本系统又设计了一个 代理类 作为曝露给插件的接口。 实现了一个插件系统所应当具有的基本功能,包括其工程模式接口、配置管理器接口、日志组件接口、播放核心接口、插件加载、插件管理等功能。 在 中可以通过 ; 这一工程方法获得其单例。在这里加上 键字是为了避免多个插件在初始化时访问 得单例时可能出现的多线程同步问题。获得单例时会先判断是否已存 在可用实例,若有则返回之。若无,那么新建一个实例并缓存起来。 新建一个实例时,插件系统首先会先初始化日志记录模块。然后开始加载配置管理器、播放核心实例等资源,并通过日志记录模块将信息记录下来。当资源都加载完毕后就会开始做插件加载操作。 而在插件本身看来,得到单例后便可以通过 法获得播放核心引用、配置管理器 引用、日志记录模块 引用等多个很有用的工具。 同时,作为一个插件系统, 同样提供了管理插件的接口。比如 该方法用于禁用插件 插件。 这个方法则用于启用插件。 14 还提供了获得启用插件列表、禁用插件列表的接口。这样任何获得实例的插件都获得其他已注册插件的引用,从而实现插件之间的协同工作。 插件的加载机制采用 架,即 一接口的插件。在加载插件的代码逻辑里,有这样一段: ; /如果失败的列表长度一直不变,那么表示有些插件根本无法初始化,表明应当完成插件加载工作了。 /因为第一次加载插件的失败列表长度肯定为 0,所以加以判断第一次 | = ) ; !) & !) , be ); ) ); ) ); 15 其中的启用插件 函数定义为 != ) ); ; 在插件加载的该 段代码里,解决了插件的依赖问题。这里通过一个死循环对插件进行加载,当判断条件(上一次加载完插件的失败插件列表长度与这次的长度一致)为真时,那么退出该死循环。也就是说,当剩余所有的插件因为依赖关系而一直无法被加载时,那么退出加载循环,完成加载工作。在这里,并不考虑循环依赖问题。 在这里也可以看得出插件本身也是单例的,该单例由 成,在线程池中由始化。并由插件系统统一管理维护。 代理 例作为插件 持有的插件系统引用。 这么做的好处是,插件系统 需要完成其所必须完成的必须任务即可,16 而不用管对插件访问插件系统的鉴权等额外的行为。当插件系统初始化一个插件时,插件系统将同时生成一个拥有自身引用的代理 这一代理授予插件。这一意义就可以把可以分离的业务逻辑从插件系统中分离开来,同时保障了插件系统不会失去对插件的约束控制。 插件系统生成代理 , 先从程序目录的 件中获得信任插件列表,只有存在于信任插件列表的插件才能获得禁用、启用其他插件等高级功能。 同样是整个插件系统的关键。所有继承于 现其定义接口的子类都可以被插件系统 加载。因为是 口,所以按照 言的惯例将其归入 下面。 因为插件接口需要提供给插件本身一些系统资源,但又不希望这些资源引用可以在插件中修改,所以这里将插件接口 计为抽象类。该抽象类在构造时由插件系统赋予插件系统的代理引用。 插件接口定义了一个插件所应当具有的一系列行为和属性。 插件初始化 /开启 /禁用等事件接口、插件服务方法 /销毁方法等行为。 ; ; ; ; ; 插件名称、插件类型、插件描述、插件依赖等属性。 ; ; ; ; 同时插件接口提供给插件一个只读的插件系统代理引用,插件可以通过这个引用获得插件系统提供的资 源,比如播放核心、日志组件、配置管理器等等。 ; 17 因为插件可能具有依赖关系,所以这里定义了一个抽象接口 ; 所有插件都应提供其所依赖其他插件的 样插件系统才能有序的初始化各个插件。 样设计为单例 。 播放核心至少需要提供一系 列的 、 等等方法来支持播放的控制和调节。 同时还需要提供对播放核心当前状态的描述接口,这样插件便可以通过该接口获得播放核心的相关状态。 除此之外,播放核心还应当支持事件监听机制。只有完整的事件监听机制才能使多线程的插件结构能够以更合理的方式来实现相关功能。即基于事件驱动模型。 基于事件驱动在 到打印驱动库 其中都有事件监听机制。可以说,在多线程响应中,事件监听机制是一个非常不错的选择 。 所以,这里 放事件放事件监听器接口 件可以在播放核心中注册监听器来监听播放事件的发生。 如 些状态描述了播放器可能存在的播放状态,即停止、需停止、开始、暂停、继续、播放中、跳转、跳转完毕、出错。 的状态呈现于播放事件 其方法原型为 其中第二个参数即播放状态,而第一个参数则为当前的播放位置,以毫秒计。 这样就是说每个播放事件会告诉监听者事件的类型以及事件发生时播放器的当前播放位置。 显然,事件监听者需要实现 接口只提供一个方法,即 发生事 件时,事件处理机制会通过该接口告诉监听者所发生18 的时间 另一方面,我们知道事件触发后的分发可能会有堵塞。也就是说监听者本身可能会因为某些运行时异常而堵塞 方法,从而影响到其他插件对于事件的接受。所以这里事件的分发以新线程的方法来分发。即通过本系统定义的 关代码如后文所示。 ); 配置管理器 在本设计中,配置管理器作为系统的配置保存器,通过与插件系统 定来确保其唯一性。 配置管理提供了 等方法作为配置管理接口,每个对象可以将自己传递给配置管理器来获得上次保存着的配置。 另外,本配置管理器还定义了若干使用方法,包括 这些方法的主要功能是将所有的配置保持到流和文件。 配置管理器中还维护着一个 定时保存配置,维护数据的持久性。但是我们知道, 一个程序可能会非正常终止,所以这里注册了 闭钩子来保证程序被非正常终止时能够保证数据的完整性。 闭钩子是 带来的新特性。即当 要求终止时,会通知这一钩19 子,从而允许 序可以在非正常关闭时进行额外操作。该钩子通过 添加。 因为该关闭钩子只是属于配置管理器的内部处理机制,所以就以内部私有类的方式定义该钩子。其代码为 ; 日志记录系统 在软件开发中,日志记录系统是十分重要的一环。一个好的日志记录系统可以帮助人们监视系统是否运行正常,甚至于快速定位故障原因。 在本设计前期,原 本的设计是使用 来就有的 是最终发现这个日志记录系统确实不够完善,不利于系统扩展和灵活控制。所以后期将其替代为 件。 一个开放源代码项目,通过使用 们可以控制日志信息输送的目的地是控制台、文件、 件、甚至是套接口服务器、 事件记录器、护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这 些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 在 ,只需要如下配置便可以将日志记录到文件 ,且实现日增日志独立文件命名保存。 =%t %C.%M(%L) -

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论