FileReader.readAsArray () из источника, отличного от <input type = "file"> - PullRequest
0 голосов
/ 09 мая 2018

У меня есть следующий 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 голосов
/ 09 мая 2018

Поскольку вам нужен доступ к файлу на вашем сервере, вам просто нужно сделать Ajax-запрос с ответом, установленным в ArrayBuffer, здесь не требуется FileReader.

Использование Получить 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>
...