visual spectral filter

michelez's icon

I haven't had much luck in getting answers lately, but I am willing to give it another shot.
I am building a spectral filter with a pfft~. The filter is only for visual purposes: I save magnitudes into a single row matrix to then multiply it by a [jit.texture] (I need to the pfft~ to erase/pass parts of the texture based on the sound)
What I am doing is creating a single row matrix, much like some of Jean Francois spectral patches. But I need the magnitudes to be saved into cells with coordinates corresponding to midi scale rather than Hz
Can anyone take a look at this and tell me if there is something that I am missing?
Thanks!

Max Patch
Copy patch and select New From Clipboard in Max.

Floating Point's icon

your mapping from "fft-bin-to-midi" looks correct, except for one very important error-- you are assuming that bins can be remapped from linear to log scale-- they can't-- not in the sense you have here, because bins, as discrete "objects", or structures are fixed in a linear context; they lose their meaning in this remapping process.
for example, the first two bins represent a whole octave range (of midi), while the last two bins represent 1/256 of an octave range.
To get around this you need to have something like a single row of about 2048 cells ( 8*256, 256 cells per octave) and interpolate values in the lower octaves to fill in the gaps (or just leave them blank).
You could do this by having a separate 256*1 matrix for each octave with a mapping like this:

bin octave
1 -> 1 (cells 0-255)
2,3 -> 2 (cells 256-511)
4,5,6,7 -> 3 (cells 512- 767)
8,9,10,11,12,13,14,15 ->4 (cells 768- whatever)

etc

then glue the matrices together to form a single row
the interpolation would be easy as matrices can be set up to interpolate automatically

another less heuristic way is to do the maths to map bin number to cell-number, with or without interpolation, and use the setcell message to set correct value for each cell in your midi-row, but either way is ok probably because theoretically fft information can't be remapped like this without loss or distortion of information

michelez's icon

I was wondering how I could get around the log-linear problem. Probing wth [capture~] I saw exactly what you just explained (one giant bin at the beginning etc), only I didnt know how to fix it. I will try your solution and post the results here in case anyone else is interested.
Thank you!

michelez's icon

So I tried your solution

Max Patch
Copy patch and select New From Clipboard in Max.

Something doesn't work between the [jit.catch~] and the [jit.glue]

Max Patch
Copy patch and select New From Clipboard in Max.

before I got your response I worked out a solution on my own and I was wondering if you could take a look at it and see if it does something similar to what you described here it is

let me know your thoughts

lyve forms's icon

sounds very interesting, what exactly is the patch doing?

michelez's icon

the patch is generating a single row matrix of magnitudes with a midi scale distribution. If you feed an audio signal to it you can use the matrix as a filter for other matrixes. I work with audio-visual patterns, they look like the midi piano roll notation, so I use the visual filter to only select the frequencies of the pattern that are being played. I will post some examples next week on this page
https://michelezaccagnini.com/electronicinteractive/

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

I looked at your first patch and fixed it for you (not perfectly, not sure whats happening with the last octave) before looking at the second one-- the second looks more efficient and simpler-- not sure why you divide the signal when it first comes out of the fft object-- anyway the first one has some good pedagogical value...

michelez's icon

Thanks Floating Point, I divide the fft signal to normalize the magnitudes (I learned this form this tutorial https://cycling74.com/tutorials/advanced-max-ffts-part-3). I tried the fixed patch but I am getting errors from the pwindow. I see your point about splitting the matrix now...

Floating Point's icon

oh yes, of course to normalise, I watched that tutorial last week!
the pwindow errors are just because max is in overdrive-- normally you need to take max out of overdrive when using jitter
btw if you want one-semitone "resolution" change the dimension of the interpolating matrix to 12

Floating Point's icon
Max Patch
Copy patch and select New From Clipboard in Max.

hey I realized, for the version I looked at, you don't need all that gating etc,, so here's a simplified /optimized version

michelez's icon

It works great now.
Good to know about the overdrive and jitter. The threading tutorial also mentions that (https://cycling74.com/tutorials/advanced-max-learning-about-threading).. this actually makes me wonder what is the best setting for a patch that has a heavy dsp component and needs a good timing accuracy (i.e. small signal vector size) and needs to run several jitter processes at the same time. I might start another thread but I was wondering if you have any quick thoughts.

Floating Point's icon

I've had a look at the other version you posted, and I think the matrix "dummy" which stores the filled in values should be renamed to something else so the values don't accumulate, ie call it "interpolated" or something, but still poke into "dummy"

Floating Point's icon

re scheduling, that's tricky, if your jitter is being used for display only (not audio processing) I think there are some tricks using defer/deferlow/qball/qmetro etc to deprioritize UI and jitter processes. But best to start another thread with a specific issue you can illustrate. Another option is to move jitter processes to graphics card, but I'm no expert on that.

michelez's icon

I will post something more precise about the threading issue in a different topic. And yes I was wondering if I needed two matrices so thanks for that as well!

Floating Point's icon

just thought I'd share this, as it might be an alternative to interpolating a single fft analysis into semitones. It uses multiple pfft resolutions and selectively pokes only 12 bins from each fft into single-octave groupings, so no interpolation is needed, and you get a consistent resolution across all octaves. you could fine-tune it by altering the sample rate. requires a gen file and pfft file, hence zipped, hth

multires-fft.zip
zip
michelez's icon

this is really interesting, is it more cpu intensive than the other solutions? do you really need all of the pfft~ or could one work for a lower res matrix?

Floating Point's icon

yes it would be, but I suspect not by much, maybe twice the load-- but you culd test that with a cpu monitor, also use @parallel 1 for the pfft objects; you can adapt it to your needs regarding resolution-- depends on how much of the spectrum and in what detail you want to analyse etc/

all the bin selection is determined in the gen subpatcher, so you'd need to adapt that