Skip to content

Instantly share code, notes, and snippets.

@phooky
Created November 6, 2019 22:34
Show Gist options
  • Save phooky/92c9b1501d0ef68c4836c5436c8c0e20 to your computer and use it in GitHub Desktop.
Save phooky/92c9b1501d0ef68c4836c5436c8c0e20 to your computer and use it in GitHub Desktop.
terrible fm synthesis, it's just awful
#!/usr/bin/python3
import wave
import sys
import struct
import math
outpath=sys.argv[0].rsplit('.',1)[0]+".wav"
print("Writing to {}".format(outpath))
samp_rate = 44100.
w = wave.open(outpath,'wb')
w.setframerate(samp_rate)
w.setsampwidth(2)
w.setnchannels(2)
SCALE=2**14
TIMESTEP=1./samp_rate
def wf_saw(phi):
mphi = phi % (2*math.pi)
return -1. + (mphi / math.pi)
def wf_tri(phi):
mphi = phi % (2*math.pi)
if mphi < math.pi:
return -1. + 2*(mphi / math.pi)
else:
return -1. + 2*((2*math.pi-mphi) / math.pi)
def ramp(v1,v2,t1,t2):
delta = (v2-v1) / ((t2-t1)/TIMESTEP)
while t1 > 0.:
yield v1
t1 -= TIMESTEP
t2 -= TIMESTEP
while t2 > 0.:
v1 += delta
yield v1
t2 -= TIMESTEP
while True:
yield v2
def osc(freq,phi=0.,wf=math.sin):
delta = TIMESTEP*2*math.pi*freq
while True:
yield wf(phi)
phi += delta
def vosc(vfreq,phi=0.,wf=math.sin):
while True:
yield wf(phi)
phi += TIMESTEP*2*math.pi*next(vfreq)
def switch(f1,f2,time):
while time > 0.:
yield next(f1)
time -= TIMESTEP
while True:
yield next(f2)
def alternate(f1,f2,t1,t2):
while True:
time = t1
while time > 0.:
yield next(f1)
time -= TIMESTEP
time = t2
while time > 0.:
yield next(f2)
time -= TIMESTEP
def generate(l,r,duration):
time = 0.
while time < duration:
yield (next(l),next(r))
time += TIMESTEP
dat = bytearray()
l = alternate(osc(500),osc(500,wf=wf_tri),.5,.5)
r = vosc(ramp(60,200,1,3))
for (left,right) in generate(l,r,5):
dat.extend(struct.pack('hh',int(left*SCALE),int(right*SCALE)))
w.writeframes(dat)
w.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment