Search code examples
javascriptweb-audio-apitone.js

Sample-accurate punch-in and punch-out recording using tone.js


Using the code below, I attempt to record exactly one bar of audio using tonejs` Recorder (a wrapper around MediaRecorder).

const userMedia = new Tone.UserMedia();
await userMedia.open();
const recorder = new Recorder();
userMedia.connect(recorder);

Tone.Transport.scheduleOnce(t => {
  console.log('starting recorder', t);
  recorder.start();
}, "4:0:0");

Tone.Transport.scheduleOnce(async t => {
  const data = await recorder.stop();
  // ... when I load the audio data into a SamplePlayer and inspect the buffer:
  //  * the length in seconds is 1.97 (I expect 2.0 for a bar when the tempo is 120 bpm)
  //  * the length in samples is 87317 (I expect 88200 for 2 secs w/ 44.1 sample rate) 

}, "5:0:0");

After recording, I load the audio data into a SamplePlayer and inspect the buffer:

  • the length in seconds is 1.97 (I expect 2.0 for a bar when the tempo is 120 bpm)
  • the length in samples is 87317 (I expect 88200 for 2 secs w/ 44.1 sample rate)

I am looking for advice on how to record exactly one bar of audio (i.e. 88200 samples w/ 120 bpm and 44.1 sample rate), with the start of the recorded audio being exactly on the measure.


Solution

  • This is not possible due to the fact that the Recorder class is relying on the MediaSream Recording API described here at mdn. This is a independent API and does not feature any sample accuracy.

    What you would have to do is create your own AudioProcessorWorklet, connect the UserMedia Stream with it and then grab the input samples from the worklet to create a AudioBuffer. You can then control the grabbing (recording) and not grabbing (not recording) of the samples via a parameter in a sample accurate way.