《一场内心的万物复苏》讲师专访——赵靖

适合手机应用的高品质声卡——TOPPING E 1X2 OTG 评测

杜比全景声监听控制器的奥秘:Ginger Audio 终极解决方案和性价比可以兼得

旗舰级的监听耳机新标杆:Sennheiser 森海塞尔 HD 490 PRO 监听耳机首发体验

零基础到专业制作人:HEMe 全新概念的培训 + 作品发行计划新年再出发!

REAKTOR 小贴士:关于 Table Reference Drop 的一个小问题

曾照南 添加于 2019-02-20 ·

分享到微信

暂无评论

我们在使用Table Reference,尤其是涉及到Table List模块的时候,会遇到“加载一个音频文件后是否要被选中”这样的问题。

通常,一般情况下的连接是这样的:


不过上面会出现的情况是,尽管音频文件可以加载进来,但最终Table List模块并不会选中加载后的音频文件,也就是说,Table List模块最底下的“Sel”输入需要有个事件到达来触发它选中音频文件,例如下面“未选中”和“选中”的状态。


当然,我们要的是“选中”状态的结果,要的是音频文件一旦被加载进来后就被选中。

方法可以很简单,直接利用Mouse Area模块的“DpO”输出。


提示:“DpO”输出是当音频文件拖到Mouse Area模块在Panel显示的所在区域内时将输出1,否则输出0。

不过我们并不是要这样做,而要处理的对象是“DpG”输出。

要知道,“DpG”输出不同于“DpO”输出,一旦有音频文件拖到Mouse Area模块在Panel显示的所在区域内时将反复交替输出2和0,当在该区域内释放鼠标拖拉状态,将输出1,接着输出0,然后结束。

其实我们完全可以采取上面处理“DpO”输出的方法,不过有个问题是Separator模块的“Lo”输出会在有音频文件加载进来的时候不停地发送事件,显然这是不必要的,因为对于Table List模块的“Sel”输入只需要执行一次事件到达就可以了。

好的,我们已经明确要避免多个事件触发的产生,所以我们必须要判断,滤掉重复事件,就像下面这样:


如果细心的你可能会对上面Separator模块输出的连接有疑问,为什么要选择“Lo”输出而不是“Hi”输出?事实上,这就是问题的所在,按道理,Separator模块的“Hi”输出会发送一个事件去触发Table List模块选中加载后的音频文件,可恰恰却不起作用,这个不知道是不是REAKTOR存在的Bug还是说本来就是如此,但不管怎么样,“Hi”输出肯定是不能用,因此,我们可以认为“DpG”输出发送的数值1仅仅只是个数值,并不是一个事件。

了解上面的问题所在,我们同样也可以用一个Core Cell来搞定所有问题。


除此之外,REAKTOR内部也有另外一种Core Cell的解法,我觉得解决的思路也是非常清晰,有效地避免了重复事件触发。


具体分析:首先“DpG”输出发送一个数值2的事件到达,由于2大于0,所以处理上行来判断接下来是否等于1,当然2不等于1,触发一个数值0写入Write模块,紧接着“DpG”输出发送一个数值0的事件到达,由于0不大于0,所以处理下行来触发Read模块读取上面刚写入的数值0,再接着由于0并不大于0,所以最后并没有任何输出,数值0的事件重新触发下面名为“0”的Macro复位处理。当“DpG”输出发送一个数值1的事件到达,由于1大于0,所以处理上行来判断是否等于1,很显然1等于1,所以触发一个数值1写入Write模块,紧接着“DpG”输出发送一个数值0的事件到达,由于0不大于0,所以处理下行来触发Read模块读取上面刚写入的数值1,由于1大于0,因此最终有一个数值1的事件输出。

从上面的分析,我们可以知道“DpG”输出的结果如果是2和0交替,那么最终将没有任何事件输出,而如果“DpG”输出的结果是1和0的话,那么最终将会有一个数值1的事件输出,这很巧妙地避免了不必要的事件触发,而且对“DpG”输出是单纯数值1也很合理地处理,并通过最后一个数值0的事件来重新触发这个不起作用的单纯数值1。

Internal Connections的一些用法

Internal Connections简称IC,很多人一开始会误认为它跟Send和Receive模块一样,你可以认为它们都是一种无线传输,但本质上还是会有些许不同。

