JSFiddle - React, Tailwind, and code Playground

JavaScript

AudioSynthesizer = function() {

	
	this.aContext = null;


	this.aOscillators = [];
	this.aVFOscillators = []

	this.t = 0
	this.lastLoopTime = Date.now();

	this.initializeSynthesizer = function() {

		self.aContext = new webkitAudioContext();
		self.mainLoop();

	};

	this.addOscillator = function(f) {
		if (isNaN(f))
		{
			console.log("frenquency must be a number. ")
			return;
		}
		aOscillator = self.aContext.createOscillator();
		aOscillator.frequency.value = f;
		aOscillator.connect(self.aContext.destination);
		self.aOscillators.push(aOscillator)

	};

	this.addVFOscillator = function(fn) {
		if (typeof fn != "function")
		{
			console.log("fn must be a function: time -> frequency")
		}

		VFOscillator = {
			fn: fn,
			audioNode: self.aContext.createOscillator()
		}

		VFOscillator.audioNode.frequency.value = VFOscillator.fn(0);
		VFOscillator.audioNode.connect(self.aContext.destination);
		self.aVFOscillators.push(VFOscillator)


	}

	this.playAudio = function() {
		for (i in self.aOscillators) {
			self.aOscillators[i].noteOn(0)
			self.aOscillators[i].noteOff(2)
		}

		for (i in self.aVFOscillators) {
			self.aVFOscillators[i].audioNode.noteOn(0)
			self.aVFOscillators[i].audioNode.noteOff(5)
		}
	};

	this.mainLoop = function() {

		self.t += (Date.now() - self.lastLoopTime)/1000;
		self.lastLoopTime = Date.now();

		requestAnimationFrame(self.mainLoop);
		for (i in self.aVFOscillators) {
			self.aVFOscillators[i].audioNode.frequency.value = self.aVFOscillators[i].fn(self.t)
		}

	}

	var self = this;

}



				f = function(t){
					//return 100
					return 50 + 20*Math.sin(7*t)

				}


				a = new AudioSynthesizer();
				a.initializeSynthesizer();
				a.addVFOscillator(f);
				a.playAudio();