Skip to content

Instantly share code, notes, and snippets.

@gto76
Created January 31, 2019 13:41
Show Gist options
  • Save gto76/3132ac6f44160c7fc117fa39d094bb1e to your computer and use it in GitHub Desktop.
Save gto76/3132ac6f44160c7fc117fa39d094bb1e to your computer and use it in GitHub Desktop.
Simple music sinthesizer
# pip3 install simpleaudio
import wave, struct
import simpleaudio as sa
from collections import namedtuple
from math import pi, sin
Settings = namedtuple('Setting', 'n_channels sample_width f')
S = Settings(n_channels=1, sample_width=2, f=44100)
SECONDS = 4
def get_sin(frame_no, hz=440):
return sin(frame_no * 2 * pi * hz / S.f)
def get_square(frame_no, hz=440):
return 1 if (frame_no * hz / S.f) % 1 < 0.5 else -1
def get_saw(frame_no, hz=440):
return ((frame_no * hz / S.f) % 1) * 2 - 1
def get_wave(fun=get_sin, hz=440, seconds=SECONDS):
return (fun(i, hz) for i in range(seconds * S.f))
def get_lfo(fun=get_sin, hz=0.25, seconds=SECONDS, low_value=0, hi_value=1):
wave = get_wave(fun=fun, hz=hz, seconds=seconds)
return (to_lfo(a, low_value=low_value, hi_value=hi_value) for a in wave)
def to_lfo(pressure, low_value=0, hi_value=1):
return ((pressure + 1) / 2) * (hi_value - low_value) + low_value
def filter_LFO(wave, lfo):
lpf = get_lpf()
return (lpf(pressure=p, alpha_in=a) for p, a in zip(wave, lfo))
def filter_wave(wave, alpha=0.1):
lpf = get_lpf(alpha)
return (lpf(p) for p in wave)
def get_lpf(alpha=0.1):
avg = 0
def out(pressure, alpha_in=None):
nonlocal avg, alpha
if alpha_in:
alpha = alpha_in
avg += alpha * (pressure - avg)
return avg
return out
def play(float_samples):
audio_data = get_bytes(float_samples)
play_obj = sa.play_buffer(audio_data, S.n_channels, S.sample_width, S.f)
play_obj.wait_done()
def save(float_samples):
wf = wave.open('test.wav', 'wb')
wf.setnchannels(S.n_channels)
wf.setsampwidth(S.sample_width)
wf.setframerate(S.f)
wf.writeframes(get_bytes(float_samples))
wf.close()
def get_bytes(float_samples):
samples = [struct.pack('<h', int(a * 30000)) for a in float_samples]
return b''.join(samples)
sine_wave = get_wave()
square_wave = get_wave(get_square)
filtered_w = filter_wave(get_wave(get_square), alpha=0.01)
filtered_lfo = filter_LFO(wave=get_wave(get_square), lfo=get_lfo())
save(filter_LFO(wave=get_wave(get_square), lfo=get_lfo(low_value=0.01, hi_value=0.2)))
play(filter_LFO(wave=get_wave(get_saw), lfo=get_lfo(low_value=0.01, hi_value=0.065, hz=10)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment