上海首家 Ableton 官方认证教育中心 GateMusic 門音乐正式上线

Steinberg UR-C 细节全知道!第三期:驱动

Tegeler Audio Manufaktur VTRC 评测:「昂贵」的声音长这样吗?

喜大普奔:midifan.fun 音乐人欢乐社区 iOS 和 Android 应用下载起来!

2020年10月号《Midifan 月刊》技术刊物上线,戳这里阅读

Reaktor 之高级路由设计

分享到微信朋友圈

· 曾照南 添加于 2015-07-23 · 暂无评论

很多人在学习Reaktor一段时间后仍然不知道自己究竟学了多少东西,其实原因是Reaktor它本身是有针对性的,其实从设计层面上来讲,Reaktor可分为两种设计,一是界面设计,二是声音设计,更多人对Reaktor的理解往往都只停留在认为它是用来做音效,也就是说第二种声音设计,所以他们也就会无形地忽略了第一种设计,即界面设计;如果说早期的Reaktor在界面设计很平庸的话,那么主要原因是因为那个时候普遍人对界面的要求不是很好,更多的是注重声音的部分,可当Reaktor后续的升级,我们看到了更多不一样的新颖设计,最有代表性的就属Razor,这款合成器无论是从声音还是界面的设计,都让很多Reaktor用户或者非Reaktor用户惊呼,原来Reaktor也可以这样做,但实际上,Reaktor在没升级之前,它已经是有能力做到这点了,只是随着很多人开始对界面设计的要求越来越高,很多开发者也越来越注重界面设计,所以从分工上来讲,开发一个Reaktor合成器或者效果器,项目管理者应当合理分配技术人员,比如让一些人专门去研究完成界面设计的部分,然后让另外一些人专门去研究底层声音设计的部分,最后再把这两部分完成的成果结合起来。

那么究竟什么才算是界面设计呢?可能对于一个图形设计人员来讲,无非就是做做图,但实际在Reaktor里做界面设计可不是那么简单,有时候你会觉得用编程语言去做一个界面简单操作的设计会比在Reaktor做同样的效果来得简单许多,其实是因为如果作为一个编程人员来讲,他在做之前很多逻辑都已经想好了,又加上编程语言能很有效率很直观地表达编程者的想法构思,可这在Reaktor却就不同了,它不是编程语言,但你可以认为它也是一种编程,只不过编程的方式有所不同,要知道Reaktor都是模块搭建,事实上这种搭建方式在编写一些逻辑方面是很有难度的,所以有很多在Reaktor做设计的都没有花太多时间在界面设计上,因为它们知道其实在Reaktor做界面设计是很有些难度的,当然如果只是做一些简单的界面设计,那就不算什么难度了,其实从官方上很多人做的Ensemble来看,他们设计的界面都算是比较正统,没有太多创新大胆的部分,大家也可以看到Razor这款合成器在设计上就比较新颖,尤其是中间视觉设计部分,简直就是它最大的卖点,所以这也证实了很多人在购买一款软件,首先他会先看这款软件的界面设计如何,接着再听声音效果如何,通常如果界面设计非常棒,声音设计不能算是很好但也不赖的话,买的人在心理上会觉得它是声音最好的软件,当然原因更多是界面设计的问题,好的界面设计就像催化剂一样,让你一眼就会认为它是好软件,不过上面讲的这些都仅仅只是针对那些对界面要求比较高的人,倘若你是个只专注声音好坏的人,那么界面设计对你来说都是扯淡,但个人觉得不管声音是否好坏,一个好的界面设计还是非常重要,尤其是现在。

好的,回到主题上来,究竟什么是路由设计?路由设计说到底就是改变信号的部署,这种在FM合成器的应用上表现最为明显,比如FM8或者Ableton Live的Operator,它们都有路由设计部分,当然相比FM8,Operator显然比较简单;除此之外,路由设计还有另外一种应用,那就是在效果器上,像Native Instruments推出的Molekular(图1),它就是一个带有路由设计的模块效果器。


图1

