Using FFI array renders dysfunctional

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
pkhead
Prole
Posts: 2
Joined: Fri Nov 11, 2022 11:49 pm

Using FFI array renders dysfunctional

Post by pkhead »

I'm making some sort of audio processing thing. I have an array containing the FFT transform. I'm trying to make this array an FFI array instead of a table for potential performance gains.

This is the code that declares the tables, starting from main.lua:26:

Code: Select all

-- using ffi arrays don't work, however using Lua tables does
--local data_l = ffi.new("lua_complex["..(RESOLUTION).."]")
--local data_r = ffi.new("lua_complex["..(RESOLUTION).."]")
local data_l = {}
local data_r = {}
If you switch data_l and data_r to use the FFI array, the output signal becomes garbled. For the past hour, I've struggled to understand why this happens. I've made sure to treat the array as 0-indexed, and it processes the data the same way regardless of if it's an FFI pointer or a table, and yet it only works if it's a table.

I've attached the project zip. (Keep your volume down)
Attachments
audioprocess.zip
(2.24 MiB) Downloaded 44 times
User avatar
zorg
Party member
Posts: 3465
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Using FFI array renders dysfunctional

Post by zorg »

That's not really an ffi pointer, it's an ffi array of lua_complex structs.
A pointer would be something like you allocating enough memory for RESOLUTION times the size of a lua_complex struct, then doing ffi.new("lua_complex*", memlocation); actually, i'd argue that you should try this, with the memory location being a ByteData, and you doing getFFIPointer on it, passing that to the aforementioned ffi.new call.

I'm not exacly sure though why it's crapping itself; maybe something about the metatype of that complex library it doesn't like when you put it into the array or idk.

I myself did some testing with FFTs though, and i just did it like this:

Code: Select all

local Lr, Rr, Li, Ri = love.data.newByteData(windowSize * ffi.sizeof('double')),
	love.data.newByteData(windowSize * ffi.sizeof('double')),
	love.data.newByteData(windowSize * ffi.sizeof('double')),
	love.data.newByteData(windowSize * ffi.sizeof('double'))
local Lrp, Rrp, Lip, Rip = ffi.cast("double *", Lr:getFFIPointer()),
	ffi.cast("double *", Rr:getFFIPointer()),
	ffi.cast("double *", Li:getFFIPointer()),
	ffi.cast("double *", Ri:getFFIPointer())
in other words, i treated the real and imaginary components of both left and right channels separately, when i was using luafft, which is jank.

After, this is what i did:

Code: Select all

-- used library: https://github.com/soumith/fftw3-ffi

local ffi  = require 'ffi'
local fftw = require 'fftw3'

local N      = 4096*2 -- your RESOLUTION equivalent

local data_i = fftw.alloc_complex(N);
local dptr_i = ffi.new('fftw_complex*', data_i)

local data_o = fftw.alloc_complex(N);
local dptr_o = ffi.new('fftw_complex*', data_o)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 4 guests