1

後で再生するために、decodeAudioData で作成されたバッファを soundBuffer に割り当てるにはどうすればよいですか?

decodeAudioData 関数呼び出し内の playSound() の呼び出しはバッファを正常に再生しますが、[再生] ボタンからの呼び出しは「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 でのみ動作する可能性があります。

4

2 に答える 2

1

ややこしいけど読んでみる JavaScriptは参照渡しか値渡しか?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{b}

このポインタの値は、{buffer:null} が格納されている同じメモリ位置へのポインタであり、外側の soundBuffer も指しています。

したがって、 内でバッファを割り当てる場合はloadSound、次のように soundBuffer にバッファを割り当てます。

        context.decodeAudioData(rq.response,
            function (b) {
                buffer.b = b;
                console.log("buffer loaded...");
                playSound(buffer.b);

            });

soundBuffer実際には、デコードされたバッファを、外部変数と内部buffer変数の両方が指す同じメモリ位置に割り当てて、playSound作業します。

于 2013-08-23T06:48:30.680 に答える
1

現在のスコープで soundBuffer を設定するには、コールバックを提供する必要があります。

loadSound を次のように変更します。

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

ロードサウンドの関数定義は次のとおりです。

function loadSound(url, callback) {

そして、成功関数は次のことを行います。

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

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

于 2013-08-23T06:12:57.587 に答える