xNul / drop

A LÖVE visualizer and music player
MIT License
20 stars 2 forks source link

As time passes, the waveform array is overwritten, crashing the visualizer. #35

Closed xNul closed 6 years ago

xNul commented 6 years ago

I'm using ffi to generate a dynamically allocated array of float values called waveform and for some reason if I stop writing to it, nil and extremely small values start creeping in. Here's the array at 35 seconds:

image

When a nil value creeps in, the loop in spectrum.draw() tries to iterate over it and fails to perform mathematical operations, resulting in an error message and the crash of Drop.

Example: image

To reproduce, start Drop, load some music, pause, and wait a minute or so for a nil value to creep in.

xNul commented 6 years ago

My first thought was there has to be another dynamically allocated array overflowing into my dynamically allocated array, but I wasn't using ffi anywhere else, so I didn't know how that could be possible, unless it was a Love2D issue.

Hoping that wasn't the case, I decided to check my ffi code to make sure I wasn't missing something. I googled around, but couldn't find anything there either. Luckily, I decided to post the code in a chat and someone noticed the way I passed variables to my fft C function was off.

Here's what I had:

local spectrum = fft.fft(ffi.new("float["..size.."]", wave), ffi.new("int", size), ffi.new("int", tick_count))

It turns out, ffi automatically frees variables that are no longer in use by Lua. So, when I used ffi.new("float["..size.."]", wave) to allocate the array, it immediately disappeared once the pointer was passed and did not attempt to maintain that memory space anymore, thus the same memory space which the waveform array pointed to, was being overwritten because it wasn't being protected anymore.

In order to fix, the code now looks like this:

samples_ptr = ffi.new("float["..size.."]", wave) -- keeps ffi memory allocated, don't destroy
local sample_count_ptr = ffi.new("int", size)
local tick_count_ptr = ffi.new("int", tick_count)

local spectrum = fft.fft(samples_ptr, sample_count_ptr, tick_count_ptr)

where samples_ptr is a variable local to the spectrum.lua file and is never destroyed.