Creating a filter from spectral moments (fluid.spectralshape~)

I could have sworn I made a thread asking in the past (many similar ones however), but it turns out I haven’t.

So after finding some renewed interest and efficacy in vanilla spectral moments, I was wondering if it was possible to translate the values from spectral moments into a filter that can be applied to a sound (and eventually in a similar way to the spectral compensation I’m currently doing with melbands, outlined in this thread).

Some of the moments translate quite readily and easily, notable centroid/spread, which @tremblap has a great example for in the fluid.spectralshape~ helpfile.

After experimenting with with @rolloffpercent 95 combined with @rolloffpercent 5 to capture the overall “low” and “high” range of the audio, and I can see that translating easily to a pair of highpass/lowpass filters.

Similarly, skewness could translate to a tilt filter, centered around the centroid.

Now this starts getting a bit more confusing if I try to think of how to combine those approaches (a notch filter for centroid/spread + a pair of highpass/lowpass filters to define edges + a tilt filter for skewness). I have combined the centroid/spread + skewness, and highpass/lowpass + skewness and they sound ok, though a tilt filter’s impact on the notch filter is minimal.

I did think that crest (“This is the ratio of the loudest magnitude over the RMS of the whole frame”) might be useful to determine how much a notch filter should “poke out” overtop of the spectrum, but I have no clue how it works when combining/cascading filters in this way.

Lastly, I have no clue of what to do with kurtosis/flatness, but I think I’m ok with that.

So that leaves me with this:

  • Centroid - notch filter cutoff freq
  • Spread - q of notch filter
  • Skewness - tilt up or down (centered on centroid cutoff freq)
  • Rolloffpercent(5) - highpass set to freq
  • Rolloffpercent(95) - lowpass set to freq
  • Crest - balance between notch (centroid/spread) and broadband (highpass/lowpass) filters(?)

///////////////////////////////////////////////////////

Any thoughts on how to turn those values into a functioning filter?

I’m not too sure - I think that a few of them are contradicting. Personally for now I’d just use the centroid/spread boost, plus HP and LP, and forget the skew ad crest, and see where you get with that. Good tilt filters are rare… @a.harker told me a lifetime ago that they were hard to implement in the time domain, so that might explain that…

Interesting. As in literally a peak filter for the centroid/spread? I’ve mainly been using svf~ or reson~, so wasn’t making too much sense above or below the cutoff freq.

What would you use to determine how much gain to apply? (here’s where I was thinking crest)

I have one I use from Pete’s filter goodie bags which sounds decent enough.

I guess in contrast to my cascade of 40(!) cross~ filters, anything is an improvement from that!

1 Like

I’m thinking of cascade. The middle band is the same as in my demo patch you raved about, and then a low pass and high pass. 3 filters.

Unless there’s another example I’m forgetting/missing, the example patch has a reson~ as the core(/only) filter:

If I did say (which I might have done, but I don’t remember) then I don’t know that I still agree, mainly because I don’t think I really know how a tilt filter should be built, although I think two complementary shelves is an option which would be fairly easy to build in the time domain.

try replacing it with a biquad~ and you’ll see it works too :slight_smile:

Without a gain value, it’s not really doing anything. So what sets the gain value is the question I guess?

it really depends on the use case but yes, trial and error is probably the next step… you could try to match filter values with real measured values via a neural net, or read the literature on reconstructing filters from statistical description, or just have fun with the reson~ example (which doesn’t work well for multimodal) or code a LPC to predict filters. The latter is on my wishlist for a decade. I poke at it, get annoyed by the maths, and park it. Poor @weefuzzy was helping in one of these vague attempts. One day maybe, but again, getting formants described need a good voiceallocation (to get smooth voice leading between the filters - although distance will still be a problem- that is why we have mfccs for a “formatic shape”)

keep me posted, I’m going back to bufvoiceallocation for now :smiley:

Ok, I’ll try cobbling something together based on this:

Also, am I being thick or is it not possible to edit multiple freq/q/gains for a cascade~ at the same time? (short of computing the coefficients)

Even using filtergraph~ it looks like you can only tweak a filter at a time?

In which case, would it just be a bunch of biquad~s, one after another, for each stage of the filter (HP/BP/LP/tilt).

Ok, spent quite a bit of time this afternoon cooking up something and I think I got something sounding pretty good.

It’s not optimized at all, no smoothing, etc…, but here’s a vid explaining the patch:

And here’s the patch:
patch.zip (55.9 KB)

If you have SP-Tools installed, all the audio files there will show up, which is handy as it works best with things that jump around spectrally a lot more.

So I ended up incorporating kurtosis as well, doing this:

  • Centroid - notch filter cutoff freq
  • Spread - q of notch filter
  • Skewness - tilt up or down (centered on centroid cutoff freq)
  • Rolloffpercent(5) - highpass set to freq
  • Rolloffpercent(95) - highshelf (or lowpass) set to freq, (kurtosis to highshelf gain)
  • Crest - balance between notch (centroid/spread) and broadband (highpass/lowpass) filters
  • Kurtosis - how much the main body of the filter is above the rolled off highs

Curious your thoughts on the sound, and from there, opinions on how to optimize things, as ideally it would all have signal-rate smoothing everywhere, but not sure how to do that with the vanilla biquad~s.

this is a great patch to share, thanks! A very bespoke mapping that fits well the task, I will road test it on cross-synthesis and see how it fares. Thanks for sharing!

1 Like

Yeah let me know how you get on with it. I tried testing it across a wide range of material (hence the SP-Tools examples). Will look into making more sensible versions of the filters with proper smoothing etc…

Actually here’s a slight tweak to the patch that also incorporates the melband->cross filter thing I’m doing now.

Archive.zip (79.6 KB)

The phase fuckery of 40 cascaded cross~ filters is definitely apparent in this context!

1 Like

p.s.
Need to replace this abstraction as the other one wasn’t thread safe (leading to some crashes).

dk.spectralshapeframe.maxpat.zip (9.4 KB)

(I do a thing where I switch @blocking modes after the first bang, but this version missed some connections and was sending high-priority stuff into @blocking 1 stuff)

Not ideal, but probably shouldn’t crash.

Here’s a crash report.
bufstats crash.zip (38.4 KB)

1 Like

2 posts were split to a new topic: Crash in fluid.bufstats