Created
October 13, 2011 16:20
-
-
Save daurnimator/1284679 to your computer and use it in GitHub Desktop.
OpenAL with luajit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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