BEEPs are now played limitness, without killing AL

Former-commit-id: 627561820d469f0b563832f01ee37a8b04bd6935
Former-commit-id: 16f01413bc1c6809f3402d87ebffac8731338562
This commit is contained in:
Song Minjae
2016-09-30 01:06:03 +09:00
parent 1b4aca320f
commit 20d5636b4b
2 changed files with 588 additions and 578 deletions

View File

@@ -47,7 +47,7 @@ _G.bell = function(patn) term.bell(patn or ".") end
_G.beep = _G.bell _G.beep = _G.bell
if totalMemory() == 0 then if totalMemory() == 0 then
bell "=" bell "==="
print("no RAM installed") print("no RAM installed")
__haltsystemexplicit__() __haltsystemexplicit__()
return return
@@ -457,9 +457,9 @@ do
::brk:: ::brk::
end end
return s return s
end end
local function push_onecapture(ms, i, s, e) local function push_onecapture(ms, i, s, e)
if i >= ms.level then if i >= ms.level then
if i == 0 then -- ms->level == 0, too if i == 0 then -- ms->level == 0, too
return s:head(e - s) -- add whole match return s:head(e - s) -- add whole match
@@ -475,19 +475,19 @@ local function push_onecapture(ms, i, s, e)
return ms.capture[i].init:head(l) return ms.capture[i].init:head(l)
end end
end end
end end
local function push_captures(ms, s, e) local function push_captures(ms, s, e)
local nlevels = (ms.level == 0 and s) and 1 or ms.level local nlevels = (ms.level == 0 and s) and 1 or ms.level
local captures = {} local captures = {}
for i = 0, nlevels - 1 do for i = 0, nlevels - 1 do
table.insert(captures, push_onecapture(ms, i, s, e)) table.insert(captures, push_onecapture(ms, i, s, e))
end end
return table.unpack(captures) return table.unpack(captures)
end end
-- check whether pattern has no special characters -- check whether pattern has no special characters
local function nospecials(p) local function nospecials(p)
for i = 1, #p do for i = 1, #p do
for j = 1, #SPECIALS do for j = 1, #SPECIALS do
if p:sub(i, i) == SPECIALS:sub(j, j) then if p:sub(i, i) == SPECIALS:sub(j, j) then
@@ -496,9 +496,9 @@ local function nospecials(p)
end end
end end
return true return true
end end
local function str_find_aux(str, pattern, init, plain, find) local function str_find_aux(str, pattern, init, plain, find)
checkArg(1, str, "string") checkArg(1, str, "string")
checkArg(2, pattern, "string") checkArg(2, pattern, "string")
checkArg(3, init, "number", "nil") checkArg(3, init, "number", "nil")
@@ -544,17 +544,17 @@ local function str_find_aux(str, pattern, init, plain, find)
until s1:step() > ms.src_end or anchor until s1:step() > ms.src_end or anchor
end end
return nil -- not found return nil -- not found
end end
local function str_find(s, pattern, init, plain) local function str_find(s, pattern, init, plain)
return str_find_aux(s, pattern, init, plain, true) return str_find_aux(s, pattern, init, plain, true)
end end
local function str_match(s, pattern, init) local function str_match(s, pattern, init)
return str_find_aux(s, pattern, init, false, false) return str_find_aux(s, pattern, init, false, false)
end end
local function str_gmatch(s, pattern) local function str_gmatch(s, pattern)
checkArg(1, s, "string") checkArg(1, s, "string")
checkArg(2, pattern, "string") checkArg(2, pattern, "string")
@@ -585,9 +585,9 @@ local function str_gmatch(s, pattern)
end end
return nil -- not found return nil -- not found
end end
end end
local function add_s(ms, b, s, e, r) local function add_s(ms, b, s, e, r)
local news = tostring(r) local news = tostring(r)
local i = 1 local i = 1
while i <= #news do while i <= #news do
@@ -606,9 +606,9 @@ local function add_s(ms, b, s, e, r)
i = i + 1 i = i + 1
end end
return b return b
end end
local function add_value(ms, b, s, e, r, tr) local function add_value(ms, b, s, e, r, tr)
local res local res
if tr == "function" then if tr == "function" then
res = r(push_captures(ms, s, e)) res = r(push_captures(ms, s, e))
@@ -623,9 +623,9 @@ local function add_value(ms, b, s, e, r, tr)
error("invalid replacement value (a "..type(res)..")") error("invalid replacement value (a "..type(res)..")")
end end
return b .. res -- add result to accumulator return b .. res -- add result to accumulator
end end
local function str_gsub(s, pattern, repl, n) local function str_gsub(s, pattern, repl, n)
checkArg(1, s, "string") checkArg(1, s, "string")
checkArg(2, pattern, "string") checkArg(2, pattern, "string")
checkArg(3, repl, "number", "string", "function", "table") checkArg(3, repl, "number", "string", "function", "table")
@@ -669,55 +669,55 @@ local function str_gsub(s, pattern, repl, n)
end end
b = b .. src:head() b = b .. src:head()
return b, n -- number of substitutions return b, n -- number of substitutions
end end
string.find = str_find string.find = str_find
string.match = str_match string.match = str_match
string.gmatch = str_gmatch string.gmatch = str_gmatch
string.gsub = str_gsub string.gsub = str_gsub
end end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function spcall(...) local function spcall(...)
local result = table.pack(pcall(...)) local result = table.pack(pcall(...))
if not result[1] then if not result[1] then
error(tostring(result[2]), 0) error(tostring(result[2]), 0)
else else
return table.unpack(result, 2, result.n) return table.unpack(result, 2, result.n)
end end
end end
local sgcco local sgcco
local function sgcf(self, gc) local function sgcf(self, gc)
while true do while true do
self, gc = coroutine.yield(pcall(gc, self)) self, gc = coroutine.yield(pcall(gc, self))
end end
end end
local function sgc(self) local function sgc(self)
local oldDeadline, oldHitDeadline = deadline, hitDeadline local oldDeadline, oldHitDeadline = deadline, hitDeadline
local mt = debug.getmetatable(self) local mt = debug.getmetatable(self)
mt = rawget(mt, "mt") mt = rawget(mt, "mt")
local gc = rawget(mt, "__gc") local gc = rawget(mt, "__gc")
if type(gc) ~= "function" then if type(gc) ~= "function" then
return return
end end
if not sgcco then if not sgcco then
sgcco = coroutine.create(sgcf) sgcco = coroutine.create(sgcf)
end end
debug.sethook(sgcco, checkDeadline, "", hookInterval) debug.sethook(sgcco, checkDeadline, "", hookInterval)
deadline, hitDeadline = math.min(oldDeadline, computer.realTime() + 0.5), true deadline, hitDeadline = math.min(oldDeadline, computer.realTime() + 0.5), true
local _, result, reason = coroutine.resume(sgcco, self, gc) local _, result, reason = coroutine.resume(sgcco, self, gc)
debug.sethook(sgcco) debug.sethook(sgcco)
if coroutine.status(sgcco) == "dead" then if coroutine.status(sgcco) == "dead" then
sgcco = nil sgcco = nil
end end
deadline, hitDeadline = oldDeadline, oldHitDeadline deadline, hitDeadline = oldDeadline, oldHitDeadline
if not result then if not result then
error(reason, 0) error(reason, 0)
end end
end end
--[[ This is the global environment we make available to userland programs. ]] --[[ This is the global environment we make available to userland programs. ]]
@@ -727,262 +727,262 @@ end
-- persisted. -- persisted.
local sandbox, libprocess local sandbox, libprocess
sandbox = { sandbox = {
assert = assert, assert = assert,
dofile = nil, -- in boot/*_base.lua dofile = nil, -- in boot/*_base.lua
error = error, error = error,
_G = nil, -- see below _G = nil, -- see below
getmetatable = function(t) getmetatable = function(t)
if type(t) == "string" then -- don't allow messing with the string mt if type(t) == "string" then -- don't allow messing with the string mt
return nil return nil
end end
local result = getmetatable(t) local result = getmetatable(t)
-- check if we have a wrapped __gc using mt -- check if we have a wrapped __gc using mt
if type(result) == "table" and system.allowGC() and rawget(result, "__gc") == sgc then if type(result) == "table" and system.allowGC() and rawget(result, "__gc") == sgc then
result = rawget(result, "mt") result = rawget(result, "mt")
end end
return result return result
end, end,
ipairs = ipairs, ipairs = ipairs,
load = function(ld, source, mode, env) load = function(ld, source, mode, env)
if not system.allowBytecode() then if not system.allowBytecode() then
mode = "t" mode = "t"
end end
return load(ld, source, mode, env or sandbox) return load(ld, source, mode, env or sandbox)
end, end,
loadfile = nil, -- in boot/*_base.lua loadfile = nil, -- in boot/*_base.lua
next = next, next = next,
pairs = pairs, pairs = pairs,
pcall = function(...) pcall = function(...)
local result = table.pack(pcall(...)) local result = table.pack(pcall(...))
checkDeadline() checkDeadline()
return table.unpack(result, 1, result.n) return table.unpack(result, 1, result.n)
end, end,
print = nil, -- in boot/*_base.lua print = nil, -- in boot/*_base.lua
rawequal = rawequal, rawequal = rawequal,
rawget = rawget, rawget = rawget,
rawlen = rawlen, rawlen = rawlen,
rawset = rawset, rawset = rawset,
select = select, select = select,
setmetatable = function(t, mt) setmetatable = function(t, mt)
if type(mt) ~= "table" then if type(mt) ~= "table" then
return setmetatable(t, mt) return setmetatable(t, mt)
end end
if rawget(mt, "__gc") ~= nil then -- If __gc is set to ANYTHING not `nil`, we're gonna have issues if rawget(mt, "__gc") ~= nil then -- If __gc is set to ANYTHING not `nil`, we're gonna have issues
-- Garbage collector callbacks apparently can't be sandboxed after -- Garbage collector callbacks apparently can't be sandboxed after
-- all, because hooks are disabled while they're running. So we just -- all, because hooks are disabled while they're running. So we just
-- disable them altogether by default. -- disable them altogether by default.
if system.allowGC() then if system.allowGC() then
-- For all user __gc functions we enforce a much tighter deadline. -- For all user __gc functions we enforce a much tighter deadline.
-- This is because these functions may be called from the main -- This is because these functions may be called from the main
-- thread under certain circumstanced (such as when saving the world), -- thread under certain circumstanced (such as when saving the world),
-- which can lead to noticeable lag if the __gc function behaves badly. -- which can lead to noticeable lag if the __gc function behaves badly.
local sbmt = {} -- sandboxed metatable. only for __gc stuff, so it's local sbmt = {} -- sandboxed metatable. only for __gc stuff, so it's
-- kinda ok to have a shallow copy instead... meh. -- kinda ok to have a shallow copy instead... meh.
for k, v in next, mt do for k, v in next, mt do
sbmt[k] = v sbmt[k] = v
end end
sbmt.__gc = sgc sbmt.__gc = sgc
sbmt.mt = mt sbmt.mt = mt
mt = sbmt mt = sbmt
else else
-- Don't allow marking for finalization, but use the raw metatable. -- Don't allow marking for finalization, but use the raw metatable.
local gc = rawget(mt, "__gc") local gc = rawget(mt, "__gc")
rawset(mt, "__gc", nil) -- remove __gc rawset(mt, "__gc", nil) -- remove __gc
local ret = table.pack(pcall(setmetatable, t, mt)) local ret = table.pack(pcall(setmetatable, t, mt))
rawset(mt, "__gc", gc) -- restore __gc rawset(mt, "__gc", gc) -- restore __gc
if not ret[1] then error(ret[2], 0) end if not ret[1] then error(ret[2], 0) end
return table.unpack(ret, 2, ret.n) return table.unpack(ret, 2, ret.n)
end end
end end
return setmetatable(t, mt) return setmetatable(t, mt)
end, end,
tonumber = tonumber, tonumber = tonumber,
tostring = tostring, tostring = tostring,
type = type, type = type,
_VERSION = _VERSION:match("5.3") and "Lua 5.3" or "Lua 5.2", _VERSION = _VERSION:match("5.3") and "Lua 5.3" or "Lua 5.2",
xpcall = function(f, msgh, ...) xpcall = function(f, msgh, ...)
local handled = false local handled = false
local result = table.pack(xpcall(f, function(...) local result = table.pack(xpcall(f, function(...)
if handled then if handled then
return ... return ...
else else
handled = true handled = true
return msgh(...) return msgh(...)
end end
end, ...)) end, ...))
checkDeadline() checkDeadline()
return table.unpack(result, 1, result.n) return table.unpack(result, 1, result.n)
end, end,
coroutine = { coroutine = {
create = coroutine.create, create = coroutine.create,
resume = function(co, ...) -- custom resume part for bubbling sysyields resume = function(co, ...) -- custom resume part for bubbling sysyields
checkArg(1, co, "thread") checkArg(1, co, "thread")
local args = table.pack(...) local args = table.pack(...)
while true do -- for consecutive sysyields while true do -- for consecutive sysyields
debug.sethook(co, checkDeadline, "", hookInterval) debug.sethook(co, checkDeadline, "", hookInterval)
local result = table.pack( local result = table.pack(
coroutine.resume(co, table.unpack(args, 1, args.n))) coroutine.resume(co, table.unpack(args, 1, args.n)))
debug.sethook(co) -- avoid gc issues debug.sethook(co) -- avoid gc issues
checkDeadline() checkDeadline()
if result[1] then -- success: (true, sysval?, ...?) if result[1] then -- success: (true, sysval?, ...?)
if coroutine.status(co) == "dead" then -- return: (true, ...) if coroutine.status(co) == "dead" then -- return: (true, ...)
return true, table.unpack(result, 2, result.n) return true, table.unpack(result, 2, result.n)
elseif result[2] ~= nil then -- yield: (true, sysval) elseif result[2] ~= nil then -- yield: (true, sysval)
args = table.pack(coroutine.yield(result[2])) args = table.pack(coroutine.yield(result[2]))
else -- yield: (true, nil, ...) else -- yield: (true, nil, ...)
return true, table.unpack(result, 3, result.n) return true, table.unpack(result, 3, result.n)
end end
else -- error: result = (false, string) else -- error: result = (false, string)
return false, result[2] return false, result[2]
end end
end end
end, end,
running = coroutine.running, running = coroutine.running,
status = coroutine.status, status = coroutine.status,
wrap = function(f) -- for bubbling coroutine.resume wrap = function(f) -- for bubbling coroutine.resume
local co = coroutine.create(f) local co = coroutine.create(f)
return function(...) return function(...)
local result = table.pack(sandbox.coroutine.resume(co, ...)) local result = table.pack(sandbox.coroutine.resume(co, ...))
if result[1] then if result[1] then
return table.unpack(result, 2, result.n) return table.unpack(result, 2, result.n)
else else
error(result[2], 0) error(result[2], 0)
end end
end end
end, end,
yield = function(...) -- custom yield part for bubbling sysyields yield = function(...) -- custom yield part for bubbling sysyields
return coroutine.yield(nil, ...) return coroutine.yield(nil, ...)
end end
}, },
string = { string = {
byte = string.byte, byte = string.byte,
char = string.char, char = string.char,
dump = string.dump, dump = string.dump,
find = string.find, find = string.find,
format = string.format, format = string.format,
gmatch = string.gmatch, gmatch = string.gmatch,
gsub = string.gsub, gsub = string.gsub,
len = string.len, len = string.len,
lower = string.lower, lower = string.lower,
match = string.match, match = string.match,
rep = string.rep, rep = string.rep,
reverse = string.reverse, reverse = string.reverse,
sub = string.sub, sub = string.sub,
upper = string.upper upper = string.upper
}, },
table = { table = {
concat = table.concat, concat = table.concat,
insert = table.insert, insert = table.insert,
pack = table.pack, pack = table.pack,
remove = table.remove, remove = table.remove,
sort = table.sort, sort = table.sort,
unpack = table.unpack unpack = table.unpack
}, },
math = { math = {
abs = math.abs, abs = math.abs,
acos = math.acos, acos = math.acos,
asin = math.asin, asin = math.asin,
atan = math.atan, atan = math.atan,
atan2 = math.atan2, atan2 = math.atan2,
ceil = math.ceil, ceil = math.ceil,
cos = math.cos, cos = math.cos,
cosh = math.cosh, cosh = math.cosh,
deg = math.deg, deg = math.deg,
exp = math.exp, exp = math.exp,
floor = math.floor, floor = math.floor,
fmod = math.fmod, fmod = math.fmod,
frexp = math.frexp, frexp = math.frexp,
huge = math.huge, huge = math.huge,
ldexp = math.ldexp, ldexp = math.ldexp,
log = math.log, log = math.log,
max = math.max, max = math.max,
min = math.min, min = math.min,
modf = math.modf, modf = math.modf,
pi = math.pi, pi = math.pi,
pow = math.pow or function(a, b) -- Deprecated in Lua 5.3 pow = math.pow or function(a, b) -- Deprecated in Lua 5.3
return a^b return a^b
end, end,
rad = math.rad, rad = math.rad,
random = function(...) random = function(...)
return spcall(math.random, ...) return spcall(math.random, ...)
end, end,
randomseed = function(seed) randomseed = function(seed)
spcall(math.randomseed, seed) spcall(math.randomseed, seed)
end, end,
sin = math.sin, sin = math.sin,
sinh = math.sinh, sinh = math.sinh,
sqrt = math.sqrt, sqrt = math.sqrt,
tan = math.tan, tan = math.tan,
tanh = math.tanh tanh = math.tanh
}, },
-- Deprecated in Lua 5.3. -- Deprecated in Lua 5.3.
bit32 = bit32 and { bit32 = bit32 and {
arshift = bit32.arshift, arshift = bit32.arshift,
band = bit32.band, band = bit32.band,
bnot = bit32.bnot, bnot = bit32.bnot,
bor = bit32.bor, bor = bit32.bor,
btest = bit32.btest, btest = bit32.btest,
bxor = bit32.bxor, bxor = bit32.bxor,
extract = bit32.extract, extract = bit32.extract,
replace = bit32.replace, replace = bit32.replace,
lrotate = bit32.lrotate, lrotate = bit32.lrotate,
lshift = bit32.lshift, lshift = bit32.lshift,
rrotate = bit32.rrotate, rrotate = bit32.rrotate,
rshift = bit32.rshift rshift = bit32.rshift
}, },
io = nil, -- in lib/io.lua io = nil, -- in lib/io.lua
os = { os = {
clock = os.clock, clock = os.clock,
date = function(format, time) date = function(format, time)
return spcall(os.date, format, time) return spcall(os.date, format, time)
end, end,
difftime = function(t2, t1) difftime = function(t2, t1)
return t2 - t1 return t2 - t1
end, end,
execute = nil, -- in boot/*_os.lua execute = nil, -- in boot/*_os.lua
exit = nil, -- in boot/*_os.lua exit = nil, -- in boot/*_os.lua
remove = nil, -- in boot/*_os.lua remove = nil, -- in boot/*_os.lua
rename = nil, -- in boot/*_os.lua rename = nil, -- in boot/*_os.lua
time = function(table) time = function(table)
checkArg(1, table, "table", "nil") checkArg(1, table, "table", "nil")
return os.time(table) return os.time(table)
end, end,
tmpname = nil, -- in boot/*_os.lua tmpname = nil, -- in boot/*_os.lua
}, },
debug = { debug = {
getinfo = function(...) getinfo = function(...)
local result = debug.getinfo(...) local result = debug.getinfo(...)
if result then if result then
-- Only make primitive information available in the sandbox. -- Only make primitive information available in the sandbox.
return { return {
source = result.source, source = result.source,
short_src = result.short_src, short_src = result.short_src,
linedefined = result.linedefined, linedefined = result.linedefined,
lastlinedefined = result.lastlinedefined, lastlinedefined = result.lastlinedefined,
what = result.what, what = result.what,
currentline = result.currentline, currentline = result.currentline,
nups = result.nups, nups = result.nups,
nparams = result.nparams, nparams = result.nparams,
isvararg = result.isvararg, isvararg = result.isvararg,
name = result.name, name = result.name,
namewhat = result.namewhat, namewhat = result.namewhat,
istailcall = result.istailcall istailcall = result.istailcall
} }
end end
end, end,
traceback = debug.traceback traceback = debug.traceback
}, },
checkArg = checkArg checkArg = checkArg
} }
sandbox._G = sandbox sandbox._G = sandbox

View File

@@ -311,7 +311,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
beepCursor = 0 beepCursor = 0
} }
// continue emitTone queue // advance emitTone queue
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) { if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor) beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
beepCursor += 1 beepCursor += 1
@@ -321,7 +321,6 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
// complete emitTone queue // complete emitTone queue
if (beepCursor >= beepQueue.size) { if (beepCursor >= beepQueue.size) {
clearBeepQueue() clearBeepQueue()
AL.destroy()
if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear") if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear")
} }
@@ -329,6 +328,12 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) { if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) {
playTone(beepQueue[beepCursor].first, beepQueue[beepCursor].second) playTone(beepQueue[beepCursor].first, beepQueue[beepCursor].second)
beepQueueFired = true beepQueueFired = true
// delete sources that is finished. AL is limited to 256 sources. If you exceed it,
// we won't get any more sounds played.
AL10.alSourcei(oldBeepSource, AL10.AL_BUFFER, 0)
AL10.alDeleteSources(oldBeepSource)
AL10.alDeleteBuffers(oldBeepBuffer)
} }
if (beepQueueFired) beepQueueLineExecTimer += delta if (beepQueueFired) beepQueueLineExecTimer += delta
@@ -338,6 +343,8 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
beepQueue.clear() beepQueue.clear()
beepCursor = -1 beepCursor = -1
beepQueueLineExecTimer = 0 beepQueueLineExecTimer = 0
//AL.destroy()
} }
fun enqueueBeep(duration: Int, freq: Double) { fun enqueueBeep(duration: Int, freq: Double) {
@@ -352,8 +359,10 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
//////////////////// ////////////////////
private val sampleRate = 44100 private val sampleRate = 44100
private var beepSource: Int? = null private var beepSource: Int = -1
private var beepBuffer: Int? = null private var beepBuffer: Int = -1
private var oldBeepSource: Int = -1
private var oldBeepBuffer: Int = -1
var audioData: ByteBuffer? = null var audioData: ByteBuffer? = null
/** /**
@@ -424,36 +433,37 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
// Clear error stack. // Clear error stack.
AL10.alGetError() AL10.alGetError()
oldBeepBuffer = beepBuffer
beepBuffer = AL10.alGenBuffers() beepBuffer = AL10.alGenBuffers()
checkALError() checkALError()
try { try {
AL10.alBufferData(beepBuffer!!, AL10.AL_FORMAT_MONO8, audioData, sampleRate) AL10.alBufferData(beepBuffer, AL10.AL_FORMAT_MONO8, audioData, sampleRate)
checkALError() checkALError()
oldBeepSource = beepSource
beepSource = AL10.alGenSources() beepSource = AL10.alGenSources()
checkALError() checkALError()
try { try {
AL10.alSourceQueueBuffers(beepSource!!, beepBuffer!!) AL10.alSourceQueueBuffers(beepSource, beepBuffer)
checkALError() checkALError()
AL10.alSource3f(beepSource!!, AL10.AL_POSITION, 0f, 0f, 1f) AL10.alSource3f(beepSource, AL10.AL_POSITION, 0f, 0f, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_REFERENCE_DISTANCE, 1f) AL10.alSourcef(beepSource, AL10.AL_REFERENCE_DISTANCE, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_MAX_DISTANCE, 1f) AL10.alSourcef(beepSource, AL10.AL_MAX_DISTANCE, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_GAIN, 0.3f) AL10.alSourcef(beepSource, AL10.AL_GAIN, 0.3f)
checkALError() checkALError()
AL10.alSourcePlay(beepSource!!) AL10.alSourcePlay(beepSource)
checkALError() checkALError()
} }
catch (e: ALException) { catch (e: ALException) {
AL10.alDeleteSources(beepSource!!) AL10.alDeleteSources(beepSource)
} }
} }
catch (e: ALException) { catch (e: ALException) {
if (beepSource != null) AL10.alDeleteSources(beepSource!!) AL10.alDeleteSources(beepSource)
} }
} }