IC的实现有两种,直接和间接的方式。我们先来说说直接的方式。

要实现一个IC非常简单,最直接的体现就在Panel类的模块,比如一个Knob控制另一个Knob,我们可以这样来操作:

假设你已经有两个Knob,分别为“Knob A”和“Knob B”,如果你想要用“Knob A”控制“Knob B”,那么请直接在“Knob A”Connect选项下的INTERNAL CONNECTIONS部分点击To...,然后接着同样地操作在在“Knob B”Connect选项下的INTERNAL CONNECTIONS部分点击From...,这样一个简单的IC就搭好了。


这种控制方式有个好处是,无论“Knob A”和“Knob B”各自的数值范围怎么变,它们都是一一对应,专业的说法叫不变性。举个例子,默认Knob的数值范围都是0到1,如果“Knob A”不变,“Knob B”数值范围变成0到100,那么当“Knob A”数值变为0.5的时候,“Knob B”数值就变为50,反过来,如果“Knob B”不变,“Knob A”数值范围变成0到100,那么当“Knob A”数值变为50的时候,“Knob B”数值就变为0.5。

好的,我们来看另外一种间接的方式,它是利用额外的模块来实现,而这些模块分别叫IC Send和IC Receive。


我们先来说说IC Send模块,很显然,这是一个发送端的模块,因此,继续上面的例子,如果你想让“Knob A”去控制“Knob B”的另一种做法就是连接“Knob A”的输出到IC Send模块的输入。


不过到这里,IC还未建立,此刻的“Knob A”还没有控制“Knob B”,接下来我们需要一步关键性的操作,那就是通过IC Send模块来指向“Knob B”。


没错,IC Send模块在Panel上有自己的控件显示,通过它可以快速去选择要控制的对象,比如要控制的对象是“Knob B”,理所当然地选择“Knob B”,这样,间接的IC就搭好了。

你可能认为这样就理解透了IC,不,IC的理解是简单了,可IC Send模块可没那么简单,当你试着以第一种简单方式搭建的IC的思路来操作,结果可能会坑到你,比如你重新设定了“Knob A”的数值范围,当你旋控它的时候,你会发现你控制“Knob B”不是一一对应的,于是这就是这种间接方式的可变性。

搁此,不难发现问题肯定是出在IC Send模块,因为IC Send模块确实存在一个可变的因素,那就是它有自己的数值范围。


很显然默认的数值范围是0到1,这跟Knob默认的数值范围是一样的,所以一开始如果对Knob或者IC Send没有任何操作的话,结果肯定是一一对应,但现在要是改变了“Knob A”的数值范围,那么它与连接的IC Send模块的数值范围就不一致了,这势必会影响到被控制的“Knob B”,比如我们设置了“Knob A”数值范围是0到2,IC Send模块的数值范围不变,那么对于IC Send模块能接收到的“Knob A”的数值范围只能是0到1,1到2这个范围显然是没有任何作用的,也就是说你还想“Knob A”和“Knob B”一一对应,那你必须得保证“Knob A”和IC Send模块它们的数值范围都是一样的,可能你觉得这会影响参数控制的准确,当然我们往往要的就是这种不同,恰恰利用这一点,可以分段去控制不同的参数。(多个IC Send控制,例如下面“Knob A”在0到1范围控制“Knob B”,在1到2范围控制“Knob C”)


OK,讲完了IC Send模块,我们最后来讲讲IC Receive模块。相比IC Send模块,IC Receive模块就更好理解了,当然IC Receive模块也有数值范围设定。


不过如果你把IC Receive模块的数值范围当做IC Send模块的数值范围来理解的话,那就大错特错了,实际上,它是可灵性的设置,你可以根据自己要求的数值范围来设定它,比如你依然利用IC Send模块指定到IC Receive,那么在默认不改变“Knob A”和IC Send的情况下,即“Knob A”和IC Send是一一对应的,那么当你旋控“Knob A”的时候,IC Receive模块输出的数值跟“Knob A”一样,但这个时候你改变了IC Receive模块的数值范围,假设1到5,那么“Knob A”的数值跟IC Receive模块输出的数值就会不同,可它们的控制却是线性,也就是0到1会对应好1到5,例如数值0.5就会对应到3(1到5的中间值)。

