Some happy little lines. (No relation.)
This is a little single I started working on last year with the goal of improving the facility for sequencing at larger time scales with the drum machine abstraction I use in my music sometimes. (It’s still a WIP but this helped me work some new ideas out.)
It ended up as mini EP arranged with Ardour into three parts based around two main renders (the ‘single’ and an earlier extended alternate version) and some other intermediate renders.
Here’s the (raw, just pasting it as-is) score for happy
(which features some additional renders in the intro section not represented here before starting the main single)
import aubio
import numpy as np
from pippi import dsp, fx, oscs, shapes, tune, rhythm, noise
from pippi.wavesets import Waveset
from pathlib import Path
RN = 56
dsp.seed(RN)
WINSIZE = 4096
HOPSIZE = WINSIZE//2
SR = 44100
KEY = 'e'
c3 = dsp.read('/home/hecanjog/sounds/kits/001/clap3.wav')
sn = dsp.read('/home/hecanjog/sounds/kits/001/snap1.wav')
snr = dsp.read('/home/hecanjog/sounds/kits/001/snare4.wav')
kik = dsp.read('/home/hecanjog/sounds/kits/002/707 KICK 1.wav')
rhodes = dsp.read('sounds/nycrhodesC.wav')
suite = dsp.read('sounds/suitetoneC#.wav').remix(2).speed(0.99)
rolls = dsp.read('sounds/melonpans.wav')
pour = dsp.read('sounds/melonpour.wav')
hat_lfo = dsp.win(shapes.win('sine'), 0.01, 0.1)
kick_lfo = dsp.win(shapes.win('sine'), 0.05, 0.1)
clap_lfo = dsp.win(shapes.win('sine'), 0.01, 0.07)
snar_lfo = dsp.win(shapes.win('sine'), 0.01, 0.07)
time_lfo = dsp.win('hann', 0.001, 0.2)
segs = [ dsp.read(s) for s in Path('./segments').glob('seg-*.wav') ]
chords = ['ii6', 'V', 'V7', 'i11', 'I', 'I11', 'vi9']
chords = ['ii11', 'ii11', 'III7', 'ii11', 'i11', 'i11', 'vii*9']
chords = ['ii7', 'ii9', 'ii7', 'ii11', 'IV9', 'vii*9']
chords = ['ii7']
#freqs = tune.chord('i11', octave=2, key='e')
##########
# SEGMENTS
##########
def flatten(snd):
return np.asarray(snd.remix(1).frames, dtype='f').flatten()
def divide(snd, lpf=None, hpf=None):
o = aubio.onset('specflux', WINSIZE, HOPSIZE, SR)
# Filters
if lpf is not None:
snd = fx.hpf(snd, 200)
if hpf is not None:
snd = fx.lpf(snd, 12000)
pos = 0
length = len(snd)
start = None
while pos < length - HOPSIZE:
frames = flatten(snd[pos:pos+HOPSIZE])
if o(frames):
# Found onset
onset = o.get_last()
#print(count, onset, start, pos)
if start is not None:
yield snd[start:onset]
start = onset
pos += HOPSIZE
def chop():
segcount = 0
for s in divide(g):
s.write('segments/seg-%00d.wav' % segcount)
segcount += 1
#######
# DRUMS
#######
def makehat(pos, count):
length = hat_lfo.interp(pos)
lowhz = dsp.win('rnd', 5000, 6000)
highhz = dsp.win('rnd', 6000, 14000)
h = noise.bln('sine', length, lowhz, highhz).env('pluckout') * dsp.rand(0.2, 0.4)
basehz = dsp.rand(3000, 10000)
widthz = dsp.rand(100, 3000)
curve = dsp.win(shapes.win('hann'), basehz, basehz + widthz)
return fx.hpf(h, curve, dsp.rand())
def makekick(pos, count):
return kik.copy().env(dsp.choice(['pluckout', 'hannout', 'sineout'])) * dsp.rand(1.2, 1.5)
def makeclap(pos, count):
length = clap_lfo.interp(pos)
lowhz = dsp.win('rnd', 3000, 6000)
highhz = dsp.win('rnd', 2000, 8000)
out = noise.bln('tri', length, lowhz, highhz).env('pluckout') * 2
out = fx.fold(out, amp=dsp.win(shapes.win('hann', length=length/2), 1, 8))
out = fx.lpf(out, 6000).vspeed([1, 0.4])
out.dub(c3)
if dsp.rand() > 0.5:
out.dub(sn)
if dsp.rand() > 0.4:
if dsp.rand() > 0.4:
out = fx.delay(out, dsp.rand(0.01, 2), dsp.rand(0.25, 0.5))
elif dsp.rand() > 0.8:
out = fx.mdelay(out, [ dsp.rand(0, 8) for _ in range(dsp.randint(3, 10)) ], 0.7)
basehz = dsp.rand(300, 2000)
widthz = dsp.rand(100, 3000)
curve = dsp.win(shapes.win('hann'), basehz, basehz + widthz)
out = fx.lpf(out, curve)
return out * 0.7
def makesnare(pos, count):
length = snar_lfo.interp(pos)
lowhz = dsp.win('rnd', 3000, 6000)
highhz = dsp.win('rnd', 2000, 8000)
out = noise.bln('tri', length, lowhz, highhz).env('pluckout') * 2
out = fx.fold(out, amp=dsp.win(shapes.win('hann', length=length/2), 1, 8))
out = fx.lpf(out, 6000)
if dsp.rand() > 0.9:
out = out.vspeed([1, 0.4])
s = snr.copy()
s = s.cut(0, dsp.rand(s.dur/4, s.dur)).env('pluckout')
s = s.speed(dsp.rand(1.5, 2))
out.dub(s)
return out * 2
###################
# PITCHED / MELODIC
###################
def makecrd(pos, count):
def make_imp(freqs, segs):
seg = dsp.choice(segs)
ilen = dsp.rand(0.3, 3)
imp = dsp.buffer(length=ilen)
stack = Waveset(seg, offset=dsp.randint(50, 100), limit=dsp.randint(10, 40))
stack.normalize()
for _ in range(dsp.randint(2,6)):
freq = dsp.choice(freqs) * 2**dsp.randint(0, 3)
i = oscs.Pulsar2d(stack, windows=['hann'], freq=freq).play(ilen).pan(dsp.rand()).env('pluckout') * dsp.rand()
#i = i.env(dsp.choice(['hannout', 'sineout', 'saw', 'rsaw', 'pluckout']))
imp.dub(i)
if dsp.rand() > 0.5:
imp.dub(imp.rcut(dsp.rand()).repeat(dsp.randint(2, 30)).env('pluckout'))
#curve = dsp.win('rnd', dsp.choice(freqs) * 2, max(freqs) * 2)
#imp = fx.lpf(imp, curve)
return imp * 1.5
def make_src(freqs, segs):
seg = dsp.choice(segs)
src = fx.norm(seg, 1).env('pluckout')
src = src.vspeed(dsp.win('rnd', 0.75, 1))
if dsp.rand() > 0.5:
src = src.rcut(dsp.rand()).repeat(dsp.randint(2, 30)).env('pluckout')
return src
freqs = tune.chord(chords[0], octave=2, key=KEY)
out = make_src(freqs, segs)
imp = make_imp(freqs, segs)
out.dub(imp)
out = fx.norm(out, dsp.rand(0.7, 1))
return out.env('pluckout') * 1.6
def makebas(pos, count):
s = ['e1', 'e1', 'e1', 'e1', 'd1', 'd1', 'c1']
freq = tune.ntf(s[count % len(s)]) * 1.5
if dsp.rand() > 0.8 and count % 3 == 0:
freq *= 2
blength = dsp.rand(0.4, 0.6)
out = dsp.buffer(length=blength)
for o in range(3):
amp = abs(1 - (o/3)) + 0.15
b = oscs.Osc('square', freq=freq * 2**o, quality=8, phase=dsp.rand()).play(blength).pan(dsp.rand()) * amp
out.dub(b)
out = fx.fold(out, amp=dsp.win('rnd', 10, dsp.rand(30,100)))
out = fx.lpf(out, freq*dsp.rand(3,7))
out = fx.norm(out, dsp.rand(0.7, 0.9))
return out.env('pluckout') * 5
def makeswell(pos, count):
swelllength = dsp.rand(4, 10)
out = dsp.buffer(length=swelllength)
freq = dsp.choice(tune.chord(chords[0], key=KEY, octave=dsp.randint(4, 10)))
rfreq = False
if dsp.rand() > 0.5:
rfreq = True
for _ in range(dsp.randint(1,4)):
if rfreq:
freq = dsp.choice(tune.chord(chords[0], key='e', octave=dsp.randint(1, 4)))
o = oscs.Osc('sine', freq=freq, phase=dsp.rand(), quality=6).play(swelllength) * dsp.rand(0.04, 0.1)
o = o.pan(dsp.rand())
out.dub(o)
out = out.env(dsp.win(shapes.win('hann'), 0.4, 0.8)).env('sine').env('hann')
out = out.pad(start=dsp.rand())
return out
def makebells(pos, count):
#freqs = tune.chord(chords[0], octave=2, key=KEY)
freqs = tune.fromdegrees([2,4,2,4,2,3,6,7,2,4,7,8], octave=3, root=KEY)
freq = freqs[count % len(freqs)]
r = rhodes.copy().speed(freq / tune.ntf('c3'))
r = r.cut(0.05, dsp.rand(1, 4)).env('pluckout')
r = r.pan(dsp.rand())
if dsp.rand() > 0.4:
rd = fx.delay(r, dsp.rand(0.01, 2), dsp.rand(0.25, 0.5))
elif dsp.rand() > 0.8:
rd = fx.mdelay(r, [ dsp.rand(0, 8) for _ in range(dsp.randint(3, 10)) ], 0.7)
else:
rd = r.copy()
rd = rd.cut(0, 0.5).cloud(rd.dur,
grainlength=dsp.win(shapes.win('hann'), dsp.MS*40, dsp.MS*400),
grid=dsp.win(shapes.win('hann'), dsp.MS*40, dsp.MS*4000),
)
rd = fx.hpf(rd, dsp.win(shapes.win('hann'), freq, freq*4))
r.dub(rd)
s = suite.copy().speed(freq / tune.ntf('c#4')) * dsp.rand(0.2, 0.5)
s = s.cut(0.05, dsp.rand(1, 4)).env('pluckout')
s = s.pan(dsp.rand())
#if dsp.rand() > 0.5:
# s = s.speed(dsp.choice([2,4]))
if dsp.rand() > 0.4:
sd = fx.delay(s, dsp.rand(0.01, 2), dsp.rand(0.25, 0.5))
elif dsp.rand() > 0.8:
sd = fx.mdelay(s, [ dsp.rand(0, 8) for _ in range(dsp.randint(3, 10)) ], 0.7)
else:
sd = s.copy()
sd = sd.cut(0, 0.5).cloud(sd.dur,
grainlength=dsp.win(shapes.win('hann'), dsp.MS*40, dsp.MS*400),
grid=dsp.win(shapes.win('hann'), dsp.MS*40, dsp.MS*4000),
)
sd = fx.hpf(sd, dsp.win(shapes.win('hann'), freq, freq*4))
s.dub(sd)
out = r & s
for o in range(3):
amp = abs(1 - (o/3)) + 0.15
b = oscs.Osc('square', freq=freq * 2**o, quality=8, phase=dsp.rand()).play(out.dur).pan(dsp.rand()) * amp * 0.25
b = fx.lpf(b, freq * 2**o * 2).env('pluckout')
out.dub(b)
if dsp.rand() > 0.5:
out = fx.fold(out, amp=dsp.win(shapes.win('hann'), 2, 20))
out = out.env('pluckout')
if dsp.rand() > 0.8:
out = fx.hpf(out, dsp.win(shapes.win('hann'), freq, freq*4))
return out
def makerolls(pos, count):
return rolls.cloud(dsp.rand(2,rolls.dur),
grainlength=dsp.win(shapes.win('hann'), 1, rolls.dur/2),
speed=dsp.win(shapes.win('hann'), 0.5, 1.5),
spread=1
).env(dsp.win(shapes.win('hann'), 0, 0.3)) * 2
def makepour(pos, count):
return pour.cloud(dsp.rand(2,pour.dur),
grainlength=dsp.win(shapes.win('hann'), 1, rolls.dur/2),
speed=dsp.win(shapes.win('hann'), 0.25, 1.5),
spread=1
).env(dsp.win(shapes.win('hann'), 0, 0.75))
def makebeat():
hatpat = {'a': 'x..x..x..'}
ha2pat = {'a': 'x.x.'}
kikpat = {'a': 'x..x..'}
clapat = {'a': '.x..x'}
snarat = {'a': '...x..', 'b': '...xx.', 'c': '..x.'}
crdpat = {'a': 'x...x.', 'b': 'xx..xx', 'c': 'xx.xx.'}
baspat = {'a': 'x...' '....' '....' '..x.'}
swellpat = {'a': 'x.x.'}
bellpat = {'a': 'xx..xx', 'b': 'xxx', 'c': 'xx.'}
rollpat = {'a': 'x..'}
pourpat = {'a': 'x.'}
score = {
# sections
'a': {
'swell': 'aaaa' 'aaaa',
'hats': '----' 'aa--',
'hatsalt': 'aaaa' 'aaaa',
'kicks': '--aa' 'a-aa',
'claps': '----' '----',
'snr': '----' '----',
'crd': 'aaaa' 'aaaa',
'bass': 'aaaa' 'aaa-',
'pour': 'aaaa' 'aaaa',
},
'b': {
'swell': 'aaaa' 'aaaa',
'hats': 'aaaa' 'aaa-',
'hatsalt': 'aaaa' 'aaa-',
'kicks': 'aaaa' 'aaaa',
'claps': 'aaaa' 'aaaa',
'snr': 'aaab' 'aaab',
'crd': 'bbbb' 'cccc',
'bass': 'aaaa' 'a-a-',
'pour': 'aaaa' 'aaaa',
'roll': '----' '---aa',
},
'c': {
'swell': 'aaaa' 'aaaa',
'hats': 'aaaa' '----',
'hatsalt': 'aaaa' '----',
'kicks': '--aa' 'a-a-',
'claps': '----' '----',
'snr': 'cccc' '----',
'crd': 'aaaa' 'aaa-',
'bass': 'aaaa' 'aaaa',
'bell': 'cccc' 'aac-',
'roll': 'aaaa' '----',
},
'z': {
'swell': 'aaaa' 'aaaa',
'hats': 'aaaa' '----',
'kicks': '--aa' 'a-a-',
'bass': 'aaaa' 'aaaa',
'bell': 'cccc' 'bbaa',
'roll': 'a---' '----',
},
'seq': 'aabbccaabbccz', # section sequence
#'seq': 'abccz',
}
beat = dsp.win(shapes.win('hann'), 60 / 90., 60 / 130.)
#beat = 60 / 100.0
dm = rhythm.Seq(beat)
dm.add('swell', swellpat, makeswell, div=1)
dm.add('hats', hatpat, makehat, div=6)
dm.add('hatsalt', ha2pat, makehat, div=4)
dm.add('kicks', kikpat, makekick, div=2)
dm.add('claps', clapat, makeclap, div=2)
dm.add('snr', snarat, makesnare, div=4)
dm.add('crd', crdpat, makecrd, div=6)
dm.add('bass', baspat, makebas, div=4)
dm.add('bell', bellpat, makebells, div=1.5)
dm.add('roll', rollpat, makerolls, div=3)
dm.add('pour', pourpat, makepour, div=2)
return dm.score(score, barlength=4, stems=True, stemsdir='stems/', pool=True)
def main():
#g = dsp.read('soup.flac')
out = makebeat()
out = fx.compressor(out, 15, -15)
out = fx.norm(out, 1).trim()
out.write('renders/soup-breaks%03d.wav' % RN)
if __name__ == '__main__':
exit(main())
Dl codes for anyone who likes:
d9ez-7c8d
st7n-vhbh
jxeh-658v
7c6h-yu39
vsns-3qlz
9jde-c95g
zb4g-wtn3
zasn-cbq4
39ql-xc6a
wyrh-jw87
pkmh-ywbv
rngp-34d9
adkb-cqwt
6h35-3zac
ucx9-hzuw
xpcz-5gj4
49hu-739a
43cx-vx67
qdps-kp8v
b49c-gf39
5c2c-3mlz
8jlq-cz5g
tfs9-wgn3
ta4u-c3q4
x6pk-uwgd
hy72-v4rh
h25w-6pcv
4l6e-knd8
qcyf-gmx2
ghum-36ac
34w6-h6uw
wphk-5yj4
s642-ur9a
snsw-j467
pdqc-ka8v
7u8q-blw9
vwzf-wjdt
6ptv-cgwb