[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[sc-users] FFT diff - a solution with a new UGen
Hi -
Having realised that my original strategy (of taking the FFT and then
trying to output from the FFT buffer without converting back to the
time domain first) doesn't fit with SC's way of doing FFT work, I've
written a UGen to do the job for me.
The idea is to find the 'distance' between two signals in terms of FFT
bin magnitudes, and then output that to the FFT buffer's DC component,
so that when IFFT is called we can get the result in the time domain:
void PV_DiffAndToDC_next(PV_Unit *unit, int inNumSamples)
{
PV_GET_BUF2
SCComplexBuf *p = ToComplexApx(buf1);
SCComplexBuf *q = ToComplexApx(buf2);
p->dc = sc_abs(p->dc - q->dc) + sc_abs(p->nyq - q->nyq);
p->nyq = 0.;
for (int i=0; i<numbins; ++i) {
float rdiff = p->bin[i].real - q->bin[i].real;
float idiff = p->bin[i].imag - q->bin[i].imag;
p->dc += sqrt(rdiff*rdiff + idiff*idiff);
p->bin[i].real = 0.;
p->bin[i].imag = 0.;
}
}
void PV_DiffAndToDC_Ctor(PV_Unit *unit)
{
SETCALC(PV_DiffAndToDC_next);
ZOUT0(0) = ZIN0(0);
}
I'm using it much like any other PV_ unit:
Server.default_(s = Server.internal.boot);
b = Buffer.alloc(s, 128, 1);
c = Buffer.alloc(s, 128, 1);
(
{
var chain1, chain2, chain, sig1, sig2;
sig1 = Pulse.ar(440, MouseX.kr(0.1, 0.9));
sig2 = Pulse.ar(440, MouseY.kr(0.1, 0.9));
chain1 = FFT(b.bufnum, sig1);
chain2 = FFT(c.bufnum, sig2);
chain = PV_DiffAndToDC(chain1, chain2);
[IFFT(chain), sig1+sig2];
}.play
)
s.scope;
It's crude (the output is artificially bumpy because of the windowing)
but it works for me. If it's useful for anyone else that'd be nice.
Best
Dan