11#include " recorder.h"
22
33#include < config.h>
4+ #include < gnuradio/analog/agc2_cc.h>
45#include < gnuradio/blocks/complex_to_interleaved_char.h>
56#include < gnuradio/blocks/file_sink.h>
67#include < gnuradio/blocks/stream_to_vector.h>
8+ #include < gnuradio/filter/fir_filter.h>
9+ #include < gnuradio/filter/fir_filter_blk.h>
10+ #include < gnuradio/filter/firdes.h>
11+ #include < gnuradio/filter/freq_xlating_fir_filter.h>
12+ #include < gnuradio/filter/pfb_arb_resampler_ccf.h>
713#include < gnuradio/filter/rational_resampler.h>
814#include < gnuradio/zeromq/sub_source.h>
915#include < logger.h>
1319
1420constexpr auto LABEL = " recorder" ;
1521
22+ // most blocks based on
23+ // https://github.com/gqrx-sdr/gqrx/blob/master/src/applications/gqrx/receiver.cpp
24+
25+ Block buildDecimator (Frequency sampleRate, Frequency shift, int decim) {
26+ if (1 < decim) {
27+ const auto filter = gr::filter::freq_xlating_fir_filter_ccf::make (decim, {1 }, 0.0 , sampleRate);
28+ const auto outRate = sampleRate / decim;
29+ const auto lpf_cutoff = 120e3 ;
30+ filter->set_center_freq (shift);
31+ filter->set_taps (gr::filter::firdes::low_pass (1.0 , sampleRate, lpf_cutoff, outRate - 2 * lpf_cutoff, gr::fft::window::WIN_BLACKMAN_HARRIS));
32+ return filter;
33+ } else {
34+ auto shiftBlock = gr::blocks::rotator_cc::make ();
35+ shiftBlock->set_phase_inc (2 .0l * M_PIl * (static_cast <double >(shift) / static_cast <float >(sampleRate)));
36+ return shiftBlock;
37+ }
38+ }
39+
40+ Block buildResampler (Frequency inputRate, Frequency outputRate) {
41+ const auto rate = static_cast <double >(outputRate) / inputRate;
42+ const auto cutoff = rate > 1 .0f ? 0.4 : 0.4 * (double )rate;
43+ const auto trans_width = rate > 1 .0f ? 0.2 : 0.2 * (double )rate;
44+ const auto flt_size = 32 ;
45+ const auto d_taps = gr::filter::firdes::low_pass (flt_size, flt_size, cutoff, trans_width);
46+ auto resampler = gr::filter::pfb_arb_resampler_ccf::make (rate, d_taps, flt_size);
47+ resampler->set_output_multiple (4096 );
48+ return resampler;
49+ }
50+
1651Recorder::Recorder (const Config& config, const Device& device, const std::string& zeromq, Frequency sampleRate, const Recording& recording, std::function<void (const nlohmann::json&)> send)
1752 : m_config(config), m_sampleRate(sampleRate), m_recording(recording), m_send(send), m_tb(gr::make_top_block(" recorder" )), m_connector(m_tb) {
1853 Logger::info (
@@ -26,18 +61,14 @@ Recorder::Recorder(const Config& config, const Device& device, const std::string
2661
2762 auto source = gr::zeromq::sub_source::make (sizeof (gr_complex), 1 , const_cast <char *>(zeromq.c_str ()));
2863 std::vector<Block> blocks;
29- m_shiftBlock = gr::blocks::rotator_cc::make ();
3064 blocks.push_back (source);
31- blocks.push_back (m_shiftBlock);
32-
33- Block lastResampler;
34- for (const auto & [factor1, factor2] : getResamplersFactors (m_sampleRate, m_recording.bandwidth , RESAMPLER_THRESHOLD)) {
35- Logger::debug (LABEL, " rational resampler factors: {}, {}" , colored (GREEN, " {}" , factor1), colored (GREEN, " {}" , factor2));
36- lastResampler = gr::filter::rational_resampler<gr_complex, gr_complex, gr_complex>::make (factor1, factor2);
37- blocks.push_back (lastResampler);
38- }
65+ const auto decim = std::max (1 , static_cast <int >(sampleRate / RECORDER_SAMPLE_RATE_DECIMATOR));
66+ blocks.push_back (buildDecimator (m_sampleRate, m_recording.shift (), decim));
67+ blocks.push_back (buildResampler (sampleRate / decim, m_recording.bandwidth ));
68+ auto raw = blocks.back ();
3969
4070 const auto samplesSize = roundUp (m_recording.bandwidth * RECORDER_FLUSH_INTERVAL.count () / 1000 , 4096 );
71+ blocks.push_back (gr::analog::agc2_cc::make (2e-3 , 2e-3 , 0.585 , 53 ));
4172 blocks.push_back (gr::blocks::complex_to_interleaved_char::make (true , 127.0 ));
4273 blocks.push_back (gr::blocks::stream_to_vector::make (sizeof (SimpleComplex), samplesSize));
4374 m_buffer = std::make_shared<Buffer<SimpleComplex>>(" RecorderBuffer" , samplesSize);
@@ -46,12 +77,11 @@ Recorder::Recorder(const Config& config, const Device& device, const std::string
4677
4778 if (config.dumpRecording ()) {
4879 const auto fileName = getRawFileName (config.workDir (), device, " recording" , " fc" , m_recording.recordingFrequency , m_recording.bandwidth );
49- m_connector.connect <Block>(lastResampler , gr::blocks::file_sink::make (sizeof (gr_complex), fileName.c_str ()));
80+ m_connector.connect <Block>(raw , gr::blocks::file_sink::make (sizeof (gr_complex), fileName.c_str ()));
5081 }
5182
5283 m_firstDataTime = getTime ();
5384 m_lastDataTime = m_firstDataTime;
54- m_shiftBlock->set_phase_inc (2 .0l * M_PIl * (static_cast <double >(-m_recording.shift ()) / static_cast <float >(m_sampleRate)));
5585 m_tb->start ();
5686}
5787
0 commit comments