来自<input type =“file”/>以外的源文件的FileReader.readAsArray()

时间:2018-05-09 00:50:03

标签: javascript filereader fileinputstream

我有以下HTML:

    <script type="text/javascript">
      window.onload = function() {

        var volumeBars = {
          mono: document.getElementById("monoFill")
        };

        document.getElementById("open-file").onchange = function(evt) {
          var file = evt.target.files[0];
          var reader = new FileReader();
          reader.onload = function(e) {
            playSound(e.target.result);
            console.log(e.target.result);
          }
          reader.readAsArrayBuffer(file);
        }

        var context = new AudioContext();

        function playSound(arraybuffer) {
          context.close();
          context = new AudioContext();

          var source = context.createBufferSource();
          context.decodeAudioData(arraybuffer, function(buffer) {
            source.buffer = buffer;
          });


          //=
          console.log(arraybuffer)
          var analyser = context.createAnalyser();
          analyser.smoothingTimeConstant = .9;
          analyser.fftSize = 1024;

          jsNode = context.createScriptProcessor(2048, 1, 1);
          jsNode.onaudioprocess = function() {
            var array = new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(array);
            volumeBars.mono.style.height = Math.average(array) * 2 + "px";
            volumeBars.mono.innerHTML = Math.floor(Math.average(array));
            console.log(volumeBars.mono.innerHTML);

          }

          source.connect(analyser);
          source.connect(context.destination);
          jsNode.connect(context.destination);
          analyser.connect(jsNode);

          source.start();
        }

        Math.average = function(arguments) {
          var numbers;
          if (arguments[0] instanceof Array) {
            numbers = arguments[0];
          } else if (typeof arguments[0] == "number") {
            numbers = arguments;
          }
          var sum = 0;
          var average = 0;
          for (var i = 0; i < numbers.length; i++) {
            sum += numbers[i];
          }
          average = sum / numbers.length;
          return average;
        }

      }

    </script>


    <div id="container">
      <div class="bar" id="mono">
        <div class="fill" id="monoFill"></div>
      </div>
    </div>

    <input type="file" id="open-file" accept="audio/*">

我面临的问题是,我想要替换块

  var file = evt.target.files[0];

使用本地文件,不需要每次都加载。我一直无法找到将文件编码为ArrayBuffer的方法。我确信这是一个非常业余的问题,有一个明显的答案,但欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

由于你想要的是访问服务器上的文件,你只需要发出一个Ajax请求,将响应设置为ArrayBuffer,这里不需要FileReader。

使用fetch API看起来像

const a_ctx = new(window.AudioContext || window.webkitAudioContext)();
fetch('https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3')
  .then(resp => resp.arrayBuffer()) // request as ArrayBuffer
  .then(buf => a_ctx.decodeAudioData(buf))
  .then(a_buf => {
    btn.onclick = e => {
      let node = a_ctx.createBufferSource();
      node.buffer = a_buf;
      node.connect(a_ctx.destination);
      node.start(0);
    };
    btn.disabled = false;
  });
<button id="btn" disabled>play</button>


<!-- Promising decodeAudioData for Safari https://github.com/mohayonao/promise-decode-audio-data/ [MIT] -->
<script src="https://cdn.rawgit.com/mohayonao/promise-decode-audio-data/eb4b1322/build/promise-decode-audio-data.min.js"></script>

使用XMLHttpRequest API

var a_ctx = new(window.AudioContext || window.webkitAudioContext)();
var xhr = new XMLHttpRequest();
xhr.open('get', 'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3');
xhr.responseType = 'arraybuffer'; // request as ArrayBuffer
xhr.onload = function() {
  var buf = xhr.response;
  a_ctx.decodeAudioData(buf, function(a_buf) {
    btn.onclick = function(e) {
      let node = a_ctx.createBufferSource();
      node.buffer = a_buf;
      node.connect(a_ctx.destination);
      node.start(0);
    };
    btn.disabled = false;
  });
};
xhr.send();
<button id="btn" disabled>play</button>