You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tone.js中sampler.triggerAttackRelease()多次调用后无声问题求助

解决Tone.Sampler添加time/velocity参数后多次点击无声音的问题

问题根源

你遇到的问题是因为triggerAttackRelease方法的time参数传入了固定值0。Tone.js的time参数基于音频上下文的时间线,第一次点击时0对应音频上下文启动后的初始时间,是有效的;但后续点击时,音频上下文的时间已经推进,0这个时间点已成为“过去”,Tone.js会自动跳过所有落在过去的事件,导致没有声音输出。

而仅传递notes和duration时,time参数会使用默认值Tone.now()(当前音频上下文的实时时间),所以每次点击都会立即触发声音,不会出现失效问题。

修复方案

将time参数改为Tone.now()(表示立即触发),或者直接省略time参数(使用默认值),同时保留velocity参数即可:

修改后的核心代码

function playSample() 
{
    if (Tone.context.state !== 'running') 
    {
        Tone.start();
    }
    // 方案1:使用Tone.now()作为time参数,明确指定立即触发
    sampler.triggerAttackRelease(["Eb4", "G4", "Bb4"], 4, Tone.now(), 0.1);
    
    // 方案2:省略time参数,直接传递velocity(参数顺序自动匹配)
    // sampler.triggerAttackRelease(["Eb4", "G4", "Bb4"], 4, undefined, 0.1);
}

完整修复代码

<!DOCTYPE HTML>
<html>
    <head>  
        <meta charset="utf-8" />
        <title>Simple HTML</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src="https://unpkg.com/tone"></script>

        <script>
            const sampler = new Tone.Sampler({
                urls: {
                    C4: "C4.mp3",
                    "D#4": "Ds4.mp3",
                    "F#4": "Fs4.mp3",
                    A4: "A4.mp3",
                },
                release: 1,
                baseUrl: "https://tonejs.github.io/audio/salamander/",
            }).toDestination();

            // 提前等待资源加载完成,避免每次点击重复判断
            Tone.loaded().then(() => {
                console.log("Sampler资源加载完成");
            });

            function playSample() 
            {
                if (Tone.context.state !== 'running') 
                {
                    Tone.start();
                }
                sampler.triggerAttackRelease(["Eb4", "G4", "Bb4"], 4, Tone.now(), 0.1);
            }
        </script>
    </head>
    <body>
        <h1>Un accord répété, Demo</h1>
        <button onclick="playSample()">Click me to play sample note!</button>
    </body>
</html>

额外优化说明

  • 把Tone.loaded().then()移到全局初始化阶段,不需要每次点击都执行资源加载判断,提升性能。
  • 如果需要延迟触发声音,可以在Tone.now()基础上加偏移值,比如Tone.now() + 1表示1秒后触发。

内容的提问来源于stack exchange,提问作者Frédéric Faure

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:53:19