将一个音频信号除以另一个音频信号

时间:2017-02-09 18:40:45

标签: javascript web-audio-api

短版

我需要音频信号除以另一个音频信号(幅度方向)。如何在不使用ScriptProcessorNode的情况下在Web Audio API中完成此操作? (使用ScriptProcessorNode,任务很简单,但由于固有的性能问题,完全无法用于生产

长版

考虑两个音频源,例如两个OscillatorNodesoscAoscB

var oscA = audioCtx.createOscillator();
var oscB = audioCtx.createOscillator();

现在,考虑这些振荡器是LFO,两者都具有低(即<20Hz)频率,并且它们的信号用于控制单个目的地AudioParam,例如, GainNode增益。通过各种路由设置,我们可以定义这两个信号之间的数学运算。

加成

如果oscAoscB 直接连接到目标AudioParam,则其输出已添加

var dest = audioCtx.createGain();

oscA.connect(dest.gain);
oscB.connect(dest.gain);

减法

如果oscB的输出首先通过另一个 GainNode路由,增益为-1,然后连接到目标AudioParam,则输出{{} 1}}实际上是从oscB减去,因为我们实际上正在执行oscA操作。使用这个技巧我们可以从另一个信号中减去一个信号:

oscA + -oscB

乘法

同样,如果var dest = audioCtx.createGain(); var inverter = audioCtx.createGain(); oscA.connect(dest.gain); oscB.connect(inverter); inverter.gain = -1; inverter.connect(dest.gain); 的输出连接到另一个 GainNode,并且oscA的输出连接到增益 AudioParam GainNode,然后oscB乘以oscB的信号:

oscA

分部(?)

现在,我希望var dest = audioCtx.createGain(); var multiplier = audioCtx.createGain(); oscA.connect(multiplier); oscB.connect(multiplier.gain); multiplier.connect(dest.gain); 的输出 划分 oscB的输出。 如何执行此操作,不使用ScriptProcessorNode

修改

我之前,绝对荒谬的尝试解决这个问题是:

  • 使用PannerNode来控制oscA参数,其中会产生随信号B(positionZ)增加而减少的结果,但它完全关闭(例如它已产生oscB12/1 = 8.5) - 现在可以使用GainNode将其增益设置为12/2 = 4.2(近似值)来补偿此值,但它仅支持值12 / 8.48528099060058593750
  • 使用AnalyserNode快速采样音频信号,然后使用该值(LOL)

修改2

ScriptProcessorNode对于比技术演示更复杂的应用程序基本上无用的原因是:

  1. 它在主线程(!)上执行音频处理,繁重的UI工作将引入音频故障
  2. 一个简单的死简单ScriptProcessorNode将在现代设备上占用5%的CPU能力,因为它使用JavaScript执行处理并且需要在音频线程(或渲染线程)和主线程(或UI线程)之间传递数据

1 个答案:

答案 0 :(得分:1)

应该注意,ScriptProcessorNodedeprecated

如果您需要A/B,则需要1/B反转信号。您可以使用WaveShaperNode进行反转。此节点需要一组相应的值。反转意味着-1变为-1,-0.5变为-2等。

此外,请确保您知道除零。你必须处理它。在下面的代码中,我只需在零之后取下一个值并加倍。

function makeInverseCurve( ) {
  var n_samples = 44100,
      curve = new Float32Array(n_samples),
      x;
  for (var i = 0 ; i < n_samples; i++ ) {
    x = i * 2 / n_samples - 1;
    // if x = 0, let reverse value be twice the previous 
    curve[i] = (i * 2 == n_samples) ? n_samples : 1 / x;
  }
  return curve;
};

工作fiddle is here。如果从音频链中删除.connect(distortion),则会看到一个简单的正弦波。可视化代码来自sonoport