2017-3-19 21:03 | 发布者: 梒小婵
作者:曾照南 在 Reaktor 你肯定会遇到这样一种情况,那就是每一次事件到达,它们的数值永远都是一样,通常我们称它们是相同的事件;可有时候我们并不需要重复的事件,比如触发音序器,也就是我们需要去滤掉相同的事件,只有当新事件的数值跟前一个事件数值不同才允许通过,像这样的模块,Reaktor 刚好为我们提供一个,它叫 Step Filter。(图1.1) 图1.1 这个模块有两个输入,一个叫 In,一个叫 Tol,In 很简单,只要有事件通过,它就会跟它前一个数值比较,如果不相等就输出到 Out;可能大家对 Tol 不大理解,实际上,Step Filter 模块对它的描述是说,当In的事件数值大于前事件数值加上 Tol 或者小于前事件数值减去 Tol,那么事件将会输出到 Out。 上面说的看上去好像很简单,但要是自已用 Core Cell 来鼓捣一个是否也很简单?好好好,稍等一下,别那么急,在开动之前,先理清一个思路,做一个分析。 假设 In 依次到达的事件数值分别是 1 和 2,那么这两个事件将会依次输出,因为两次的数值都不同,有些会问第一次数值 1 的事件是跟什么比较,答案当然是0,因为一开始 Step Filter 模块默认的数值就是 0,所以 1 跟 0 不相等,显然是可以被输出的,当然这是在 Tol 等于 0 的情况下,如果 Tol 不等于 0 的情况又将会是如何的?我们还是一样上面的两个数值事件 1 和 2,然后给Tol一个设定值,假设这个值为1,那么现在第一个数值1的事件就不是跟 0 比较了,而是跟判断是否大于1或者小于-1,显然1并没有大于1,所以对于数值1的事件,它并没有被输出;好的,接下来第二个数值2的事件,它能否被输出吗?答案是可以的,因为2显然是大于1的,所以数值2的事件将会被输出;不过这里再等等,如果又到达一个数值3的事件,是否会被输出呢?因为我们上面已经说过了,如果对于 In 输入的事件数值大于In输入前一个事件数值加上 Tol 或者小于 In 输入前一个事件数值减去Tol,那么事件将会被输出,所以我们来看看,对于 Step Filter 当前内部的数值已经不再是 0 了,而变成了 2,所以对于新的事件数值必须要大于2加上1或者小于2 减去 1,即大于 3 或者小于 1,那么不好意思,3 依旧没大于 3,因此新数值3事件不能被输出,Step Filter 输出依旧不变,仍然等于 2,也仅仅只是一个等于2的数字,并不发送事件。 OK,有了上面这么详细的分析,接下来搭建的工作就可以准备开始了,还是一样创建一个 Core Cell,给它命名为 “Step Filter”,并添加相应的输入和输出。(图1.2) 图1.2 好的,从刚才的分析,我们知道要想知道事件是否能通过,就要知道事件和前一个事件数值的差值的绝对值是否大于 Tol;等等...这个结论是不是有点懵了,哈哈,学过数学的都应该知道,如果A的绝对值大于B,那么 A>B 或者 A<-b in="" x="" y="" x-y="">Tol,即 x-y>To l或者 x-y<-tol x="">y+Tol 或者 x<Y-TOL,这里我直接给出搭建好的结果。(图1.3) 图1.3 上面的搭建不难看出,先求差值的绝对值,然后把它与 Tol 比较,看是否大于Tol,如果大于 Tol 就触发新的事件数值输出并写入;当然这个搭建还是比较能看得懂,不过我们也可以把 Read 和 Write 的部分重新用 Macro 封装起来,我给它命名“z-1”,意思就是说它是延迟一个采样点的数值事件,这刚好跟我们要的前一个数值事件是吻合的,不过需要注意的是,这里的连接会产生一个反馈,为了更好地去解决它,必须要对 z-1这个 Macro 的 Soild 属性进行关闭,所以你会看到关闭后 z-1 边缘是虚线的状态。(图1.4) 图1.4 第二天 搭建了 Step Filter 后,你会发现原来用 Core Cell 搭建东西也不会那么困难,只要我们能比较一个数跟前一个数的差值就可以解决问题了,当然差值的用法不仅仅如此,我们也可以利用它来知道两个事件前后的时间差,这实际上就是 Tap 的开始。 现在很多 DAW 都有 Tap 的功能,这只是个小功能,但对于一些不能马上知道自己歌曲该用什么 Tempo 的用户来说是一个不错的帮助,尽管它可有可无;同样,Reaktor 也提供了这样一种功能的模块,它叫 Timer。(图2.1) 图2.1 这个模块的图标很形象地表示了它就是处理两个事件的时间差,除了时间差,它也能知道事件到达的快慢,也就是频率F;那么怎么去实现这样一个模块呢?哈哈,其实这个不难,我们可以想一下,要知道两个事件的前后时间差,那么前提是不是需要一个计时器,来确定每个到达事件的时间点,只要知道它们的时间点,就能求出它们之间的时间差了;好的,那我们先来创建一个计时器,比如这样:(图2.2) 图2.2 这个计时器很简单,但需要注意的是,如果从 0 开始算的话,它累计的数要达到44099 才是 1 秒,因为对 CR.C 它默认就是一秒钟滴答 44100 次,当然它也有不同的设置,比如 48000,这样看你设置的采样率;这样如果要换算成秒的话,我们还需要对累计的数除以4 4100,才能得到秒,而如果要得到毫秒的话,那么还要再乘以 1000 才能得到毫秒的结果;除了计时器,我们还需要对Trig进行判断,让大于 0 的才能去触发,然后利用Read和Write去读取当前事件数值和上一个事件数值,并求出它们的差值,即可得到T的结果,而F的结果就是 1000 除以T的结果。(图2.3) 图2.3 第三天 建完了 Step Filter 和 Timer 模块,我们发现其实它们内部的原理都非常简单,并没有那么复杂,尤其是针对 Timer 模块,我们知道对于 Core Cell 事件模块来说,采样率时钟是失效的,并不是说它没有在运作,而是说它不能输出到事件类型的接口,但我们只是把利用 Latch 模块来触发,先让数值写入,然后再用Trig触发输出,这是一个非常不错的用法;可这种方法的限制就会比较多了,有很多时候我们是需要采样率时钟,但我们又想让它可以做为事件类型输出,恰巧的是,Reaktor 为了用户考虑到了,对于 Core Cell 的事件输出接口,它允许你通过“ Allow Audio Events” 这个选项去开启事件接口可以作为声音接口来用,也就是一旦开启了这个功能选项,那么这个接口既可以当事件来用也可以当声音来用,这种功能像有些模块也具备,比如我们之前用过的Compare/Equal或者Modulo模块等等都是。 好的,有了这样一个功能,我们就可以再来做些不同的模块了,比如接下来要搭建的 Hold 模块(图3.1)。 图3.1 其实这个模块的原理更简单了,一个事件到达,然后让这个事件停留多长时间后回归到 0,也就是我们同样需要一个计时器,有了 Timer 模块的经验,相信再来搭建一个计时器不难了吧(图3.2)。 图3.2 有些人可能觉得这里为什么要有个 Rst?其实它是用来对计时器进行复位的,因为我们想让每次触发的时候,计时器先复位到 0 的位置;除了计时器以外,接下来我们依然要回归到常见的问题解决,就是去判断时间是否超过了 H 设定的时间,因为 H 时间的单位是毫秒,所以只要超过H时间,那么结果将会等于 0。(图3.3) 图3.3 图3.3 需要注意的是我们 Out 输出类型已经开启了 “Allow Audio Events”,所以你会发现它的图标有点不同,是事件类型的图标叠加声音类型的图标;然后还有一点需要注意的是,针对Merge模块输出要连接一个 Dup Flt’ 模块,这个模块是用来过滤相同的事件,因为采样率时钟一直在运行,也就是说对于我们搭建的计时器(Stopwatch),它时间一直在走,尽管我们已经限制了当它大于H设定时间后触发一个 0 的事件,但这个数值0的事件会一直输出到 Out,显然这个是没必要的,所以这里就必须要用到 Dup Flt’模块。 第四天 感觉有了上面几个模块的搭建经验,我们似乎就可以往更复杂一点的模块进行了,就好比 Iteration 模块。(图4.1) 图4.1 这个模块也算是经常会用到的模块之一,比如在跟一些图形显示类型的模块搭配,像 Multi Display 和 Poly Display,更是展示了它的好处。 好的,从图 4.1 我们可以看到这个模块有四个输入和两个输出,而且有三个输入接口类型是声音的,不过这并不是说它就是个声音的模块,因为它的输出依然是事件;然后我们从模块的图标可以大体猜一下它有点像是一个计数器,类似于Counter 模块,但它跟 Counter 又有些细微的差别,比如 Counter 模块的增量都是 1,而 Iteration 模块可以通过 Inc 改变这个增量,并且它也能限制计数的数量N,至于 Brk 输入,它全称叫 Break,当这个输入是一个正值的信号,Iteration模块将会停止数数,跟其对应的 Gate 输出也将会变成 0,只有当 Iteration 开始数数的时候它会变成1,直到结束才回归 0;不过除了这些,Iteration 模块还有一个比较不灵活的地方,那就是它累计的速度,也就是 Iteration Per Second,它实际上就是指每秒累计多少下,说白了就是一分钟触发多少次,而这也是我们要搭建它的重点。 行,通过上面的陈述,我们已经知道了 Iteration 模块的运作原理,但接下来怎么利用 Core Cell 去搭建它呢?首先我们还是需要一个计数器,这个很简单,它主要用来累计N次后的数值。(图4.2) 图4.2 我们看到了这个计数器跟之前搭建过的一样,唯独不同的是,我们把之前增量 1换成了可以控制的 Inc;还有除了这个,我们还发现了 Read 模块事件触发的输入不再是时钟信号了,而换成一个名 C 的输入,这样我们就能去控制它触发的变化,因为我们可能不需要像时钟信号那么快的触发速率。 由于上面增加了个 C 的输入,也就是说我们接下来需要去搭建一个能控制触发速率的模块,那么这个模块应该怎么去搭建呢?其实这个模块也不难,同样我们可以利用计数器的思路给它转变一下。(图4.3) 图4.3 哈哈,看到上面的搭建是不是又觉得好熟悉啊,它就是实现 Itertaion Per Second 的控制,我们把Inc的部门改成 Speed,并对累计的结果进行判断,如果大于等于CR.R,那它就触发一个数值 0 的事件,接着计数从新开始,而那个数值0的事件就是我们想要的结果,于是它被连接到了 Trig 输出;可能有些还不是很懂上面具体的原理,我们可以来假设一下,假如我们设置 Speed 等于 1,采样率默认是 44100,那么它要累计 44099 下才能等于 44100,也就是说要等到1秒后才能触发一个数值0的事件,相反 Speed 等于 2,每秒就会触发2才,然后依次推算,所以显然它是符合我们要求的。 好了,有了上面这两个问题的解决,接下来的事情就没那么复杂了,我们直接看搭建好的结果。(图4.4) 图4.4 图4.4 算是解决了累计的问题了,有几个问题要注意的是,可能很多人会忽略掉最终结果还要加上In的数值,可能大部分人在使用 Iteration 模块,很自然而然地认为这个 In 一定都是 0,也通常都设置为 0,所以要加不加都无所谓,但实际上它是要加上去的,而且还有一个重点就是最后的输出要给它添加一个 Dup Flt’ 模块,防止结果依然有事件输出,尽管数值都是一样的。 OK,那么上面的问题算完了吗?如果我们不考虑去实现Break的功能,那么它算是完成了99%,而剩下的1%就是初始化的问题;没错,我们还需要考虑它的初始化,因为当我们在改变Inc、N或者Speed这几个输入接口的数值变化,都会引起Iteration重新累计,但这个跟原有的Iteration模块的初始化是不同的,因为原有的并没有受到影响,因此我们还需要借助一个模块,它就是Latch模块,来改善这种初始化的状态;除了这个,我还打算把Break的部分也同时实现,因为它的原理更简单,只要把触发的信号关闭即可。(图4.5) 图4.5 我们看到了上面都用到了 Latch 模块并加入了 Break 的搭建,而且也算是完成了Iteration 模块的搭建,但你是否觉得搭建看起来有点乱乱的,当然我们可以给它做一下调整;不过,如果你认为这样一个I teration 模块已经满足你的需求,更何况现在用它去跟其他模块搭建已经不影响它跟原有Iteration模块的比较,但倘若细心的你肯定会发现,尽管输出的结果是我们想要的,也把一些重复性的数值事件阻挡了,可触发依然还在进行当中。(图4.6) 图4.6 那么怎么让它不再继续触发呢?这个问题的答案并非困难,我们只需要结果再做一次判断,然后利用判断的结果来启动或关闭触发,当然还有一点就是,当In触发开始,也要重新开启Iteration模块计数。(图4.7) 图4.7 好吧,上面这个搭建估计很多人会看乱了,但它的思路却很简单,首先判断结果是否超过 Inc*N,如果超过就触发一个数值 1 的事件流,否则就触发一个数值 0 的事件流,这里就等同于把问题归结到了 1 和 0 真假值的判断,如果大于 0,则关闭了时钟信号,否则继续开启时钟信号;除了这个以外,我们刚说一开始也要让时钟信号在触发后也开启着,相应的 Break 功能也同时解决了,甚至我们还可以给它好好整理一番。(图4.8) 图4.8 最后就留个问题,Gate 输出怎么办?哈哈,还有想想前面搭建的 Hold 模块是不是也可以用这种方法!!!哈哈,如果实在是看不懂,也不会做,没关系,洗洗睡吧,天起来继续看;如果还是看不懂,那想方设法联系我吧,或许我会一口气给你讲很多。 |
|雷鸾编曲(原编曲186)
( 蜀ICP备2021031672号-1 )|川公网安备 51202202511082-1号
增值电信业务经营许可证:川B2-20221165
GMT+8, 2024-9-8 08:49
Powered by Discuz! X3.4