local Sounds = {} local sources = {} local SAMPLE_RATE = 44100 local function makeSoundData(duration, generator) local samples = math.floor(SAMPLE_RATE * duration) local sd = love.sound.newSoundData(samples, SAMPLE_RATE, 16, 1) for i = 0, samples - 1 do local t = i / SAMPLE_RATE local p = i / samples sd:setSample(i, math.max(-1, math.min(1, generator(t, p)))) end return sd end local function makeSource(sd) return love.audio.newSource(sd, "static") end local function genThrust(t, p) local noise = (math.random() * 2 - 1) * 0.25 local low = math.sin(2 * math.pi * 45 * t) * 0.2 local rumble = math.sin(2 * math.pi * 25 * t) * 0.15 return (noise + low + rumble) * 0.4 end local function genLandGood(t, p) local freq if p < 0.33 then freq = 500 elseif p < 0.66 then freq = 700 else freq = 900 end local env = 0.7 if p > 0.9 then env = (1-p)/0.1 * 0.7 end return math.sin(2 * math.pi * freq * t) * env * 0.35 end local function genLandHard(t, p) local env = (1 - p) ^ 2 return math.sin(2 * math.pi * 250 * t) * env * 0.3 end local function genCrash(t, p) local env = (1 - p) ^ 1.2 local sine = math.sin(2 * math.pi * (60 + 30*(1-p)) * t) * 0.5 local noise = (math.random() * 2 - 1) * 0.5 return (sine + noise) * env * 0.5 end local function genFuelWarn(t, p) local freq = 800 local env = 0.6 if p > 0.5 then env = 0 end return math.sin(2 * math.pi * freq * t) * env * 0.3 end local function genAbort(t, p) local freq = 600 - p * 300 local env = (1 - p) ^ 1.5 local noise = (math.random() * 2 - 1) * 0.3 return (math.sin(2 * math.pi * freq * t) * 0.4 + noise) * env * 0.4 end function Sounds.init() sources = {} local defs = { thrust = {0.25, genThrust}, land_good = {0.4, genLandGood}, land_hard = {0.3, genLandHard}, crash = {0.6, genCrash}, fuel_warn = {0.15, genFuelWarn}, abort = {0.3, genAbort}, } for name, def in pairs(defs) do sources[name] = makeSource(makeSoundData(def[1], def[2])) end end function Sounds.play(name) local src = sources[name] if not src then return end src:clone():play() end return Sounds