Skip to content

Instantly share code, notes, and snippets.

@LPGhatguy

LPGhatguy/synth.lua

Last active Aug 29, 2015
Embed
What would you like to do?
Synthesizer Prototype 2 - A synthesizer for an organ without need for any assets. Use the keys 1Q2W3ER5T6YU8I9O0P[=], backspace, \ZSXDCVGBHNM,L.;/, and right shift to play it.
--[[
PUBLIC DOMAIN
Where this designation is not recognized, you are
permitted to copy, modify, and distribute this code
without restriction.
Lucien Greathouse
(LPGhatguy)
]]
local default_samples = 48000 --Sample rate in hertz
local pitch_rate = 2^(1 / 12) --The base to use for producing tones
local pitch_offset = -12 --Tone offset in semitones (12 is one octave)
local function round(n)
return math.floor(n + 0.5)
end
local function hertz(semitones, base)
base = base or 220
return base * pitch_rate ^ (semitones + pitch_offset)
end
local function build_tone(frequencies, samples)
samples = samples or default_samples
local data = love.sound.newSoundData(samples, samples, 16, 1)
local scalars = {}
for index = 1, #frequencies do
local frequency, amplitude
if (type(frequencies[index]) == "table") then
frequency = frequencies[index][1]
amplitude = frequencies[index][2] or 1
else
frequency = frequencies[index]
amplitude = 1
end
scalars[index] = {math.floor(frequency + 0.5) * math.pi * 2 / samples, amplitude}
end
for pos = 0, samples - 1 do
local sum = 0
for index = 1, #scalars do
sum = sum + (scalars[index][2] * math.sin(pos * scalars[index][1]))
end
data:setSample(pos, math.min(1, math.max(-1, sum / #frequencies)))
end
local wrapper = love.audio.newSource(data)
wrapper:setLooping(true)
return wrapper
end
local tones = {}
local fading = {}
local keys = {
["1"] = -13,
q = -12,
["2"] = -11,
w = -10,
["3"] = -9,
e = -8,
r = -7,
["5"] = -6,
t = -5,
["6"] = -4,
y = -3,
u = -2,
["8"] = -1,
i = 0,
["9"] = 1,
o = 2,
["0"] = 3,
p = 4,
["["] = 5,
["="] = 6,
["]"] = 7,
["backspace"] = 8,
["\\"] = 9,
z = 5,
s = 6,
x = 7,
d = 8,
c = 9,
v = 10,
g = 11,
b = 12,
h = 13,
n = 14,
j = 15,
m = 16,
[","] = 17,
l = 18,
["."] = 19,
[";"] = 20,
["/"] = 21,
["rshift"] = 22
}
function love.update(delta)
for key, value in pairs(fading) do
value:setVolume(math.max(0, value:getVolume() - delta * 1.3))
if (value:getVolume() <= 0) then
value:stop()
end
end
end
function love.keypressed(key)
if (keys[key]) then
local semitones = keys[key]
if (not tones[semitones]) then
tones[semitones] = build_tone({
{hertz(semitones), 1},
{hertz(semitones + 12), 0.937},
{hertz(semitones + 19), 0.960},
{hertz(semitones + 24), 0.863},
{hertz(semitones + 28), 0.889},
{hertz(semitones + 31), 0.789}
}, 48000)
end
if (fading[semitones]) then
fading[semitones] = nil
end
--tones[semitones]:stop()
tones[semitones]:setVolume(0.5)
tones[semitones]:play()
end
end
function love.keyreleased(key)
if (keys[key]) then
local semitones = keys[key]
if (tones[semitones]) then
fading[semitones] = tones[semitones]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment