demantz / RFAnalyzer

Spectrum Analyzer for Android using the HackRF
GNU General Public License v2.0
858 stars 206 forks source link

[questions] Multirate decimation implementation #40

Open pavlus opened 7 years ago

pavlus commented 7 years ago

I'm now working on implementing multistage multirate decimator, decimation selection and factorization are almost ready, will commit them soon, but I need to clarify how your pipeline exactly works right now and how you see the way it should be implemented.

It's said, that current decimator works only for fixed input rate of 1Msps(https://github.com/demantz/RFAnalyzer/blob/master/app/src/main/java/com/mantz_it/rfanalyzer/Decimator.java#L47 https://github.com/demantz/RFAnalyzer/blob/master/app/src/main/java/com/mantz_it/rfanalyzer/Decimator.java#L138), but AFAIR, it works well with 2Msps stream recorded from HackRf, and there is a branch which checks if we need to apply second and third stages (https://github.com/demantz/RFAnalyzer/blob/master/app/src/main/java/com/mantz_it/rfanalyzer/Decimator.java#L195-L206), so I'm confused here.

Also I don't understand how exactly you are using Half band filters+FIR filter pipeline, are halfband filters used for actual decimation and FIR filter only for gain normalization?

I've also read your blog post http://tech.mantz-it.com/2014/10/performance-optimizations-of.html but still doesn't get it. How last pass FIR filter will get rid of aliasing after decimation, if aliased frequencies are already mixed in? Everywhere I've read about multistage decimation, It's said, that signal must be filtered first and then decimated, going form higher factors to lower.

Do you think it's possible to use current code base of half band filter and FIR filter to implement variable rate decimation, or you feel that some tweaks needed?

Maybe some nuances you know on these filter realizations that can introduce problems?

I understand, that this code was written two years ago and you may not really remember how it actually works and why you made some decisions, but how did you feel about it? as finished work or a temporary solution that should be rewritten in future with some kind of improvements?

I have time for work on it and want it to be compliant with your idea of how it should be implemented, so any suggestions, recommendations and workarounds are welcome.

UPD: groundwork on decimation factorization and output rate selection: https://github.com/pavlus/RFAnalyzer/commit/013b0bbe39b71eabf9081649a2d94863c5c5adc1#diff-ae773265f7d84a5ece96aa61d94a7f5a

demantz commented 7 years ago

Hi Pavlus, good to hear that you are working on this! I always wanted to refactor the decimation code to be more flexible and work with other input rates, but it's not easy and I never did.. Main problem I had was that the FIR filters are not really efficient as they are implemented now (in java, no vectoring like in GNU Radio with volk). That's why I decided to fix the input rate to 1MSps and build a rather static decimation chain from half-band filters. Turns out they aren't really that much more efficient as the plain FIR filters -.- so this is still not a good solution. I couldn't get it to work at higher sample rates on my old nexus 7 (2012). Maybe this can be improved by improving the filters (e.g. maybe use IIR filters?)

Now to you questions: The decimation chain supports two settings: 1MSps->250KSps (decimate by 4, used for wide band FM) and 1MSps->62500Sps (decimate by 16, used for AM, nFM and SSB). That's why you see this branch in the decimator: https://github.com/demantz/RFAnalyzer/blob/master/app/src/main/java/com/mantz_it/rfanalyzer/Decimator.java#L195-L206

In the first case I use one half band filter to decimate by 2 and then a FIR filter to decimate by 2 again and to correct the gain level. In the second case I use 3 half band filters (decimate by 2x2x2=8) and again a FIR filter to decimate by 2 and correct the gain level.

As stated above, I don't really like this design and wish it could be improved. However, I spend a lot of time back in 2014 to get the whole demodulation chain working on a nexus 7 (2012) and couldn't do it nicer. I started another project (https://github.com/demantz/android_dsp_lib) in order to make DSP more efficient on Android because of that. But the dsp lib using RenderScript turned out to be unstable and wouldn't work on all Android devices. Also the efficiency gain was not as high as expected, so the project stalls right now..

If you find a good solution to reduce the sample rate efficiently please let me know! I'm willing to help where I can! The performance issue with the filters is also what makes it difficult to implement some digital demodulation modes..

pavlus commented 7 years ago

After inspection of SSB demodulation code, which was very laggy, I've noticed, that it uses sideband suppression method with narrow transition filter, which had 181 taps(!!!) that's was the problem with it performance, and not actually filters code. By using other demodulation method performance of this demodulator can be improved a lot, other demodulators (except wbFM at maximum band) work well on my dual core 1,2 GHz Droid 3.

After hours spent on benchmarking I feel that actual decimation performance is very good and current FIR filters codebase is good for implementing multistage decimation if used carefully (by not letting them to have high taps count), but I'm still going to refactor filters and demodulator for more flexibility in the future.