Re: [chuck-users] FFT Convolution and CPU Load
Hum…. Just checked my example and my CPU went from 7% to 11% when I kicked on the FFTConvolve.ck program you cite. We can’t see all your code, so not sure what’s going on. Are you updating really often, like advancing time every sample or something? PRC
On Sep 22, 2015, at 9:00 AM, chuck-users-request@lists.cs.princeton.edu wrote:
// FFT convolution with static impulse response // by Perry R. Cook, November 2014 // upsides: as efficient as it could be, save for // constructing a specific fft convolution chugin // downsides: minimum delay is length of impulse response + buffers // fix: break into pieces and overlap add // Other fix: see filter version using my FIR Filter chugin
// our fixed convolution kernal (impulse response) SndBuf s => FFT ffth => blackhole; "CelloBodyShort.wav" => s.read; // whatever you like (caution of length!!) 2 => int fftSize; while (fftSize < s.samples()) 2 *=> fftSize; // next highest power of two fftSize => int windowSize; // this is windowsize, only apply to signal blocks windowSize/2 => int hopSize; // this can any whole fraction of windowsize 2 *=> fftSize; // zero pad by 2x factor (for convolve) // our input signal, replace adc with anything you like adc => Gain input => FFT fftx => blackhole; // input signal IFFT outy => dac; // our output fftSize => ffth.size => fftx.size => outy.size; // sizes Windowing.hann(windowSize) => fftx.window; // <<< s.samples(), fftSize >>>; windowSize::samp => now; // load impulse response into h ffth.upchuck() @=> UAnaBlob H; // spectrum of fixed impulse response s =< ffth =< blackhole; // don't need impulse resp signal anymore
complex Z[fftSize/2]; 1000 => input.gain; // fiddle with this how you like/need
while (true) { fftx.upchuck() @=> UAnaBlob X; // spectrum of input signal
// multiply spectra bin by bin (complex for free!): for(0 => int i; i < fftSize/2; i++ ) { fftx.cval(i) * H.cval(i) => Z[i]; } outy.transform( Z ); // take ifft hopSize :: samp => now; // and do it all again }
Dear Perry, Thanks very much for the response and for testing the program performance. I am certainly running much much more than the convolution process. I'm not advancing time every sample but I am sending and receiving Events at a fundamental frequency (every 6 - 15 kHz depending on the configuration) however, I would not expect this to take over the system performance. I mentioned previously that running my program without the convolution function took the JACK DSP Load from about 2.5% to about 3.5%. After further tests I've found that the sample size, the equivalent to "CelloBodyShort.wav", has very big impacts on the performance. A sample size of 8KB or about 160ms raises the JACK DSP Load to about 30%. A sample size of between 16KB or about 320ms raises the JACK DSP Load to over 60%. And finally a sample size above 16KB pushes the DSP Load to 100% with lots of Xruns. Is this consistent with your measurements? I am now running the convolution process and my CPU usage is around 8.5% with the JACK DSP Load running at about 35%. So it appears that my problem is more around the performance of JACK. I'll keep testing. I'd like to run much longer samples than 320ms. Regards, Mitch
From: prc@CS.Princeton.EDU Date: Wed, 23 Sep 2015 14:15:13 -0700 To: chuck-users@lists.cs.princeton.edu Subject: Re: [chuck-users] FFT Convolution and CPU Load
Hum….
Just checked my example and my CPU went from 7% to 11% when I kicked on the FFTConvolve.ck program you cite. We can’t see all your code, so not sure what’s going on. Are you updating really often, like advancing time every sample or something?
PRC
On Sep 22, 2015, at 9:00 AM, chuck-users-request@lists.cs.princeton.edu wrote:
// FFT convolution with static impulse response // by Perry R. Cook, November 2014 // upsides: as efficient as it could be, save for // constructing a specific fft convolution chugin // downsides: minimum delay is length of impulse response + buffers // fix: break into pieces and overlap add // Other fix: see filter version using my FIR Filter chugin
// our fixed convolution kernal (impulse response) SndBuf s => FFT ffth => blackhole; "CelloBodyShort.wav" => s.read; // whatever you like (caution of length!!) 2 => int fftSize; while (fftSize < s.samples()) 2 *=> fftSize; // next highest power of two fftSize => int windowSize; // this is windowsize, only apply to signal blocks windowSize/2 => int hopSize; // this can any whole fraction of windowsize 2 *=> fftSize; // zero pad by 2x factor (for convolve) // our input signal, replace adc with anything you like adc => Gain input => FFT fftx => blackhole; // input signal IFFT outy => dac; // our output fftSize => ffth.size => fftx.size => outy.size; // sizes Windowing.hann(windowSize) => fftx.window; // <<< s.samples(), fftSize >>>; windowSize::samp => now; // load impulse response into h ffth.upchuck() @=> UAnaBlob H; // spectrum of fixed impulse response s =< ffth =< blackhole; // don't need impulse resp signal anymore
complex Z[fftSize/2]; 1000 => input.gain; // fiddle with this how you like/need
while (true) { fftx.upchuck() @=> UAnaBlob X; // spectrum of input signal
// multiply spectra bin by bin (complex for free!): for(0 => int i; i < fftSize/2; i++ ) { fftx.cval(i) * H.cval(i) => Z[i]; } outy.transform( Z ); // take ifft hopSize :: samp => now; // and do it all again }
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
participants (2)
-
Mitch Kaufman
-
Perry Cook