javascript - 在 Web Audio API 中,是否可以从一组样本中随机选择音频播放?

标签 javascript web-audio-api

我有一个包含大约 100 个样本的网页,其中许多是同一声音的不同版本;包含四个样本的简化版本位于 http://stephenandrewtaylor.net/sample-array-test/sample-loader.html

此页面使用 William Turner 的优秀著作《Javascript for Sound Artists》中的代码,将所有样本加载到一个对象中(从 var appSounds 开始 - 我在顶部包含了 Turner 的代码)。

// *** adapted from William Turner's "Javascript for Sound Artists" ***
"use strict";

var audioContext = new AudioContext();

function audioFileLoader(fileDirectory, callback) {
  var soundObj = {};
  var playSound = undefined;
  var getSound = new XMLHttpRequest();
  soundObj.fileDirectory = fileDirectory;
  getSound.open("GET", soundObj.fileDirectory, true); // 'true' argument enables asynchronous download
  getSound.responseType = "arraybuffer";
  getSound.onload = function() {
    audioContext.decodeAudioData(getSound.response, function(buffer) { // callback function
      soundObj.soundToPlay = buffer;  // stored as global variable
    });
};

  getSound.send(); // initiate the XMLHttpRequest

  soundObj.play = function(time, setStart, setDuration) {
    playSound = audioContext.createBufferSource();
    playSound.buffer = soundObj.soundToPlay;
    playSound.start(audioContext.currentTime + time || audioContext.currentTime, setStart || 
      0, setDuration || soundObj.soundToPlay.duration);

  if (typeof callback === "function") {
    return callback(playSound);
    } else {
      return playSound.connect(audioContext.destination);
    }
  };

  soundObj.stop = function(time) {
    playSound.stop(audioContext.currentTime + time || audioContext.currentTime);
  };
  return soundObj;
}

function audioBatchLoader(obj) {
  var callback = undefined;
  var prop = undefined;
  for (prop in obj) {
    if (typeof obj[prop] === "function") {
      callback = obj[prop];
      delete obj[prop];
    }
  }
  for (prop in obj) {
    obj[prop] = audioFileLoader(obj[prop], callback);
  }
  return obj;
}

// *** here is the code I would like to improve if possible ***
var appSounds = {
  stringPluck0: "StringA4-0.mp3",
  stringPluck1: "StringA4-1.mp3",
  stringPluck2: "StringA4-2.mp3",
  stringPluck3: "StringA4-3.mp3",
// *** how to make this an array, like stringPluck[0] etc.? ***

  nodes: function nodeGraph(sound) {
   sound.connect(audioContext.destination);
  }
};

var sounds = audioBatchLoader(appSounds);

function playback() {
  var rand = Math.floor(Math.random() * 4);
 switch (rand) {
  case 0: sounds.stringPluck0.play(); break;
  case 1: sounds.stringPluck1.play(); break;
  case 2: sounds.stringPluck2.play(); break;
  case 3: sounds.stringPluck3.play(); break;
  }
}

window.addEventListener("mousedown", playback);

我真的希望这是对象内的一个数组:

stringPluck: ["StringA4-0.mp3", "StringA4-1.mp3", 
  "StringA4-2.mp3", "StringA4-3.mp3"]

然后我可以使用随机数来触发stringPluck[rand]。但我无法让它发挥作用;我在这里查看了几个例子,并研究了威廉·特纳的书。我现在所拥有的正在工作,但是当您开始加载大量示例时,代码会变得非常冗长。

如果您有兴趣,使用 d3 的主要项目在这里: http://stephenandrewtaylor.net/exo-sonification/exoplanets.html .

最佳答案

与其他人的答案类似,重写的audioBatchLoader可以解决问题——必须确保返回整个对象而不仅仅是stringPluck:)

function audioBatchLoader(obj) {
    let callback = obj.nodes;
    let mp3;
    for (mp3 in obj.stringPluck) {
        obj.stringPluck[mp3] = audioFileLoader(obj.stringPluck[mp3], callback);
    }

    return obj;
}

教授干杯!

(P.S.将“sounds.stringPluck.length”更改为“appSounds.stringPluck.length”,这样可以减少错误):

        let rand = Math.floor(Math.random() * appSounds.stringPluck.length);

--洛根

关于javascript - 在 Web Audio API 中,是否可以从一组样本中随机选择音频播放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46312822/

相关文章:

javascript - 如何通过表单验证防止重复提交

javascript - 将 DateTime 字符串转换为 javascript 中的时间戳

javascript - 无法使用 Web Audio API 让基本振荡器产生噪音?

web-audio-api - 是否可以更改 MediaRecorder 的流?

html5-audio - HTML5 音频 : createMediaElementSource breaks audio output

javascript - 在 HTML5 WebAudio 中如何知道声音是否停止或播放完毕?

javascript - 使变量不是全局的

javascript - 在 css 中使用圆形 div mask 动画

javascript - TestCafe Runner.run(runOptions)永不返回,浏览器挂起(Firefox和Chrome)

node.js - 从 NodeJs 使用 WebAudio API