2

我正在尝试使用 jQuery 中的 .keydown() 事件播放声音。我希望声音能够快速播放,但是当我执行 keydown 事件的速度超过每秒 3 次时,似乎会有延迟。

这是我的示例代码的 jsFiddle:http: //jsfiddle.net/pfrater/FRudg/3/

我正在使用音频 html 标签来播放声音和播放:

<audio controls id="sound" preload="auto"> 
<source src="http://www.wavlist.com/soundfx/011/duck-baby.wav" type="audio/wav"/> 
</audio>

<audio controls id="sound2" preload="auto"> 
<source src="http://rezound.sourceforge.net/examples/chirp.wav" type="audio/wav"/> 
</audio>

<audio controls id="sound3" preload="auto"> 
<source src="http://www.all-birds.com/Sound/downychirp.wav" type="audio/wav"/> 
</audio>

这是我的jQuery:

$(document).ready( function() {
var playing;
$(document).bind("keydown", function(key) {
    playing = undefined;
    switch(parseInt(key.which, 10)) {
        case 65:
            playing = $("#sound").get(0);
            break;
        case 83:
            playing = $("#sound2").get(0);
            break;
        case 68:
            playing = $("#sound3").get(0);
            break;
     };
     if (playing) {
        playing.play();
     }
  }).on("keyup", function() {
    if(playing){
        playing.pause();
        playing.currentTime=50;
        playing = undefined;
     }
  });
});

有谁知道摆脱这种滞后的方法?此外,我将播放的实际文件是 mpeg。以上只是一个例子。

感谢您的帮助,
保罗

4

1 回答 1

1

You won't be able to do this with the audio element. This is because the cost setting up and filling the buffers will take too much time.

The good news though is that you can do it using the Web Audio API instead.

I made you an example based on this code from HTML5 rocks (which you should check out for more details) and your original fiddle.

Currently this API is supported in Chrome, Firefox, Safari and Opera will be able to use this:

Fiddle demo

window.AudioContext = window.AudioContext || window.webkitAudioContext;

/// custom buffer loader
/// see http://www.html5rocks.com/en/tutorials/webaudio/intro/
function BufferLoader(context, urlList, callback) {
    this.context = context;
    this.urlList = urlList;
    this.onload = callback;
    this.bufferList = new Array();
    this.loadCount = 0;
}

BufferLoader.prototype.loadBuffer = function (url, index) {
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.responseType = "arraybuffer";

    var loader = this;

    request.onload = function () {
        // Asynchronously decode the audio file data in request.response
        loader.context.decodeAudioData(
        request.response,

        function (buffer) {
            if (!buffer) {
                alert('error decoding file data: ' + url);
                return;
            }
            loader.bufferList[index] = buffer;
            if (++loader.loadCount == loader.urlList.length)
                loader.onload(loader.bufferList);
        },

        function (error) {
            console.error('decodeAudioData error', error);
        });
    }

    request.onerror = function (e) {
        alert('BufferLoader: XHR error');
    }    
    request.send();
}

BufferLoader.prototype.load = function () {
    for (var i = 0; i < this.urlList.length; ++i)
    this.loadBuffer(this.urlList[i], i);
}

The main code:

/// setup audio context and start loading samples
var actx = new AudioContext(),
    blst,
    bLoader = new BufferLoader(
    actx, [
        'duck-baby.wav', 'chirp.wav', 'downychirp.wav'],
    done),
    isReady = false;

/// start loading the samples
bLoader.load();

function done(bl) {
    blst = bl;                           /// buffer list
    isReady = true;                      /// enable keys
    $('#status').html('Ready!');         /// update statusw
}

/// this sets up chain so we can play audio
function play(i) {
    var src = actx.createBufferSource(); /// prepare sample
    src.buffer = blst[i];                /// set buffer from loader
    src.connect(actx.destination);       /// connect to speakers
    src.start(0);                        /// play sample now
}

/// check keys
$(window).bind("keydown", function (key) {
    if (!isReady) return;
    switch (parseInt(key.which, 10)) {
        case 65:
            play(0);
            return;
        case 83:
            play(1);
            return;
        case 68:
            play(2);
            return;
    }    
})

NOTE: When using external samples you must make sure they can be used cross-origin or else loading will fail (I used my DropBox to enable the samples to be loaded with fiddle).

于 2013-11-05T04:46:56.600 回答