小计划:AudioNode

核心利用:

MonoBehaviour::OnAudioFilterRead(float[] data, int channel)

​ 这个函数会以DSP常用的形式输出声音数据,即波形构成本身。通过对这些数据的操控可以实现对音频本身的控制。

​ 基于以上信息,可以在unity内部进行DSP编程,但仅能在unity内部使用。因此可以定义一个类来在unity内专门处理DSP。

​ 缺点:优化差,未经过Burst优化的代码极其容易造成严重的延迟。


​ 基于以上信息,可以尝试制作一个基于模块进行的声音处理。

​ 在MIDI CC协议中,信息交互的控制是基于特定通道的,因此可以借鉴这一点来实现控制

public class ccMap{
    public float[] channel = new float[32];
}

​ 如果当前插件需要用外部控制信息的时候,只需在channel数组内指定一个位置并读取即可。而外部插件连线需要将控制数据输出给当前插件时仅需要找到对应channel数组位置调整即可。

其实channel数组倒也是没必要限制在32,只不过MIDI CC协议在最早的时候给的通道也就128,这128通道只要不过分基本用不干净的,更何况我这个是小项目,基于我对效果器参数的理解来说,可控参数估摸着也不会超过32个吧,又不是serum这种大头玩意(笑)

因此基于以上信息,一个模块父类将会有至少以下信息:

public class pluginBase{
    public ccMap map;
    public bool isActive;
	public float[] inData;
    public float[] outData;
    void active(){}
}

​ isActive: 用于确认该插件是否启用,如果为否则状态为bypass,将会把inData数据直接传输给outData并输出至下一个,即active()的功能。


基于模块父类上,一个模块应该具备这样子的框架:

public class plugin: pluginBase{
    public plugin audioFrom, audioTo;
    public class modulation{
        public plugin[] to;
        public float[] channel;
    }
    public void output(){}
    void Function1(){/*Implementation...*/}
    void Function2(){/*Implementation...*/}
    void Function3(){/*Implementation...*/}
	//...
}

​ audio前缀代表着音频流,通常情况下,仅允许有一个输入口和一个输出口,否则容易发生数据混合但不能确定要如何处理混合数据的情况。如果需要混合数据则需编写额外模块来处理。

​ [等待更新...]

posted @ 2023-07-17 23:16  ComputerEngine  阅读(25)  评论(0编辑  收藏  举报