从声音设计上来讲,Molekular做得非常好,它总共有四个效果器模块选择,每个模块都提供多种不同效果器选择,如果有认真去玩过Molekular都会觉得它很多效果做得非常棒,当然声音这种太感官性的东西都因人而异,不过不可否认的是这款效果器的界面设计太完美了,丝毫不逊Razor;我相信很多人都玩过不少效果器,但这样玩效果的还真是第一次见,你不需要担心每个效果模块究竟加载哪种效果,你只需要考虑怎么在路由设计界面安排它们的处理顺序即可,而且Molekular还提供了八种路由方式,结果如图2所示。


图2

其实路由设计在我们平时加载效果器是一样的,举个例子,我们通常会给一个音轨添加一个或者一个以上的效果器,但当你添加越来越多的效果器后,这些效果器的先后顺序就变得非常重要了,比如你可能想某个效果器移到另一个效果器前面或者后面,这个时候你可以拖动这个效果器来改变它的位置,要知道一个效果器在另外一个效果器前面和后面所得到的效果是截然不同的,比如把一个失真效果器放在滤波器前面跟放在后面的效果肯定是不一样的,所以实际上我们平时在改变这些效果器位置就是一种路由设计,只不过这样的路由设计显然比较单一,可以知道这些效果器连接都是串联的方式,但Molekular就不同,它考虑更多的情况,比如有可能是两个效果器串联跟另外一个效果器并联,像这样,有些DAW就没法做到,不过有些DAW倒是有提供实现的具体办法,比如Reason有个Combinator,利用Combinator就能把一些效果器整合在一起,并实现了我们想要的效果;除了Reason之外,Ableton Live也提供了相应的实现,它提供了Effects Rack,同样也能整合效果器;尽管上面说的能实现不同路由设计要求,但事实上它们在操作方式还是处于比较尴尬不够灵活,就简单举个例子来说,假设我想要串联三个效果器,然后跟一个效果器并联,那么通过上面的方法是可以实现的,但假设我想改变串联三个效果器彼此的位置,或者说我想让串联三个效果器里其中一个效果器跟并联效果器交换,那么这种在操作上显然就比较麻烦了,尽管花点时间能改变过来,但从操作层面上来讲,显然是不够灵活的,所以Molekular好就是好在它能时刻改变某个效果器的位置,只需要通过鼠标拖动即可实现,比如你想改变效果器1跟效果器3的位置,你只需要通过鼠标按住效果器1不放并拖动到效果器3的位置释放,这样效果1的位置将会取代效果器3的位置,而效果器3将会跳到效果器1的位置,想想这是多么激动人心的设计啊。

可能大家看到这里还不知道我在讲什么,不过没关系,现在我会通过一些图来讲解我们要做的路由设计究竟是什么。

首先我们先考虑所有都是串联的方式,然后以四个为准,结果如图3所示。


图3

上面数字方块代表每个效果模块,假如我们想让方块1跟方块2,那么我们必须有两种方式实现,第一种是移动方块1到方块2进行交换,第二种是移动方块2到方块1进行交换,结果如图4所示。


图4

上面两种方式实际上都是一样的,可以说操作上是一样的,达到的效果也是一样的,或许你会觉得这样的操作确实太小儿科了,但如果你这个时候想开始着手在Reaktor去做这样的效果,估计你肯定摸不着北,当然你可能会说为什么要这样做,为什么要想那么复杂呢?不就是一个简单的操作而已吗,实际上你可能会把所有情况都列举出来,比如如图5所示的所有情况。


图5

我们可以看到,如果要考虑所有情况的话,那么它总共就有24种,如果你稍微学过数学的排列组合,你立马就能知道总共是24种,倘若如果上面是以五个为准,那么总共就有5*4*3*2*1,即120种情况,这个时候我想问,你能列出所有情况出来吧,即使能,估计列完所有情况后,你都累成狗了;那么你肯定会说,不需要那么多效果出来,就以四个为准,也就是24种,这个还是可以列出来,好吧,我不排斥这样的做法,但随着复杂性越来越大,这种做法简直是不可取的,所以我们希望能像套公式一样,有个规则让你套用,因此我们必须要把所有更复杂的问题想清楚一遍。

