HydrogenAudio

Hydrogenaudio Forum => Scientific Discussion => Topic started by: jrp on 2006-04-01 11:44:02

Title: FIR filter gain determination
Post by: jrp on 2006-04-01 11:44:02
I would like to be able to determine the best gain value for a FIR filter, so that if you apply it to a signal (ie, by convolution) in the [-1,1] range, you get a signal in the [-1,1] range.  (Assume that the signal is music.)

There seem to be several possible approaches:

Peak gain:

If the FIR coefficients are h0, h1, h2, ..., hN-1  then the sum of the absolute values of the coefficients will give an upper bound of applying the filter to [-1,1], so scaling the input by it's reciprocal should keep you within limits.  It is, however, a very conservative limit.

DC gain:

If the input signal is a constant 1, then the DC gain is just the sum of the coefficients.  Seems to be of limited application.

"AC gain":

If you take the Fourier Transform of the FIR to get a set of (complex) coefficients (Hi) then the maximum absolute value of the real part of the Hi (ie, the amplitude, as opposed to the complex part, which corresponds to phase) produces another limit.  What are the circumstances under which this is determines a useful gain limit?

"Gain to noise:"

SUM( hi^2) / N


"RMS gain":

This limit is just SQRT(SUM( Re(Hi)^2 + Im(Hi)^2)).  Again, under what circumstances is does this determine a useful limit?

"White Noise gain":

Applying the FIR filter to some White Noise and using maximum of the output as an indicator.  I don't know what the theory behind this is, but presumably it is based on the observation that white noise contains signals of a wide range of frequencies.  Does it matter whether the noise is generated from a uniform [-1,1] distribution or does it have to be gaussian/normal?


Can anyone provide any pointers to which methods work best under what circumstances?  Thanks
Title: FIR filter gain determination
Post by: benski on 2006-04-01 18:56:46
The gain will always be the sum of the absolute value of the coefficients.  It is best to normalize the FIR to a 0dB gain (coefficients sum to 1) to prevent anything unexpected.

You won't ever know the "realized gain" because it highly dependent on what your input signal is.  If your signal has frequencies where your poles are, you'll see much higher gain (for example) then one without any frequencies there at all.  So it all depends on the application and your expected input.
Title: FIR filter gain determination
Post by: jrp on 2006-04-01 19:54:47
Thanks.  I feared that this might be the case.

What if I know the sample rate (eg, 44.1kHz) or the max and min frequency (20Hz-20kHz, say) will that provide me with a more accurate fix on the maximum gain?
Title: FIR filter gain determination
Post by: Woodinville on 2006-04-03 19:43:38
Quote
The gain will always be the sum of the absolute value of the coefficients.   It is best to normalize the FIR to a 0dB gain (coefficients sum to 1) to prevent anything unexpected.

You won't ever know the "realized gain" because it highly dependent on what your input signal is.  If your signal has frequencies where your poles are, you'll see much higher gain (for example) then one without any frequencies there at all.  So it all depends on the application and your expected input.
[a href="index.php?act=findpost&pid=377889"][{POST_SNAPBACK}][/a]



Oeeerrr. If you have "poles" in your FIR filters, ....

Obviously the biggest value you can get out of the FIR filter is the sum of the absolute values of the coef's. That corresponds to a signal that is +- 1 using the same sign as the coef's.

This may be a very unusual sort of signal, though. Very few signals can be created like that inside a sampled system, except synthetically.  Consider what the input to the anti-aliasing filter would have to be to make that happen, eh?
Title: FIR filter gain determination
Post by: jrp on 2006-04-03 20:06:57
Yes. That is really why I am asking whether there are other ways of calculating the gain that might provide more realistic limits.
Title: FIR filter gain determination
Post by: Woodinville on 2006-04-03 20:47:58
Quote
Yes. That is really why I am asking whether there are other ways of calculating the gain that might provide more realistic limits.
[a href="index.php?act=findpost&pid=378665"][{POST_SNAPBACK}][/a]



Well, for a constant-delay filter (symmetric, antisymmetric for HP) you might consider the implications of constant-delay and an FFT that never goes above '1', yes, say even when analysed on a much finer grid than the length of the filter?
Title: FIR filter gain determination
Post by: jrp on 2006-04-03 22:08:02
Sorry. Don't understand. HP?

Suppose I am just using room impulse response filters, or high/low pass filters, eg?
Title: FIR filter gain determination
Post by: SebastianG on 2006-04-04 08:51:57
You could "normalize" the impulse response by scaling it so that the sum of the squared impulse response's samples equals one. AFAIK this is what the convolver plugin for Foobar optionally does. It also lets you adjust the gain by a slider since the "normalizing" approach might produce clipping.

