音乐演奏程序.docx
《音乐演奏程序.docx》由会员分享,可在线阅读,更多相关《音乐演奏程序.docx(27页珍藏版)》请在冰点文库上搜索。
音乐演奏程序
学号:
课程设计
题目
音乐演奏程序
学院
自动化学院
专业
电气工程及其自动化
班级
姓名
指导教师
2014
年
1
月
9
日
课程设计任务书
学生姓名:
专业班级:
指导教师:
工作单位:
自动化学院
题目:
音乐演奏程序设计
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1.使用汇编语言设计一个在计算机上运行的音乐演奏程序;
2.屏幕显示钢琴图像;
3.按大写字母“A”,唱乐曲1;按大写字母“B”,唱乐曲2;按大写字母“C”,唱乐曲3,依次类推;
4.按"X"鍵,退出
5.撰写课程设计说明书。
内容包括:
摘要、目录、正文、参考文献、附录(程序清单)。
正文部分包括:
设计任务及要求、方案比较及论证、软件设计说明(软件思想,流程,源程序设计及说明等)、程序调试说明和结果分析、课程设计收获及心得体会。
时间安排:
月日-----月日查阅资料及方案设计
月日-----月日编程
月日-----月日调试程序
月日-----月日撰写课程设计报告
指导教师签名:
年月日
系主任(或责任教师)签名:
年月日
目录
摘要……………………………………………………………………………………..1
1音乐演奏的基本原理2
2设计方案2
2.1设计内容2
2.2主要宏与主要过程3
2.2.1音乐载入宏3
2.2.2PlayMusic宏3
2.2.3通用发声程序都soundout4
2.2.4WAITF延时程序5
2.2.5CLEAR清屏程序6
2.2.6stdout宏7
2.3主程序实现7
2.3.1数据段定义7
2.3.2堆栈段定义8
2.3.3初始化8
2.4程序调试运行9
3软件设计10
3.1主程序流程图10
3.2PlayMusic子程序流程图11
4结论12
5心得和体会12
参考文献……………………………………………………………………………….…14
附录……………………………………………………………………………………....15
摘要
音乐演奏实现的一个主要步骤是乐谱编程。
通过相应的频率表将乐谱中对应的音符转化为计数器的计数初值,节奏通过延时程序利用硬件实现频率计数和延时时间的控制,利用8253-5定时/计数器芯片和8255A并行I/O接口芯片。
使8253的一个通道工作在“方波发生器”模式,实现对频率的计数;利用8255A的PB3端口实现发声时间的计数控制。
转化为对喇叭发音时间的控制,从而实现音符和节拍的数字化。
知道了音调与频率和时间的关系,就可以按照乐曲的曲谱将每个音符的频率和持续时间定义成两个数据表;然后编写程序一次取出表中的频率和时间值,调用程序发出各种声音。
这个程序最终通过菜单所提示的信息选取音乐。
以80x86未处理器为对象,以8253为计数器的核心,通过宏指令和BOIS系统功能的调用,以及运用MASM软件在PC机上来进行调试和运行,从而模拟地来实现“音乐演奏”的目的。
关键词:
乐谱编程8253定时/计数器8086音乐演奏
音乐演奏程序
1音乐演奏的基本原理
这次课程设计的设计思想是在熟练掌握汇编程序的设计方法的基础上,利用通用发生程序编写音乐程序。
组成音乐的每个音符的频率值和持续时间是音乐程序发声所需要的两个数据,根据音调与频率和时间之间的关系,把要编辑的音乐的每个音符的频率和持续时间进行定义,进而把它们写入通用发声程序,音乐程序就完成。
在IBM-PC/XT机中都带有8253-5定时/计数器,IBM-PC/AT中带有8254定时/计数器,这两种芯片功能十分类似。
本文通过对8253-5定时/计数器芯片的操作实现音乐演奏。
该声音接口通过汇编语言对8253-5的端口直接进行操作,可以不必要过多的使用BIOS的调用和DOS的调用。
在编制此音乐演奏程序时,应该知道ROMBIOS中有个BEEP子程序,这能根据BL中组出的时间计数值控制8254定时器,产生持续时间为1个或几个0.5秒,频率为896HZ的声音,我们可以利用并修改BEEP,使其产生任一频率的声音。
首先要了解计算机是如何产生声音和乐曲的。
找出相关程序源代码,弄清楚各功能的环节间的联系、联接方法,搞清楚单调与频率和时间的关系,利用计算机控制发声的原理,依照基本的算法思想写程序,测试,更正,扩充功能,修饰细节。
2设计方案
2.1设计内容
要求完成一个音乐程序,即通过按下键盘上某个按键就可以按预先设定的程序播放音乐或者终止程序。
当键入大写字母“A”时,唱乐曲“玛丽有只小羔羊”;当键入大写字母“B”,唱乐曲“生日快乐”;当键入大写字母“C”,唱乐曲“两只老虎”;当键入大写字母"X"鍵,退出。
此程序涉及到过程和宏的调用,要掌握关于过程和宏的定义和使用。
可以设定播放某一段音乐为一个过程,设定对音乐进行播放的操作为一个宏操作。
2.2主要宏与主要过程
2.2.1音乐载入宏
歌曲包含节拍和频率。
此处定义的音乐地址宏包含两个参数,将歌曲频率地址导入SI将歌曲节拍导入BP。
当选择不同的歌曲时,主程序调用该宏,将用户要求的歌曲的频率和节拍导入,以便在MUSIC中实现发声。
音乐地址宏实现如下:
LoadMusicMACROA,B
LEASI,A
LEABP,DS:
B
ENDM
2.2.2PlayMusic宏
在PlayMusic中,程序已经将歌曲的首个频率地址和首个节拍地址分别导入SI、BP。
为了检测歌曲是否结束,在PlayMusic中,首先将SI传递到DI,DI与-1相减,如等于0,则得出该频率定义为-1。
在歌曲频率表定义中将-1定为该歌曲结束标志,此时PlayMusic跳出结束。
若该频率不为-1。
调用通用发生程序soundout,将该音符按照频率和节拍表发声。
发声后SI、BP分别加2,跳转到下一个音符的频率和节拍,继续检测歌曲是否结束。
如频率不为0,继续将该音符发声,并循环此过程。
具体实现方法如下:
PlayMusicPROCNEAR
PUSHDS
SUBAX,AX
PUSHAX
FREQ:
MOVDI,[SI]
CMPDI,-1
JEEND_MUS
MOVBX,DS:
[BP]
CALLsoundout
ADDSI,2
ADDBP,2
JMPFREQ
END_MUS:
RET
PlayMusicENDP
2.2.3通用发声程序都soundout
该发生程序是在修改BEEP发声程序的基础上,以实现为8088/86编写一个任意频率和任意持续时间的通用发声程序。
该程序包括以下三个步骤:
(1)在8253/54中的43端口送一个控制字0B6H(10110110B),该控制字对定时器2进行初始化,使得定时器2准备接受计数初值。
(2)在8253/54中的42H端口装入一个16位计数值,已建立将要产生的声音频率。
(3)把输出端口61H的0、1两位置1,发出声音。
具体实现如下:
soundoutPROCNEAR
PUSHAX
PUSHBX
PUSHCX
PUSHDX
PUSHDI
MOVAL,0B6H
OUT43H,AL
MOVDX,12H
MOVAX,348CH
DIVDI
OUT42H,AL
MOVAL,AH
OUT42H,AL
INAL,61H
MOVAH,AL
ORAL,3
OUT61H,AL
WAIT1:
MOVCX,3314
CALLWAITF
DELAY1:
DECBX
JNZWAIT1
MOVAL,AH
OUT61H,AL
POPDI
POPDX
POPCX
POPBX
POPAX
RET
soundoutENDP
该soundout程序能产生19~65535Hz的声音,这个频率的下限是使除法不产生溢出的最小值。
其上限65535是多余的,因为人能听到的声音最高频率为20000Hz。
此外一般情况下,soundout程序产生的声音不单单和频率有关,还和CPU有关。
CPU工作频率越高,时延越短,产生的声音越急促。
为了使程序产生一个与CPU工作频率无关的合适时延,在soundout中调用了一个时间延时程序WAITF。
2.2.4WAITF延时程序
80x86的各种处理器采取了6~66MHz的工作频率,loop指令的执行时间在这些处理器上也不相同。
为了建立一个与处理器无关的延时,IBM采用了一种利用硬件产生时间延时的方法,即通过监控端口61H和PB4,使PB4每15.08微秒触发一次,一产生一个固定不变的时间基准。
在IBMPCATBIOS的WAITF子程序,就是一个产生N*15.08us时间演示的程序。
调用WAITF子程序时,CX寄存器必须装入15.08微秒的倍数N。
利用WAITF子程序能获得任意的时间延时,而不必在考虑CPU的型号和工作频率。
具体实现如下:
WAITFPROCNEAR
PUSHAX
WAITF1:
INAL,61H
ANDAL,10H
CMPAL,AH
JEWAITF1
MOVAH,AL
LOOPWAITF1
POPAX
RET
WAITFENDP
2.2.5CLEAR清屏程序
当程序初始化或用户输入错误时,程序调用CLEAR清屏程序。
清屏程序将AX、BX、CX、DX先入栈,以保存现场,保证清屏后重新执行不会出现错误。
随后启用BIOS功能调用,将屏幕初始化或上卷。
其中AL=0表示初始化窗口,AL=上卷行数,BH=卷入行属性,CH/CL=左上角行/列号,DH/DL=右上角行/列号。
该程序段表示从左起0行0列到右起24行79列全部清屏。
将屏幕清空后重新将AX、BX、CX、DX出栈。
CLEARPROCNEAR
PUSHAX
PUSHBX
PUSHCX
PUSHDX
MOVAH,6
MOVAL,0
MOVCH,0
MOVCL,0
MOVDH,24
MOVDL,79
MOVBH,7
INT10H
POPDX
POPCX
POPBX
POPAX
RET
CLEARENDP
2.2.6stdout宏
为将事先定义的数据段字符串显示在屏幕上,定一个参数为b的宏。
将b的地址传到DX。
随后调用DOS09号功能调用。
将字符串显示到屏幕。
调用DISPLAY的实例为:
stdoutINFO1
stdoutINFO2
stdoutINFO3
stdoutMUSLIST
在此段代码中,程序显示提示作用的字符串和歌曲列表。
DISPLAY宏具体实现如下:
stdoutMACROB
LEADX,B
MOVAH,9
INT21H
ENDM
2.3主程序实现
2.3.1数据段定义
数据段分别定义了INFO2、INFO3、INFO4、INFO5各字符串分别显示程序运行之初对用户的提示。
MUSLIST中显示用户能选择的三首歌曲列表。
程序用MUS_FREQ、MUS_TIME分别定义了音乐频率和节拍。
使得发声程序可以按照理想的要求发出连续的乐曲。
节拍和频率定义原理如下:
乐曲是按照一定的高低、长短和强弱关系组成的音调,在每一首乐曲中,每个音符的音高和音长与发声系统中的频率、节拍有关。
可参考下表。
音名频率对照表
音名
C
D
E
F
G
A
B
C
D
E
F
G
A
B
C
唱名
频率(Hz)
1
131
2
147
3
165
4
175
5
196
6
220
7
247
1
262
2
294
3
330
4
349
5
392
6
440
7
492
1^
523
其中,低音阶从低音C(131Hz)到中央C(262Hz),高音阶从中央C(262Hz)到高音C(523Hz)。
组成乐曲的音符的频率值和持续时间是乐曲程序发声所必需的两组数据,频率可以查上表,音符的持续时间根据乐曲的速度及每个音符的节拍数来确定。
在4/4拍中,四分音符为一拍,每小节四拍,全音符持续四拍,二分音符持续二拍,四分音符持续一拍,八分音符持续半拍。
如果给全音符分配1秒(100*10ms)的时间,则二分音符持续时间为0.5秒,四分音符持续时间为0.25秒,八分音符持续时间为0.125秒。
知道了音调及频率、时间的关系后,可以按照乐曲的乐谱将每个音符的频率和持续时间定义为两个数据表,然后编写程序依次取出表中的频率值和时间值。
“玛丽有只小羊羔”的乐谱如下:
3212|333—|222—|355—|3212|3333|2232|1——|
可设置该乐曲的频率表如下:
MUS1_FDW330,294,262,294,3DUP(330)
DW3DUP(294),330,392,392
DW330,294,262,294,4DUP(330)
DW294,294,330,294,262,-l
设置该乐曲的节拍时间表如下:
一般延迟时间取10ms的倍数。
MUS1_TDW6DUP(25*2),50*2
DW2DUP(25*2,25*2,50*2)
DW12DUP(25*2),100*2
2.3.2堆栈段定义
程序定义了一个长度了400的堆栈段,用以保存运行时的临时数据,代码如下:
STACKSEGMENT
DB400DUP(0)
STACKENDS
2.3.3初始化
程序初始化使用了BIOS功能调用。
使用10H号功能设置显示方式。
本程序对显示要求较为简单,故使用640*200彩色图形显示方式(EGA)。
若要求改变显示方式,可以根据BIOS功能设置表自行添加。
START:
MOVAX,DATA
MOVDS,AX
MOVAH,0
MOVAL,0EH
INT10H
2.4程序调试运行
本次使用的是MasmforWindows集成开发环境,该集成开发环境在x86架构机器上能直接访问BIOS,这对本次课设的程序来说至关重要。
我的电脑使用win7操作系统,由于该系统有良好的安全机制,不允许程序任意访问BIOS,以免造成系统故障,一开始运行程序多次之后没有发出任何声音,后修改成XP兼容模式,该模式下使用DOSBox模拟器运行程序,可以顺利发出声音。
成功编译与连接并生成了exe文件如图1所示。
图1编译与连接成功提示
程序运行界面如图1所示。
图2程序运行界面
DOSBox模拟器不支持unicode字符集,因此钢琴界面不能使用制表符,退一步选用简单的中划线和竖线,表示出7个按键的钢琴键盘。
显示效果比较满意。
3软件设计
3.1主程序流程图
图3主系统流程图
3.2PlayMusic子程序流程图
图4PlayMusic子程序流程图
完整程序代码请见附录1。
4
结论
本次课程设计已经顺利的结束了,在王老师悉心指导以及我们这组全体成员的共同努力下,圆满完成了本次课程设计的任务,并且达到了预期的效果。
经过一周的磨炼和努力,无论从学习上还是从自身角度,我自认都提高了不少,发现了自己的能力和未被挖掘的潜力,认证了自身的坚强与韧力,总结出只有在强压与竞争中才会有意想不到的收获和进步。
本次课程设计充分体现了团队合作的重要性,在遇到问题时,我们总会第一时间讨论研究,这次汇编课程设计为我们提供了与众不同的学习方法和学习机会,让我们从传统的被动授学转变为主动求学,把所学的理论知识真正的运用到实践中学习,增强了领悟、创新和推断的能力。
掌握自学的方法,形成工程理论整体模式,使工作、学习、生活都步入系统化流程。
思考方式成熟,逻辑性规范、明确。
这些方法的提高是终身受益的,我认为这难得的一周,让我真正懂得了生活和学习的基本规律。
总之,我认为我本次课程设计基本达到了要求,所编程序的功能也基本完善,而且程序有友好的交互界面和可扩充性,就是说可以在数据段中定义音乐的频率表和时间节拍表,然后在代码段中修改一下即可或者如果想演奏另一个乐曲。
我想经过这一个周的课程设计所发现的问题对我们会有很大的启示,在以后的学习中也会大有帮助。
在以后的学习中我会不断的改进学习方法,不断提高自我,完善自我,全面提高自己的理论知识的运用能力,在实践中学习,在学习中收获乐趣。
5心得和体会
这次微机原理课程设计历时两个星期,在整整两星期的日子里,不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
汇编语言是比较原始,接近硬件的一种编程语言,形式非常简单,但这也给复杂程序的编写带来困难,越是复杂的程序,其可读性越差。
因此我们编写汇编程序时一定要有清晰的程序流程与程序逻辑结构,不仅要在纸上画出流程图,还要在脑海中呈现出每一步的代码,才能把较大的程序顺利编写完成。
除此之外,还应敏锐地把我程序的每一个部分,将大程序分割成一个一个子程序分别实现其功能,这样便可自底向上、循序渐进地完成大程序的编写。
在这次的课程设计中,对于汇编语言的各种功能终于有了一个比较全面和具体的认识,在亲自动手编写程序的过程中,发现了很多读程序时不能发现的漏洞。
虽然上课学过很多的理论,平时也看了一些辅导书上的程序,但是真正自己动手才发现各种指令和伪指令代码间的联系和应用,这次经过一段上机的实践,对于怎么去排错、查错,怎么去看每一步的运行结果,怎么去了解每个寄存器的内容以确保程序的正确性上都有了很大程度的提高。
通过这次课程设计使我更加体会到了理论与实际相结合的重要性,只有理论知识是远远不够的,在实践中可能会遇到各种各样的问题,不多经历就无法感受到这一点。
要在实践中提高自己的动手能力和解决问题的能力,从而学以致用。
参考文献
[1]陆忠华等,《汇编语言程序设计》,科学出版社,2000.
[2]宋锦河,《汇编语言程序设计》,中国水利水电出版社,2003.
[3]杨季文,《80X86汇编语言程序设计教程》,清华大学出版社,2001.
[4]沈美明,温冬蝉.《IBM-PC汇编语言程序设计(第2版)》.北京:
清华大学出版社,2001.
[5]周明德.《微型计算机系统原理及应用(第4版)》.北京:
清华大学出版社,2005.
[6]陈章龙,陈泽文.《IBM-PC机软硬件接口及实验》.北京:
人民邮电出版社,1993.
[7]王爽.《汇编语言(第2版)》.北京:
清华大学出版社,2008.
[8]周佩玲,彭虎,傅中谦.《微机原理与接口技术》.北京:
电子工业出版社,2005.
附录
1.完整程序代码:
DATASEGMENT
PIANO
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||||||||||||||||||||||",0ah,0dh
DB"||||||||",0ah,0dh
DB"||||||||",0ah,0dh
DB"||||||||",0ah,0dh
DB"||||||||",0ah,0dh
DB"||||||||",0ah,0dh
DB"---------------------------------------------------------------$"
INFO2DB0DH,0AH,'~MusicPlayer~!
$'
INFO3DB0DH,0AH,'Selectonetoplay!
$'
INFO4DB0DH,0AH,'INPUTERROR!
$'
INFO5DB0DH,0AH,'PLEASEINPUTAGAIN!
$'
MUSLISTDB0DH,0AH,'AMusic:
Maryhasalittlesheep'
DB0DH,0AH,'BMusic:
Happybirthday'
DB0DH,0AH,'CMusic:
Twotigers'
DB0DH,0AH,'XEXIT'
DB0DH,0AH,'$'
;******************************************音乐一玛丽有只小羊羔
MUS_FREQ1DW330,294,262,294,3DUP(330);音乐1的频率节拍1,2小节
DW3DUP(294),330,392,392;3,4小节
DW330,294,262,294,4DUP(330);5,6小节
DW294,294,330,294,262,-1;7,8小节
MUS_TIME1DW6DUP(25*2),50*2;音乐1的节拍表1,2小节
DW2DUP(25*2,25*2,50*2);3,4小节
DW12DUP(25*2),100*2;5~8小节
;*******************************************音乐二祝福歌
MUS_FREQ2DW262,262,294,262,349
DW330,262,262,294,262
DW392,349,262,262,523
DW440,349,262,262,466
DW466,440,262,392,349,-1
MUS_TIME2DW50,50,100,100,100