Skip to content

Instantly share code, notes, and snippets.

@vrld
Created December 13, 2012 11:35
Show Gist options
  • Save vrld/4275871 to your computer and use it in GitHub Desktop.
Save vrld/4275871 to your computer and use it in GitHub Desktop.
Grain synthesis with LHC.
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