I feel like I get a lot from this message board but do not give nearly enough back. Hopefully I can change that. This is the first in a series of patches (2 or 3) showing how jit.fft can be used for offline fft calculations. I do not see much on here about using jit.fft with audio. Hopefully it will be useful to some :)
In making an arbitrary filter, one of the easiest ways is to put a frequency response into a buffer~ and apply it using index~ and some multiplication inside a pfft~. This patch shows how to get similar results using a different approach. Instead of doing an fft on the incoming audio, it uses the often overlooked buffir~ filter. Normally calculating the coefficients needed would be a hassle, which is where jit.fft comes in handy.
Drawing in the frequency graph writes into a 1D floating point jit.matrix object that is 256 “samples” wide. This matrix follows the shape of the graph, starting with low frequencies and working upwards. Before taking the fft, the frequency response data has to be mirrored and shifted so that a frequency of zero moves to the outer edges and high frequencies move to the middle. Jit.repos using boundmode 4 provides a simple way to mirror a matrix.
Now the frequency response is ready, but the jit.fft object also needs some phase values to do an inverse fft. In this case the jit.pack object essentially sets all the phase values to 0 for a linear phase filter. To go from frequency data back to the time domain, jit.fft performs an inverse fft on the data.
At this point jit.fft outputs all the coefficients we need, but not in the proper order. Previously the data was shifted so that “0” moved to the outer edges of the matrix. Now, the reverse is needed. To arrange the coefficients properly, a jit.repos object (boundmode 2) wraps the data into position. Because the filter is linear phase, it is symmetric and delayed. In this case the “0” point of the data is now in the middle.
Because the original frequency response going into jit.fft was on a scale from 0 to 1 and not 0 to 1/(length of the data), it has to be scaled down by a jit.op. Lastly, since the buffir~ object has a length limit of 256 samples, a jit.submatrix grabs the 256 values around the center.