一个初始化小插曲

一开始先抛个图:


来了,问题是当你打开REAKTOR后,上面和的最终数值是什么?

可能很多人的答案是1和0,其实如果单单只是从上图给的情况来分析的话,这个答案是对的,但请注意我上面的问题,一个关键点在于“当你打开REAKTOR后”,这个很重要的,也就说打开REAKTOR后,一些模块的初始化会不会有所变化。

好吧,我们先撇开“当你打开REAKTOR后”来分析,首先的情况,分析这个简单结构的初始化,你要学会看出起关键性的模块是什么,很显然,Merge模块是关键点,最终初始化的结果也是由这个来决定,要知道Merge模块在初始化期间只发送一个数值事件,无论它输入端有多少事件到达,输出端发送的永远都是其底部输入的数值事件,所以情况的最终数值当然是1了。

同样地,的情况也如此,因为Merge模块在初始化期间只发送一个数值0的事件,这对于Counter模块是没有任何作用的,所以最终数值当然是0。

上面的分析都是建立在打开和关闭Run audio(快捷键Ctrl+R)。


OK,让我们回到一开始的问题,当你重新打开REAKTOR后,和的最终数值是什么?答案是2和1。

为什么会这样呢?我们会觉得我们上面分析的并没有错,可为什么打开REAKTOR后,结果变了呢?其实很简单,因为REAKTOR做了两次初始化的工作。

好,我们继续拿的情况来分析,按正常初始化,我们知道结果肯定还是等于1,可现在的结果是2,很明显,从数值上来看,就是再加上1而已,而从模块上来看,Merge模块显然没有这个能力,但Counter模块就有了,假设一开始Counter模块的“Up”输入接收到一个数值1的事件,那么它会促使内部累加1的运算,并在其输出发送一个数值1的事件,如果在这个基础上又有一个数值1的事件也到达“Up”输入,那么同样地也会促使Counter模块累加1的运算,由于前一个数值状态是1,再次累加1后,肯定在其输出发送一个新的数值2事件。

同样地,我们也可以在的情况上来假设,假设结果要从0变到1,无非就是要让Counter模块执行累加1的运算,但从Merge模块初始化期间的行为,我们知道它会发送一个数值0的事件,可这个数值0的事件显然对Counter模块一点作用都没有,所以问题的棘手就在这里,因为Merge模块的底部永远处于未连接的状态,也就是说它永远被连接到一个数值0的隐性模块(一种看不到的内部虚拟模块),无论怎么初始化,Merge模块的输出都是0。

对于这个问题该怎么解决呢?有人说可以再添加一个Constant模块,如果是这样,那么这个已经跟原有的问题不同了。其实REAKTOR做了一件巧妙的事,那就是打开REAKTOR后,我给两次初始化操作,第一次初始化所有模块,第二次初始化部分模块。

可能到这里,你们觉得“怎么还可以这样玩啊”!确实REAKTOR还真这样玩,不行我来分析给你们看。

首先,对于第一次初始化所有模块,这个没有什么异议,大家统统“归零”处理(注意这里的“归零”不是指所有模块的内部数值状态都变0的意思),这个比较好分析,依然拿的情况来具体分析。

再经过第一次初始化后,的情况的最终数值显然是等于1。行,紧接着,迎来第二次初始化,这次有点不同,假设所有模块还是跟第一次初始化一样,那么最终数值肯定还是1,但我们也看到了,结果是2,不是1,尤其,我们可以这样来认为,Counter模块在第二次初始化没有任何操作,因此它还是保留了第一次初始化的内部数值状态,然后在第二次初始化后,Counter模块就会发送一个数值2的事件。

回到的情况的假设,分析同样也如此,只是有个不同的地方在于,第二次初始化,隐性模块并没有任何操作,REAKTOR也只能这样来规定,才能确保最终数值等于1,因为如果隐性模块在第二次初始化也来一波,那么结果显然是0,而不是1,由此我们也得到了一个结论:隐性模块在第二次初始化没有初始化。

好的,谈论的情况,让我们继续回到的情况,为什么还要继续讲回呢?因为这里有个“不一样”的模块,它叫“Constant 1”,它是Core Cell,所以我们要来弄清这个模块跟正常的Constant模块的初始化是否相同。

