Jay White
Jay White

Reputation: 315

How can I link the current time in the audio context to input type=range?

I'm using React.js and the web audio API to create an app that plays music.
Demo

Could you please tell me how to link the input type=range to the music being played?
And by moving input type=range, I want to change the current time of the music being played.


The source code is as follows.

let audioCtx, audioBuffer, source;
const audioURL = "/piano.mp3";

const App = () => {
  const [load, setLoad] = useState(true);
  const [playing, setPlaying] = useState(false);
  const [total, setTotal] = useState(0);
  const [current, setCurrent] = useState(0);

  const audioLoad = async () => {
    const response = await fetch(audioURL);
    const arrayBuffer = await response.arrayBuffer();
    if (arrayBuffer) {
      audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
      setTotal(audioBuffer.duration);
    }
    setLoad(false);
  };
  useEffect(() => {
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    audioLoad();
    return () => {
      audioCtx.close();
      audioCtx = null;
    };
  }, []);

  const playAudio = () => {
    if (!playing) {
      source = audioCtx.createBufferSource();
      source.buffer = audioBuffer;
      source.connect(audioCtx.destination);
      source.start();
      setPlaying(true);
      return;
    }
    source.stop();
    setCurrent(0);
    setPlaying(false);
  };

  const changeSeek = (e) => {
    setCurrent(e.target.value);
    audioCtx.currentTime = current;
    console.log(audioCtx.currentTime);
  };

  return (
    <>
      <p>Total time {total}</p>
      <p>Current time {current}</p>
      <button onClick={playAudio} disabled={load ? true : false}>
        {playing ? "stop" : "play"}
      </button>
      <input
        onChange={changeSeek}
        value={current}
        type="range"
        max={total}
        style={inputStyle}
      />
    </>
  );
};

The audio context has a currentTime property, and I thought I could change the current time of the music by assigning the value of input type=range to this property, but I was unable to do so.

Also, I couldn't figure out how to automatically move input type=range to match the current time of the music.

Upvotes: 1

Views: 1368

Answers (1)

Raymond Toy
Raymond Toy

Reputation: 6048

BaseAudioContext.currentTime is immutable. It represents the HW audio clock so you can't just arbitrarily set to to move things around in time. If you want to be able to seek through an AudioBuffer, you'll have implement the seeking there, by creating an AudioBufferSourcNode with the desired AudioBuffer, and calling start(startTime, offset, duration) appropriately (possibly leaving off the duration parameter).

Or use a MediaElementAudioSourceNode with the src set up appropriately since a MediaElement supports seeking. This won't be sample accurate, but perhaps that's ok for your use case.

Upvotes: 1

Related Questions