My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Is a custom RxJS scheduler required for accurate music playback?

mvsica ficta's photo
mvsica ficta
·Aug 3, 2017

I recently saw the following video about making music with RxJS and was surprised that it was not scheduling notes using the Web Audio API clock. Rather, it was just playing audio directly using the System based timers with the standard schedulers in RxJS: youtube.com/watch?v=Wa5-DePTWdA&feature..

The Web Audio clock has a much higher resolution than the System clock, which is suitable for sample accurate playback (see info on clock differences below). The common setInterval and setTimeout functions typically used are based on the System clock, these functions are known to be imprecise and these happen to be what the current RxJS schedulers all use!

I'm aware that Tone.js can be used for playback but it comes with a large API and it's own idea of a music timeline that is limiting and not well suited for playing back arbitrary note structures. Using RxJS music can be processed in many ways so it makes sense to have the right scheduler as well.

From my research it looks like a custom RxJS scheduler is required that uses the Web Audio clock as a source. This way events scheduled on an Observable become queued actions that get scheduled directly to the Web Audio context (thread). How do I go about creating such a custom scheduler (there does not seem to be much info about this topic)? For most tasks the standard RxJS schedulers would suffice but for accurate music playback I see no other way.

CLOCK INFO

The Web Audio API has an extremely high-resolution and reliable timing system which differs in many ways from the JavaScript timing system of which the maximum resolution is only 1 millisecond, 0.001. The Web Audio API timing system has a resolution of 1/1000 of a picosecond, 0.000000000000001, or 1 femtosecond. This resolution is designed to be able to specify alignment on the sample-level, even with high-resolution audio. The timing system is always relative to the creation of the AudioContext, always starting at 0, and progressing in high-resolution seconds. The value can be accessed at any time by calling the ‘currentTime’ parameter of the AudioContext. This timing system makes it possible to build accurate sequencers, drum-machines, or time-reliant effects.

    var audioContext = new AudioContext;
    audioContext.currentTime; // example: 507.570793650793631

Music notes or any numerical AudioParam can be automated and scheduled. For instance, you could schedule the cutoff frequency of a filter to change over time, creating a filter sweep, or fadeout a sound over time.