首页 > 解决方案 > 是否可以使用 Web Auido API 在不扭曲声音的情况下向 MediaElementAudioSourceNode 添加效果?

问题描述

我试图通过连接MediaElementAudioSourceNodeGainNode来操纵音量。
下面是它的演示。
代码沙盒

如果按下播放按钮,音乐将正常播放。
但是,操作input type=range以更改音量会使您正在播放的声音失真。(如果您尝试,请调低音量。)

有没有办法在不扭曲声音的情况下改变音量?
或者,如果您使用 MediaElementAudioSourceNode,这是不可避免的事情吗?
我找了一篇提到声音失真现象的文章,但我找不到。

在演示中,我们的目标只是改变音量,但我们还想添加混响、延迟等。


演示代码如下。

let audio, gainNode;

const App = () => {
  const [playing, setPlaying] = useState(false);
  useEffect(() => {
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    audio = new Audio("/piano.mp3");
    audio.crossOrigin = "anonymous"
    const sourceNode = audioCtx.createMediaElementSource(audio);
    gainNode = audioCtx.createGain();
    sourceNode.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    return () => audioCtx.close();
  }, []);

  const playPause = () => {
    if (playing) {
      audio.pause();
      setPlaying(false);
      return;
    }
    audio.play();
    setPlaying(true);
  };

  const cahngeVolume = (e) => (gainNode.gain.value = e.target.value);

  return (
    <>
      <button onClick={playPause} style={{ display: "block" }}>
        {playing ? "Pause" : "Play"}
      </button>
      <div>
        <span>Volume</span>
        <input type="range" onChange={cahngeVolume} step="any" />
      </div>
    </>
  );
};

标签: javascriptreactjsweb-audio-api

解决方案


失真的原因可能是 的范围GainNode并没有真正映射到您输入的范围。默认情况下,范围输入的最小值/最大值为 0 和 100。但是,GainNode确实将信号乘以其增益值。这意味着滑块的最大值应为 1。

<input type="range" onChange={cahngeVolume} step="any" max="1" />

这样,滑块从 0(无声音)变为 1(无放大)。


推荐阅读