首先要判断这个“Constant 1”模块在两次初始化的行为如何,我们只需要断开Merge模块上面的那个Constant模块:


我们知道按照的情况分析,这里Merge模块顶部的输入只发生一次初始化,当然从Merge模块初始化本身来看,这个断开并没有多大影响,因为Merge模块最终还是以底部输入的事件为主,除非底部输入也处于未连接的状态,那么这种情况就另外讨论了。

在断开操作后,我们保存并重新打开REAKTOR,我们会发现,结果等于1,按道理如果是下面这种情况,结果肯定还是等于2:


由此我们可以知道“Constant 1”模块也只是初始化一次,也就说它第二次初始化并没有任何操作。

不过上面只是“Constant 1”模块默认的情况下,如果你对这个“Constant 1”模块的初始化行为做如下这样的设置,那么在REAKTOR重新打开后,最终结果就是2了,相当于跟真正的Constant模块一样。


IC Send的一个小用途

今天要用IC Send模块来实现一个小东西,那就是动态深度控制。

可能你不知道什么叫动态深度控制,其实说白了就是用一个旋钮去控制另一个旋钮的动态变化。通常性,我们所说的旋钮(比如Knob)都静态的,只有当你鼠标或者外部控制器去控制它的时候,它才会旋动,但我们现在要做的是,让它可以动起来,而这个动起来的幅度大小则由另外一个旋钮来控制。

一开始我们需要一些准备,比如两个旋钮,一个叫“Knob A”,一个叫“Knob B”:


从上图可以很明显看出,“Knob A”比“Knob B”大,这是为了更好地区分它们的主次,说明“Knob A”是主控制,“Knob B”是深度控制,目的让“Knob A”动起来。

增加设置好这两个旋钮,接下来该想想如何实现我们所要的结果,假如我们直接利用IC Send来控制“Knob A”的话,那么会遇到一个很无言的问题,那就是你永远无法用鼠标或者外部控制器来控制“Knob A”。

好的,那么怎么来做呢?方法很简单,我们需要Mouse Area模块来辅助,也就是我们需要添加一个Mouse Area模块,利用Mouse Area模块来控制“Knob A”。


不过也不是简简单单增加个Mouse Area模块就了事了,我们还需要对Mouse Area模块的一些属性进行设置,比如作用宽高设置为41像素*60像素,重要的是Incremental Mouse Mode选项要勾选。


有了这些设置,我们可以在Panel上选择IC Send下拉菜单里要控制的对象“Knob A”。

到这里,基本工作都已经做好了,紧接着就是怎么让它动起来,也就是怎么让它能根据“Knob B”的增加而旋动起来,一个直接靠谱的选择无非就是LFO(低频振荡器)模块,让我们直接给出结果吧!


从搭建结构来看,我们可以知道“Knob A”其实就是个幌子,它只是用来做表面效果,主要的还是在于Mouse Area模块,所以Mouse Area模块实现了一个华丽的转接,并通过“BL”输入过滤LFO对“Knob A”的控制,注意我们用到了Router M->1模块来进行切换,一旦鼠标按下,就切断了LFO对“Knob A”的控制,友情提示,最后别忘了连接Router M->1模块输出到Mouse Area模块的“BY”输入。

6-Step步进器

说到Sequencer步进器,大家都会觉得它太他妈重要了,尤其是作为演出者,一个步进器能好到简直天降奇兵,无所不用其极啊。

当然它最直接的用途就是轻松搞定一段Riff,比起你在那边傻乎乎地一直按着几个音符键效率多了,而且它可以让你腾出更多时间去玩转其他的硬件合成器。

对于REAKTOR来说,它同样也应该有、必须有步进器。

我们知道REAKTOR为了提供几个简单的步进器。


上图从左到右依次是6-Step、8-Step、12-Step和16-Step模块,可能细心的朋友会发现漏掉了一个,没错,其实REAKTOR Sequencer分类下最后一个是Multiplex 16模块,不过这个模块我们先不谈论它,因为一旦你懂得以上这个四个模块,不不不,应该说,你只要懂得上面第一个模块的原理,即6-Step模块,其他的模块对你来说都不是事了。

Let’s go,让我们开始吧!!!

