Global/shared FFT Buffer

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

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.

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!