Output range of fluid.nmfmatch~?

Unless I’m missing it, I can’t seem to find out what the output range of fluid.nmfmatch~ is. I would have thought normalized from 0. to 1. but that’s definitely not the case. It seems to be related to the FFT size (and not hop) but in a manner I’m not sure about.

Using the sine wave example from the fluid.nmfmatch~ helpfile having an FFT size of 1024 seems to give an output range of ~300, which I would expect is about the best it can be given that this is pure sine waves as the bases. Shrinking it down to an FFT of 512 gives me a range of ~155.

In both cases that seems to be about 30% of the FFT size, which seems like an odd amount.

Makes me think that the range would be something like 1/2 FFT size in a theoretically perfect context and the practical examples fall short of that, but I don’t see how pure sine wave input would be any more perfect.

Is there some other relationship here I’m missing?

Actually is there a weird not-zero-but-super-close-to-zero-ness to the output as well? zl change doesn’t seem to filter the output.

Even print-ing the output shows nothing but 0. 0. 0. s as well.

This is definitely the case but thankfully a round 0. after did the trick.

Still no idea about what the output range is supposed to be though.

I don’t think we ever worked out how to normalize the output range – it’s the strength of the activation that comes out of doing the NMF, which will indeed be affected by FFT settings etc., but is calculated on the basis of a matrix multiply with the bases, so it ends up being really hard to reason about. It’s a bit of a pain though, so warrants revisiting.

The not-quite-zero thing sounds like standard issue floating point horror: maybe using minimum to clip the lower bound of the list to something small before the zl change will help? Basically, equality tests against floating point numbers are fraught with peril…



Not really knowing what/how the matrix multiply factors into this, but would it be safe to assume that it won’t be less than zero and can’t be greater than the fft size (or 1/2 fft size)?

I’ve not done comprehensive testing on different kinds of material to see if this ~30% factor holds up, but I’d sooner have some kind of normalized (range) output even if it doesn’t always use the full range.

Adding round 0. seemed to work well enough (I didn’t know you could round 0.). I actually started by doing round 0.0000000000000001 sort of thing and it eventually “corrected” to just being round 0. and it had the same effect…

It certainly shouldn’t go below 0, but the maximum is hard to predict because it depends on the amplitudes of the bases across the whole spectrum. I feel like, for nmfmatch~ where the bases are fixed, we should in principle be able to work out what the maximum possible activations would be and derive a normalisation factor to apply.

Is that as simple as it sounds?

As in, flatten/dump all the bases (say for a @bases 3 instantiation, 3 channels of a buffer’s worth) and zl sum it?

Alas, I fear not. I had a quick look at the code, and it looks like a pen and paper (and an alert brain) job to figure it out.

1 Like


1 Like