Web Audio API的音量控制和缓冲问题

时间:2014-12-17 15:22:55

标签: javascript audio volume web-audio buffering

我遇到了使用Web Audio API编写应用程序的一些问题。

我尝试使用Web Audio API播放多种声音,每种声音都有一个独立的音量控制,并且能够同时播放多种不同的声音。但我无法弄清楚如何实现它。

我可以弄清楚如何实现通用音量控制,但希望能够增加/减少单个声音。我也遇到这样的问题:当我播放多个声音时,我似乎无法阻止它们......一个声音似乎总是卡在某个地方。

有关如何更新以下代码的任何建议将不胜感激。

    <head> 
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/loopy_styles.css" />
    <script>
        context = new (window.AudioContext || window.webkitAudioContext)();

        //We set up an array of buffers to store our sounds in, with an extra entry as dummy '0' entry
        var soundBuffers = [null,null,null,null,null,null];

        //We load our sounds into the buffer when the page is opened.
        window.onload = function() {
          loadSound('sounds/fire_test1.wav', 1);
          loadSound('sounds/wind_test.wav', 2);
          loadSound('sounds/rain_test1.wav', 3);
          loadSound('sounds/stream.mp3', 4);
          loadSound('sounds/spring_test.wav', 5);
        };


        var currentlyPlayingSoundNum = 0;
        var currentlyPlayingSound = null;

        //Function to play sound, take in a number to represent each sound icon.
        function play_sound(num){
          if (num) {
            //Shows the paused version of button, hides the play version of the button.
            document.getElementById('playBtn'+num+'_play').style.display = 'none';
            document.getElementById('playBtn'+num+'_stop').style.display = 'block';
            //Sets the currently playing sound to the number supplied to the function.
            currentlyPlayingSoundNum = num;
            //Creates buffer for sound.
            currentlyPlayingSound = context.createBufferSource();
            //Sets the sound to loop continuously so we have seemless play-back.
            currentlyPlayingSound.looping = true;
            //Sends the sound at spot num in our buffer array to the buffer for our currently playing sound.
            currentlyPlayingSound.buffer = soundBuffers[num];
            currentlyPlayingSound.connect(context.destination);
            //Start playing the sound.
            currentlyPlayingSound.start(0);
          }
        }
        //Function to stop sound, take in a number to represent each sound icon.
        function stop_sound(num){
          if(num){
            document.getElementById('playBtn'+num+'_play').style.display = 'block';
            document.getElementById('playBtn'+num+'_stop').style.display = 'none';
          }
          if (currentlyPlayingSound) {
            //Shows the play version of button, hides the paused version of the button.
            document.getElementById('playBtn'+currentlyPlayingSoundNum+'_play').style.display = 'block';
            document.getElementById('playBtn'+currentlyPlayingSoundNum+'_stop').style.display = 'none';
            //Stops playing the currently playing sound.
            currentlyPlayingSound.stop(0);
            currentlyPlayingSound = null;
            currentlyPlayingSoundNumber = 0;
          }
        }
        function loadSound(url, bufferNum) {
          var request = new XMLHttpRequest();
          request.open('GET', url, true);
          request.responseType = 'arraybuffer';

          request.onload = function() {
            var successCallback = function(buffer) {
              soundBuffers[bufferNum] = buffer;
            }
            var errorCallback = function(e) {
              console.log(e);
            }
            context.decodeAudioData(request.response, successCallback, errorCallback);
          }
          request.send();
        }
    </script>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <title>Ambient Sound Generator</title>  
  </head>
<body>
<div class="background">
  <div id="intro-text">
    <h1 id="site-title">Ambient Sound Generator</h1>
    <p>Mix ambient sounds together to block out distractions and help you focus or relax</p>
    <p>Click the buttons below to begin</p>
  </div>
  <div id="button-container">
    <div id="btn1">
      <input type="image" class="pp_img" src="img/fire-pause.png" name="Fire" id="playBtn1_play" onclick="play_sound(1);"   />
      <input type="image" class="pp_img" src="img/fire-play.png" name="Fire" id="playBtn1_stop" onclick="stop_sound(1);" style="display:none"   />
      <p><input type="range" min="0" max="100" value="100" onchange="sample.changeVolume();">Volume</p>
    </div>
    <div id="btn2">
      <input type="image" class="pp_img" src="img/wind-pause.png" name="Wind" id="playBtn2_play" onclick="play_sound(2);"  />
      <input type="image" class="pp_img" src="img/wind-play.png" name="Wind" id="playBtn2_stop" onclick="stop_sound(2);" style="display:none" />
      <p><input type="range" min="0" max="100" value="100" onchange="sample.changeVolume();">Volume</p>
    </div>
    <div id="btn3">
      <input type="image" class="pp_img" src="img/rain-pause.png" name="Rain" id="playBtn3_play" onclick="play_sound(3);"/>
      <input type="image" class="pp_img" src="img/rain-play.png" name="Rain" id="playBtn3_stop" onclick="stop_sound(3);" style="display:none"/>
      <p><input type="range" min="0" max="100" value="100" onchange="sample.changeVolume();">Volume</p>
    </div>
    <div id="btn4">
      <input type="image" class="pp_img" src="img/stream-pause.png" name="Stream" id="playBtn4_play" onclick="play_sound(4);"/>
      <input type="image" class="pp_img" src="img/stream-play.png" name="Stream" id="playBtn4_stop" onclick="stop_sound(4);" style="display:none"/>
      <p><input type="range" min="0" max="100" value="100" onchange="sample.changeVolume();">Volume</p>
    </div>
    <div id="btn5">
      <input type="image" class="pp_img" src="img/forest-pause.png" name="Rain" id="playBtn5_play" onclick="play_sound(5);"/>
      <input type="image" class="pp_img" src="img/forest-play.png" name="Rain" id="playBtn5_stop" onclick="stop_sound(5);" style="display:none" />
      <p><input type="range" min="0" max="100" value="100" onchange="sample.changeVolume();">Volume</p>
    </div>
      </div>
    </div>
    </body>
    <script>
      function refreshData(){
        x = 1;  // x = seconds
        var d = new Date()
        var h = d.getHours();
        var m = d.getMinutes();
        var s = d.getSeconds();

        if (h<=9) {h = '0'+h};
        if (m<=9) {m = '0'+m};
        if (s<=9) {s = '0'+s};

        var color = '#'+h+m+s;

          $("div.background").css("background-color", color );
          $("p#hex").text(color);
          setTimeout(refreshData, x*1000);
      }
      refreshData(); // execute function
    </script>

1 个答案:

答案 0 :(得分:2)

而不是

currentlyPlayingSound.connect(context.destination);

您只需要创建另一个GainNode并将其链接到:

var gain = context.createGain();
gain.gain.value = /*insert your gain variable here */;
currentlyPlayingSound.connect(gain);
gain.connect(context.destination);

您可能希望在某处缓存增益节点(因此您可以使用滑块等)