[Clam-devel] overlap-save method, trying to apply a fir filter in realtime
Hernán Ordiales
h at ordia.com.ar
Tue Dec 4 16:30:32 PST 2007
hi all,
just as a proof of concept (or simple fun) i was trying to implent
this kind of processing:
given one audio input and one finite impulse response (fir filter)[1]
this processing should apply the IR to the input signal using the
overlap-save[2] method (in realtime, doing the convolution in the
spectral domain) given as output another audio signal. As you can
imagine, this could be very useful for a lot of things (it's already
implemented in somewhere? i did not find it)
i had to do all inside one processing because i need to perform FFT's
of different size of the input size (audio length) and remember "old"
data (previous function call) to fill it
well i have some questions related to this (please look between code
for better understanding):
first, some definitions:
L = 512; // input block length (fixed rigth now)
M = 64+1; // discard points (M = length (h) ) actually FIR filter
length ; L >> M
N = L+M-1; // processing block length (through FFT)
fft_size = 1024; // next power of two of N (fixed rigth now)
-> comment: rest of buffers init, size set and other configuration are
in the constructor
bool Do(const Audio& in, Audio& out)
{
int size = in.GetSize();
CLAM_DEBUG_ASSERT( size==L, "Input audio size different from expected" );
DataArray& inBlock_L = in.GetBuffer();
DataArray& outBlock_L = out.GetBuffer();
for ( int i=0; i<M-1; i++ )
{
mProcBuffer[i] = mBufferM[i]; //previous M buffer
//saving next block of M-1 points
mBufferM[i] = inBlock_L[ (L-(M-1)-1) + i ];
}
// adding new data to the process block
for ( int i=0; i<L; i++ )
mProcBuffer[ (M-1) + i ] = inBlock_L[i];
// zero padding until fill the fft_size
for ( int i=L; i<fft_size; i++ )
mProcBuffer[ i ] = 0.;
-> comment: (about these for's) AFAIK to perform this kind of
operation a memcpy should be better, don't? but this kind of thing
could be possible in CLAM? also AFAIK all data types in clam are
managed at the end with one std::vector and that's has dynamic
allocations (also AFAIK :-D) i mean not contiguos in memory... or
after a resize that could be guaranteed? i'm not sure about this issue
right now
(btw, i know "early optimizations are the root of all evil" but i
would like to know what do you think about this)
can/should i use std::copy or std:fill? could i break something with
something like this?
mFFT.Start();
mFFT.Do( mProcAudio, mProcSpecBuffer );
mFFT.Stop();
->comment: "Start()" "Stop()" how is working that? is really needed in NE?
// Y_m(k) = X_m(k)H(k)
// mSpecProduct.Do( mProcSpecBuffer, mImpulseResponseH, mOutSpecBuffer );
->comment: here i tried to use the SpectrumProduct clas, but i'm
getting: "SpectrumProduct::Do(): Not in execution mode" :-(
->comment: then i replaced it with this "in place" implementation of
the spectrum product:
Array<Complex>& outbuffer = mOutSpecBuffer.GetComplexArray();
Array<Complex>& in1specbuffer = mProcSpecBuffer.GetComplexArray();
Array<Complex>& in2specbuffer = mImpulseResponseH.GetComplexArray();
for (int i=0; i<fft_size/2+1; i++)
{
TData a = in1specbuffer[i].Real();
TData b = in1specbuffer[i].Imag();
TData c = in2specbuffer[i].Real();
TData d = in2specbuffer[i].Imag();
outbuffer[i].SetReal( a*c - b*d );
outbuffer[i].SetImag( a*d + b*c );
}
// mIFFT.Start();
// mIFFT.Do( mOutSpecBuffer, mOutAudio );
// mIFFT.Stop();
->comment: again "IFFT_fftw3: Do(): Not in execution mode" how can avoid this???
// discard first M-1 points
for ( int i=0; i<L; i++ )
outBlock_L[i] = mOutBuffer[ (M-1) + i ];
return true;
}
any kind of comments are welcome,
very thanks!
[1] right now is not defined how to load/setup this on the processing
[2] or overlap-add, right now i'm only implemented the first one
--
Hernán
http://h.ordia.com.ar
GnuPG: 0xEE8A3FE9
More information about the clam-devel
mailing list