At the moment is has amplitude modulation but not frequency modulation yet. An example script is attached at the end of the script.
I will probably put this on github soon enough.
ssynth.py
Code: Select all
from scipy.io.wavfile import write
from numpy import linspace, sin, pi, int16
import seaborn as sns; sns.set()
import numpy as np
from scipy import signal
def tone(freq, len, amp=1, rate=44100):
t = linspace(0, len, len*rate)
data = sin(2*pi*freq*t) * amp
return data
def square(freq, len, duty=0.5, amp=1, rate=44100):
t = linspace(0, len, len*rate)
sq = signal.square(2*pi*t*freq, duty=duty)
return sq * amp
def sawtooth(freq, len, width=1., amp=1, rate=44100):
t = linspace(0, len, len*rate)
saw = signal.sawtooth(2*pi*t*freq, width)
return saw * amp
def pause(len, rate=44100):
t = linspace(0, 0, len*rate)
return t
def extract_snip(tone, start, end, rate=44100):
nsamples = len(tone)
length = float(nsamples)/rate
start_sample = start * rate
end_sample = end * rate
return tone[start_sample:end_sample]
def modulate(tone, mod):
assert len(tone) == len(mod)
return tone * mod
def modulate_gaussian(tone, c, rate=44100):
nsamples = len(tone)
length = float(nsamples)/rate
t = linspace(-length/2, length/2, nsamples)
#tshift = -nsamples/2
g = np.exp(-(t)**2/(2*c**2))
return modulate(tone, g)
def modulate_fadein(tone, in_by=0.25, rate=44100):
nsamples = len(tone)
length = float(nsamples)/rate
in_by_sample = int(in_by * rate)
t = linspace(0, 1, in_by_sample)
nfollowing = int(nsamples - in_by_sample)
following = linspace(1, 1, nfollowing)
t = np.append( [t], [following] )
return modulate(tone, t)
def modulate_fadeout(tone, start_fade=0.75, rate=44100):
nsamples = len(tone)
length = float(nsamples)/rate
fade_at_sample = start_fade * rate
nfade = int(nsamples - fade_at_sample)
fade = linspace(1, 0, nfade)
t = linspace(1, 1, fade_at_sample)
t = np.append( [t], [fade] )
return modulate(tone, t)
def modulate_parabola(tone, rate=44100):
nsamples = len(tone)
length = float(nsamples)/rate
t = linspace(0, length, nsamples)
length = length/2
p = length**2 - (t - length)**2
p /= np.max(p)
return modulate(tone, p)
def write_waveform(data, fn, bitrate=44100):
write(fn, bitrate, data.astype(int16))
def plot_waveform(data, fn='waveform.png'):
sns.plt.plot(data)
sns.plt.savefig(fn)
sns.plt.close()
example.py
Code: Select all
import numpy as np
from ssynth import *
# presets
rumble_low = square(15, len=6, amp=10000)
rumble = square(40, len=6, amp=10000)
rumble_mid = square(100, len=6, amp=10000)
rumble_high = square(150, len=5, amp=10000)
spike = tone(2000, len=4, amp=15000)
rampup = modulate_fadein(sawtooth(100, len=30, amp=12500), in_by=27)
pulse_high = modulate_parabola(tone(1500, len=2, amp=20000))
pulse_low = modulate_parabola(tone(200, len=2, amp=12500))
p0 = pause(0.25)
p1 = pause(1)
p2 = pause(2)
p3 = pause(3)
stream = np.zeros(1)
stream = np.append(stream, rumble)
stream = np.append(stream, p1)
stream = np.append(stream, rumble_low)
stream = np.append(stream, p0)
stream = np.append(stream, rumble_mid)
stream = np.append(stream, spike)
stream = np.append(stream, rumble_mid)
stream = np.append(stream, spike)
stream = np.append(stream, rumble_mid)
stream = np.append(stream, spike)
stream = np.append(stream, p1)
stream = np.append(stream, pulse_high)
stream = np.append(stream, pulse_low)
stream = np.append(stream, p1)
stream = np.append(stream, rampup)
stream = np.append(stream, p1)
stream = np.append(stream, rampup)
write_waveform(stream, 'audio.wav')