FFT into filter problem

Hi,
I am getting clicks when using the following code: (sounds like the filter blowing)

~synth = { Saw.ar(110) };
~fftSynth = { |input|
    var chain;
    chain = FFT( LocalBuf(2048), input );
    chain = PV_BinScramble( chain, 0.6, 0.5, 0 );
    IFFT( chain );
};
~filterSynth = { |into| LPF.ar(into,440) };

SynthDef(\test, { |out, gate=1|
    var synth, fftSynth, filterSynth;
    synth = ~synth.value;
    fftSynth = ~fftSynth.value( synth );
    filterSynth = ~filterSynth.value( fftSynth );
    Out.ar(
        out,
        Pan2.ar(
            filterSynth *
                EnvGen.ar( 
                    Env.adsr(0.1,0.2,0.3,0.4),
                    gate,
                    doneAction:2
                ),
            0
        )
    );
}).add;

~bind = Pbind(
    \instrument, \test,
    \dur, 0.5
);

p = ~bind.play;
p.stop;

I have used this format to match that of a larger project.
Is there something wrong with the code /
is there a fix?

Thanks,
L.

Sounds fine to me. No clicks.

Sam

That’s strange, could it be because I’m using SC 3.8.0? I don’t have any problems putting the filter before the FFT…

Can anyone else reproduce this problem or is it just my system?

It also sounds fine to me.

I can’t see anything wrong with the code. You might verify the order of UGens – it should be like this.

SynthDescLib.at(\test).def.dumpUGens;

[ 0_Control, control, nil ]
[ 1_Saw, audio, [ 110 ] ]
[ 2_MaxLocalBufs, scalar, [ 1 ] ]
[ 3_LocalBuf, scalar, [ 1, 2048, 2_MaxLocalBufs ] ]
[ 4_FFT, control, [ 3_LocalBuf, 1_Saw, 0.5, 0, 1, 0 ] ]
[ 5_PV_BinScramble, control, [ 4_FFT, 0.6, 0.5, 0 ] ]
[ 6_IFFT, audio, [ 5_PV_BinScramble, 0, 0 ] ]
[ 7_LPF, audio, [ 6_IFFT, 440 ] ]
[ 8_EnvGen, audio, [ 0_Control[1], 1.0, 0.0, 1.0, 2, 0.0, 3, 2, -99, 1.0, 0.1, 5, -4.0, 0.3, 0.2, 5, -4.0, 0.0, 0.4, 5, -4.0 ] ]
[ 9_*, audio, [ 7_LPF, 8_EnvGen ] ]
[ 10_Pan2, audio, [ 9_*, 0, 1.0 ] ]
[ 11_Out, audio, [ 0_Control[0], 10_Pan2[0], 10_Pan2[1] ] ]

Which OS? At this point I can’t rule out that maybe some UGen is mis-compiled on one OS but not others.

It is very very strange that Saw → LPF → FFT → IFFT is OK for you while Saw → FFT → IFFT → LPF isn’t.

Can you also trace the synth, and post the output here?

a = Synth(\test);
a.trace;
a.release;

One thing to note with FFT is that IFFT output is delayed by the duration of one frame. This is unavoidable because IFFT can’t produce any output until an entire FFT frame has been collected. So the attack phase of your envelope is not controlling the onset:

(
a = {
	var sig = Saw.ar(440);
	var fft = FFT(LocalBuf(2048), sig);
	var ifft = IFFT(fft);
	var eg = EnvGen.kr(Env.linen(0.05, 0.2, 0.1), doneAction: 2);
	[sig, ifft, eg, ifft * eg]
}.plot(0.15);
)

But this shouldn’t produce clicks, because the sine windowing function applied in FFT and IFFT should produce a ~23 ms ramp up (half frame = 1024/44100 = ~23 ms).

hjh

I’m stuck on OSX 10.9.5 (SC 3.8.0) due to other hardware restrictions.

The order of UGens is the same.
If I trace the synth I get:

TRACE 1020  test    #units: 10
  unit 0 Control
    in
    out 0 1
  unit 1 Saw
    in 110
    out 0.255201
  unit 2 FFT
    in 16384 0.255201 0.5 0 1 0
    out -1
  unit 3 PV_BinScramble
    in -1 0.6 0.5 0
    out -1
  unit 4 IFFT
    in -1 0 0
    out -0.0199474
  unit 5 LPF
    in -0.0199474 440
    out 0.00859902
  unit 6 EnvGen
    in 1 1 0 1 2 0 3 2 -99 1 0.1 5 -4 0.3 0.2 5 -4 0 0.4 5 -4
    out 0.3
  unit 7 BinaryOpUgen
    in 0.00859902 0.3
    out 0.0025797
  unit 8 Pan2
    in 0.0025797 0 1
    out 0.00182413 0.00182413
  unit 9 Out
    in 0 0.00182413 0.00182413
    out

This must be the issue.
If I use:

EnvGen.ar( Env.dadsr(0.024,0.1,0.2,0.3,0.4), gate, doneAction:2 )

in the SynthDef, no clicks :slightly_smiling_face:

I could manage with this but is there a way to correct the issue at its source?

Many thanks,
L.

Well… no.

If you think the source is the fact that IFFT’s output is one frame later… it’s quite literally impossible to improve on the current situation. IFFT can’t produce any audio until it has a full FFT frame. FFT can’t produce a frame until it receives enough audio, and… this will always take longer than 0 samples. FFT cannot know the future.

Envelopes by definition start at the moment the gate is open. Imagine the possible complications of EnvGen magically guessing when a delay might be needed, and how long.

hjh

I thought maybe the FFT sine windowing function wasn’t working but I might be misunderstanding. I use dadsr envelopes anyway so that is fine for me…
Thanks again for your help.
ATB,
L.

Try explicitly setting the window type on the FFT and the IFFT. Maybe your build is set to rectangular window or something silly like that. Try it with a hann window with an overlap of 4 and see if that fixes it.

Sam

Oh OK! I thought you were talking about the delay.

I checked to see if there were old issues about FFT on Mac, but nothing like this.

Sam’s suggestion to set the window type explicitly is a good idea, at least for a test. If it makes a difference, then we have a better idea what the problem is.

hjh

Thanks.
I tried a few different settings but same issue. It’s just that 23ms at the start…