上面讲述的是针对所有情况的考虑,但除此之外,还有一点我们需要考虑的是,我们这样做是否对我们想要的结果有所帮助,也就是说,我们每切换一种情况,效果模块的处理顺序是否真会发生改变,如果可以的话,我们应该怎么样来实现?其实这个有点复杂,但我必须要提前阐述清楚,不然等到我们所有界面设计都完成的话,才发现所有的时间和精力都是白费的,所以我们真的有必要提前来考虑这些问题。

OK,那我们就以刚才的图3和图4的情况来进行讨论,我们已经知道这只是两个效果器的位置互相交换,那么我们应该怎么来实现呢?其实如果你对Reaktor的搭建有点经验的话,这一点事情真难不倒你,其实我们可以在每个效果模块里加入所有效果,也就是说每个效果模块都包含其本身和本身以外的其他三个效果,这样一来的话,我们就可以利用路由模块,比如像Selector模块通过不同索引值来让信号路由到不同的效果,这点是非常容易轻松办到,当然更好地建议是利用Switch模块,它能节省不必要的CPU开销。

注意上面的情况是考虑每隔效果模块的效果都是固定不变,比如效果模块1是Filter,效果模块2是Delay,效果模块3是Distort,效果模块4是Reverb,因此所有效果只有四个,也就是说对于效果模块1的效果永远都是滤波效果,对于效果模块2的效果永远都是延迟效果,其他的也便是如此,所以我们在对每个效果模块列举所有效果仅仅只需要4个即可,示意图如图6所示。


图6

事实上我们上面是考虑每个效果模块都有效果加载,其实我们还需要考虑没有效果加载的情况,也就是Bypass,其实从图6我们可以看出要实现Bypass一点都不难,我们只需要让Selector的Pos为0的时候就是Bypass,其他的效果从1开始依次排列下来即可,也就是说现在Filter效果不是路由到0,而是路由到1,其他的效果路由依次增加,那么可能有些会说,你上面那考虑的24种情况都是在0到3这个范围在讨论,现在已经变成是从1到4开始讨论,那这不是很简单吗,我们只需要把上面考虑的24种情况都加上1不就变成了1到4这个范围内讨论了吗;那么你可能还会再说Bypass的部分要怎么处理,好吧,我想说如果你按照上面我讲这样做再去实现Bypass的话,可能难度会有些不同,其实我们是可以不需要让Selector增加一个端口来处理Bypass,我们为何不再增加一个Selector,然后给它指定两个端口,并利用Button模块来进行切换,当Button处于打开的情况,信号就处理带有4个不同效果的Selector,如果Button处于关闭的情况,那么信号就直接让原信号通过,结果示意图如图7所示。


图7

好的,按照上面讨论开始进行设计,基本上你已经完成了声音路由的部分了,但我们上面只是考虑每个效果模块仅仅只有一种效果可以选择,假设要是每个效果模块都提供很多种不同的效果处理,那么情况是如何?实际上,我们不需要担心,我们仍然有办法可以解决,我们可以利用把每个效果模块内的所有效果打包在一块,然后利用List进行选择,也就是说你依然可以利用图7的方式进行设计,你需要的只是在Filter、Delay、Distort和Reverb内设计不同的效果即可,路由的方式依然不改变,当然随着你效果越来越多的话,处理量就会越来越大,于是优化就显得非常重要了,所以我个人建议使用Switch模块,不仅仅是四大效果模块的路由,连同每个效果模块内的所有效果都可以使用Switch模块,因为它确实能有效地节省你电脑CPU开销。

OK,我们分析了声音路由的走向,接下来我们就需要对此要求作出相应的界面操作,也就说怎么样才能让界面操作实现上面的声音路由,我们还是以四个效果模块为准,那么如果如上面说的全部情况都列举出来的话,总共也才24种,说实在,你可以把所有情况都做成一个选择列表来选择,当然这也是最常用,最直接的方式,只不过我们上面说,如果效果模块不仅仅局限在四种,那么这样一来就不利于对整个搭建工程的维护,所以我们必须要寻找一种合理的方式来处理这种路由方式,不用说,开头说到的Molekular里的路由方式就是个很好的例子,所以我也是参照这种方式来进行设计,注意我本身并没有买下Molekular,所以也不知道Molekular里路由操作具体的搭建是如何的,所以接下来实现的过程都是经过我自己多日地不停思考测试和研究才做出来的,由于这种方式真的有其灵活性,因此有必要好好来讲解一番。

