如何在不停止Tone.Transport时动态修改Tone.js Sequencer事件数组?
在Tone.js Sequencer播放时动态修改events数组
问题描述
我希望在Tone.js Sequencer的播放过程中修改它的events数组,官网示例代码如下:
const synth = new Tone.Synth().toDestination() const seq = new Tone.Sequence((time, note) => { synth.triggerAttackRelease(note, .1, time) }, ["C4", ["E4", "D4", "E4"], "G4", ["A4", "G4"]] /* 我想修改这个数组 */).start(0)
我发现seq对象存在Tone.Sequencer._events属性,内部通过Proxy实现了get和set处理器,源码如下:
private _createSequence(array: any[]): any[] { return new Proxy(array, { get: (target: any[], property: PropertyKey): any => { // property is index in this case return target[property]; }, set: (target: any[], property: PropertyKey, value: any): boolean => { if (isString(property) && isFinite(parseInt(property, 10))) { if (isArray(value)) { target[property] = this._createSequence(value); } else { target[property] = value; } } else { target[property] = value; } this._eventsUpdated(); // return true to accept the changes return true; }, }); }
我的疑问是:能否在不停止Tone.Transport的情况下修改或替换正在播放的events数组?
解答
完全可以在不停止Tone.Transport的前提下动态修改或替换Sequencer的events数组,官方设计的Proxy机制就是专门用来支持这类实时更新场景的。
具体操作方法
- 修改单个元素:直接通过索引操作
seq._events数组即可,Proxy的set处理器会自动调用_eventsUpdated()通知Sequencer更新序列,无需额外操作:
// 修改第0位的音符 seq._events[0] = "D4"; // 修改嵌套数组中的元素 seq._events[1][1] = "F4";
- 替换整个数组:直接给
seq._events赋值新数组,Proxy会自动处理并触发序列更新:
seq._events = ["F4", "A4", ["C5", "B4"], "G4"];
- 调整数组长度:使用
push/pop/splice等数组方法修改元素数量,同样会被Proxy捕获并触发更新:
// 在序列末尾添加新音符 seq._events.push("C5"); // 删除第2个元素 seq._events.splice(2, 1);
关键说明
- 尽管
_events是私有属性,但从源码逻辑来看,官方通过Proxy开放了修改入口,这种操作是符合设计预期且安全的; - 修改后的新序列会在下一个循环周期生效,不会中断当前正在播放的音符,实现无缝过渡;
- 所有对
_events数组的修改都会触发_eventsUpdated()方法,该方法会重新计算序列的时间轴,确保新的事件能正确按时触发。
内容的提问来源于stack exchange,提问作者merkwur
相关产品推荐
相关产品推荐