首先,我们上面已经提及到了,无需那么麻烦地把每一个模块都研究过去,如果你仔细观察这些模块,你会很快地发现它们的共同和差异性,显然废话一句,它们都是步进器模块,它们都有相同的一些输入和输出,唯独不同的是步进长度不同,从长度6到长度16,所以事实上我们只需要针对第一个6-Step模块研究即可。

好吧,让我们瞧瞧这个6-Step模块吧。


很明显这是一个事件模块(由于输出端都是事件类型的),它包含9个输入和3个输出。在REAKTOR里,我们了解想要搞懂一个模块,必须就要弄明白其模块的所有输入和输出,这里同样如此,先从输入开始。

6-Step模块有9个输入,但乍看分析下,你可以把它看成是4个输入,因为其实从“S1”以后的输入的性质都跟“S1”一样,所以弄懂了“S1”就等于弄懂了“S2”到“S6”,而这个输入想必没有什么不好理解的吧,它就是用来设置每个步进的数值。

接着,我们来看看其他的三个输入,它们分别是“Clk”、“Rst”和“GA”。

首先“Clk”是一个时钟输入,一旦有个过零的信号到这个输入,就会促使6-Step模块当前步进移到下一个步进;接着“Rst”很显然了,一旦有个过零的信号到这个输入,就会促使6-Step模块复位到开始步进,也就是“S1”位置;至于“GA”是跟输出“G”挂钩的,比如给“GA”输入设定一个数值,那么“G”输出就会在0和“GA”输入设定的数值两个数之间不停地切换,这仅仅发生在“Clk”输入大于0的情况,才会使得“GA”输入等于“G”输出。

剩下的,我们来看看输出,它们分别是“Out”、“G”和“Stp”。

首先“Out”不用说了,肯定是输出每个步进相应的数值,“G”在上面已经讲过了,至于“Stp”,它是用来输出步进序号,也是告诉你当前步进的位置,但有一点需要注意的是,它的输出数值是从1到6,不是从0到5。 

行,搞懂了输入和输出还不算什么,关键要懂得用,怎么跟其他模块配合,这才是最重要的。一个最直接的用法就是,利用6-Step模块去控制音高,比如下面这样,它是一个Macro。


不过一开始我不想马上来谈论它怎么用的问题,而是要让你再更深入了解它的原理,这样吧,换句话说,如果让你重新用REAKTOR有的模块搭建一个6-Step模块,你能实现吗?

额,这个问题,我想应该难度不是很大吧!

梳理下,我们应该需要一个计数器,显然Counter模块最合适不过,再来就是需要一个能求余的模块,这个问题也不大,Modulo模块就能胜任了,再者就是需要一个选择器,Selector模块一直是主力,因此最终的搭建是这样的:


请容我给你们分析下,为了和原6-Step模块的输入端都是声音类型输入,这里只好加入了A to E模块,这是为了确保能处理声音信号,接着肯定要用到Compare模块来判断信号是否大于0,从而利用这个判断后的数值变化去触发Counter模块计数运算,请注意Compare模块输出的信号需要用Step Filter模块来过滤重复的,这样才能保证Separator模块也能筛选好有用的数值事件去作用Counter模块正常运作;同样地“Rst”输入也如此,“GA”相比就简单,只需要把Compare模块的结果与之相乘即可;当然这些都是前期的,关键的还在后面,因为Counter模块计数会无限增加,为了避免数值溢出,我们还需要Modulo这样的求余模块来进行折回,把数值控制在0到5之间,这样就可以利用这个数值去控制Selector模块的切换。

到这里,你应该能大概明白6-Step模块的运作原理,当然上面的搭建还有一个问题,只是这个问题小到可以忽略,那就是Counter模块数值无限累计的问题,解决的手段可以利用Order模块来处理,具体搭建结果如下:


上面是用REAKTOR内有模块搭建的6-Step模块,但需要注意的是,它是一个Macro,但只谈内有模块并不能说明REAKTOR的精髓,其实REAKTOR更为深入的当属Core Cell,所以接下来我要用Core Cell来实现一个6-Step模块,你将会发现Core Cell的神奇之处。

首先我们先增加一个新的Core Cell模块,依次添加相应的输入和输出,结果如下图所示:


看到了吧,一模一样,一个模块就搞定了,我们要做的就是只管在Core Cell模块内部搭建即可。

