Skip to content

Instantly share code, notes, and snippets.

@charlieroberts
Last active August 28, 2024 18:57
Show Gist options
  • Select an option

  • Save charlieroberts/4efc0ab599f88a5561d63bc3bc49f882 to your computer and use it in GitHub Desktop.

Select an option

Save charlieroberts/4efc0ab599f88a5561d63bc3bc49f882 to your computer and use it in GitHub Desktop.
2-op FM synthesis, beginning with low-frequency oscillation
/* ****** low-frequency modulation (vibrato) ******
This example shows how to use a second oscillator to
modulate the frequency of a oscillator over time. */
ctx = new AudioContext()
// create our primary oscillator, called the "carrier"
// in frequency modulation terminology (from radio)
carrier = ctx.createOscillator()
carrier.type = 'square'
// create an oscillator for modulation
mod = ctx.createOscillator()
mod.type = 'sine'
// slow oscillation...
mod.frequency.value = .5
// by default, oscillators output values in the range of {-1,1}.
// To create a wider range we use a gainNode
gainNode = ctx.createGain()
// scale input by 20... {-1,1} becomes {-20,20}
gainNode.gain.value = 20
// route modulating oscillator into gain node
mod.connect( gainNode )
// plug the gain node into the frequency of
// our carrier
gainNode.connect( carrier.frequency )
// connect carrier to master output
carrier.connect( ctx.destination )
// start both oscillators
mod.start( ctx.currentTime )
carrier.start( ctx.currentTime )
/************* classic 2-op FM Synthesis *****************/
ctx = new AudioContext()
// gong
// const index = .95
// const cmRatio = 1.4
// const attack .01
// const decay = 5
// bass
// const index = 1
// const cmRatio = 3
// const attack = .001
// const decay = .25
// glockenspiel
const index = 1
const cmRatio = 3.5307
const attack = .01
const decay = .5
playNote = function( frequency, duration ) {
// create our primary oscillator
let osc = ctx.createOscillator()
osc.type = 'sine'
osc.frequency.value = frequency
// create an oscillator for modulation
let mod = ctx.createOscillator()
mod.type = 'sine'
// change oscillation speed...
mod.frequency.value = frequency * cmRatio
// this will amplify our modulator
// and control the range of modulation
let modGainNode = ctx.createGain()
modGainNode.gain.value = frequency * index
mod.connect( modGainNode )
// plug the gain node into the frequency of
// our oscillator
modGainNode.connect( osc.frequency )
let envelope = ctx.createGain()
envelope.gain.linearRampToValueAtTime( 1, ctx.currentTime + attack )
envelope.gain.linearRampToValueAtTime( 0, ctx.currentTime + attack + decay )
osc.connect( envelope )
envelope.connect( ctx.destination )
mod.start( ctx.currentTime )
osc.start( ctx.currentTime )
// remove the node two seconds from
// the current audio time
osc.stop( ctx.currentTime + duration )
}
// 220 Hz, 2 seconds
playNote( 880, 2 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment