Skip to content

Instantly share code, notes, and snippets.

@dlandahl
Created December 10, 2018 20:31
Show Gist options
  • Save dlandahl/a99907e0ca4e9aa969c383451bca26e9 to your computer and use it in GitHub Desktop.
Save dlandahl/a99907e0ca4e9aa969c383451bca26e9 to your computer and use it in GitHub Desktop.
Python sound synthesis
import random, pyaudio
from math import sin, cos, pi
from array import array
p = pyaudio.PyAudio()
τ = 2 * pi
SAMPLE_RATE = 44100
LEN = SAMPLE_RATE * 4
class Buffer:
def __init__(self, size):
self.size = size
self.data = [0] * size
def __getitem__(self, key):
if key < 0: return 0
if key > self.size: return 0
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def apply_gain(self, gain):
for n in range(self.size):
self[n] *= gain
def zero(self):
self.data = [0] * self.size
def fill_with_noise(self):
for n in range(self.size):
self[n] = random.uniform(-1, 1)
class Biquad:
def __init__(self, cutoff = 220, resonance = 1):
self.Fs = SAMPLE_RATE
self.ƒ0 = cutoff
self.dBgain = 0
self.Q = resonance
def calculate_intermediates(self):
self.A = 10**(self.dBgain / 40)
self.ω = τ * self.ƒ0 / self.Fs
self.α = sin(self.ω) / (2*self.Q)
def make_lowpass(self, cutoff = None, resonance = None):
if cutoff is not None: self.ƒ0 = cutoff
if resonance is not None: self.Q = resonance
self.calculate_intermediates()
self.b0 = (1 - cos(self.ω)) / 2
self.b1 = 1 - cos(self.ω)
self.b2 = (1 - cos(self.ω)) / 2
self.a0 = 1 + self.α
self.a1 = -2 * cos(self.ω)
self.a2 = 1 - self.α
def process_buffer(self, buffer):
x = buffer
y = Buffer(x.size)
for n in range(buffer.size):
y[n] = (self.b0*x[n] + self.b1*x[n-1] + self.b2*x[n-2]
- self.a1*y[n-1] - self.a2*y[n-2]) / self.a0
return y
output = Buffer(LEN)
input = Buffer(LEN)
input.fill_with_noise()
filter = Biquad()
filter.make_lowpass(cutoff = 310, resonance = 15)
output = filter.process_buffer(input)
output.apply_gain(0.4)
stream = p.open(format = pyaudio.paFloat32, channels = 1, rate = SAMPLE_RATE, output = True)
stream.write(array('f', output.data).tobytes(), LEN)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment