我有一个包含大约 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/