Tone.js 完全停止所有播放声音

2023-12-21

简而言之,按下按钮我想使用PolySynth and 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()
}

在开始播放之前我怎样才能完全消除所有声音(如果有的话)?


简答

仔细思考一下,如果我理解正确的话,这实际上是有意的行为。 您正在 Synth(基本上是一个 AudioWorkletNode)上触发一个音符。因此,一旦音符触发合成器,该音符就会消失。阻止该音符播放的唯一方法是将合成器本身静音。

长答案

在您所说的评论中,您可能在概念上遗漏了一些东西,我认为您在这一点上是正确的。

让我们考虑一下 MIDI 是如何产生声音的。

  1. 您正在将 Synth(它获取 MIDI 音符并生成声音)连接到输出
  2. 您正在传输上安排一些 MIDI 音符
  3. 你开始运输
  4. 一旦传输达到音符的预定时间,该 MIDI 值就会发送到合成器。
  5. Since the Synth is basically an AudioWorkletNode with an Envelope Generator, the Synth takes that MIDI note and triggers the internal sound generation (via the envelope). So a MIDI note at a specific point in time triggers a specific length of sound generation (which would be the ADS part). Even if the MIDI notes duration is only 1ms long in your example, the sound generation would hold on for at least 1.001 seconds (Release plus 1 milliseconds MIDI duration). Let's break this down a bit more:
    • MIDI 音符在假想的传输时间轴上有一个起点和终点。
    • Start 触发 Envelope 的 ADS 部分。
    • End 触发包络的 R 部分。
    • 一旦您的 MIDI 音符触发了包络,就会生成声音。

那么,当你停止运输或序列本身时,会发生什么? 如果 MIDI 音符已触发包络,则包络将接收 MIDI 结束触发器并触发释放包络。

