简单地说,按一下按钮,我想用PolySynth和Sequence弹几个音符。如果用户重复按下按钮,我想要停止播放的任何内容,然后重新启动。
问题:,无论我尝试什么,我都不能完全取消/沉默之前播放的音符,以防序列再次启动(再次单击按钮)。这很可能是因为信封的衰败/维持。
我的合成人:
import { PolySynth } from 'tone'
const synth = new PolySynth(Synth, {
oscillator: {
type: 'sine4',
volume: -6,
},
envelope: {
attack: 0.01,
decay: 0.5,
sustain: 0.1,
release: 1,
},
}).toDestination()
synth.maxPolyphony = 4 // max notes playing at a time, not sure if necessary我的顺序:
import { Sequence } from 'tone'
// Play the 2 notes individually then play them together
const notes = [
{ note: 'C4', duration: '8n' },
{ note: 'G4', duration: '8n' },
{ note: ['C4', 'G4'], duration: '4n' }
]
// The sequence that should play the notes after one another
const sequence = new Sequence({
subdivision: '8n',
loop: false,
events: notes,
callback: (time, note) => synth.triggerAttackRelease(note.note, note.duration, time),
})按照我的方式,这是一个事件处理程序:
import { start, Transport } from 'tone'
// Event handler simply attached to a button's onClick
function onButtonClicked() {
// Call whatever this start is, doc says it can only happen in an event handler
start()
// Try everything to kill current sound
Transport.cancel()
Transport.stop()
// Start it again
Transport.start()
sequence.start()
}在开始播放之前,我怎么能完全杀死所有的声音(如果有的话)?
发布于 2020-09-30 14:48:27
简短回答
仔细想想,如果我正确地理解了你,这实际上是有意的行为。您正在触发合成器上的一个注释(基本上是一个AudioWorkletNode)。所以只要一个音符触发合成器,音符就消失了。阻止这个音符演奏的唯一方法是使合成器本身静音。
长答案
在你的评论中,你说你可能在概念上遗漏了一些东西,我认为你在正确的轨道上这样做。
让我们想想MIDI是如何产生声音的。
所以,当你停止你的运输或序列本身,这会做什么?如果MIDI便条已经触发信封,则信封将接收MIDI末端触发器并触发释放信封。
所以,你的合成器总是会有尾声,因为MIDI音符并不决定你的合成器的起点和终点,而是触发了你的信封的一部分。所以,实际上,你的合成器创造了声音,它既不与运输有关,也不可能。
希望这个解释能对你有所帮助。如果我误解了你,我很乐意纠正。
发布于 2022-06-25 22:51:20
该解决方案可能很难在较长的序列中实现,但在您的情况下,它应该可以工作。我曾挑战过相当类似的问题,而且成功了。
polySynth的问题是,您只能添加音符,而这些音符是播放的。但是对于正常的合成器来说,用空音符覆盖播放的音符是可以“杀死声音”的。
// It would create continuously playing note.
synth = synth || new Tone.Synth().toMaster();
synth.triggerAttackRelease(noteToPlay);
// It would mute the sound.
synth = synth || new Tone.Synth().toMaster();
synth.triggerAttackRelease();可以同时播放多个合成器,因此您可以手动创建多声子合成器。
synth1 = synth1 || new Tone.Synth().toMaster();
synth1.triggerAttackRelease(noteToPlay);
synth2 = synth2 || new Tone.Synth().toMaster();
synth2.triggerAttackRelease(noteToPlay2);
synth3 = synth3 || new Tone.Synth().toMaster();
synth3.triggerAttackRelease(noteToPlay3);构建序列要复杂得多,但是您可以通过在play函数的开头添加"soundKiller“来静音播放序列。重要的是:不要声明序列,然后通过调用“传输”来播放它,只需在事件处理程序中播放注释(因为--正如另一个人已经写过的那样--调用它之后传输不能停止)。
发布于 2022-03-10 13:43:03
音符继续播放,因为传输在触发后和释放之前停止。因此,一个解决方案是在您按下“停止”按钮时触发所有注释的释放。我在使用坦比安/钢琴时遇到了一个类似的问题(基于Tonejs)。
Tone.Transport.toggle()
if (Tone.Transport.state === 'stopped') {
for (let i=9; i<97; i++) {
piano.keyUp({midi: i}, '+0')
}
}https://stackoverflow.com/questions/63994325
复制相似问题