jgaeddert / liquid-dsp

digital signal processing library for software-defined radios
http://liquidsdr.org
MIT License
1.82k stars 426 forks source link

Question : using randricekf() for multi-path simulation #261

Open pfeatherstone opened 2 years ago

pfeatherstone commented 2 years ago

Currently, the channel object uses msequence to generate multipath filters:

https://github.com/jgaeddert/liquid-dsp/blob/f831b9565de57afcd9c78b5cb8143816d0002e51/src/channel/src/channel.c#L177-L187

You always get the same filter for a given number of taps. Can we use randricekf() to generate slightly "better" filters and make them different for any given number of taps?

If so, what are good values for _m, _K and _omega? Is there anything else to do other than call randricekf() N times for a multi-path filter of length N? For example set the first tap to 1.

I can foresee that people are going to say : "well it depends what you mean by better", "it depends on the environment", ... I just want to generate a wide range of multi-path filters.

jgaeddert commented 2 years ago

Right. I really need to use a proper random number generator. As you have guessed using a LFSR gives the same filter coefficients each time, but doesn't necessarily mean it's a representative channel.

The Rice-K random number generator is appropriate for fading amplitudes, but for the channel filter coefficients you probably would want something like a non-circular Gauss random variable. In fact, the Rice-K random variable is derived from the amplitude of adding two circular Gauss random variables with the same standard deviation, one of which has zero mean and the other is non-zero mean (where K is related to this value).

pfeatherstone commented 2 years ago

How do i generate a non-circular gauss random variable? Thanks

jgaeddert commented 2 years ago

Take a look at how Rice-K random numbers are generated below. Notice that "y" is a complex random variable with an offset "s" in its real component. Instead of using "cabs(y)" (the Rice random variable), you can just use "y" itself. I called this non-circular in my previous comment but it might be more appropriate to say "offset".

// Rice-K
float randricekf(float _K, float _omega)
{
    float complex x, y;
    float s = sqrtf((_omega*_K)/(_K+1));
    float sig = sqrtf(0.5f*_omega/(_K+1));
    crandnf(&x);
    y = _Complex_I*( crealf(x)*sig + s ) +
                   ( cimagf(x)*sig     );
    return cabsf(y);
}
pfeatherstone commented 2 years ago

Thanks a lot! What would be a good range of values for K and omega, or s and sigma ?

jgaeddert commented 2 years ago

K dictates the fading severity and indicates the linear ratio of the line-of-sight (LoS) component to all the multi-path components. So with as K approaches infinity, the channel approaches just the LoS component ("sig" -> 0). Omega is the signal power, IIRC.