因此,您的合成器总会有拖尾声音,因为 MIDI 音符无法确定您的合成器的起点和终点,但会触发您的包络的部分内容。所以实际上你的合成器创造了声音,它既不依赖于传输,也不可能依赖于传输。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Tone.js 完全停止所有播放声音 的相关文章

  • JavaScript 中的“new”关键字是什么?

    The newJavaScript 中的关键字第一次遇到时可能会很混乱 因为人们倾向于认为 JavaScript 不是面向对象的编程语言 它是什么 它解决什么问题 什么时候合适 什么时候不合适 它做了 5 件事 它创建一个新对象 这个对象的
  • Webpack 缺少 CommonsChunk 和 extract-text-webpack-plugin 模块

    我正在跟进Maxime Fabre 的 Webpack 教程 https blog madewithlove be post webpack your bags 我正在尝试获得一个非常简单的 webpack 包 其中包含 1 个入口点和 2
  • 如果浏览器在 asp .net 中关闭,请从浏览器中注销?

    我的要求有点复杂 用户正在使用 Web 浏览器访问数据库 而在访问数据库时 如果用户关闭活动页面而不是注销会话 该会话需要自动注销 有人可以指导我如何做这个吗 我在母版页中使用了jquery onbeforeunload 我收到消息离开页面
  • 动态表中每个按钮的 Jquery-Ui 对话框表单

    我正在生成一个 HTML 表 每行都有一个按钮 必须打开 Jquery ui 对话框表单 The table table class table table reporting table condensed table striped t
  • 在 JavaScript 中定位提示弹出窗口

    我有一个如下所示的 JavaScript 提示 我想将提示放在屏幕中心 如何使用 javascript 做到这一点 function showUpdate var x var name prompt Please enter your na
  • 在 IE10 中禁用捏合放大

    在 IE10 触摸模式下 我希望仅使页面的特定部分可缩放 其余的不应该 我找到了这个 http msdn microsoft com en US library ie hh772044 aspx http msdn microsoft co
  • 单击输入字段会触发窗口调整大小

    我有一个带有徽标 菜单和搜索的标题 当我在桌面上时 我会按该顺序显示所有元素 但如果我的窗口宽度小于 980 像素 菜单会隐藏 有一个切换按钮 并且徽标会与nav并附在徽标之后 如果宽度更大 则徽标将再次分离并附加到 DOM 中的旧位置 w
  • 将 Google 电子表格解析为 Javascript 数组

    我有一个 Google 电子表格 https docs google com spreadsheets d e 2PACX 1vRc8Lx0N wf3f1xAAXkNFUqQjaWPFcde3YjK02gCBqGpUrULwHC6NC0sn
  • 离子旋转器未显示

    我用 http 请求填充 Ionic 集合重复列表 但我不想将所有内容直接加载到 DOM 中 因此 我只显示其中一些项目 并在您向下滚动时添加其余项目 为此我实现了无限滚动功能 当我到达页面底部时 它应该显示一个旋转器 但它没有 这些物品至
  • 获得一次性绑定以适用于 ng-if

    这个问题已经被之前问过 https stackoverflow com questions 23969926 angular lazy one time binding for expressions 但我无法让该解决方案发挥作用 所以我想
  • 无法在渲染器进程中使用 Node.js API

    无法在 Electron 中使用任何与 Electron 或节点相关的操作 未定义获取错误过程 我检查了他们指导添加节点支持的各个地方 但这已经完成了 所以卡在这里 我的主要应用程序代码是 const electron require el
  • 如何将当前元素传递给 Knockout.js 绑定中的 Javascript 函数?

    因此 我尝试根据是否选中子复选框 使用 Knockout js 将类添加到元素 为此 我试图通过this作为我的函数的参数 目前 我的精简 DOM 结构如下 tr td td tr
  • 从相机视图中拖动锁定在一定距离/半径处的对象

    我在场景中心有一个相机 距离相机 z 400 处有 1 个球体 其父级位于中心 我想从视图中向上 向下 向左 向右拖动球体 但同时不改变它相对于中心的 z 位置 我最终使用了另一个球体并使其不可见 添加side THREE DoubleSi
  • 如何修复 getImageData() 错误画布已被跨源数据污染?

    我的代码在本地主机上运行得很好 但在网站上却不起作用 我从控制台收到此错误 对于这一行 getImageData x y 1 1 data Uncaught SecurityError Failed to execute getImageD
  • `ie9` - contenteditable false 在父级可编辑时不起作用

    我正在尝试制作内容可编辑和不可编辑的容器 用户可以通过 3 种方式使用它 他们可以将内容与non editable 他们可以将内容与editable 他们可以在不选择其中之一的情况下放置内容 可编辑 我正在努力实现以下目标 content
  • JavaScript 中最长的通用前缀

    我正在尝试解决 Leet Code 挑战14 最长公共前缀 https leetcode com problems longest common prefix 编写一个函数来查找字符串数组中最长的公共前缀字符串 如果没有公共前缀 则返回空字
  • Angular 2访问组件内的ng-内容

    我怎样才能访问 content 来自组件类本身的组件 我想做这样的事情
  • 跨浏览器:禁用输入字段的不同行为(文本可以/不能复制)

    我有一个被禁用的输入 html 字段 在某些浏览器 Chrome Edge Internet Explorer 和 Opera 中可以选择并复制文本 但至少在 Firefox 中这是不可能的 您可以通过在不同浏览器中执行以下代码来测试
  • 如何从配置加载套接字 io 事件监听器? [复制]

    这个问题在这里已经有答案了 我有使用套接字io 的nodejs 应用程序 我将存储在 config routes js 中的所有事件侦听器 module exports routes auth login controller auth a
  • 如何设置 Firebase 用户的显示名称?

    根据Firebase网站上的JS Auth文档 它只展示了如何获取 displayName 以及如何更新 displayName 所以我尝试更新它 但这有点不合逻辑 因为你怎么能在不创建某些东西的情况下更新它呢 所以我的问题是 如何设置注册

随机推荐