When I run AudioBufferSourceNode.start() when I have multiple tracks, I sometimes get a delay

Jay White

I am making an application that reads and plays two audio files.
CodeSnadBox
The above CodeSandBox has the following specifications.

  • Press the "play" button to play the audio.
  • The volume of each of the two audio tracks can be changed.

Problem

When playing audio, there is sometimes a delay.
However, there is not always an audio delay, and there are times when two tracks can be played back at exactly the same time.

Although not implemented in the CodeSandBox above, the application I am currently working on implements a seek bar to indicate the current playback position. By moving the seek bar to indicate the current playback position, the audio is reloaded and the resulting delay may be cured. On the other hand, moving the seek bar may cause a delay even though the audio was playing at exactly the same timing.

Anyway, is there a way to play multiple audio tracks at the same time in a stable and consistent manner?

Code

let ctx,
  tr1,
  tr2,
  tr1gain = 0,
  tr2gain = 0,
  start = false;

const trackList = ["track1", "track2"];

const App = () => {
  useEffect(() => {
    ctx = new AudioContext();
    tr1 = ctx.createBufferSource();
    tr2 = ctx.createBufferSource();
    tr1gain = ctx.createGain();
    tr2gain = ctx.createGain();
    trackList.forEach(async (item) => {
      const res = await fetch("/" + item + ".mp3");
      const arrayBuffer = await res.arrayBuffer();
      const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
      item === "track1"
        ? (tr1.buffer = audioBuffer)
        : (tr2.buffer = audioBuffer);
    });
    tr1.connect(tr1gain);
    tr1gain.connect(ctx.destination);
    tr2.connect(tr2gain);
    tr2gain.connect(ctx.destination);
    return () => ctx.close();
  }, []);

  const [playing, setPlaying] = useState(false);
  const playAudio = () => {
    if (!start) {
      tr1.start();
      tr2.start();
      start = true;
    }
    ctx.resume();
    setPlaying(true);
  };
  const pauseAudio = () => {
    ctx.suspend();
    setPlaying(false);
  };

  const changeVolume = (e) => {
    const target = e.target.ariaLabel;
    target === "track1"
      ? (tr1gain.gain.value = e.target.value)
      : (tr2gain.gain.value = e.target.value);
  };
  const Inputs = trackList.map((item, index) => (
    <div key={index}>
      <span>{item}</span>
      <input
        type="range"
        onChange={changeVolume}
        step="any"
        max="1"
        aria-label={item}
      />
    </div>
  ));

  return (
    <>
      <button
        onClick={playing ? pauseAudio : playAudio}
        style={{ display: "block" }}
      >
        {playing ? "pause" : "play"}
      </button>
      {Inputs}
    </>
  );
};
chrisguttandin

When calling start() without a parameter it's the same as calling start with currentTime of the AudioContext as the first parameter. In your example that would look like this:

tr1.start(tr1.context.currentTime);
tr2.start(tr2.context.currentTime);

By definition the currentTime of an AudioContext increases over time. It's totally possible that this happens between the two calls. Therefore a first attempt to fix the problem could be to make sure both function calls use the same value.

const currentTime = tr1.context.currentTime;

tr1.start(currentTime);
tr2.start(currentTime);

Since currentTime usually increases by the time of a render quantum you could add an extra safety net by adding a little delay.

const currentTime = tr1.context.currentTime + 128 / tr1.context.sampleRate;

tr1.start(currentTime);
tr2.start(currentTime);

If this doesn't help you could also use an OfflineAudioContext to render your mix upfront into a single AudioBuffer.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

How do I change the boot menu when I have no display?

来自分类常见问题

In jQuery, how do I get the value of a radio button when they all have the same name?

来自分类Dev

problem with udev rules when i want to start bash script

来自分类Dev

Why do I have to overload operators when implementing CompareTo?

来自分类Dev

Where is my APK stored when i run program on a android device?

来自分类Dev

Firefox crash when I run selenium unit test

