Created
December 13, 2012 11:35
-
-
Save vrld/4275871 to your computer and use it in GitHub Desktop.
Grain synthesis with LHC.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local lhc = require 'lhc' | |
local SAMPLERATE = 44100 | |
local generator = { | |
sine = function(x) return math.sin(x * 2 * math.pi) end, | |
tri = function(x) x = (x-.5)%1 return math.min(2*x-1, 1-2*x) end, | |
saw = function(x) return (2*x-1)%2 - 1 end, | |
rect = function(x) return 2 * math.floor((2*x)%2) -1 end, | |
wn = function(x) return math.random() end, | |
} | |
local function randu(a,b) | |
if not a then return math.random() end | |
if not b then return math.random() * a end | |
if a > b then a, b = b,a end | |
return a + (b-a) * math.random() | |
end | |
local function grain(freq, width, amp, gen, e) | |
freq = freq or 440 | |
width = width or 0.1 | |
gen = gen or generator.sin | |
e = e or lhc.env.perc(.3*width, .7*width, amp or 0.2, -2, SAMPLERATE) | |
return lhc.buffer(width * SAMPLERATE, function(i) | |
local t = freq * i / SAMPLERATE | |
return gen(t) * e(t) | |
end) | |
end | |
local sequence = {} | |
function sequence.play(s, channels, rate) | |
table.sort(s, function(a,b) return a[1] < b[1] end) | |
rate = rate or SAMPLERATE | |
channels = channels or 1 | |
local t = 0 | |
for i = 1,#s do | |
local item = s[i] | |
lhc.sleep(item[1] - t) | |
lhc.play(item[2], rate, channels) -- TODO: should keep player instance! | |
t = item[1] | |
end | |
end | |
function sequence.render(s, channels, rate) | |
table.sort(s, function(a,b) return a[1] < b[1] end) | |
rate = rate or SAMPLERATE | |
channels = channels or 1 | |
local len = 0 | |
for i = 1,#s do | |
len = math.max(len, math.floor(s[i][1] * rate) + #s[i][2]) | |
end | |
local out = lhc.buffer(len, 0) | |
for i = 1,#s do | |
local offset = math.floor(s[i][1] * rate) | |
local len = #s[i][2] | |
out:map(offset, offset+len-1, function(k,v) | |
return s[i][2][k-offset+1] + v | |
end) | |
end | |
return out | |
end | |
-- make a cloud | |
local cloud = {} | |
local delay = 0 | |
local K = 1000 | |
for i = 1,K do | |
local freq = (300 + i / K * 2700) * randu(.8,1.2) | |
local dur = 20 / freq * randu(2/3,3/2) | |
local sustain = dur * randu(1,1.3) | |
cloud[i] = {delay, grain(freq, sustain, .2)} | |
delay = delay + dur | |
end | |
print(delay) | |
sequence.play(cloud) | |
--local b = sequence.render(cloud) | |
--lhc.play(b) | |
print('done') | |
io.read() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment