Vendor libs/hump, sfxrlua, json4lua, narrator as real files

These were committed as empty submodule gitlinks with no .gitmodules,
so the folders were never populated and the game could not load
(require of libs/hump/timer, libs/sfxrlua/sfxr, narrator.narrator).
Checked out each at its pinned commit and vendored the files, matching
the existing bundled-libs convention. Removed the junk libs/libs/ tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-08-11 11:37:09 -04:00
parent e73f63b5d4
commit 03532d29e4
219 changed files with 20254 additions and 252 deletions

@ -1 +0,0 @@
Subproject commit 949429d4618aee8b019899af101bd5f793d07a64

40
libs/sfxrlua/.gitignore vendored Normal file
View file

@ -0,0 +1,40 @@
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

3
libs/sfxrlua/.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "loveframes"]
path = demo/loveframes
url = https://github.com/NikolaiResokav/LoveFrames

21
libs/sfxrlua/LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 nucular
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

61
libs/sfxrlua/README.md Normal file
View file

@ -0,0 +1,61 @@
sfxr.lua
========
```
luarocks install sfxr
```
A port of the sfxr sound effect synthesizer to pure Lua, designed to be used
together with the *awesome* [LÖVE](https://love2d.org) game framework.
Demo
----
To run the demo application you first need to download
[LoveFrames](https://github.com/NikolaiResokav/LoveFrames) as a submodule:
```
git submodule update --init
love demo
```
Note: Due to LoveFrames only supporting LÖVE 0.9.x, this dependency is inherited
by the demo. A move to a new GUI framework is pending.
Example usage
-------------
The following code examples demonstrate how to play a randomly generated sound:
With [LÖVE](http://love2d.org):
```lua
local sfxr = require("sfxr")
function love.load()
local sound = sfxr.newSound()
sound:randomize()
local sounddata = sound:generateSoundData()
local source = love.audio.newSource(sounddata)
source:play()
end
```
With [lao](https://github.com/TheLinx/lao):
```lua
require("ao")
local sfxr = require("sfxr")
local driverId = ao.defaultDriverId()
local device = ao.openLive(driverId, {bits = 16, rate = 44100, channels = 1})
local sound = sfxr.newSound()
sound:randomize()
device:play(sound:generateString())
```
Documentation
-------------
[**The latest documentation build is available here**](http://nucular.github.io/sfxrlua/)
This project uses [LDoc](http://stevedonovan.github.io/ldoc/) for autogenerated
API documentation.

12
libs/sfxrlua/config.ld Normal file
View file

@ -0,0 +1,12 @@
project = "sfxr.lua"
description = "A port of the sfxr sound effect synthesizer to Lua"
title = "sfxr.lua Documentation"
format = "markdown"
not_luadoc = true
style = "!pale"
kind_names = {topic = "Topics", module = "API"}
dir = "./docs"
file = "sfxr.lua"
topics = {
}

View file

@ -0,0 +1,6 @@
function love.conf(t)
t.version = love._version:match("0%.9%.%d+") or "0.9.x"
t.window.width = 640
t.window.height = 600
t.window.title = "sfxr.lua Demo"
end

695
libs/sfxrlua/demo/main.lua Normal file
View file

@ -0,0 +1,695 @@
#/usr/bin/env love
-- love .
local sfxr = require("sfxr")
-- Global stuff
local source
local sound
local sounddata
local seed
local playbutton
local playing = false
local wavecanvas
local statistics = {
generation = 0,
transfer = 0,
waveview = 0,
duration = 0
}
-- This will hold all sliders and the wave form box
local guiparams = {}
-- The parameter list is built from this
-- {{"Text", "table name", {{"Text", "table paramter", min, max}, ...}}, ...}
local guicategories = {
{
"Envelope",
"envelope",
{
{"Attack Time", "attack", 0, 1},
{"Sustain Time", "sustain", 0, 1},
{"Sustain Punch", "punch", 0, 1},
{"Decay Time", "decay", 0, 1}
}
},
{
"Frequency",
"frequency",
{
{"Start", "start", 0, 1},
{"Minimum", "min", 0, 1},
{"Slide", "slide", -1, 1},
{"Delta Slide", "dslide", -1, 1}
}
},
{
"Vibrato",
"vibrato",
{
{"Depth", "depth", 0, 1},
{"Speed", "speed", 0, 1}
}
},
{
"Change",
"change",
{
{"Amount", "amount", -1, 1},
{"Speed", "speed", 0, 1}
}
},
{
"Square Duty",
"duty",
{
{"Ratio", "ratio", 0, 1},
{"Sweep", "sweep", -1, 1}
}
},
{
"Phaser",
"phaser",
{
{"Offset", "offset", -1, 1},
{"Sweep", "sweep", -1, 1}
}
},
{
"Low Pass",
"lowpass",
{
{"Cutoff", "cutoff", 0, 1},
{"Sweep", "sweep", -1, 1},
{"Resonance", "resonance", 0, 1}
}
},
{
"High Pass",
"highpass",
{
{"Cutoff", "cutoff", 0, 1},
{"Sweep", "sweep", -1, 1}
}
}
}
-- Easy lookup of wave forms
local waveFormList = {
["Square"] = 0,
["Sawtooth"] = 1,
["Sine"] = 2,
["Noise"] = 3,
[0] = "Square",
[1] = "Sawtooth",
[2] = "Sine",
[3] = "Noise"
}
function stopSound()
playbutton:SetText("Play")
if source then
source:stop()
end
end
function playSound()
-- Stop the currently playing source
if source then
source:stop()
end
local t = love.timer.getTime()
local tab = sound:generateTable(sfxr.FREQ_44100, sfxr.BITS_FLOAT)
t = love.timer.getTime() - t
statistics.generation = math.floor(t * 10000) / 10
if #tab == 0 then
return nil
end
sounddata = love.sound.newSoundData(#tab, 44100, 16, 1)
statistics.duration = math.floor(sounddata:getDuration() * 10000) / 10
-- Stuff for the wave view
local waveview = {}
local j = 0
local max = -1
local min = 1
local avg = 0.5
local t = love.timer.getTime()
for i = 0, #tab - 1 do
local v = tab[i + 1]
-- Copy the sample over to the SoundData
sounddata:setSample(i, v)
-- Add the minimal and maximal sample to the wave view
-- every 256 samples. This is how Audacity does it, actually.
j = j + 1
min = math.min(v, min)
max = math.max(v, max)
if j >= 256 then
waveview[#waveview + 1] = min
waveview[#waveview + 1] = max
j = 0
min, max = 1, -1
end
end
t = love.timer.getTime() - t
statistics.transfer = math.floor(t * 10000) / 10
updateWaveCanvas(waveview)
updateStatistics()
if sounddata then
source = love.audio.newSource(sounddata)
source:play()
playbutton:SetText("Stop Playing")
playing = true
end
end
function createSeedBox()
local f = lf.Create("form"):SetName("Random Seed")
seed = lf.Create("numberbox")
:SetValue(math.floor(love.timer.getTime()))
:SetMax(math.huge)
:SetMin(-math.huge)
:SetWidth(100)
f:AddItem(seed):SetPos(5, 240)
end
function createPresetGenerators()
local f = lf.Create("form")
:SetName("Preset Generators")
local generators = {
{"Pickup/Coin", sound.randomPickup},
{"Laser/Shoot", sound.randomLaser},
{"Explosion", sound.randomExplosion},
{"Powerup", sound.randomPowerup},
{"Hit/Hurt", sound.randomHit},
{"Jump", sound.randomJump},
{"Blip/Select", sound.randomBlip}
}
for i, v in ipairs(generators) do
local b = lf.Create("button")
:SetText(v[1])
:SetWidth(100)
f:AddItem(b)
b.OnClick = function(self)
v[2](sound, seed:GetValue())
seed:SetValue(seed:GetValue() + 1)
updateParameters()
playSound()
end
end
f:SetPos(5, 5):SetWidth(110)
end
function createRandomizers()
local f = lf.Create("form"):SetName("Randomizers")
local b = lf.Create("button")
:SetText("Mutate")
:SetWidth(100)
f:AddItem(b)
b.OnClick = function(self)
sound:mutate()
updateParameters()
playSound()
end
local b = lf.Create("button")
:SetText("Randomize")
:SetWidth(100)
f:AddItem(b)
b.OnClick = function(self)
sound:randomize(seed:GetValue())
updateParameters()
seed:SetValue(seed:GetValue() + 1)
playSound()
end
f:SetPos(5, 515):SetSize(110, 80)
end
function createParameters()
local f = lf.Create("form"):SetName("Parameters")
local l = lf.Create("list")
:SetSpacing(5)
:SetPadding(5)
:SetSize(340, 565)
f:AddItem(l)
-- Waveforms
l:AddItem(lf.Create("text"):SetPos(0, pheight):SetText("Wave Form"))
local m = lf.Create("multichoice")
for i = 0, #waveFormList do
m:AddChoice(waveFormList[i])
end
m:SetChoice("Square")
m.OnChoiceSelected = function(o, c)
sound.wavetype = waveFormList[c]
end
l:AddItem(m)
guiparams.waveform = m
-- Repeat speed
local t = lf.Create("text")
:SetText("Repeat Speed 0")
:SetPos(0, pheight)
local s = lf.Create("slider")
:SetWidth(120)
:SetMinMax(0, 1)
:SetValue(sound.repeatspeed)
s.OnValueChanged = function(o)
local v = o:GetValue()
if v <= 0.02 and v >= -0.02 and v ~= 0 then
o:SetValue(0)
sound.repeatspeed = 0
t:SetText("Repeat Speed 0")
else
sound.repeatspeed = v
t:SetText("Repeat Speed " .. tostring(math.floor(v * 100) / 100))
end
end
l:AddItem(t):AddItem(s)
guiparams.repeatspeed = {s, t}
for i1, v1 in ipairs(guicategories) do
local c = lf.Create("collapsiblecategory"):SetText(v1[1])
l:AddItem(c)
local p = lf.Create("panel")
local pheight = 0
p.Draw = function() end
c:SetObject(p)
guiparams[v1[2]] = {}
for i2, v2 in ipairs(v1[3]) do
lf.Create("text", p)
:SetText(v2[1])
:SetPos(0, pheight)
local t = lf.Create("text", p)
:SetText("0")
:SetPos(95, pheight)
local s = lf.Create("slider", p)
:SetPos(130, pheight - 3)
:SetWidth(170)
:SetMinMax(v2[3], v2[4])
:SetValue(sound[v1[2]][v2[2]])
s.OnValueChanged = function(o)
local v = o:GetValue()
if v <= 0.02 and v >= -0.02 and v ~= 0 then
o:SetValue(0)
sound[v1[2]][v2[2]] = 0
t:SetText("0")
else
sound[v1[2]][v2[2]] = v
t:SetText(math.floor(v * 100) / 100)
end
end
guiparams[v1[2]][v2[2]] = {s, t}
pheight = pheight + 30
end
p:SetHeight(pheight - 10)
end
f:SetPos(125, 5):SetSize(350, 590)
end
function createActionButtons()
local f = lf.Create("form"):SetName("Actions")
local b = lf.Create("button")
:SetText("Generate and Play")
:SetWidth(140)
b.OnClick = function(o)
if not playing then
playSound()
else
stopSound()
end
end
playbutton = b
f:AddItem(b)
local fr = lf.Create("frame")
:SetName("File Picker")
:SetSize(400, 300)
:Center()
:SetVisible(false)
:SetModal(false)
local frl = lf.Create("columnlist", fr)
:SetPos(5, 30)
:SetSize(390, 235)
:AddColumn("Name")
local frt = lf.Create("textinput", fr)
:SetPos(5, 270)
:SetWidth(300)
local frb = lf.Create("button", fr)
:SetPos(315, 270)
frl.OnRowSelected = function(p, row, data)
frt:SetText(data[1])
end
fr.OnClose = function(o)
frl:Clear()
fr:SetVisible(false):SetModal(false)
return false
end
local function saveHandler(type, cb)
return function()
fr:SetName("Save to ." .. type)
frt:SetText("sound." .. type)
frb:SetText("Save")
love.filesystem.getDirectoryItems("sounds", function(name)
if name:find(type, #type-#name+1, true) then
frl:AddRow(name)
end
end)
frb.OnClick = function(o)
local name = frt:GetText()
if (#name > 0) then
local f = love.filesystem.newFile("sounds/" .. name, "w")
if f then
cb(f)
frl:Clear()
fr:SetVisible(false):SetModal(false)
end
end
end
frt.OnEnter = frb.OnClick
fr:SetVisible(true)
:SetModal(true)
:Center()
end
end
local function loadHandler(type, cb)
return function()
fr:SetName("Load from ." .. type)
frt:SetText("sound." .. type)
frb:SetText("Load")
love.filesystem.getDirectoryItems("sounds", function(name)
if name:find(type, #type-#name+1, true) then
frl:AddRow(name)
end
end)
frb.OnClick = function(o)
local name = frt:GetText()
if (#name > 0) then
local f = love.filesystem.newFile("sounds/" .. name, "r")
if f then
cb(f)
frl:Clear()
fr:SetVisible(false):SetModal(false)
end
end
end
frt.OnEnter = frb.OnClick
fr:SetVisible(true)
:SetModal(true)
:Center()
end
end
local sb = lf.Create("button")
:SetText("Save Lua")
:SetWidth(67)
sb.OnClick = saveHandler("lua", function(f) sound:save(f, true) end)
f:AddItem(sb)
local lb = lf.Create("button")
:SetText("Load Lua")
:SetWidth(67)
lb.OnClick = loadHandler("lua", function(f) sound:load(f) end)
f:AddItem(lb)
local bsb = lf.Create("button")
:SetText("Save binary")
:SetWidth(67)
bsb.OnClick = saveHandler("sfs", function(f) sound:saveBinary(f) end)
f:AddItem(bsb)
local blb = lf.Create("button")
:SetText("Load binary")
:SetWidth(67)
blb.OnClick = loadHandler("sfs", function(f) sound:loadBinary(f) end)
f:AddItem(blb)
local eb = lf.Create("button")
:SetText("Export WAV")
:SetWidth(140)
eb.OnClick = saveHandler("wav", function(f) sound:exportWAV(f) end)
f:AddItem(eb)
f:SetPos(485, 455):SetSize(150, 140)
lb:SetPos(78, 47)
bsb:SetY(77)
blb:SetPos(78, 77)
eb:SetY(107)
end
function createOther()
local f = lf.Create("form")
:SetName("Wave View")
:SetPos(485, 5)
:SetSize(150, 170)
local draw = function(o)
if source then
love.graphics.setColor(255, 255, 255)
love.graphics.draw(wavecanvas, 495, 25)
-- Draw a fancy position cursor
local pos = source:tell("samples")
local max = sounddata:getSampleCount()
local x = 495 + (pos / max) * 125
love.graphics.setColor(255, 153, 0)
love.graphics.line(x, 25, x, 165)
end
lf.skins.available["Orange"].DrawForm(o)
end
f.Draw = draw
local f = lf.Create("form"):SetName("Volume")
local t = lf.Create("text"):SetText("Master 0.5")
f:AddItem(t)
local s = lf.Create("slider")
:SetMinMax(0, 1)
:SetSize(135, 20)
s.OnValueChanged = function(o)
local v = o:GetValue()
if v <= 0.52 and v >= 0.48 and v ~= 0.5 then
o:SetValue(0.5)
v = 0.5
end
sound.volume.master = v
t:SetText("Master " .. tostring(math.floor(v * 100) / 100))
end
s:SetValue(sound.volume.master)
f:AddItem(s)
local t = lf.Create("text"):SetText("Sound 0.5")
f:AddItem(t)
local s = lf.Create("slider")
:SetMinMax(0, 1)
:SetSize(135, 20)
s.OnValueChanged = function(o)
local v = o:GetValue()
if v <= 0.52 and v >= 0.48 and v ~= 0.5 then
o:SetValue(0.5)
v = 0.5
end
sound.volume.sound = v
t:SetText("Sound " .. tostring(math.floor(v * 100) / 100))
end
s:SetValue(sound.volume.sound)
f:AddItem(s)
f:SetPos(485, 340):SetWidth(150)
local f = lf.Create("form"):SetName("Times / Duration")
local t = lf.Create("text"):SetText("Generation: 0ms")
f:AddItem(t)
statistics.generationtext = t
local t = lf.Create("text"):SetText("Transfer: 0ms")
f:AddItem(t)
statistics.transfertext = t
local t = lf.Create("text"):SetText("Wave View: 0ms")
f:AddItem(t)
statistics.waveviewtext = t
local t = lf.Create("text"):SetText("Duration: 0ms")
f:AddItem(t)
statistics.durationtext = t
f:SetPos(485, 185):SetWidth(150)
end
function updateParameters()
-- Iterate through the list of parameters and update all of them
for i1, v1 in ipairs(guicategories) do
for i2, v2 in ipairs(v1[3]) do
local v = sound[v1[2]][v2[2]]
local s, t = unpack(guiparams[v1[2]][v2[2]])
s:SetValue(v)
t:SetText(math.floor(v * 100) / 100)
end
end
local s, t = unpack(guiparams.repeatspeed)
local v = sound.repeatspeed
s:SetValue(v)
t:SetText("Repeat Speed " .. tostring(math.floor(v * 100) / 100))
guiparams.waveform:SetChoice(waveFormList[sound.wavetype])
end
function updateWaveCanvas(waveview)
local t = love.timer.getTime()
wavecanvas:clear()
love.graphics.setCanvas(wavecanvas)
love.graphics.setColor(255, 255, 255)
love.graphics.setLineStyle("rough")
-- Iterate through the passed table and draw all lines to the canvas
local step = 125 / #waveview
local last = 70
for i, v in ipairs(waveview) do
local x = (i * step)
local y = (-v + 1) * 70
love.graphics.line(x - step, last, x, y)
last = y
end
-- Draw the zero line
love.graphics.setColor(255, 80, 51, 200)
love.graphics.line(0, 70, 125, 70)
love.graphics.setCanvas()
t = love.timer.getTime() - t
statistics.waveview = math.floor(t * 10000) / 10
end
function updateStatistics()
statistics.durationtext:SetText("Duration: " .. statistics.duration .. " ms")
statistics.transfertext:SetText("Transfer: " .. statistics.transfer .. " ms")
statistics.waveviewtext:SetText("Wave View: " .. statistics.waveview .. " ms")
statistics.generationtext:SetText("Generation: " .. statistics.generation .. " ms")
end
function love.load()
require("loveframes")
lf = loveframes
lf.util.SetActiveSkin("Orange")
love.graphics.setBackgroundColor(200, 200, 200)
if not love.filesystem.isDirectory("sounds") then
love.filesystem.createDirectory("sounds")
end
sound = sfxr.newSound()
createSeedBox()
createPresetGenerators()
createRandomizers()
createParameters()
createActionButtons()
createOther()
wavecanvas = love.graphics.newCanvas(125, 140)
love.mousepressed = lf.mousepressed
love.mousereleased = lf.mousereleased
love.keyreleased = lf.keyreleased
love.textinput = lf.textinput
end
function love.update(dt)
lf.update(dt)
if source then
if playing and not source:isPlaying() then
playing = false
playbutton:SetText("Generate and Play")
end
end
end
function love.draw()
lf.draw()
end
function love.keypressed(key)
if key == " " then
playSound()
elseif key == "escape" then
love.event.push("quit")
end
lf.keypressed(key)
end

File diff suppressed because it is too large Load diff

1799
libs/sfxrlua/docs/index.html Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,304 @@
/* BEGIN RESET
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.8.2r1
*/
html {
color: #000;
background: #FFF;
}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
font-style: inherit;
font-weight: inherit;
}
del,ins {
text-decoration: none;
}
li {
list-style: disc;
margin-left: 20px;
}
caption,th {
text-align: left;
}
h1,h2,h3,h4,h5,h6 {
font-size: 100%;
font-weight: bold;
}
q:before,q:after {
content: '';
}
abbr,acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: baseline;
}
sub {
vertical-align: baseline;
}
legend {
color: #000;
}
input,button,textarea,select,optgroup,option {
font-family: inherit;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
}
input,button,textarea,select {*font-size:100%;
}
/* END RESET */
body {
margin-left: 1em;
margin-right: 1em;
font-family: arial, helvetica, geneva, sans-serif;
background-color: #ffffff; margin: 0px;
}
code, tt { font-family: monospace; font-size: 1.1em; }
span.parameter { font-family:monospace; }
span.parameter:after { content:":"; }
span.types:before { content:"("; }
span.types:after { content:")"; }
.type { font-weight: bold; font-style:italic }
body, p, td, th { font-size: .95em; line-height: 1.2em;}
p, ul { margin: 10px 0 0 0px;}
strong { font-weight: bold;}
em { font-style: italic;}
h1 {
font-size: 1.5em;
margin: 0 0 20px 0;
}
h2, h3, h4 { margin: 15px 0 10px 0; }
h2 { font-size: 1.25em; }
h3 { font-size: 1.15em; }
h4 { font-size: 1.06em; }
a:link { font-weight: bold; color: #004080; text-decoration: none; }
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
a:link:hover { text-decoration: underline; }
hr {
color:#cccccc;
background: #00007f;
height: 1px;
}
blockquote { margin-left: 3em; }
ul { list-style-type: disc; }
p.name {
font-family: "Andale Mono", monospace;
padding-top: 1em;
}
pre {
background-color: rgb(245, 245, 245);
border: 1px solid #C0C0C0; /* silver */
padding: 10px;
margin: 10px 0 10px 0;
overflow: auto;
font-family: "Andale Mono", monospace;
}
pre.example {
font-size: .85em;
}
table.index { border: 1px #00007f; }
table.index td { text-align: left; vertical-align: top; }
#container {
margin-left: 1em;
margin-right: 1em;
background-color: #ffffff;
}
#product {
text-align: center;
border-bottom: 1px solid #cccccc;
background-color: #ffffff;
}
#product big {
font-size: 2em;
}
#main {
background-color:#FFFFFF; // #f0f0f0;
//border-left: 2px solid #cccccc;
}
#navigation {
float: left;
width: 14em;
vertical-align: top;
background-color:#FFFFFF; // #f0f0f0;
border-right: 2px solid #cccccc;
overflow: visible;
}
#navigation h2 {
background-color:#FFFFFF;//:#e7e7e7;
font-size:1.1em;
color:#000000;
text-align: left;
padding:0.2em;
//border-top:1px solid #dddddd;
border-bottom:1px solid #dddddd;
}
#navigation ul
{
font-size:1em;
list-style-type: none;
margin: 1px 1px 10px 1px;
}
#navigation li {
text-indent: -1em;
display: block;
margin: 3px 0px 0px 22px;
}
#navigation li li a {
margin: 0px 3px 0px -1em;
}
#content {
margin-left: 14em;
padding: 1em;
width: 700px;
border-left: 2px solid #cccccc;
// border-right: 2px solid #cccccc;
background-color: #ffffff;
}
#about {
clear: both;
padding: 5px;
border-top: 2px solid #cccccc;
background-color: #ffffff;
}
@media print {
body {
font: 12pt "Times New Roman", "TimeNR", Times, serif;
}
a { font-weight: bold; color: #004080; text-decoration: underline; }
#main {
background-color: #ffffff;
border-left: 0px;
}
#container {
margin-left: 2%;
margin-right: 2%;
background-color: #ffffff;
}
#content {
padding: 1em;
background-color: #ffffff;
}
#navigation {
display: none;
}
pre.example {
font-family: "Andale Mono", monospace;
font-size: 10pt;
page-break-inside: avoid;
}
}
table.module_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.module_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; }
table.module_list td.summary { width: 100%; }
table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.function_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; }
table.function_list td.summary { width: 100%; }
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
dl.table h3, dl.function h3 {font-size: .95em;}
ul.nowrap {
overflow:auto;
whitespace:nowrap;
}
/* stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* make the target distinct; helps when we're navigating to a function */
a:target + * {
background-color: #FF9;
}
/* styles for prettification of source */
pre .comment { color: #558817; }
pre .constant { color: #a8660d; }
pre .escape { color: #844631; }
pre .keyword { color: #aa5050; font-weight: bold; }
pre .library { color: #0e7c6b; }
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
pre .string { color: #8080ff; }
pre .number { color: #f8660d; }
pre .operator { color: #2239a8; font-weight: bold; }
pre .preprocessor, pre .prepro { color: #a33243; }
pre .global { color: #800080; }
pre .user-keyword { color: #800080; }
pre .prompt { color: #558817; }
pre .url { color: #272fc2; text-decoration: underline; }

View file

@ -0,0 +1,28 @@
package = "sfxr"
version = "0.0.2-1"
source = {
url = "git://github.com/nucular/sfxrlua",
tag = "v0.0.2"
}
description = {
summary = "A port of the sfxr sound effect synthesizer to Lua",
detailed = [[
A port of the sfxr sound effect synthesizer to pure Lua, designed to be used
together with the awesome LÖVE game framework.
]],
homepage = "https://github.com/nucular/sfxrlua",
license = "MIT/X11"
}
dependencies = {
"lua ~> 5.1"
-- bitop?
}
build = {
type = "builtin",
modules = {
sfxr = "sfxr.lua"
},
copy_directories = {
"docs"
}
}

View file

@ -0,0 +1,28 @@
package = "sfxr"
version = "scm-1"
source = {
url = "git://github.com/nucular/sfxrlua",
branch = "master"
}
description = {
summary = "A port of the sfxr sound effect synthesizer to Lua",
detailed = [[
A port of the sfxr sound effect synthesizer to pure Lua, designed to be used
together with the awesome LÖVE game framework.
]],
homepage = "https://github.com/nucular/sfxrlua",
license = "MIT/X11"
}
dependencies = {
"lua ~> 5.1"
-- bitop?
}
build = {
type = "builtin",
modules = {
sfxr = "sfxr.lua"
},
copy_directories = {
"docs"
}
}

1536
libs/sfxrlua/sfxr.lua Normal file

File diff suppressed because it is too large Load diff