Skip to content

Instantly share code, notes, and snippets.

@daurnimator
Created October 13, 2011 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save daurnimator/1284679 to your computer and use it in GitHub Desktop.
Save daurnimator/1284679 to your computer and use it in GitHub Desktop.
OpenAL with luajit
local ffi = require"ffi"
local function process_defines(file,defines)
defines = defines or {}
--TODO: unifdef
for line in io.lines(file) do
local n ,v = line:match("#define%s+(%S+)%s+(.*)")
if n then
v = defines[v] or v
v = tonumber(v) or v
defines[n] = v
end
end
return defines
end
local function add_dep(ob,dep)
local reg = debug.getregistry()
local t = reg[dep]
if not t then
t = setmetatable({},{__mode="k"})
reg[dep] = t
end
t[ob]=true
end
local openal_lib = ffi.load("OpenAL32.dll")
ffi.cdef(assert(io.open([[U:\Programming\OpenAL\processed_al.h]])):read("*a"))
ffi.cdef(assert(io.open([[U:\Programming\OpenAL\processed_alc.h]])):read("*a"))
local openal_defs = {}
process_defines([[C:\Program Files (x86)\OpenAL 1.1 SDK\include\al.h]],openal_defs)
process_defines([[C:\Program Files (x86)\OpenAL 1.1 SDK\include\alc.h]],openal_defs)
local openal = setmetatable({},{__index = function (t,k) return openal_defs[k] or openal_lib[k] end;})
openal.format = {
MONO8 = openal_defs.AL_FORMAT_MONO8 ;
MONO16 = openal_defs.AL_FORMAT_MONO16 ;
STEREO8 = openal_defs.AL_FORMAT_STEREO8 ;
STEREO16 = openal_defs.AL_FORMAT_STEREO16 ;
}
openal.error = {
[openal_defs.AL_NO_ERROR] = "No Error." ;
[openal_defs.AL_INVALID_NAME] = "Invalid Name paramater passed to AL call." ;
[openal_defs.AL_ILLEGAL_ENUM] = "Invalid parameter passed to AL call." ;
[openal_defs.AL_INVALID_VALUE] = "Invalid enum parameter value." ;
[openal_defs.AL_ILLEGAL_COMMAND] = "Illegal call." ;
[openal_defs.AL_OUT_OF_MEMORY] = "Out of memory." ;
}
local function checkforerror()
local e = openal.alGetError()
return e == openal_defs.AL_NO_ERROR , openal.error[e]
end
openal.checkforerror = checkforerror
function openal.opendevice(name)
local dev = assert(openal.alcOpenDevice(name),"Can't Open Device")
ffi.gc(dev,openal.alcCloseDevice)
return dev
end
function openal.newcontext(dev)
local ctx = assert(openal.alcCreateContext(dev,nil),"Can't create context")
add_dep(ctx,dev)
ffi.gc(ctx,function(ctx)
if ctx == openal.alcGetCurrentContext() then
openal.alcMakeContextCurrent(nil)
end
return openal.alcDestroyContext(ctx)
end)
return ctx
end
function openal.newsources(n)
n = n or 1
local source = ffi.new("ALuint[?]",n)
openal.alGenSources(n,source)
ffi.gc(source,function(source) return openal.alDeleteSources(n,source) end)
return source
end
function openal.newbuffers(n)
local buffers = ffi.new("ALuint[?]",n)
openal.alGenBuffers(n,buffers)
assert(checkforerror())
ffi.gc(buffers,function(buffers) return openal.alDeleteBuffers(n,buffers) end)
return buffers
end
local dev = openal.opendevice()
local ctx = openal.newcontext(dev)
openal.alcMakeContextCurrent(ctx)
local source = openal.newsources()
local NUM_BUFFERS = 5
local buffers = openal.newbuffers(NUM_BUFFERS)
local BUFFER_SIZE = 4400*10
local frequency = 44100
local format = openal.format.MONO16;
local source_data = ffi.new("int16_t[?]",BUFFER_SIZE)
local source_len = ffi.sizeof(source_data)
--Generate sinusoidal test signal
local m = 2*math.pi/frequency*440
for i=0,BUFFER_SIZE-1 do
source_data[i]=(2^15-1)*math.sin(m*i)
end
for i=0,NUM_BUFFERS-1 do
openal.alBufferData(buffers[i],format,source_data,source_len,frequency)
end
assert(checkforerror())
openal.alSourceQueueBuffers(source[0],NUM_BUFFERS,buffers)
openal.alSourcePlay(source[0]);
assert(checkforerror())
local buffer = ffi.new("ALuint[1]")
local val = ffi.new("ALint[1]")
while true do
openal.alGetSourcei(source[0],openal.AL_BUFFERS_PROCESSED,val)
if val[0]>0 then
for i=val[0],1,-1 do
openal.alSourceUnqueueBuffers(source[0], 1, buffer)
openal.alBufferData(buffer[0], format, source_data, source_len, frequency)
openal.alSourceQueueBuffers(source[0], 1, buffer)
end
openal.alGetSourcei(source[0], openal.AL_SOURCE_STATE, val)
if val[0] ~= openal.AL_PLAYING then
print("HERE")
openal.alSourcePlay(source[0])
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment