如何操作和可视化Web音频

Web Audio API功能强大,可用于实时音频处理和分析,但这可能会使其变得棘手。使用路由图来管理节点之间的音频,它与其他Web API不同 - 并且在第一次接近时有点令人生畏规格。在这篇文章中,我们将介绍一个实时操作音频的简单示例,然后可视化音频数据。

即插即用

想象一下,你是你最喜欢的乐队的吉他手:声音来自你的吉他,通过效果踏板(你想听起来很重,对吗?)并进入你的放大器,这样才能听到。 Web Audio API的工作原理类似:数据从源节点传输,通过转换节点,最终从计算机的声卡中传出。

Web音频中的所有内容都以实例化为开头AudioContext实例。该AudioContext可以被认为是我们的音频环境,从我们创建所有音频节点的上下文。因此,所有音频节点都存在于内部AudioContext,它成为连接节点的网络。

首先,我们需要一个音频源自的源节点。有几种类型的源节点,例如MediaElementAudioSourceNode使用元素,aMediaStreamAudioSourceNode用于使用WebRTC的实时麦克风输入,OscillatorNode对于方波和三角波,或带有的音频文件AudioBufferSourceNode。在这种情况下,我们将使用MediaElementAudioSourceNode利用本机控件元素给了我们。

在这里,我们将为前缀对象名称做好准备,并支持不同的音频编解码器。您可能需要从服务器提供此页面,以便设置适当的音频文件头。让我们创建一个元素,实例化AudioContext和勾一个MediaElementAudioSourceNode我们的元件:

  

元素的音频被输入我们的网络音频环境。那么为什么我们点击播放时听不到曲目呢?当我们将音频从元素重新路由到我们的上下文时,我们需要将源连接到上下文的目标。就好像我们正在弹奏没有插入放大器的电吉他一样。

Oursimple  tag and slide rcontrolling the audio nodes

Oursimple

一切AudioContext实例有一个目的地Property:一个特殊的音频节点,表示计算机的音频输出,我们所有的音频节点都有一个使我们能够将音频数据从一个传输到另一个的方法。让我们将音频元素节点连接到目标节点,就像吉他线到放大器一样。

elSource.connect(ctx.destination);

现在,当我们播放时,我们有了元素节点被泵入目标节点,并可以听到歌曲。但这与使用它没有什么不同标签本身。让我们添加一个滤波器节点来播放音轨的频率。首先,我们将使用滑块和显示器控制滤镜,以便我们可以看到值是什么:

100

现在我们必须创建一个BiquadFilterNode:我们的过滤器和功能,如网络音频中的均衡器。与我们制作的所有节点一样,我们将实例化我们的过滤器AudioContext。以前,我们连接了我们的MediaElementAudioSourceNode直接到我们的背景目的地。现在我们希望源节点首先连接到我们的过滤器,然后我们的过滤器连接到目标,因此我们的过滤节点可以操纵通过它传递的音频。我们现在应该有类似的东西:

var ctx = new(window.AudioContext || window.webkitAudioContext)(); var audioEl = document.getElementById(“audio-element”); var elSource = ctx.createMediaElementSource(audioEl); var filter = ctx.createBiquadFilter(); filter.type =“lowpass”; filter.frequency.value = 100; elSource.connect(过滤器); filter.connect(ctx.destination);

过滤节点有几种频率过滤,但我们会使用默认的“低通“ - 只有低于的频率频率可以通过。听一听:注意听起来有点像隔壁的聚会。只有低于100hz的频率才能到达目的地,因此我们只能听到低音。让我们连接我们的滑块,以便我们可以操作这个过滤器。

var slider = document.getElementById(“slider”); var freqDisplay = document.getElementById(“freq-display”); //跨浏览器事件处理程序if(slider.addEventListener){slider.addEventListener(“change”,onChange); } else {slider.attachEvent(“onchange”,onChange); function onChange(){//使用滑块值filter.frequency.value = slider.value更新过滤节点的频率值; freqDisplay.innerHTML = slider.value; }

