870920 Menu

Synthesiser类群详解 3-2

SynthesiserVoice

抽象类,该类可将所持有的SynthesiserSound渲染为Synthesiser所需的音频流。一个SynthesiserVoice相当于合成器发声时的一个声部,一个声部在同一时间产生一个SynthesiserSound所“描述”的声音。合成器持有一个声部数组,因此,可在同一时间播放多个声部,从而实现可同时发声的最大音符数,即MIDI音源的最大复音数。

也就是说:MIDI音源(合成器)最多有多少复音,就必须拥有多少个本类的对象,每个本类的对象持有并负责渲染一个SynthesiserSound。

Synthesiser添加本类对象(增加复音数),通过其Synthesiser::addVoice()来完成。

SynthesiserVoice的构造函数无参,其纯虚函数有:
 canPlaySound () 如果能够渲染给出的合成音,则必须返回true
 startNote () 开始渲染音符
 stopNote () 停止渲染音符
 pitchWheelMoved () 弯音值变化时所执行的代码
 controllerMoved () MIDI控制器变化时所执行的代码
 renderNextBlock () “渲染”下一个音频块,产生合成器所需的音频流

SynthesiserVoice的public非虚函数:
 getCurrentlyPlayingNote () 返回当前正在播放的MIDI音符
 getCurrentlyPlayingSound () 返回当前正在播放的合成音
 isPlayingChannel () 检测本类所持有的合成音是否可响应给出的MIDI通道
 setCurrentPlaybackSampleRate () 设置采样率

SynthesiserVoice的protected函数:
 getSampleRate () 返回当前使用的采样率
 clearCurrentNote () 当前所持有的合成音置零,重置本对象的状态

SampleVoice

SampleVoice是SynthesiserVoice的派生类,持有(且只能持有)并负责渲染一个SampleSound(音频文件、录音采样)。本类继承了基类的所有public和protected函数,没有进行重写,实现了基类的所有纯虚函数,没有增加任何新的成员函数,同样是默认的无参构造。由此可知,所有使用本类的代码,均可直接针对基类来编程(依赖倒转原则)。

SampleVoice所实现的6个纯虚函数详解如下

 canPlaySound () 直接返回本类所持有的SampleSound是否为空,此处使用了动态强转,见下:

 startNote () 基于所持有的SampleSound的标准音高(频率),计算所给出的MIDI音符的对应音高,设置该音符在开始发声和结束发声时的缓始、缓释的音量变化信息

 stopNote () 所持有的SampleSound指针置零,音符发声的缓始和缓释状态重置

 pitchWheelMoved() 空函数,没有执行任何代码。程序员的派生类可在此定义或处理MIDI弯音轮事件

 controllerMoved() 空函数,没有执行任何代码。程序员的派生类可在此定义或处理MIDI控制轮事件

 renderNextBlock() 将本类所持有的SampleSound所代表的音频数据保存到本函数的1参缓冲对象中

SampleSound和SampleVoice是实现MIDI软采样器的核心类。通过研究这两个类的源代码可得知:

  • SampleSound代表一个音频文件,SampleVoice则负责将该文件的数据转为内存中的音频流。
  • SampleVoice负责设置SampleSound发声时的缓始、缓释、音量(力度)、弯音值对应的音高变化。
  • 一个SampleVoice对应一个SampleSound。
  • 一个SampleSound可响应多个MIDI音符和所有的MIDI通道,SampleVoice负责处理不同音符的音高问题。
  • SampleVoice的职责除了转换音频数据和设置有关信息之外,还作为Synthesiser(合成器)的复音声部。
  • Synthesiser最大几复音,就需要添加几个SampleVoice。
  • Synthesiser将收到的MIDI信息发送给所持有的每个SampleVoice,使一到多个SampleVoice同时发声。
  • 多个SampleVoice同时发声,相当于不同音高的多个MIDI音符同时发声。
  • 同时发声的每个MIDI音符均对应一个SampleVoice,从而均对应一个SampleSound。
  • 等等……