我有一个包含大约100个样本的网页,其中许多是相同声音的不同版本;包含四个样本的简化版本位于http://stephenandrewtaylor.net/sample-array-test/sample-loader.html。
此页面使用William Turner的优秀书籍Javascript for Sound Artists的代码,将所有样本加载到一个对象中(从var appSounds
开始 - 我已经包含了特纳的代码顶部)。
// *** 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
答案 0 :(得分:0)
我没有弄清楚所有细节,但你可以从定义
开始
var appSounds = {
stringPluck: ["StringA4-0.mp3", "StringA4-1.mp3",
"StringA4-2.mp3", "StringA4-3.mp3"];
...
};
然后将audioBatchLoader
更新为
function audioBatchLoader(obj) {
// Get the nodeGraph method
let callback = obj.nodes;
// Run through the stringPluck array and create a corresponding
// soundObj for each element.
return obj.stringPluck.map(mp3 => {
audioFileLoader(mp3, callback);
});
}
然后你可以做,我想,
function playback() {
let rand = Math.floor(Math.random() * sounds.length);
sounds[rand].play();
}
答案 1 :(得分:0)
与其他人的回答类似,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);
- 洛根