使用 Web Audio API 将两个声音分配给两个 Div,并通过带有 javascript 的 click 事件独立播放

Posted

技术标签:

【中文标题】使用 Web Audio API 将两个声音分配给两个 Div,并通过带有 javascript 的 click 事件独立播放【英文标题】:Using Web Audio API to assign two sounds to two Divs and play each independently via a click event with javascript 【发布时间】:2012-10-28 06:03:13 【问题描述】:

我一直在挑选下面链接中的代码,但我无法到达任何地方。 我只设法将事件处理程序重新分配给一个小 div 而不是整个页面。我不知道如何调整它以加载多个声音。

http://www.f1lt3r.com/w3caudio/web-audio-api/basic-examples/low-latency-playback-user-input.html

使用下面的代码示例,我根本无法通过单击 div 来触发声音。不过这段代码看起来更好看,所以我真的很想修改它以供学习。

   var context = new webkitAudioContext(),
        buffer;

    var playAudioFile = function (buffer) 
        var source = context.createBufferSource();
        source.buffer = buffer;
        source.connect(context.destination);
        source.noteOn(0); // Play sound immediately
    ;

    var loadAudioFile = (function (url) 
        var request = new XMLHttpRequest();

        request.open('get', 'A.mp3', true);
        request.responseType = 'arraybuffer';

        request.onload = function () 
                context.decodeAudioData(request.response,
                     function(incomingBuffer) 
                         playAudioFile(incomingBuffer);
                     
                );
        ;

        request.send();
    ());





// I added this & it doesn't work



var divElement = document.getElementById("divElement");

divElement.addEventListener("click", playAudioFile , false);


// END of code I added

我了解如何创建振荡器以及连接滤波器/增益和其他节点。到目前为止,这是我使用 API 时的参考点。 XMLHttpRequest 进程与缓冲区创建相结合是令人困惑的。我了解缓冲区是什么,我了解 XMLHttprequest 是什么,但由于某种原因,加载音频文件以进行播放的过程对我来说似乎并不清晰,更不用说加载多个我最终想要做的事情了。我也尝试阅读 HTML-5 Rocks 教程,但如果没有可以调整的 C&P 代码,我永远无法判断我是否走在正确的轨道上。顺便说一句,我不想​​使用抽象库。我想从头开始学习 API。谢谢

【问题讨论】:

【参考方案1】:

首先,当您单击 div 时,您正在执行 playAudioFile。 playAudioFile 需要一个缓冲区作为参数,否则它将无法做它应该做的事情。但是,当您单击 div 时没有传递缓冲区,playAudioFile 函数在没有缓冲区的情况下执行(并且被赋予事件对象作为参数,但这并不重要),因此没有声音。

您可能想要做的是在单击 div 时分配 loadAudioFile 。目前 loadAudioFile 被写入在页面加载时执行(当您将函数包装在括号中时会发生这种情况)。所以我将 loadAudioFile 函数更新为如下所示:

var loadAudioFile = function () 
    var request = new XMLHttpRequest();

    request.open('get', 'A.mp3', true);
    request.responseType = 'arraybuffer';

    request.onload = function () 
            context.decodeAudioData(request.response,
                 function(incomingBuffer) 
                     //HERE is where the playAudioFile function is called, with a buffer to play
                     playAudioFile(incomingBuffer);
                 
            );
    ;

    request.send();
;

然后

divElement.addEventListener("click", loadAudioFile , false);

现在,这会使应用程序在您每次单击 div 时加载 mp3。只需加载一次并保存缓冲区供以后使用,就可以对其进行很多优化。

var context = new webkitAudioContext(),
    savedBuffer;

var playAudioFile = function () 
    var source = context.createBufferSource();
    source.buffer = savedBuffer;
    source.connect(context.destination);
    source.noteOn(0); // Play sound immediately
;

var request = new XMLHttpRequest();

request.open('get', 'A.mp3', true);
request.responseType = 'arraybuffer';

request.onload = function () 
        context.decodeAudioData(request.response,
             function(incomingBuffer) 
                 //save the buffer, we'll reuse it
                 savedBuffer = incomingBuffer;
                 //once the file has been loaded, we can start listening for click on the div, and use playAudioFile since it no longer requires a buffer to be passed to it
                 var divElement = document.getElementById("divElement");
                 divElement.addEventListener("click", playAudioFile , false);
             
        );
;

request.send();

【讨论】:

我假设如果我想加载多个音频文件,我基本上必须重复同样庞大的代码块而不是抽象它?我没有足够的经验来判断 API 的开发人员是否有其他想法。谢谢。 是的,只是重复请求部分。您可以将其包装在一个函数中,并使用您要加载的文件传递一个 url(并将“A.mp3”替换为 url 变量)。然后,您必须以其他方式(例如对象)存储收到的缓冲区,以供以后检索。 我把底部复制了两次,只播放了一个音频文件。我在这里添加了一个 JS fiddle 来演示:jsfiddle.net/RHR8b/1 这个想法是它会为每个 div 触发不同的文件。我认为问题是音频文件被保存在一个缓冲区中,我假设每个文件需要多个缓冲区。我试图通过重命名第二个副本上的各种缓冲区分配变量来解决这个问题,但它似乎不是正确的路径。 注意。我让它工作了,但实际上我不得不复制整个块并对其进行修改。我想我可能误解了你的指示。 jsfiddle.net/N3eQY

以上是关于使用 Web Audio API 将两个声音分配给两个 Div,并通过带有 javascript 的 click 事件独立播放的主要内容,如果未能解决你的问题,请参考以下文章

如何下载我刚刚使用 Web Audio API 创建的声音?

Web Audio API:将 mp3 声音流合并到一个文件并在 <audio> 标签中播放

使用 Web Audio API 为声音的开头添加静音 [关闭]

暂停 Web Audio API 声音播放

Web Audio API - 获取正确的频率

WEB AUDIO API 产生雨水噼啪声