首先我就想我需要一个Mouse Area模块,这个是一个可以显示鼠标操作的区域,接下来我还需要一个处理的对象,一开始我本想做图来表示,后来想想直接用Multi-Display来做研究测试再好不过了,但很快问题就来了,究竟我单单用一个Multi-Display就能实现吗?实际上我很清楚Multi-Display只是用来要操作的图形,如果不考虑太多细节的话,我想应该是没什么问题,可后来的几次测试让我发现,我并不能实现图形缓动效果,即Easing,这是一种鼠标移动效果,可能不懂一点物理的人不知道这个到底是什么,其实这种效果非常简单,就是假设鼠标一开始在(0,0)位置,图形的位置跟你鼠标的位置是一样的,当你快速移动鼠标到某个位置,那么图形的位置也将会发生变化,但这种变化不是瞬间的,也就是说这个图形的位置不会立马变成鼠标的位置,而是会从一开始的位置慢慢移动到你变化后的位置,如果在Reaktor里实现这种效果,最有效的模块属Smoother模块,注意Smoother模块有两种模块,一个叫Event Smoother,另外一种叫Audio Smoother(如图8所示)。


图8

好的,似乎Event Smoother已经帮解决了缓动的问题,但问题依然是我是需要一个或者是四个Multi-Display呢?由于Multi-Display(如图9)除了Idx是一个Audio Input外,其他的都是Event Input,也就说当我拖动一个图形是跟另外一个图形交换位置时候,释放鼠标后,它会执行它们,让它们进行交换,而且这个交换过程必须是平滑进行的,意思就是如果我选择一个Multi-Display,我需要在这个Multi-Display显示区域里显示四个图形,并且这四个图形无论我鼠标如何拖动如何释放,它都要让图形做Easing运动,举个简单的例子,假设我给Multi-Display设置四个对象,然后每个对象都要通过Idx来访问,那么比如我想让第一个对象跟第三个对象交换位置,执行后,第一个对象应该是慢慢移动到第三个对象的位置,同时第三个对象也是慢慢地移动到第一个对象的位置,也就是说我可以让第一对象到达第三个对象位置后再来通知Multi-Display要执行第三个对象的操作了,可什么时候才能让第一个对象执行完去执行第三个对象呢?我发现这样思考方式会让问题越来越复杂,因为我还有一个操作范围的部分要考虑,就是鼠标必须要在对象的执行范围内才能执行对象,于是我们就是要设定访问范围,我们设置了Multi-Display的尺寸为200像素*120像素,这样我可以把四个图形分布到这个宽度范围内,四等分后也就是每等分50,因此,每个图形的执行范围都是在最小单位50内,即第一个图形的执行范围在0到50,第二个图形在50到100,第三个图形...反正依次类推。

图9

上面说了那么多,可能大家还真不知道我在说什么,索性我就直接给出最终的搭建,如图10所示。


图10

很多人第一感觉估计会说有点复杂?不过老实确实很复杂,不是一言两语就能说得清,大家也知道我上面已经废话了好多都还没让大家听明白在讲什么,但我想说明的是,上面只是在讲动机和需求,真正涉及到实现的设计都是非常复杂,就好比讲一个原理,可能稍微举个例子,很多人就会明白这个原理到底是什么,但说到真正应用这个原理,并去实现一些需求,这个可就需要费很多脑力了,大家也看到上面的最终搭建图,实际上我是把它们每部分实现的功能都封装到了Macro里去了,如果你随便点开一个Macro里去看看,你就会知道里面还有不同的搭建,甚至Macro里还有其他的Macro,这样做是让自己能更快更清晰地分清每部分该执行的任务,像图形的部分,实际上我是用到了四个Multi-Display,为什么要这么做呢?原因是为了更好的实现Easing效果,而且我们把它实现的功能封装到了Macro,这样每个图形就互不干扰,细节部分如图11所示。


图11

