2

在 Tone.js 中,我创建了一个类,该类创建一个.play()在音序器函数中调用的合成器实例,从而播放声音。this.synth在下面的课程中,当inupdateSynthType是单声道时,绝对没有问题Tone.Synth,但是当它是单声道时,整个事情都会中断Tone.Polysynth,我在尝试调用时收到以下错误updateSynthType

Uncaught Error: Synth was already disposed
    at ti (Tone.js:1)
    at ra._scheduleEvent (Tone.js:21)
    at Object.callback (Tone.js:21)
    at Gi._timeoutLoop (Tone.js:21)
    at Gi.emit (Tone.js:7)

我不明白为什么这种情况永远不会发生在常规情况下,Tone.Synth但是当我尝试更改时会Tone.PolySynth出现错误。我正在尝试更新设置以在多合成器类型(例如Synth, AMSynth, MetalSyth等)之间进行更改。我怎样才能阻止这个问题?为什么这个类只对普通人有效Tone.Synth?有没有更好的方法来更新这个类中的 PolySynth 类型?

这是有问题的课程:

class PolyInstrument {
  constructor(){
    this.synth = null
    this.gain = new Tone.Gain()
    this.gain.toDestination()
  }

  play(note = null, beat, time = null){
    if (this.synth){
      if (note === null){
        time ? this.synth.triggerAttackRelease(beat, time) : this.synth.triggerAttackRelease(beat)
      } else { 
        time ? this.synth.triggerAttackRelease(note, beat, time) : this.synth.triggerAttackRelease(note, beat)
      }
    } else {
      alert('error: no synth')
    }
  }

  get defaultSettings(){
    return {
      Synth: {
        oscillator: {
          type: 'triangle'
        },
        envelope: {
          attack: 0.005,
          decay: 0.1,
          sustain: 0.3,
          release: 1
        }
      },
      AMSynth: {
        harmonicity: 3 ,
        detune: 0 ,
        oscillator: {
          type: 'sine'
        },
        envelope: {
          attack: 0.01 ,
          decay: 0.01 ,
          sustain: 1 ,
          release: 0.5
        },
        modulation: {
          type: 'square'
        },
        modulationEnvelope: {
          attack: 0.5 ,
          decay: 0 ,
          sustain: 1 ,
          release: 0.5
        }
      }
    }
  }

  updateSynthType(synthType){
    if (this.synth){
      this.synth.disconnect(this.gain)
      this.synth.dispose()
    }
    let settings = this.defaultSettings[synthType] || {}
    this.synth = new Tone.PolySynth(Tone[synthType], settings)
    this.synth.connect(this.gain)
    this.play()
  }
}

谢谢阅读。

4

2 回答 2

0

我可以通过在处理之前清除上下文时间线来解决此问题:

synth.context._timeouts.cancel(0);
synth.dispose();
于 2022-02-08T15:32:50.310 回答
0

而不是使用synth.dispose(),调用synth.releaseAll()

https://tonejs.github.io/docs/14.7.77/PolySynth#releaseAll说:

立即触发所有当前活动声音的释放部分。用于使合成器静音。

于 2021-09-04T17:32:22.293 回答