1

我想给 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 注释和相应的 ms 进行播放?

4

1 回答 1

2

我不熟悉 Tone.js,所以可能有更好的方法来做到这一点。您使用的数组速记的官方示例似乎不起作用,因此可能是库问题。

至于您要实现的目标,出于好奇,我摆弄了它,这就是我的想法:

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;
}, []);

这个想法是一样的,你正在构建一个对象数组,这些对象具有所有需要的属性(note、duration、time),但这次来自不同的来源(notes 数组和 durations 数组)。
您要确保这两个数组的长度相同。

于 2021-07-20T13:20:48.220 回答