来自分类Dev

Show alert when I get null record using if/else statement

来自分类Dev

Why don't I get correct result when I use original parseList function in Kotlin?

来自分类Dev

How can I get the x/y location of a touch relative to the entire view when I touch a button?

来自分类Dev

When I run msbuild, it makes a call to aspnet_compiler, but doesn't compile my site

来自分类Dev

When using (substack's) Tape module for testing, how do I run only one test in a file?

来自分类Dev

"No, missing feature: WATCH" when I try to run my smartphone app with wear app?

来自分类Dev

How do I run a global npm program when an ubuntu program has the same name?

来自分类Dev

I'm getting error when I import stream from tweepy

来自分类Dev

How can I disable backlight when I lock the screen?

来自分类Dev

How can I change the selected text when using Multiple Select jQuery plugin

来自分类Dev

ObjectDisposedException when I try to use an Image source

来自分类Dev

Should I use a pointer when dealing with lists?

来自分类Dev

Undeclared identifier for [i] when creating variables dynamically

来自分类Dev

When can I pass a function handle?

来自分类Dev

Do something when I clear an input

来自分类Dev

I have a multiple checkbox but i want save only single checkbox value in activity

来自分类Dev

How do I get my aliases to have correct completion?

来自分类Dev

NodeJS & Socket.IO: Emit a request event and get the response, when/where should I bind the listener?

来自分类Dev

QTableView: How can I get the data when user click on a particular cell using mouse

来自分类Dev

Dividing with big(ish) numbers in C (Get a zero, when I know it isn't zero)

来自分类Dev

In JIRA Agile, when I click a quickfilter I want other quickfilters to be unclicked, how can I do this?

来自分类Dev

How do I report error when setting a swift property?

来自分类Dev

Do I need to cleanup my event handlers when DOM changes?

Related 相关文章

  1. 1

    How do I change the boot menu when I have no display?

  2. 2

    In jQuery, how do I get the value of a radio button when they all have the same name?

  3. 3

    problem with udev rules when i want to start bash script

  4. 4

    Why do I have to overload operators when implementing CompareTo?

  5. 5

    Where is my APK stored when i run program on a android device?

  6. 6

    Firefox crash when I run selenium unit test

  7. 7

    Show alert when I get null record using if/else statement

  8. 8

    Why don't I get correct result when I use original parseList function in Kotlin?

  9. 9

    How can I get the x/y location of a touch relative to the entire view when I touch a button?

  10. 10

    When I run msbuild, it makes a call to aspnet_compiler, but doesn't compile my site

  11. 11

    When using (substack's) Tape module for testing, how do I run only one test in a file?

  12. 12

    "No, missing feature: WATCH" when I try to run my smartphone app with wear app?

  13. 13

    How do I run a global npm program when an ubuntu program has the same name?

  14. 14

    I'm getting error when I import stream from tweepy

  15. 15

    How can I disable backlight when I lock the screen?

  16. 16

    How can I change the selected text when using Multiple Select jQuery plugin

  17. 17

    ObjectDisposedException when I try to use an Image source

  18. 18

    Should I use a pointer when dealing with lists?

  19. 19

    Undeclared identifier for [i] when creating variables dynamically

  20. 20

    When can I pass a function handle?

  21. 21

    Do something when I clear an input

  22. 22

    I have a multiple checkbox but i want save only single checkbox value in activity

  23. 23

    How do I get my aliases to have correct completion?

  24. 24

    NodeJS & Socket.IO: Emit a request event and get the response, when/where should I bind the listener?

  25. 25

    QTableView: How can I get the data when user click on a particular cell using mouse

  26. 26

    Dividing with big(ish) numbers in C (Get a zero, when I know it isn't zero)

  27. 27

    In JIRA Agile, when I click a quickfilter I want other quickfilters to be unclicked, how can I do this?

  28. 28

    How do I report error when setting a swift property?

  29. 29

    Do I need to cleanup my event handlers when DOM changes?

热门标签

归档