Open tristanbay opened 5 months ago
Thanks for reporting! I had a look at the code and I think the issue is not with the length of the target array, but with that of the sample array which, at least based on the current implementation of FFT.analyzeSample()
, also needs to be a power of two (but not necessarily the same power of 2 as the target array??). The culprit is the second argument here, which I'm not sure is actually the correct way to call transform()
(it should probably be target.length
instead of sample.length
):
For now, if you change the length of vtemp_l
to the next-lowest power of two of the length you actually want (vframelen * (voverlap + 1)
) it should work. (If you get an ArrayIndexOutOfBoundException then the sample actually needs to be the same length as the target array. Which would make sense in the context of an FFT, but in that case the documentation of analyzeSample()
needs some serious updating to reflect that!
The culprit is the second argument here, which I'm not sure is actually the correct way to call
transform()
(it should probably betarget.length
instead ofsample.length
):
I think that's the issue. 🤦♂️ This should be changed as soon as possible.
For now, if you change the length of
vtemp_l
to the next-lowest power of two of the length you actually want (vframelen * (voverlap + 1)
) it should work. (If you get an ArrayIndexOutOfBoundException then the sample actually needs to be the same length as the target array. Which would make sense in the context of an FFT, but in that case the documentation ofanalyzeSample()
needs some serious updating to reflect that!
Seems to work. I guess one of the devs got those arrays mixed up.
Thanks for the pull request, I'll merge it for now but it introduces another quirk: after the change, analyzeSample()
only analyzes the first numBands
samples, even if the sample
array is actually longer. For example in your sketch, assuming usual framerates of 44khz and 25fps respectively, your vtemp
arrays have a length of ~1764 (actually a bit more because of the overlap), but the FFT result you get back is only based on the first 512 samples of that array, which is probably not the expected behaviour. Ideally we should use something like Welch's method and return the average FFT of all numBands
-length sliding windows that fit into the sample array.
The analyzeSample()
method current also doesn't apply a Hann window before analysis like the continuous-analysis of FFT
objects does:
https://github.com/processing/processing-sound/blob/23108c9a201724c6e231b63d1fc631809462568a/src/processing/sound/JSynFFT.java#L39-L41
The application of such a window should probably be moved to the FFT.calculateMagnitudesFromSample()
method anyway (I've got a hunch that the JSynFFT
class should be ditched altogether, actually the only instance variable necessary is the FixedMonoWriter
with its buffer, all the arrays used for computations are never concurrent and can therefore be shared between instances).
I dug into the Processing source code to figure out why this is happening, and it apparently thinks that powers of 2 aren't powers of 2 when passing into the assert line in the numBits function of the FourierMath class in jsyn's softsynth code, even though it gets past the check in this function.
Here's the code I'm trying to run (just copy and paste it into the IDE, version 4.3). Even adapting and printing out the
PowerOf2 & (PowerOf2 - 1)
expression in my own code gives a0
on the console:Something seems to be altering the perceived length of those target arrays between checks. Could it have to do with using 2D arrays?