本次基本完成了效果器界面的部分,加入3个Slider控制参数,3个Display显示参数。以下进行总结。
图镇楼
1. AudioEffectX & AEffGUIEditor
用户自定义两个类分别继承于AudioEffectX和AEffGUIEditor(暂称为效果类和界面类),AudioEffectX负责信号处理,AEffGUIEditor负责显示。在这里自定义了ACompressor继承自AudioEffectX ,AEffGuiComp继承自AEffGUIEditor。另外,由于界面类要监听界面类Slider的动作,所以这里AEffGuiComp同时继承自CControlListener。
2. CVerticalSlider
构造时传递如下参数:
/* AEffGuiComp.cpp */
m_p_sld_ratio =
new CVerticalSlider(
rc_slider_size,
this, PARA_RATIO, rc_slider_size.top, rc_slider_size.bottom - 40,
pbmp_thumb, pbmp_sld_back,
CPoint(0,40),kTop);
第二个参数为Slider的listener。由于AEffGuiComp继承了CControlListener,所以是没有问题的。
AEffGuiComp类也因此重写了valueChanged虚函数,这个虚函数来自CControlListener类。
3. effect & editor
在界面类中需要知道效果的parameter(界面类的setParameter),通过effect指针获得。
记不记得ACompressor构造时调用了:
setEditor(new AEffGuiComp(this));
就是把ACompressor*类型的this作为AudioEffect* effect构造了AEffGuiComp实例,这个实例由this->editor接收。ACompressor和AEffGuiComp的关系其实也就是effect和editor的关系。构造effect的同时构造了editor,effect知道editor的存在,editor也知道effect的存在,也可以说这是两个类之间的一种通信方式。上述过程其实就是AEffGuiComp通过调用ACompressor公有函数获得ACompressor的参数,反过来也是一样,比如在ACompressor的setParameter中:
if (editor)
{
((AEffGUIEditor*)editor)->setParameter(index, value);
}
表示editor要跟着effect一起setParameter。
4. Display
setStringConvert可设置字符串转换函数指针。如果有显示字符串格式修改的需求,如,加百分号、单位等,可以自定义一个函数,将函数指针传入。
5. 参数
VST SDK要求所有受控件控制的参数必须为0.0f ~ 1.0f(这也解释了ChannelMixer一章中“相当奇怪的写法”,原先以为是Trick的东西,没想到真的要这样)。这就需要实现一个转换的函数,这个怎样实现都可以。我的做法是使用静态函数,不保存控件参数,接收时直接转化为实际参数。不保存参数的坏处就是要提供相互转换的两组函数,而且可能损失一点精度。如果保存参数只需要提供一组(想想为什么)。参数只能是float 0~1其实很烦,即使是想要一个bool的参数也必须由float转换。
6. 其他细节
- 效果类如果不重写getProductString/getEffectName,宿主端显示的效果器名默认为文件名,如果重写了getProductString/getEffectName,即为设定的字符串。
- CColor可以只定义一个,使用时直接clr(255, 255, 255, 255)修改值(语法糖,不用白不用)
- 界面类中的effect其实是ACompressor*型的,必要的时候可以强转。
7. 改进 & 遗留问题
- Program如何改成默认提供一个只读的预设
- 哪些函数可以删掉(不提供界面时写的那些函数)
- Display如何手动输入修改参数