2

简而言之,按下按钮我想使用 aPolySynth和 a演奏一些音符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()
}

我怎么能在开始播放之前完全杀死所有声音(如果有的话)?

4

2 回答 2

2

简答

想了很多,如果我理解正确,这实际上是预期的行为。您正在触发 Synth(基本上是 AudioWorkletNode)上的音符。所以一旦一个音符触发了合成器,这个音符就消失了。阻止该音符播放的唯一方法是将合成器本身静音。

长答案

在你所说的评论中,你可能会在概念上遗漏一些东西,我认为你在正确的轨道上。

让我们考虑一下如何使用 MIDI 生成声音。

  1. 您正在将合成器(接收 MIDI 音符并生成声音)连接到输出
  2. 您正在传输上安排一些 MIDI 音符
  3. 你开始运输
  4. 一旦传输达到音符的预定时间,该 MIDI 值将被发送到合成器。
  5. 由于 Synth 基本上是一个带有 Envelope Generator 的 AudioWorkletNode,Synth 接收 MIDI 音符并触发内部声音生成(通过包络)。因此,特定时间点的 MIDI 音符会触发特定长度的声音生成(这将是 ADS 部分)。即使在您的示例中 MIDI 音符持续时间只有 1 毫秒,声音生成也会持续至少 1.001 秒(释放加上 1 毫秒的 MIDI 持续时间)。让我们再分解一下:
    • MIDI 音符在假想的传输时间线上有一个起点和终点。
    • 开始触发信封的 ADS 部分。
    • End 触发包络的 R 部分。
    • 一旦你的 MIDI 音符触发了包络,就会生成声音。

因此,当您停止传输或序列本身时,会发生什么?如果 MIDI 音符已经触发了包络,包络将接收 MIDI 结束触发器并触发释放包络。

所以你的合成器总会有拖尾的声音,因为 MIDI 音符不会决定你的合成器的开始和结束点,但会触发你包络的一部分。所以实际上你的合成器创造了声音,它既不依赖于传输,也不可能是。

希望这个解释对你有所帮助。如果我误解了你,我很乐意纠正。

于 2020-09-30T14:48:27.053 回答
-1

使用 Tone.Transport.pause()

如果您有一个“暂停播放”类的播放/暂停按钮,请参见下面的示例:

$( '.pause-play' ).on('click', function(e) {

    if (Tone.Transport.state === "paused" ) {  
          Tone.Transport.start("+0.1") })
    else {
          Tone.Transport.pause()  }
    }
)
于 2021-06-02T18:29:27.770 回答