Instead of applying the filter on white noise you could do a little math. If the samples of your noise generator are IID (independant and identically distributed => white) and the distribution is known you can easily derive a PDF for the convoluted signal's samples and calculate for a given probability p a certain level so that a sample exceeds this level with a probability of p. Your "peak gain" approach is a special case of this (p=0, full scale noise). To be less paranoid set p to, say, 0.05 ...

One might want to do this with pink noise since it better matches signal properties of natural audio. But the whole computation gets trickier because the pink noise signal is correlated.

Try this: Generate some pink noise (say, one second) apply the filter and compute the samples' standard deviation. Use a certain multiple of this standard deviation as an approximation of a "peak". Assuming that the convoluted signal's samples are approximately gaussian distributed (not 100% correct) you can choose a factor of 3 to get a level that is not exceeded with a probability of 99.6% (on a per sample basis) for example.

edit: I just realized this can be done quite efficiently If you work solely in the frequency domain. Multiply the filter's amplitude response A:frequency->amplitude with a curve P:frequency->amplitude that matches the spectral envelope of pink noise: R(f) = A(f)*P(f) and compute sqrt(int(R^2(f), f=0..pi)). Multiplied with a certain factor you have to choose this will give you your "peak". (Easy implementation: Start with an FFT on the impulse response to get a frequency discrete amplitude response and integrate by accumulating the squares after weighting.)

HTH,
Sebi
Title: FIR filter gain determination
Post by: jrp on 2006-04-04 19:27:16
Quote
(Easy implementation: Start with an FFT on the impulse response to get a frequency discrete amplitude response and integrate by accumulating the squares after weighting.)
[a href="index.php?act=findpost&pid=378879"][{POST_SNAPBACK}][/a]


Let's see if I have understood this correctly:

If the FFT of the hi (real) are Hi (complex)

then the convolution scaling factor should X / (sum (Re Hi^2))

How does X relate to the degree of certainty that I am looking for?  Or have I got the wrong end of the stick?
Title: FIR filter gain determination
Post by: SebastianG on 2006-04-05 21:51:49
The FFT without the weighting step is of no use. Also don't forget the square root. This is what I meant:

Suppose hi is the time domain impulse response, Hi = fft(hi,fftSize) (zeropadding to fftSize samples) and weights is a weighting vector of the same dimension fftSize. Then your scaling would be:

max_value_allowed/(X*std_dev_estimated)  where  std_dev_estimated := sqrt( sum( (abs(Hi).*weights).^2 ) ) / fftSize

(Matlab notation, ".*" and ".^" are "component-wise" operators)
If I'm correct with all the scaling involved (not sure!) std_dev_estimated will be an estimate for the convolved signal's samples deviation from zero (a.k.a. the the square root of the distribution's 2nd moment). Assuming a gaussian sample value distribution X can be chosen so that the probability of a sample value not exceeding a certain level is your desired certainty. For example:
X=1 => probability of a abs(some_sample)<max_value_allowed is around 66 %
X=2 => probability of a abs(some_sample)<max_value_allowed is around 95 %
X=3 => probability of a abs(some_sample)<max_value_allowed is around 99.6 %
(certainty can be computed via integrating a zero-mean & unit-deviation gaussian PDF from -X to X)

The weights should reflect the sound's level and coloration you work with (like pink for example). They can be attained for example by computing sqrt(2).*|fft(hann_windowing(fftSize samples of pink noise))|.

HTH,
Sebi
Title: FIR filter gain determination
Post by: jrp on 2006-04-05 23:10:45
The mists are clearing:

I assume that

std_dev_estimated := sqrt( 2 * sum( (Re(Hi)^2 + Im(Hi)^2).* weightsi^2) ) ) / fftSize

Turning to the calculation of the weights:

I need to calculate a [hanning] window of fftSize using something like

void clDSPOp::WinHanning (float *fpDest, long fftSize )
{
    long lLoopCntr;

    for (lLoopCntr = 0L; lLoopCntr < fftSize ; lLoopCntr++)
    {
        fpDest[lLoopCntr] = 0.5F -
            0.5F * cos((2.0F * fPI * (float) lLoopCntr) / (float) fftSize );
    }
}

multiply fpDest by the relevant random samples, take the FFT and sqrt(Re^2 + Im^2) to get the real weights.

Is that right?  Thanks for bearing with me.