问题描述
我想给 Tone.js 一个音符列表和每个音符对应的持续时间,并让它播放序列。据我所知,没有简单的方法可以做到这一点。
在下面,对应的时间值不是我输入的(即0.25、0.5、0.25),如console.log所示:
var part = new Tone.Part(function(time,note){
console.log(time);
console.log(note);
synth.triggerAttackRelease(note,time);
},[[0.25,"C2"],[0.5,"C3"],[0.25,"G2"]]);
part.start(0).loop = false;
Tone.Transport.start();
如何给 Tone.js 注释和对应的毫秒播放?
解决方法
我不熟悉 Tone.js,所以可能有更好的方法来做到这一点。您使用的数组简写的 official example 似乎不起作用,因此可能是库问题。
至于您想要实现的目标,我出于好奇而摆弄它,这是我得出的结论:
function timeFromDurations(value,i,arr) {
const prevTime = arr[i - 1]?.time;
value.time = prevTime + arr[i - 1]?.duration || 0;
return value;
}
const notesAndDurations = [
{ note: 'C3',duration: .25 },{ note: 'C4',duration: .5 },{ note: 'G2',duration: 1 },].map(timeFromDurations);
console.log(notesAndDurations);
const synth = new Tone.Synth().toDestination();
// use an array of objects as long as the object has a "time" attribute
const part = new Tone.Part((time,value) => {
// the value is an object which contains both the note and the velocity
synth.triggerAttackRelease(value.note,value.duration,time);
},notesAndDurations).start(0);
Tone.Transport.start();
这个想法是你需要根据上一个音符的开始时间+持续时间来设置每个音符的开始时间。这消除了手动设置开始时间(非可选)的需要。
编辑
对于持续时间和音符在单独数组中的第二种情况,您可以使用以下 reduce 函数:
const notes = ['C3','C4','G2'];
const durations = [0.25,0.5,1];
const noteDurationTime = notes.reduce((acc,note,i) => {
const prevTime = acc[i - 1]?.time;
const time = prevTime + acc[i - 1]?.duration || 0;
const duration = durations[i];
acc.push({ note,duration,time });
return acc;
},[]);
想法是一样的,您正在构建一个具有所有所需属性(音符、持续时间、时间)的对象数组,但这次来自不同的来源(音符数组和持续时间数组)。
您要确保这两个数组的长度相同。