Skip to content

Instantly share code, notes, and snippets.

@frostburn
Created June 8, 2022 07:38
Show Gist options
  • Save frostburn/814aa3ca09a4eac12075d423dd87c835 to your computer and use it in GitHub Desktop.
Save frostburn/814aa3ca09a4eac12075d423dd87c835 to your computer and use it in GitHub Desktop.
Turning drawings from SOB into audio
from numpy import arange, linspace, where, maximum, sqrt, floor, clip, concatenate
from matplotlib.pyplot import plot, legend, show
import scipy.io.wavfile
# --- Helpers ---
def sqrt0(x):
return sqrt(maximum(0, x))
def triangle(x):
x = x - floor(x)
return 1 - 4*abs(x - 0.5)
def fold(x):
return triangle(0.25*x + 0.25)
# --- SOB drawings ---
def cups(x, separation=1):
x = x - floor(x)
return where(x < 0.5,
separation - sqrt0(1 - (4*x-1)**2),
sqrt0(1 - (4*x-3)**2) - separation
)
def clipped_triangle(x, overdrive=2):
return clip(triangle(x + 0.25) * overdrive, -1, 1)
def folded_triangle(x, overdrive=2):
return fold(triangle(x + 0.25) * overdrive)
# --- Plot waveforms ---
phase = linspace(0, 2, 1000)
plot(phase, cups(phase), label="cups")
legend()
show()
plot(phase, clipped_triangle(phase), label="flat peak")
legend()
show()
plot(phase, folded_triangle(phase), label="double peak")
legend()
show()
# --- Render audio ---
SAMPLE_RATE = 44100
t = arange(SAMPLE_RATE) / SAMPLE_RATE
def chord(waveform):
return 0.4 * (waveform(220 * t) + waveform(275 * t) + waveform(330 * t) + waveform(385 * t))
data = 0.49 * concatenate([
cups(220 * t),
clipped_triangle(220 * t),
folded_triangle(220 * t),
0*t,
chord(cups),
chord(clipped_triangle),
chord(folded_triangle)
])
scipy.io.wavfile.write("/tmp/sob.wav", SAMPLE_RATE, (data * 2**15).astype("int16"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment