I've succeded in implementing the uniformly partitioned convolution algorithm and now I'm looking to implement the non-uniformly partitioned version. I've had no luck with running parallel threads on JACK audio connection kit, so I'm now shooting for a single thread implementation. The somewhat obvious solution would be to create two input buffers to work at different frequencies (meaning that one runs every 128 samples and the other one runs every 1024 samples, for example) but this will mean that the processor load will spike when both buffers are filled up. This problem is described here (page 162).
How would we go about scheduling the sub-convolutions in a single thread process so that the DSP load remains constant? Here is the starting code I'm using for the UPOLS convolution. It gives me about 10% DSP load with a 2048 samples long IR at a 48000hz sampling rate, so there's no way I can run a 2 second long IR with it. Any help (even if it's only optimizing the UPOLS code) will be greatly appreciated.
int jack_callback (jack_nframes_t nframes, void *arg){
jack_default_audio_sample_t *in, *out;
int i, j, k;
in = (jack_default_audio_sample_t *)jack_port_get_buffer (input_port, nframes);
out = (jack_default_audio_sample_t *)jack_port_get_buffer (output_port, nframes);
for (i = 0; i < nframes; i++){
// nframes come in and are then saved in the right part of the input buffer
buffer[nframes + i] = in[i];
i_time[i] = buffer[i];
i_time[nframes+i] = buffer[nframes+i];
}
// take the FFT of the input:
fftw_execute(i_forward);
// circular shift of the frequency delay line:
for (i = 0; i < two_nframes; i++){
for (k = partitions - 1; k > 0; k--){
fdl[k][i] = fdl[k-1][i];
}
}
// write the most recent FFT to the first slot of the FDL,
// reset o_fft to zero to erase the previous calculations
for (i = 0; i < two_nframes; i++){
fdl[0][i] = i_fft[i];
o_fft[i] = 0.0 + I*0.0;
}
// multiply-add the frequency domain line (fdl) with
// the frequency domain ir partitions (fir)
for (i = 0; i < two_nframes; i++){
for (k = 0; k < partitions; k++){
o_fft[i] += fdl[k][i] * fir[k][i];
}
}
// take the ifft.
fftw_execute(o_inverse);
// output the right half of the ifft, discard the rest.
for (i = 0; i < nframes; i++){
out[i] = vol*creal(o_time[nframes+i])/two_nframes;
// shift the input buffer to the left.
buffer[i] = in[i];
}
return 0;
}