好吧,在前面我们已经知道6-Step模块所有输入和输出的含义了,也很好地用Macro实现一番了,套上这样的思路,我们也在Core Cell里转换一下。

先拿“Clk”输入下手,我们知道这个必须要过零的信号才能触发计数(这里意思就是我们还要搭建个计数器),那我们就来想,怎么处理过零的信号?很简单,比较,就像上面用到的Compare模块,所以我们在Core Cell模块内也必须找到这样一个比较模块。

那么Core Cell模块内部有这样的模块吗?答案是肯定的,像这样的:


好吧,实话告诉你,这个也是一个Macro,不过跟我们上面提到的Macro有点不同,它是Core Cell独有的,也就是说它不是一个纯粹的模块,它可以点击进去,里面是由Core Cell的一些内置模块来实现的:


同样地对于“Rst”输入也需要这样的模块,而接下来我们需要重点实现的是计数器,也就是说我们需要搭建一个跟Counter模块一样的模块,怎么实现呢?肯定得用Macro。

我们先在Core Cell模块内增加一个Macro,命名为“Counter”,添加相应的输入和输出:


没错,跟REAKTOR原有的Counter模块一样,同样的输入和输出,因此在功能实现应该也是要同样的。

好的,在搭建之前,我们先来简单了解下Counter模块下。


“Set”输入:设定计数的复位值,注意这里不一定是复位到0,它可以是任意值,只不过大多数参考的数值都是0。

“Up”输入:一个正值(只要是大于0的任何数)事件到达触发计数加1计算。

“Dn”输入:一个正值(只要是大于0的任何数)事件到达触发计数减1计算。

有了这样对Counter模块一些基本的了解之后,我们可以到Core Cell模块内开始操作了。

对于“Set”输入比较简单,“Up”输入和“Dn”输入呢?我们依然还是要判断到达它们这里的信号是否大于0,这个问题不难。


对的,我们用到了刚刚说的模块,其实它名叫Route GT,但是我们还是没有完成一个真正的计数器,我们需要一些能用来计数的模块,而在Core Cell里也为我们提供了些可以处理这种问题的模块,它们就是Read和Write模块。


左边是Read模块,右边是Write模块,那么怎么使用它们去实现一个计数器呢?

不用着急,让我想把一个搭建好的计数器呈现给你看:


看似简单,但你肯定还是会问,尤其是对Core Cell一点都不了解。首先这里除了Route GT模块、Read模块和Write模块以外,有多了三个不一样的模块,它们其实分别是Latch模块、Merge模块和x+a模块。


Latch模块说白了,就是Read模块和Write模块最好的应用,它的原理就是先把数值写入,然后通过底下输入的事件来触发,为什么要Latch模块呢!因为我们需要来改变计数的加减,由于Route GT模块的输出不是1就是0,当然我们也是可以去得到-1,但用Latch是最合适不过了。

Merge模块跟REAKTOR原有的Merge模块类似,主要用来整合从Latch模块发送出的数值1和数值-1的事件。

最后一个x+a模块是Latch模块的一种应用,也是先把数值写入底部输入,然后通过顶部输入事件到达来触发加法运算。


OK,计数器Counter完成了,让我们继续回到“Clk”输入,上面说过对于这个输入要判断的是信号是否过零,我们也知道可以用Route GT模块,可有个问题来了,假设,如果假设一个1Hz的正弦波信号输入,那么这个信号有一半是负信号、一半是正信号,对于负信号肯定没有什么影响,但正信号的问题就来了,我们不可能让正信号的每个采样点都去触发Counter计数,想想这个Counter计数该多快,事实上我们只需要当信号过零的时候触发一次就可以了,因此我们需要过滤没必要的触发,一个很好的方法就是利用Latch模块和Dup Flt’模块。


思路很简单,这里的Dup Flt’模块是过滤数值相同的事件,Route GT模块通过Merge模块整合重复发送事件,比如正弦波信号来说,“Clk”输入经过Route GT模块和Merge模块处理后先发送数值1的事件,后发送数值0的事件,注意这里的事件是持续发送的,然后通过Dup Flt’模块过滤下,就变成了当信号大于0的时候才发送数值1的事件,小于等于0的时候才发送数值0的事件,最后我们只需要数值1的事件,于是再用Route GT模块过滤下,取数值1的事件去触发Counter计数,为了界面的简洁,我们可以利用Macro把这样的处理封装起来,命名Gate&Trigger,这样更方便我们复制利用,因为“Rst”输入也需要这样的处理。


