Global/shared FFT Buffer


#1

Hello List!

I’m trying to figure out a way to share a global FFT Buffer between multiple synths. My goal is to have one synth which runs an FFT on some signal and to have other synths which do different PV_ manipulations in parallel (i.e. without modifying the global buffer).

So far I tried to use PV_Copy in the modifying synths (see code below)… but it doesn’t seem to work as expected — I think I’ve seen some examples doing just that but I can’t seem to find them

(~fftBuffer=Buffer.alloc(s,1024,bufnum:0);

// silently record some FFT data into ~fftBuffer 
{FFT(~fftBuffer,WhiteNoise.ar)}.play;

// then copy the same buffer, make an IFFT of the copy and play it
{
	var chain, localBuffer = LocalBuf(1024);
	chain = PV_Copy(~fftBuffer, localBuffer);
	Out.ar(0,IFFT(chain));
	// simply resynthesizing ~fftBuffer works...
	// Out.ar(0,IFFT(~fftBuffer));
}.play)

I’d be super happy about suggestions.
Cheers! :slight_smile:

Mac OS 10.13
SC 3.9.3


#2

The result of FFT in the SynthDef graph is iirc a trigger (specifying the buffer index) that fires every time a new chunk of FFT data is available. This trigger causes downstream UGens to process the new chunk of data. In your example case, ~fftBuffer is simply a buffer number but is not triggering in the way that I mentioned. I believe you CAN make this work, but you’ll need to find a way to share this trigger of your “global” FFT buffer. You might start with something like this:

~fftBuffer = Buffer.alloc(s, 1024);
~fftBus = Bus.audio(s, 1);

Ndef(\globalFFT, {
    var fft;
    fft = FFT(~fftBuffer, WhiteNoise.ar);
    Out.ar(~fftBus, fft);
});

Ndef(\childFFT, {
    var fft, sig;
    fft = InFeedback.ar(~fftBus, 1);
    sig = IFFT(fft);
    Out.ar(0, sig);
}).play;

Some caveats:

  • I haven’t tried this before, so you might encounter additional problems :slight_smile: - please report what you find, it could be helpful to others!
  • You don’t need to PV_Copy the fft buffer unless you’re modifying it. Obviously, it wouldn’t be so useful to use FFT if you were not modifying the signal somehow, so you probably need it - but if you were e.g. only displaying or analyzing the FFT data you wouldn’t need to copy.

#3

You are absolutely right Scott. The ‘FFT Overview’ Helpfile is quite clear about that.

The FFT UGen returns a signal (usually called chain) is constant at -1, only when a new FFT window starts, the signal equals the buffer number. This is how subsequent FFT UGens can write to that buffer and know when to do this.

FFT is returning a control rate signal - so the only thing missing to make this little snippet work is an K2A.ar

~fftBuffer = Buffer.alloc(s, 1024);
~fftBus = Bus.audio(s, 1);

Ndef(\globalFFT, {
    var fft;
    fft = FFT(~fftBuffer, WhiteNoise.ar);
    fft = K2A.ar(fft);
    Out.ar(~fftBus, fft);
}).play;

Ndef(\childFFT, {
    var fft, sig;
    fft = InFeedback.ar(~fftBus, 1);
    sig = IFFT(fft);
    Out.ar(0, sig);
}).play;

Thanks a lot for the clue!