有人在实时音频合成编程方面有什么建议吗?

7
我目前正在进行一个个人项目:在Flash中创建实时音频合成库。简而言之,这是将波形发生器、滤波器、混音器等工具相互连接并向声卡提供原始(实时)数据的工具,类似于max/msp或Reaktor。
我已经有一些可用的东西了,但我想知道我编写的基本设置是否正确。我不想在以后遇到问题,迫使我改变我的应用程序核心(尽管这种情况总是可能发生)。
基本上,我现在所做的就是从链的末端开始,在声音数据(原始)“输出”(到声卡)的地方。为此,我需要将字节块(ByteArrays)写入对象,并获取该块,然后要求连接到我的“Sound Out”模块的任何模块提供他的块。该模块对连接到其输入的模块发出同样的请求,直到到达链的起点。
这是正确的方法吗?如果存在反馈循环或没有输出的另一个模块,则可能会遇到问题:如果我在某个地方连接频谱分析仪,那将是链中的死胡同(只有一个输入而没有输出的模块)。在我目前的设置中,这样的模块将无法正常工作,因为我只从声音输出模块开始计算。
有没有人有编写类似内容的经验?我非常想听听对正确方法的一些想法。(为了清晰起见:我不是在寻找特定的Flash实现,这就是为什么我没有在flash或actionscript下标记此问题的原因。)
2个回答

1

我之前做过类似的事情,使用了和你一样的方法 - 从虚拟出口开始追踪信号,并沿着顶部返回。不过我是每个样本进行的,而不是每个缓冲区;如果我今天要编写相同的应用程序,我可能会选择每个缓冲区,因为我认为它可能会表现得更好。

分光计被设计为插入模块,也就是说,只有在其输入和输出都连接时才能工作,并且会将其输入未经修改地传递到输出。

为了处理反馈,我有一个特殊的辅助模块,引入了1个采样延迟,并且每个周期仅获取一次其输入。

另外,我认为,将所有内部处理都使用浮点数,因此将浮点数组作为缓冲区会比使用字节数组容易得多,并且可以节省您在整数和浮点数之间转换的额外努力。


0

在以后的版本中,您可能会在网络不同部分有不同的数据包速率。

一个例子是,如果您将其扩展到与磁盘传输数据。另一个例子是,低数据速率控制变量(例如控制回声延迟的变量)可能会成为您网络的一部分。您可能不希望像处理音频数据包一样频繁地处理控制变量,但它们仍然是“实时”的并且是功能网络的一部分。例如,它们可能需要平滑以避免突然的过渡。

只要您以相同的速率调用所有函数,并且所有函数基本上都需要花费恒定时间,您的拉取数据方法就可以正常工作。在拉取数据和推送之间几乎没有什么区别。对于播放音频而言,拉取更自然,对于录制来说,推送更自然,但两者都可以,并且最终会对底层音频处理函数进行相同的调用。

对于光谱仪,你面临的问题是多个数据源,但这不是问题。从真正的数据源引入一个虚拟链接。虚拟链接可以导致请求未被满足的数据。只要虚拟链接知道它是虚拟的,并且不关心缺少的数据,一切都会没问题。这是将多个数据源或接收器减少到单个接收器的标准技术。
在这种网络中,您不希望在一个完整的更新中重复执行相同的计算。例如,如果您混合了信号的高通和低通版本,则不希望两次评估原始信号。您必须做一些像记录每个缓冲区的计时器滴答值,并在看到当前滴答值已经存在时停止拉取传播。这个机制也将保护您免受评估中的反馈环的影响。
因此,这两个问题在您当前的框架内很容易解决。

速率匹配是指在网络的不同部分存在不同的数据包速率,这就是当前方法存在问题的地方。如果您要将音频写入磁盘,则为了效率,您需要较少但更大的块进行写入。在这些写入期间,您不希望阻塞更频繁的小型音频输入和输出处理数据包的服务。单一速率拉取或推送策略本身是不够的。

接受这样一个事实,即在某个时刻,您可能需要比单一速率网络更复杂的更新方式。当发生这种情况时,您需要运行不同速率的线程,或者编写自己的简单调度程序,可能只需每n次调用较少评估的函数一次,以使速率匹配。您无需提前计划。您的音频函数几乎肯定已经将确保其输入缓冲区准备好的责任委托给其他函数,只有那些其他函数需要更改,而不是音频函数本身。

在这个阶段,我唯一建议的一点是要小心地集中音频缓冲区分配,注意缓冲区就像围栏柱。它们不属于一个音频函数,而是处于音频函数之间。集中缓冲区分配将使得回溯修改网络不同区域不同速率的更新策略变得容易。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接