2012-10-05 119 views
12

我试图围绕使用网络音频API重新创建类似
Winamp的10频段均衡器。使用网络音频API创建10频段均衡器

Winamp's 10-band equalizer

据我所知,我要创建10 Biquad Filters,设置其type2 (for a Bandpass filter)分别设置其frequency[60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000]。一旦我完成了这一步(这里我有点困惑),然后我会为每个频段“band”创建一个单独的Gain Node,并将其值绑定到一个滑块。

<input id="someFreqBand" type="range" min="-12" max="12" step="0.1" value="0" onchange="slide()"/> 

假设所有的这是正确的,那么剩下的唯一步骤是将所有10个增益节点连接到所述音频上下文destination(我想象将采取所有10个频率“带”和混合/将其同步到一起)。这是创建Web Audio 10频段均衡器的正确方法吗?

我很困惑的主要问题是如何将信号源“连接”到10个频带滤波器(+相关增益节点),因为所有节点只有一个输入或输出(包括目的地) 。

回答

7

正如马特D所说,连接过滤器到同一目的地应该没有问题。

但是我会说你可能想要使用类型5(峰化)的滤波器,它可以让所有的频率通过并且只在你设定的滤波器频率上进行放大/减少。filter.frequency.value。这可以让你串联连接滤波器,所以你不需要10个独立的音频路径。您也可以考虑使用低架滤波器作为第一个滤波器,并使用高架滤波器作为第十个滤波器,这在均衡器中很常见。不过,我不记得那是不是winamp的做法。最后,如果你使用串联的峰化滤波器,每个频率都不需要单独的增益节点,只需为特定滤波器设置filter.gain.value即可。

+0

除非我错了,否则所有图形均衡器都使用带通滤波器。请参阅第4页:https://rs6.eporia.com/company_38/techpaper106.pdf 低架/高架/峰值滤波器允许您直接在滤波器节点上调整增益,但不是带通滤波器... – idbehold

+0

我不确定是否所有的图形均衡器都使用带通滤波器,但我相信在系列中使用峰化滤波器是获得您所追求行为的更简单方法。正如Jagi所提到的那样, –

+0

过滤器应串联连接。 –

2

我很困惑的主要问题是如何将信号源“连接”到10个频带滤波器(+相关增益节点),因为所有节点只有一个输入或输出(包括目的地)。

这是事实,但不要把它想象成只能连接到另一个物理输入的物理输出。 Web Audio节点的单个输出可以连接到多个节点,并且节点也可以接收多个输入。例如,假设您想通过5个过滤器并行连接一个输入节点,然后将它们连接在一起。你可以做这样的事情:

source.connect(filter1); 
source.connect(filter2); 
source.connect(filter3); 
source.connect(filter4); 
source.connect(filter5); 

filter1.connect(context.destination); 
filter2.connect(context.destination); 
filter3.connect(context.destination); 
filter4.connect(context.destination); 
filter5.connect(context.destination); 

这里的关键见解是,调用.connect多次将输出不能切换到不同的节点,而只是添加额外的输出连接。换句话说,这是一个“扇出/扇入”系统。

+0

当规范说:'numberOfInputs:1. numberOfOutputs:1.'时,它看起来很糟糕的文档。当'1'它们的意思是'many'。 – idbehold

+1

我承认它可能会更清楚,但该文档仍然正确。一个输出可以连接到多个输入。想想它更像输出*端口*的数量而不是输出。 –

10

通过连接每个过滤器与目的地,你正在创建5个路径(路线),所以你会听到源声音quintupling放大。这不是正确的方法。您必须将每个过滤器连接在一条线上。

source.connect(filter1); 
filter1.connect(filter2); 
filter2.connect(filter3); 
filter3.connect(filter4); 
filter4.connect(filter5); 
filter5.connect(context.destination);