好的,解决了“Clk”输入的问题,我们来看步进的数值,很显然,这个肯定需要选择器,比如像Selector模块,这个问题的解决手段有很多,通常大家都会用比较和路由模块来实现,但有一种很快速便捷的方法,那就是利用数组的方式来实现:


可能一开始看到这个搭建看不懂,但其实很简单,无非就是利用读写模块来完成,我们通过把每个步进的数值写入到各自对应索引值的写模块内部,注意上面左侧的那六个写模块,它们都是Macro,然后通过添加数组,给数组设置长度6,最后再利用右侧的读模块读取相应索引值的步进数值。

选择模块的任务完成了,我们需要索引值来触发选择,这就需要计数器Counter了,很多人往往这个时候就把Counter直接连接到选择器,这个就将会导致数值溢出,也就是计数超过5的话,选择器将会重复发送最后一个步进的数值事件,这显然是错误的,因此我们要做一道防护,让超过5的折回到0重新开始计数,意思就是做一个求余的模块,这点很重要,我们也必须这样实现。

那么怎么实现一个求余的模块?如果你是一个新手,不知道怎么搭建的话,没关系,REAKTOR Core Cell有提供你一个现成的,它叫IDivMod:


当然如果你是一个对Core Cell有点熟悉的话,我的建议是不妨试看看,这里我就不仔细展开了,直接拿来用吧。


好吧,我们已经完成了一大部分了,我们来看一下还剩下什么事没做,首先,“Rst”输入解决了一半,“GA”输入还没解决,输出的部分还有“G”和“Stp”。从最开始对6-Step模块的一些了解,我们可以快速知道“Stp”的问题最简单了,只需要把IDivMod模块求余的数值加上1便可连接到此输出,那么“G”输出呢???我们知道它是跟“GA”挂钩在一块的,它输出的数值是由“GA”数值设置来决定的,因此我们需要搞懂的是这个“G”是怎么来的,跟什么有关系?其实它也是最容易想通却可能被复杂化的一个,“G”输出是跟“Clk”输入判断后的信号有关,上面我们已经处理过“Clk”输入,也把这个处理用Macro封装起来,请注意我的命名“Gate&Trigger”,看出我的用意了吗,我的目的就是把Gate和Trigger处理分开,于是乎我这样命名,为了做到处理分开,我只需要在原有的Gate&Trigger基础上添加一个输入端口用来接收“GA”,再添加一个输出端口用来把Gate信号乘以“GA”输出即可。


现在剩下一个“Rst”输入,我们知道在通常情况下,“Rst”输入需要复位的数值都是0,除非特殊情况,还记得我们用REAKTOR现有模块搭建的那个6-Step模块吗,实际上,我们没有考虑很深入,我们做的是让“Rst”输入让计数器复位到0,可实际上对于原有的6-Step模块,它不是复位到0,而是复位-1。很多人肯定会问,你怎么肯定它不是复位到0呢?是这样的,如果是复位到0,那么如果我一旦触发“Rst”输入去复位,那么计数器是会立马跳到0,可经过测试,计数器并不是得到这样的结果,而是停顿了下,然后再回到0,所以不管它是复位到哪个数值,但绝对不是复位到0。

可问题来了,不是复位到0,那复位到哪个数值比较合适,其实对于我的解决,我个人认为复位到-1是最合适不过了,因为只要让它复位到-1,然后再对Counter过滤处理,滤掉小于等于0的部分,这样一来你想看看,一旦“Rst”输入有过零信号经过,那么它将会启动Counter复位到-1,这个时候你用一个IRouter GE模块就能把小于等于0的-1给避开掉了,于是计数器从-1到0需要有个时间,当然这个时间间隔是由“Clk”输入来决定的,从而得到了复位不会立刻马上从0开始计算;从过滤的角度上来看,表面呈现出来的并没有看到-1,那是因为过滤掉了,但实际上内部却是从-1开始计数了,完美。



本文出自《midifan月刊》2019年01月第154期


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

暂无评论