mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Implemented efficient FFI versions of SoundData methods, which are used when the LuaJIT FFI and JIT compiler are present.
This commit is contained in:
@@ -22,11 +22,21 @@
|
||||
|
||||
#include "common/wrap_Data.h"
|
||||
|
||||
// Shove the wrap_SoundData.lua code directly into a raw string literal.
|
||||
static const char sounddata_lua[] =
|
||||
#include "wrap_SoundData.lua"
|
||||
;
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace sound
|
||||
{
|
||||
|
||||
/**
|
||||
* NOTE: Additional wrapper code is in wrap_SoundData.lua. Be sure to keep it
|
||||
* in sync with any changes made to this file!
|
||||
**/
|
||||
|
||||
SoundData *luax_checksounddata(lua_State *L, int idx)
|
||||
{
|
||||
return luax_checktype<SoundData>(L, idx, SOUND_SOUND_DATA_ID);
|
||||
@@ -105,7 +115,22 @@ static const luaL_Reg functions[] =
|
||||
|
||||
extern "C" int luaopen_sounddata(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, SOUND_SOUND_DATA_ID, functions);
|
||||
// The last argument pushes the type's metatable onto the stack.
|
||||
int ret = luax_register_type(L, SOUND_SOUND_DATA_ID, functions, true);
|
||||
|
||||
// Load and execute SoundData.lua, sending the metatable as an argument.
|
||||
if (ret > 0)
|
||||
{
|
||||
luaL_loadbuffer(L, sounddata_lua, sizeof(sounddata_lua), "SoundData.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_call(L, 1, 0);
|
||||
|
||||
// Pop the metatable.
|
||||
lua_pop(L, 1);
|
||||
ret--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // sound
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
R"luastring"--(
|
||||
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
|
||||
-- There is a matching delimiter at the bottom of the file.
|
||||
|
||||
--[[
|
||||
Copyright (c) 2006-2015 LOVE Development Team
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local SoundData_mt = ...
|
||||
|
||||
if type(jit) ~= "table" or not jit.status() then
|
||||
-- LuaJIT's FFI is *much* slower than LOVE's regular methods when the JIT
|
||||
-- compiler is disabled.
|
||||
return
|
||||
end
|
||||
|
||||
local status, ffi = pcall(require, "ffi")
|
||||
if not status then return end
|
||||
|
||||
local tonumber, assert = tonumber, assert
|
||||
|
||||
local float = ffi.typeof("float")
|
||||
local datatypes = {ffi.typeof("uint8_t *"), ffi.typeof("int16_t *")}
|
||||
|
||||
local typemaxvals = {0x7F, 0x7FFF}
|
||||
|
||||
local _getBitDepth = SoundData_mt.__index.getBitDepth
|
||||
local _getSampleCount = SoundData_mt.__index.getSampleCount
|
||||
local _getSampleRate = SoundData_mt.__index.getSampleRate
|
||||
local _getChannels = SoundData_mt.__index.getChannels
|
||||
|
||||
-- Table which holds SoundData objects as keys, and information about the objects
|
||||
-- as values. Uses weak keys so the SoundData objects can still be GC'd properly.
|
||||
local objectcache = setmetatable({}, {
|
||||
__mode = "k",
|
||||
__index = function(self, sounddata)
|
||||
local bytedepth = _getBitDepth(sounddata) / 8
|
||||
local pointer = ffi.cast(datatypes[bytedepth], sounddata:getPointer())
|
||||
|
||||
local p = {
|
||||
bytedepth = bytedepth,
|
||||
pointer = pointer,
|
||||
size = sounddata:getSize(),
|
||||
maxvalue = typemaxvals[bytedepth],
|
||||
samplecount = _getSampleCount(sounddata),
|
||||
samplerate = _getSampleRate(sounddata),
|
||||
channels = _getChannels(sounddata),
|
||||
}
|
||||
|
||||
self[sounddata] = p
|
||||
return p
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- Overwrite existing functions with new FFI versions.
|
||||
|
||||
function SoundData_mt.__index:getSample(i)
|
||||
local p = objectcache[self]
|
||||
assert(i >= 0 and i < p.size/p.bytedepth, "Attempt to get out-of-range sample!")
|
||||
if p.bytedepth == 2 then
|
||||
-- 16-bit data is stored as signed values internally.
|
||||
return tonumber(p.pointer[i]) / p.maxvalue
|
||||
else
|
||||
-- 8-bit data is stored as unsigned values internally.
|
||||
return (tonumber(p.pointer[i]) - 128) / 127
|
||||
end
|
||||
end
|
||||
|
||||
function SoundData_mt.__index:setSample(i, sample)
|
||||
local p = objectcache[self]
|
||||
assert(i >= 0 and i < p.size/p.bytedepth, "Attempt to set out-of-range sample!")
|
||||
if p.bytedepth == 2 then
|
||||
-- 16-bit data is stored as signed values internally.
|
||||
p.pointer[i] = sample * p.maxvalue
|
||||
else
|
||||
-- 8-bit data is stored as unsigned values internally.
|
||||
-- The float cast is needed to make values end up the same as in the
|
||||
-- C++ version of this method.
|
||||
p.pointer[i] = ffi.cast(float, (sample * 127) + 128)
|
||||
end
|
||||
end
|
||||
|
||||
function SoundData_mt.__index:getSampleCount()
|
||||
local p = objectcache[self]
|
||||
return p.samplecount
|
||||
end
|
||||
|
||||
function SoundData_mt.__index:getSampleRate()
|
||||
local p = objectcache[self]
|
||||
return p.samplerate
|
||||
end
|
||||
|
||||
function SoundData_mt.__index:getChannels()
|
||||
local p = objectcache[self]
|
||||
return p.channels
|
||||
end
|
||||
|
||||
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
|
||||
--)luastring"--"
|
||||
Reference in New Issue
Block a user