我无法弄清楚这个的关闭

时间:2013-08-23 06:07:46

标签: javascript audio

如何将在decodeAudioData中创建的缓冲区分配给soundBuffer以便以后播放?

请注意,在decodeAudioData函数调用中对playSound()的调用会成功播放缓冲区,但来自Play按钮的调用将返回“不是ArrayBuffer类型的值”,并且在测试时,soundBuffer仍未定义。

我假设深层嵌套函数在最外层函数中已经失去了soundBuffer的范围,但我似乎可以将soundBuffer包装在一个闭包中,以便成功传入。

$(function () {
  var soundBuffer, context;
  try {
      context = new webkitAudioContext();
  }
  catch (e) {     
      console.log("Error setting up webaudiocontext: " + e);
  }    

  loadSound("https://dl.dropboxusercontent.com/u/9780255/counting-coins-3.mp3",soundBuffer);

  $("#playSound").click(function () {
     playSound(soundBuffer);
  });

  function loadSound(url, buffer) {
      var rq = new XMLHttpRequest();
      rq.open("GET", url, true);
      rq.responseType = "arraybuffer";
      rq.onload = function () {
          context.decodeAudioData(rq.response,
              function (b) {
                  buffer = b;
                  console.log("buffer loaded...");
                  playSound(buffer);
              });
      };

      rq.onerror = function (e) {
          console.log("error loading audio:"+e);
      };
      rq.send();
  }   


  function playSound(s) {
     var sn= context.createBufferSource();
     sn.buffer = s;
     sn.connect(context.destination);
     sn.start(0);
  }         

});

此源代码位于jsfiddle:http://jsfiddle.net/karasutengu/qA5Nb/8/它可能只适用于识别webkitAudioContext的chrome。

2 个答案:

答案 0 :(得分:1)

您需要提供回调以在当前范围内设置soundBuffer。

将loadSound更改为:

loadSound("https://dl.dropboxusercontent.com/u/9780255/counting-coins-3.mp3", function(buffer) {
    soundBuffer = buffer;
});

负载声音的功能def:

function loadSound(url, callback) {

和成功函数:

function (b) {
  buffer = b;
  console.log("buffer loaded...");
  callback(buffer);
});

http://jsfiddle.net/karasutengu/qA5Nb/8

答案 1 :(得分:1)

这很棘手,但请阅读Is JavaScript a pass-by-reference or pass-by-value language?以了解为什么soundBuffer不会保留其值。

以下是带有回调函数的代码,该函数正确使用闭包来保持PlaySound函数中缓冲区的值http://jsfiddle.net/qA5Nb/9/

var Player = $(function () {
   var soundBuffer, context;

    try {
        context = new webkitAudioContext();
    }
    catch (e) {     
        console.log("Error setting up webaudiocontext: " + e);
    }    


    var registerPlayButton = function(buffer){    
       $("#playSound").click(function () {
           playSound(buffer);
       });
    }


   loadSound("https://dl.dropboxusercontent.com/u/9780255/counting-coins-3.mp3",soundBuffer, registerPlayButton);

  function loadSound(url, buffer, callbackFn) {
        var rq = new XMLHttpRequest();
        rq.open("GET", url, true);
        rq.responseType = "arraybuffer";
        rq.onload = function () {
            context.decodeAudioData(rq.response,
                function (b) {
                    buffer = b;
                    console.log("buffer loaded...");
                    playSound(buffer);
                    callbackFn(buffer);
                });
        };

        rq.onerror = function (e) {
            console.log("error loading audio:"+e);
        };
        rq.send();
    }   


   function playSound(soundBuffer) {
       var sn= context.createBufferSource();
       sn.buffer = soundBuffer;
       sn.connect(context.destination);
       sn.start(0);
    }     



});

此外:

一个简短的解释是soundBuffer是一个引用类型,并通过值传递给loadSound(所以引用的值是一个未初始化的指针)。

如果您的soundBuffer被初始化为var soundBuffer ={b:null};之类的对象,并被传递给loadSound,您将把缓冲区分配给对象的b属性{{1 }};你的代码会起作用。

你仍然会通过值传递soundBuffer,这个指针的值是指向存储{buffer:null}的同一内存位置的指针,外部soundBuffer也指向该指针。

所以,如果你要在{b}内分配一个像soundBuffer那样的缓冲区

loadSound

您实际上将解码后的缓冲区分配到外部 context.decodeAudioData(rq.response, function (b) { buffer.b = b; console.log("buffer loaded..."); playSound(buffer.b); }); 和内部soundBuffer变量指向的同一内存位置,并且buffer可以正常工作。