diff options
-rw-r--r-- | doc/example.ini | 6 | ||||
-rw-r--r-- | src/DabMod.cpp | 11 | ||||
-rw-r--r-- | src/DabModulator.cpp | 4 | ||||
-rw-r--r-- | src/DabModulator.h | 4 | ||||
-rw-r--r-- | src/FIRFilter.cpp | 87 | ||||
-rw-r--r-- | src/FIRFilter.h | 11 | ||||
-rw-r--r-- | src/Utils.cpp | 1 |
7 files changed, 75 insertions, 49 deletions
diff --git a/doc/example.ini b/doc/example.ini index 6a4b0f4..8403e8f 100644 --- a/doc/example.ini +++ b/doc/example.ini @@ -114,10 +114,12 @@ dac_clk_rate=0 [firfilter] ; The FIR Filter can be used to create a better spectral quality. +enabled=1 + ; The filter taps can be calculated with the python script ; doc/fir-filter/generate-filter.py -enabled=0 -filtertapsfile=simple_taps.txt +; If filtertapsfile is not given, the default taps are used. +;filtertapsfile=simple_taps.txt [output] ; choose output: possible values: uhd, file, zmq diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 194c441..fc28218 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -423,14 +423,7 @@ int launch_modulator(int argc, char* argv[]) // FIR Filter parameters: if (pt.get("firfilter.enabled", 0) == 1) { - try { - filterTapsFilename = pt.get<std::string>("firfilter.filtertapsfile"); - } - catch (std::exception &e) { - std::cerr << "Error: " << e.what() << "\n"; - std::cerr << " Configuration enables firfilter, but does not specify filter taps file\n"; - throw std::runtime_error("Configuration error"); - } + filterTapsFilename = pt.get<std::string>("firfilter.filtertapsfile", "default"); } // Output options @@ -609,7 +602,7 @@ int launch_modulator(int argc, char* argv[]) // When using the FIRFilter, increase the modulator offset pipelining delay // by the correct amount - if (filterTapsFilename != "") { + if (not filterTapsFilename.empty()) { tist_delay_stages += FIRFILTER_PIPELINE_DELAY; } diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 927c7bd..6d22f2d 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -60,7 +60,7 @@ DabModulator::DabModulator( unsigned outputRate, unsigned clockRate, unsigned dabMode, GainMode gainMode, float& digGain, float normalise, - std::string& filterTapsFilename + const std::string& filterTapsFilename ) : ModCodec(ModFormat(1), ModFormat(0)), myOutputRate(outputRate), @@ -214,7 +214,7 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut) myNbSymbols, mySpacing, myNullSize, mySymSize); shared_ptr<FIRFilter> cifFilter; - if (myFilterTapsFilename != "") { + if (not myFilterTapsFilename.empty()) { cifFilter = make_shared<FIRFilter>(myFilterTapsFilename); rcs.enrol(cifFilter.get()); } diff --git a/src/DabModulator.h b/src/DabModulator.h index fb2d758..41fa42d 100644 --- a/src/DabModulator.h +++ b/src/DabModulator.h @@ -55,7 +55,7 @@ public: unsigned outputRate, unsigned clockRate, unsigned dabMode, GainMode gainMode, float& digGain, float normalise, - std::string& filterTapsFilename); + const std::string& filterTapsFilename); DabModulator(const DabModulator& other) = delete; DabModulator& operator=(const DabModulator& other) = delete; virtual ~DabModulator(); @@ -78,7 +78,7 @@ protected: EtiReader myEtiReader; Flowgraph* myFlowgraph; OutputMemory* myOutput; - std::string& myFilterTapsFilename; + std::string myFilterTapsFilename; tii_config_t& myTiiConfig; size_t myNbSymbols; diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp index 86f558b..7e6014c 100644 --- a/src/FIRFilter.cpp +++ b/src/FIRFilter.cpp @@ -2,8 +2,10 @@ Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Written by - 2012, Matthias P. Braendli, matthias.braendli@mpb.li + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://opendigitalradio.org This block implements a FIR filter. The real filter taps are given as floats, and the block can take advantage of SSE. @@ -34,6 +36,7 @@ #include <stdio.h> #include <stdexcept> +#include <array> #include <iostream> #include <fstream> #include <memory> @@ -46,6 +49,29 @@ using namespace std; #include <sys/time.h> +/* This is the FIR Filter calculated with the doc/fir-filter/generate-filter.py script + * with settings + * gain = 1 + * sampling_freq = 2.048e6 + * cutoff = 810e3 + * transition_width = 250e3 + * + * It is a good default filter for the common scenarios. + */ +static const std::array<float, 45> default_filter_taps({ + -0.00110450468492, 0.00120703084394, -0.000840645749122, -0.000187368263141, + 0.00184351124335, -0.00355578539893, 0.00419321097434, -0.00254214904271, + -0.00183473504148, 0.00781436730176, -0.0125957569107, 0.0126200336963, + -0.00537294941023, -0.00866683479398, 0.0249746385962, -0.0356550291181, + 0.0319730602205, -0.00795613788068, -0.0363943465054, 0.0938014090061, + -0.151176810265, 0.193567320704, 0.791776955128, 0.193567320704, + -0.151176810265, 0.0938014090061, -0.0363943465054, -0.00795613788068, + 0.0319730602205, -0.0356550291181, 0.0249746385962, -0.00866683479398, + -0.00537294941023, 0.0126200336963, -0.0125957569107, 0.00781436730176, + -0.00183473504148, -0.00254214904271, 0.00419321097434, -0.00355578539893, + 0.00184351124335, -0.000187368263141, -0.000840645749122, 0.00120703084394, + -0.00110450468492}); + void FIRFilterWorker::process(struct FIRFilterWorkerData *fwd) { size_t i; @@ -238,7 +264,7 @@ void FIRFilterWorker::process(struct FIRFilterWorkerData *fwd) } -FIRFilter::FIRFilter(std::string& taps_file) : +FIRFilter::FIRFilter(const std::string& taps_file) : ModCodec(ModFormat(sizeof(complexf)), ModFormat(sizeof(complexf))), RemoteControllable("firfilter"), myTapsFile(taps_file) @@ -257,37 +283,44 @@ FIRFilter::FIRFilter(std::string& taps_file) : worker.start(&firwd); } -void FIRFilter::load_filter_taps(std::string tapsFile) +void FIRFilter::load_filter_taps(const std::string &tapsFile) { - std::ifstream taps_fstream(tapsFile.c_str()); - if(!taps_fstream) { - fprintf(stderr, "FIRFilter: file %s could not be opened !\n", tapsFile.c_str()); - throw std::runtime_error("FIRFilter: Could not open file with taps! "); + std::vector<float> filter_taps; + if (tapsFile == "default") { + std::copy(default_filter_taps.begin(), default_filter_taps.end(), + std::back_inserter(filter_taps)); } - int n_taps; - taps_fstream >> n_taps; + else { + std::ifstream taps_fstream(tapsFile.c_str()); + if(!taps_fstream) { + fprintf(stderr, "FIRFilter: file %s could not be opened !\n", tapsFile.c_str()); + throw std::runtime_error("FIRFilter: Could not open file with taps! "); + } + int n_taps; + taps_fstream >> n_taps; - if (n_taps <= 0) { - fprintf(stderr, "FIRFilter: warning: taps file has invalid format\n"); - throw std::runtime_error("FIRFilter: taps file has invalid format."); - } + if (n_taps <= 0) { + fprintf(stderr, "FIRFilter: warning: taps file has invalid format\n"); + throw std::runtime_error("FIRFilter: taps file has invalid format."); + } - if (n_taps > 100) { - fprintf(stderr, "FIRFilter: warning: taps file has more than 100 taps\n"); - } + if (n_taps > 100) { + fprintf(stderr, "FIRFilter: warning: taps file has more than 100 taps\n"); + } - fprintf(stderr, "FIRFilter: Reading %d taps...\n", n_taps); + fprintf(stderr, "FIRFilter: Reading %d taps...\n", n_taps); - std::vector<float> filter_taps(n_taps); + filter_taps.resize(n_taps); - int n; - for (n = 0; n < n_taps; n++) { - taps_fstream >> filter_taps[n]; - PDEBUG("FIRFilter: tap: %f\n", filter_taps[n] ); - if (taps_fstream.eof()) { - fprintf(stderr, "FIRFilter: file %s should contains %d taps, but EOF reached "\ - "after %d taps !\n", tapsFile.c_str(), n_taps, n); - throw std::runtime_error("FIRFilter: filtertaps file invalid ! "); + int n; + for (n = 0; n < n_taps; n++) { + taps_fstream >> filter_taps[n]; + PDEBUG("FIRFilter: tap: %f\n", filter_taps[n] ); + if (taps_fstream.eof()) { + fprintf(stderr, "FIRFilter: file %s should contains %d taps, but EOF reached "\ + "after %d taps !\n", tapsFile.c_str(), n_taps, n); + throw std::runtime_error("FIRFilter: filtertaps file invalid ! "); + } } } diff --git a/src/FIRFilter.h b/src/FIRFilter.h index 2dd7354..ceac4cd 100644 --- a/src/FIRFilter.h +++ b/src/FIRFilter.h @@ -22,8 +22,7 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FIRFILTER_H -#define FIRFILTER_H +#pragma once #ifdef HAVE_CONFIG_H # include <config.h> @@ -98,7 +97,7 @@ class FIRFilterWorker { class FIRFilter : public ModCodec, public RemoteControllable { public: - FIRFilter(std::string& taps_file); + FIRFilter(const std::string& taps_file); virtual ~FIRFilter(); FIRFilter(const FIRFilter&); FIRFilter& operator=(const FIRFilter&); @@ -115,14 +114,12 @@ public: protected: - void load_filter_taps(std::string tapsFile); + void load_filter_taps(const std::string &tapsFile); - std::string& myTapsFile; + std::string myTapsFile; FIRFilterWorker worker; int number_of_runs; struct FIRFilterWorkerData firwd; }; -#endif //FIRFILTER_H - diff --git a/src/Utils.cpp b/src/Utils.cpp index 54a4161..a91077c 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -73,6 +73,7 @@ void printUsage(char* progName) " requiring an external REFCLK and PPS signal and frames that do not contain a valid timestamp\n" " get muted.\n\n"); fprintf(out, "-T taps_file: Enable filtering before the output, using the specified file containing the filter taps.\n"); + fprintf(out, " Use 'default' as taps_file to use the internal taps.\n"); fprintf(out, "-a gain: Apply digital amplitude gain.\n"); fprintf(out, "-c rate: Set the DAC clock rate and enable Cic Equalisation.\n"); fprintf(out, "-g gainmode: Set computation gain mode: fix, max or var\n"); |