Created
February 3, 2019 16:11
-
-
Save jinjor/6f0fde37ae1d0971a22b88f38601cf77 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const BASE_HELTZ = 440; | |
function generateId() { | |
return Math.random() | |
.toString(36) | |
.substr(2, 9); | |
} | |
function noteToHz(note: number) { | |
return BASE_HELTZ * 2 ** ((note - 69) / 12); | |
} | |
interface Instrument { | |
id: string; | |
noteOn(note: number, duration?: number): void; | |
noteOff(note: number): void; | |
} | |
class SimpleInstrument implements Instrument { | |
id: string; | |
private gainNode: GainNode; | |
private oscillators = new Map<number, OscillatorNode>(); | |
constructor(private audioContext: AudioContext) { | |
this.id = generateId(); | |
this.gainNode = audioContext.createGain(); | |
this.gainNode.gain.value = 0.01; | |
} | |
createOscillator(note: number): OscillatorNode { | |
const oscillator = this.audioContext.createOscillator(); | |
oscillator.type = "square"; | |
oscillator.frequency.value = noteToHz(note); | |
oscillator.connect(this.gainNode); | |
this.gainNode.connect(this.audioContext.destination); | |
return oscillator; | |
} | |
cleanupOscillator(note: number, oscillator: OscillatorNode): void { | |
oscillator.disconnect(); | |
this.oscillators.delete(note); | |
} | |
noteOn(note: number, durationInSeconds?: number) { | |
this.noteOff(note); | |
const oscillator = this.createOscillator(note); | |
oscillator.addEventListener("ended", () => { | |
this.cleanupOscillator(note, oscillator); | |
}); | |
try { | |
oscillator.start(); | |
this.oscillators.set(note, oscillator); | |
if (durationInSeconds) { | |
oscillator.stop(this.audioContext.currentTime + durationInSeconds); | |
} | |
} catch (e) { | |
oscillator.stop(); | |
} | |
} | |
noteOff(note: number) { | |
const oscillator = this.oscillators.get(note); | |
if (oscillator) { | |
oscillator.stop(); | |
} | |
} | |
} | |
const audioCtx = new AudioContext(); | |
const simple = new SimpleInstrument(audioCtx); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment