#include "bench.h" #include "common/dsp/clock_recovery/clock_recovery_mm.h" #include "common/dsp/complex.h" #include "common/dsp/filter/fft_filter.h" #include "common/dsp/filter/fir.h" #include "common/dsp/filter/firdes.h" #include "common/dsp/path/splitter.h" #include "common/dsp/pll/costas_loop.h" #include "common/dsp/resamp/rational_resampler.h" #include "common/dsp/resamp/smart_resampler.h" #include "common/dsp/utils/agc.h" #include "common/dsp/utils/freq_shift.h" #include "dsp/agc/agc.h" #include "dsp/agc/agc_fast.h" #include "dsp/clock_recovery/clock_recovery_mm.h" #include "dsp/clock_recovery/clock_recovery_mm_fast.h" #include "dsp/clock_recovery/simple_gardner_recovery.h" #include "dsp/clock_recovery/simple_zc_recovery.h" #include "dsp/ddc/fft_ddc.h" #include "dsp/filter/fft.h" #include "dsp/filter/fir.h" #include "dsp/path/splitter.h" #include "dsp/pll/costas.h" #include "dsp/pll/costas_fast.h" #include "dsp/utils/freq_shift.h" #include "helpers.h" #include "logger.h" namespace satdump { namespace ndsp { std::vector getBenchCategories() { return { "fft_ddc", // "simple_gardner", // "simple_zero_crossing", // "agc", // "costas", // "rrc", // "mm_recovery", // "splitter", // "freq_shift", // "resamplers", // }; } bool catReq(std::vector &cats, std::string cat) { if (cats.size() == 0) return true; for (auto &c : cats) if (c == cat) return true; return false; } std::vector runBenchmarks(std::vector cats) { std::vector res; if (catReq(cats, "fft_ddc")) { logger->debug("Benchmarking FFT DDC..."); for (int decim : {2, 8, 16, 32, 50, 64, 128, 256}) { auto p = std::make_shared(); p->set_cfg("frequency", 100e6); p->set_cfg("samplerate", 6e6); p->add_output("out1", 101e6, 200e3, decim); auto r = benchmarkNDSPBlock(p, 10, "FFT DDC, 1 output, decim " + std::to_string(decim), decim); res.push_back(r); } } if (catReq(cats, "simple_gardner")) { logger->debug("Benchmarking Simple Gardner Recovery..."); for (float v : {1.2, 2.0, 3.0, 40.}) { auto p = std::make_shared(); p->set_cfg("sps", v); auto r = benchmarkNDSPBlock(p, 10, "Simple Gardner Recovery, omega " + std::to_string(v)); res.push_back(r); } } if (catReq(cats, "simple_zero_crossing")) { logger->debug("Benchmarking Simple Zero Crossing Recovery..."); for (float v : {1.2, 2.0, 3.0, 40.}) { auto p = std::make_shared(); p->set_cfg("sps", v); auto r = benchmarkNDSPBlock(p, 10, "Simple Zero Crossing Recovery, omega " + std::to_string(v)); res.push_back(r); } } if (catReq(cats, "agc")) { logger->debug("Benchmarking AGC..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::AGCBlock, 10, "AGC, Default", 1.0, /**/ 0.01, 1.0, 1.0, 65535); { auto p = std::make_shared>(); p->p_rate = 0.01; p->p_reference = 1.0; p->p_gain = 1.0; p->p_max_gain = 65535; auto r = benchmarkNDSPBlock(p, 10, "AGC, New"); res.push_back(r); } { auto p = std::make_shared>(); p->p_rate = 0.01; p->p_reference = 1.0; p->p_gain = 1.0; p->p_max_gain = 65535; auto r = benchmarkNDSPBlock(p, 10, "AGC Fast, New"); res.push_back(r); } } if (catReq(cats, "costas")) { logger->debug("Benchmarking Costas Loop..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::CostasLoopBlock, 10, "Costas Loop, Order 2", 1.0, /**/ 0.02, 2); benchmarkLegacyBlock(complex_t, complex_t, dsp::CostasLoopBlock, 10, "Costas Loop, Order 4", 1.0, /**/ 0.02, 4); benchmarkLegacyBlock(complex_t, complex_t, dsp::CostasLoopBlock, 10, "Costas Loop, Order 8", 1.0, /**/ 0.02, 8); for (int v : {2, 4, 8}) { auto p = std::make_shared(); p->set_cfg("order", v); auto r = benchmarkNDSPBlock(p, 10, "Costas Loop New, Order " + std::to_string(v)); res.push_back(r); } for (int v : {2, 4, 8}) { auto p = std::make_shared(); p->set_cfg("order", v); auto r = benchmarkNDSPBlock(p, 10, "Costas Loop Fast New, Order " + std::to_string(v)); res.push_back(r); } } if (catReq(cats, "rrc")) { logger->debug("Benchmarking FIR RRC..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::FIRBlock, 10, "FIR RRC, 31 taps, omega 2.0", 1.0, /**/ dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 31)); benchmarkLegacyBlock(complex_t, complex_t, dsp::FIRBlock, 10, "FIR RRC, 361 taps, omega 2.0", 1.0, /**/ dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 361)); benchmarkLegacyBlock(complex_t, complex_t, dsp::FFTFilterBlock, 10, "FFT RRC, 31 taps, omega 2.0", 1.0, /**/ dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 31)); benchmarkLegacyBlock(complex_t, complex_t, dsp::FFTFilterBlock, 10, "FFT RRC, 361 taps, omega 2.0", 1.0, /**/ dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 361)); { auto p = std::make_shared>(); p->p_taps = dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 31); auto r = benchmarkNDSPBlock(p, 10, "FIR New RRC, 31 taps, omega 2.0"); res.push_back(r); } { auto p = std::make_shared>(); p->p_taps = dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 361); auto r = benchmarkNDSPBlock(p, 10, "FIR New RRC, 361 taps, omega 2.0"); res.push_back(r); } { auto p = std::make_shared>(); p->p_taps = dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 31); auto r = benchmarkNDSPBlock(p, 10, "FFT New RRC, 31 taps, omega 2.0"); res.push_back(r); } { auto p = std::make_shared>(); p->p_taps = dsp::firdes::root_raised_cosine(1.0, 2, 1, 0.35, 361); auto r = benchmarkNDSPBlock(p, 10, "FFT New RRC, 361 taps, omega 2.0"); res.push_back(r); } } if (catReq(cats, "mm_recovery")) { logger->debug("Benchmarking MM Recovery..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::MMClockRecoveryBlock, 10, "MM Recovery, omega 1.2", 1.0, /**/ 1.2, 0.1, 0.5, 0.01, 0.01); benchmarkLegacyBlock(complex_t, complex_t, dsp::MMClockRecoveryBlock, 10, "MM Recovery, omega 2.0", 1.0, /**/ 2.0, 0.1, 0.5, 0.01, 0.01); benchmarkLegacyBlock(complex_t, complex_t, dsp::MMClockRecoveryBlock, 10, "MM Recovery, omega 3.0", 1.0, /**/ 3.0, 0.1, 0.5, 0.01, 0.01); for (float v : {1.2, 2.0, 3.0}) { auto p = std::make_shared>(); p->set_cfg("omega", v); auto r = benchmarkNDSPBlock(p, 10, "MM NEW Recovery, omega " + std::to_string(v)); res.push_back(r); } for (float v : {1.2, 2.0, 3.0}) { auto p = std::make_shared>(); p->set_cfg("omega", v); auto r = benchmarkNDSPBlock(p, 10, "MM NEW Recovery Fast, omega " + std::to_string(v)); res.push_back(r); } } if (catReq(cats, "splitter")) { logger->debug("Benchmarking Splitter (1 out)..."); // benchmarkLegacyBlock(complex_t, complex_t, dsp::SplitterBlock, 10, "Freq Shift, Default", 1.0); { auto p = std::make_shared>(); p->set_cfg("noutputs", 1); auto r = benchmarkNDSPBlock(p, 10, "Splitter, New"); res.push_back(r); } } if (catReq(cats, "freq_shift")) { logger->debug("Benchmarking Freq Shift..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::FreqShiftBlock, 10, "Freq Shift, Default", 1.0, /**/ 1e6, 100e3); { auto p = std::make_shared(); p->set_cfg("samplerate", 1e6); p->set_cfg("freq_shift", 100e3); auto r = benchmarkNDSPBlock(p, 10, "Freq Shift, New"); res.push_back(r); } } if (catReq(cats, "resamplers")) { logger->debug("Benchmarking Resamplers..."); benchmarkLegacyBlock(complex_t, complex_t, dsp::SmartResamplerBlock, 10, "Smart Resampler, Dec 10", 10.0, /**/ 1, 10); benchmarkLegacyBlock(complex_t, complex_t, dsp::SmartResamplerBlock, 10, "Smart Resampler, Dec 100", 100.0, /**/ 1, 100); benchmarkLegacyBlock(complex_t, complex_t, dsp::RationalResamplerBlock, 10, "Polyphase Resampler, Dec 10", 10.0, /**/ 1, 10); benchmarkLegacyBlock(complex_t, complex_t, dsp::RationalResamplerBlock, 10, "Polyphase Resampler, Dec 100", 100.0, /**/ 1, 100); } return res; } } // namespace ndsp } // namespace satdump