作品内容:
基于Qt平台开发的一款钢琴模拟器,主要完成了对钢琴的全键全音调模拟,使用者可以在电脑上通过28个键完成钢琴曲的演奏。另外,我们还添加了延音、变调、录音、播放、教程等功能,旨在为用户提供完整的电脑钢琴体验。
软件外观:
实现思路:
- 整体框架的构建
首先肯定是要有一个承载钢琴键的载体(mainWidow),在其中构建了88个PianoKey类的琴键,这个过程中比较重要的有两个步骤,一个是底层背景以及菜单栏的构建,这两个我们调用了Qt提供的类如QPainter等类以及其成员函数,构建了软件框架及背景,其次是其中钢琴键图像的呈现,我们在PianoKey类中添加了初始化图像的函数语句(因为其本质是一个按钮,所以可以通过设置按钮的图标即可实现。
- 钢琴弹奏的动态实现
钢琴弹奏一共有两个要点,一是音频,二是动画。
首先,当相应的按键消息进入MainWindow时,其中的KeyPress以及KeyRelease函数(重载其父类的虚函数)会识别相应的按键消息,比如对按键Key_T,窗口识别其按键消息后会调用音频播放以及动画动作的函数,从而实现演奏功能。
其中,钢琴声音的实现我们是使用了Qt提供的QSound类,对每一个键初始化了一个音频文件,当按键消息处理时,我们会播放这个文件。
然后是动画的实现,我们的按键“按下”和“弹起”的动画是通过图片的切换实现的,就是在Press的处理函数中加载按下后的琴键图片,在Release的处理中加载琴键平时状态的图片。
还有有些细节,比如Tab键和Space键是不能在KeyPress函数中响应的,因为系统已经将其使用了(Tab是窗口切换),我们在事件分发的底层装了一个“过滤器”——eventFilter,从而实现了对这两个键的使用。
- 音调的切换
我们只使用了电脑键盘的28个,这意味着我们不同一次性弹奏88个键,解决办法就是切换音调。音调的切换是通过音调类“Tone”以及其派生出的15个子类实现的,音调的切换其实就是父类指针指向不同的子类,使用不同子类中初始化的音频文件,从而实现了同一个按键,不同音调下对应的钢琴键不同,当然动画也会响应改变。
- 录制和播放
录制的过程其实是重载>>以及<<运算符之后,在按键处理函数中加入写入文件的语句即可,录制的按键特征主要有时间刻度、音频文件名称、是否延音。播放的实现流程是,先将录制好的文件中的信息读入到这个链表类(Record_list)的对象中,然后用“出队”的相似流程,对每一个音频信息处理并播放,其中使用了一个定时器,经过两个连续音频的时间差值之后,时间上溢,触发timeout信号,播放音频及按键动画。
- 新手教程等菜单栏功能
这一部分主要是对Qt提供的ui界面编辑器的使用,并用connect语句连接相应的功能函数,从而实现弹出对话框等动作。
测试过程:弹奏、播放和录音的测试可以在使用中测试。
结果是:
弹奏功能在不同机型下的流畅度会有所不同,其本质是处理器的差别(我们使用了多线程)多核的处理器会更流畅,相关按键的基本功能始终存在(包括切换音调,延音状态)。
录制功能也能顺利实现,成功的记录所弹奏曲目的信息,播放功能测试时有点问题是,在播放的同时不能弹奏,否则会出现闪退的情况,原因是程序在调用函数时,按键消息的进入会被阻塞,从而出现crash的冲突处理,函数异常退出,程序闪退。
其他功能都能顺利实现,加载需要20s左右。