通过我们的滑块可以控制滤波器节点的频率,我们可以实时操作音频播放。为了更好地了解传递的数据,我们可以可视化信号的频率数据。虽然我们的滤波器节点实际上修改了扬声器发出的声音,但我们将使用两个新节点来分析信号而不是影响信号。让我们创建一个AnalyserNode和aScriptProcessorNode

var analyzer = ctx.createAnalyser(); var proc = ctx.createScriptProcessor(1024,1,1);

CreateScriptProcessor(以前CreateJavaScriptNode)方法有三个参数。第一个是缓冲区大小,它必须是2的幂,输入和输出的数量是相应的剩余参数。使用处理器节点,我们可以安排在处理足够的音频时触发事件。如果我们的缓冲区大小为1024,这意味着每次处理1024个样本时,我们的事件将会触发。

我们的AudioContext采样率为44100Hz(每秒处理44100个样本),我们的事件将每1024个样本发射一次 - 每0.023秒,或每秒43次。保持这一点,我们的处理器节点使我们能够在处理新的音频数据时挂钩回调。我们将很快使用它来绘制画布。

使用我们的脚本处理器作为回调钩子,我们需要我们的AnalyserNode获取数据。但我们的音频信号必须通过分析仪和处理器:让我们改变我们的路由并将滤波后的信号输出发送到分析仪,然后分析仪连接到我们的音频目标和脚本处理器:

elSource.connect(过滤器); filter.connect(分析仪); analyser.connect(PROC); filter.connect(ctx.destination); proc.connect(ctx.destination);

WebKit错误意味着我们必须将处理器的输出连接回目的地以接收音频处理事件,我们将在稍后使用。

频率控制

现在我们设置了音频路由,让我们勾起前面提到的处理事件。我们可以为a分配一个函数ScriptProcessorNodeOnaudioprocess当我们的缓冲区充满处理过的样本时要调用的属性,并使用我们的AnalyserNode能够获取信号的原始频率数据。

分析仪的GetByteFrequencyData填充Uint8Array使用当前缓冲区的音频数据,在本例中为0到255之间的值。我们在每次调用时都重用相同的数组,因此我们不需要继续创建新数组。

//使Uint8Array与分析器的bin计数大小相同var data = new Uint8Array(analyser.frequencyBinCount); proc.onaudioprocess = onProcess; function onProcess(){analyser.getByteFrequencyData(data);的console.log(数据[10]); }

目前我们只是在每个进程上打印出音频数据的第十个元素(不是很有趣),但我们可以看到我们的处理器事件被我们的分析器解释通过它传递的数据。绘制画布会更令人兴奋。添加一个元素与ID“帆布”,宽度为1024,高度为256 - 让我们看看我们将添加到我们的绘图代码处理中功能。

var canvas = document.getElementById('canvas'); var canvasCtx = canvas.getContext('2d'); function onProcess(){analyser.getByteFrequencyData(data); canvasCtx.clearRect(0,0,canvas.width,canvas.height); for(var i = 0,l = data.length; i <l; i ++){canvasCtx.fillRect(i, - (canvas.height / 255)* data [i],1,canvas.height); }}

现在,每当处理音频缓冲区时都会调用一个事件,这要归功于我们的处理器节点,因为我们的分析器节点填充了一个Uint8Array使用音频数据,我们清除画布并以频率箱的形式呈现新数据,每个频率箱代表一个频率范围。当我们来回擦洗滤镜控件时,我们可以在画布中看到,当我们向左移动滑块时,我们正在移除高频。

我们可以看到,一旦我们连接音频节点,我们就可以操纵我们听到的声音并可视化音频数据。此示例使用简单的双二阶滤波器节点,但有音乐家,游戏开发人员或合成器爱好者改变音频数据的卷积器,增益,延迟和其他方法。随着音频工程师和Web开发人员之间的界限模糊,获得创造性并使用Web Audio API。

乔丹桑特尔

这篇文章最初出现在网络杂志问题254。



翻译字数超限