从上面图11,你可以看到还有其他的Macro,比如Range用来控制范围,Smoother就是实现缓动,Offset用来执行偏移,并实现最终图形的显示;除此之外,你还会看到逻辑模块AND,它是用来执行鼠标事件,比如鼠标按下去该执行什么,鼠标释放后该执行什么,当然这里鼠标释放应该执行交换,注意有个Reset就是用来指定鼠标释放后所处的位置,并利用这个位置对应的索引值来选择该回到什么位置点。

如果你点到这里,其实这些都不算是最复杂的部分,如果你有看到一个叫Route的Macro,那么你可以点进去看看,这个才是最关键的设计,结果如图12所示。


图12

你会发现Route内的搭建果然很复杂,但这里我就不一一详细解释,因为实在是有点太复杂了,导致我一不小心可能也会讲乱了,我就说说我一开始设计的思路;一开始我不是考虑在Reaktor里实现的,而是先利用代码的方式来实现,我发现利用代码语言去实现相比在Reaktor里实现简单许多了,只需要利用数组的方式就能实现,可怎么我怎么把思路套用到Reaktor上来的,其实我代码里是这样实现的:首先我创建一个索引数组Index,数组长度为4,然后我给数组Index初始化,即Index = {0,1,2,3},当然除此之外,我也创建了四个图形对象,也给它们初始化,并把它们也放到了数组里以便后面的处理,那么接下来我只需要利用赋值的方式来执行即可得到我想要的结果,所有的这些都是在Processing里实现,如图13所示。


图13

你可能觉得这个跟Reaktor无关,确实它们一点关系都没有,一个是搞图形的,一个是搞声音的,但我这样做的原因只是想理清自己的思路,当然要在Reaktor像代码那样实现是一件很困难的事,尤其是赋值,怎么赋值呢?Reaktor有数组这玩意嘛?不好意思,确实没有,当然你硬要说有的话,那么我只能说Core Cell倒是有个Array,不过Core Cell不是什么鬼都能整明白,估计等你整完了,别人早就做出来了,所以通常性我都不建议去Core Cell里去费工夫,因为那个真的是针对更为底层的开发,那么既然如此,怎么才实现呢?说实在这个问题困扰了我不少天,但最后还是被我解决了,答案是Event Table。

没错,如果说在Primary Level里有没有类似数组功能的模块,那么属Event Table最实在也最形象了,事实上我也是给Event Table设置4个数值,默认开始是0到3,然后利用Iteration来初始化和执行交换数值的功能,思维是这样的:首先我需要判断的是当我鼠标点下去,鼠标在什么位置,也就是说它的X值是多少,然后利用Modulo模块判断这个X值被50除得的除数是多少,并利用这个除数作为索引值来判断当前鼠标将调用哪个图形,而这段执行刚好就是我上面讲到过的Range;除此之外,我们接下来会移动鼠标到想要的位置,在这时,我们是要记录鼠标点下去被选择图形的当前索引值和移动后所处图形的索引值,这样做是为了鼠标释放后交换索引值,并改变Event Table里的原有的数值,比如我们移动图形1,然后它的索引值是0,当我们拖动鼠标到图形3的时候,那么图形3的索引值为2,这个时候两个索引值都要被记录下来,然后一旦释放鼠标后,索引值就进行交换,也就是Event Table原来是0123将会变成2103,这些将会被重新写入到Event Table里去,当然鼠标释放后除了写入改变的索引值外,我还让它在执行读取,以后我希望它时候是保持动态,而不是等到我再一次点击才出现上一次变化的数值,这样对我来说就无法实现最终的路由设计。

OK,Route部分确实是非常复杂,本来想利用大篇幅去讲解这个部分,但我发觉其实这种复杂的东西越讲越多,听的人和看的人反而容易犯晕,所以索性草草讲完,最后附上工程文件,如果你有意向想了解的,可以自行下载,我也欢迎有共同爱好并在Reaktor研究上有走了一段路的同道人士一起来研究探索。


本文出自《midifan月刊》2015年5月第111期


可下载Midifan for iOS应用在手机或平板上阅读(直接在App Store里搜索Midifan即可找到,或扫描下面的二维码直接下载),在iPad或iPhone上下载并阅读。

文章出处:http://magazine.midifan.com/detail.php?month=2015-06#41做人要厚道,转载文章请注明出自 midifan.com,谢谢

暂无评论

添加评论