libsdr  0.1.0
A simple SDR library
utils.hh
1 #ifndef __SDR_UTILS_HH__
2 #define __SDR_UTILS_HH__
3 
4 #include "config.hh"
5 #include "node.hh"
6 #include "traits.hh"
7 #include "operators.hh"
8 #include "logger.hh"
9 #include <ctime>
10 
11 
12 namespace sdr {
13 
16 template <class Scalar>
17 class RealImagPart: public Sink< std::complex<Scalar> >, public Source
18 {
19 public:
22  RealImagPart(bool select_real, double scale=1.0)
23  : Sink< std::complex<Scalar> >(), Source(), _buffer(), _select_real(select_real), _scale(scale)
24  {
25  // pass...
26  }
27 
29  virtual void config(const Config &src_cfg) {
30  // Needs full config
31  if ((Config::Type_UNDEFINED==src_cfg.type()) || (0 == src_cfg.bufferSize())) { return; }
32  // Assert complex type
33  if (src_cfg.type() != Config::typeId< std::complex<Scalar> >()) {
34  ConfigError err;
35  err << "Can not configure sink of RealPart: Invalid buffer type " << src_cfg.type()
36  << " expected " << Config::typeId< std::complex<Scalar> >();
37  throw err;
38  }
39  // Resize buffer
40  _buffer = Buffer<Scalar>(src_cfg.bufferSize());
41  // propergate config
42  this->setConfig(Config(Config::typeId< Scalar >(), src_cfg.sampleRate(),
43  src_cfg.bufferSize(), 1));
44 
45  if (_select_real) {
46  LogMessage msg(LOG_DEBUG);
47  msg << "Configured RealPart node:" << std::endl
48  << " type: " << Config::typeId<Scalar>() << std::endl
49  << " sample-rate: " << src_cfg.sampleRate() << std::endl
50  << " buffer-size: " << src_cfg.bufferSize();
51  Logger::get().log(msg);
52  }
53  }
54 
56  virtual void process(const Buffer<std::complex<Scalar> > &buffer, bool allow_overwrite) {
57  // Convert
58  if (_select_real) {
59  for (size_t i=0; i<buffer.size(); i++) {
60  _buffer[i] = _scale*buffer[i].real();
61  }
62  } else {
63  for (size_t i=0; i<buffer.size(); i++) {
64  _buffer[i] = _scale*buffer[i].imag();
65  }
66  }
67  this->send(_buffer);
68  }
69 
70 protected:
76  double _scale;
77 };
78 
79 
82 template <class Scalar>
83 class RealPart: public RealImagPart<Scalar>
84 {
85 public:
87  RealPart(double scale=1.0)
88  : RealImagPart<Scalar>(true, scale)
89  {
90  // pass...
91  }
92 };
93 
94 
97 template <class Scalar>
98 class ImagPart: public RealImagPart<Scalar>
99 {
100 public:
102  ImagPart(double scale=1.0)
103  : RealImagPart<Scalar>(false, scale)
104  {
105  // pass...
106  }
107 };
108 
109 
112 template <class Scalar>
113 class IQBalance: public Sink< std::complex<Scalar> >, public Source
114 {
115 public:
118 
119 public:
124  IQBalance(double balance=0.0)
125  : Sink< std::complex<Scalar> >(), Source(), _realFact(1), _imagFact(1)
126  {
127  if (balance < 0) {
128  // scale real part
129  balance = std::min(1.,-balance);
130  _realFact = (1-balance)*(1<<8);
131  _imagFact = (1<<8);
132  } else { // scale imag part
133  balance = std::min(1., balance);
134  _realFact = (1<<8);
135  _imagFact = (1-balance)*(1<<8);
136  }
137  }
138 
140  virtual ~IQBalance() {
141  _buffer.unref();
142  }
143 
145  double balance() const {
146  if (_realFact != (1<<8)) {
147  return (double(_realFact)/(1<<8)-1);
148  }
149  return (1-double(_imagFact)/(1<<8));
150  }
151 
153  void setBalance(double balance) {
154  if (balance < 0) {
155  // scale real part
156  balance = std::min(1.,-balance);
157  _realFact = balance*(1<<8);
158  _imagFact = (1<<8);
159  } else { // scale imag part
160  balance = std::min(1., balance);
161  _realFact = (1<<8);
162  _imagFact = balance*(1<<8);
163  }
164  }
165 
167  virtual void config(const Config &src_cfg) {
168  // Check if config is complete
169  if (! src_cfg.hasBufferSize()) { return; }
170  // Allocate buffer
172  // Forward config
173  Config cfg(src_cfg); cfg.setNumBuffers(1);
174  this->setConfig(cfg);
175  }
176 
178  virtual void process(const Buffer<std::complex<Scalar> > &buffer, bool allow_overwrite) {
179  if (allow_overwrite) {
180  _process(buffer, buffer);
181  this->send(buffer);
182  } else {
183  _process(buffer, _buffer);
184  this->send(_buffer.head(buffer.size()));
185  }
186  }
187 
188 protected:
190  void _process(const Buffer< std::complex<Scalar> > &in, const Buffer< std::complex<Scalar> > &out) {
191  for (size_t i=0; i<in.size(); i++) {
192  out[i] = std::complex<Scalar>((_realFact*SScalar(in[i].real()))/(1<<8),
193  (_imagFact*SScalar(in[i].imag()))/(1<<8));
194  }
195  }
196 
197 protected:
199  int32_t _realFact;
201  int32_t _imagFact;
204 };
205 
206 
210 template <class iScalar, class oScalar=iScalar>
211 class ToComplex: public Sink<iScalar>, public Source
212 {
213 public:
215  ToComplex(double scale=1.0)
216  : Sink<iScalar>(), Source(), _scale(scale)
217  {
218  // pass...
219  }
220 
222  virtual void config(const Config &src_cfg) {
223  // Requires at least type & buffer size
224  if (!src_cfg.hasType() || !src_cfg.hasBufferSize()) { return; }
225  // Check input type
226  if (Config::typeId<iScalar>() != src_cfg.type()) {
227  ConfigError err;
228  err << "Can not configure ToComplex node: Invalid buffer type " << src_cfg.type()
229  << ", expected " << Config::typeId<iScalar>();
230  throw err;
231  }
232  // Allocate buffer:
234  // Propergate config
235  this->setConfig(
236  Config(Config::typeId< std::complex<oScalar> >(),
237  src_cfg.sampleRate(), src_cfg.bufferSize(), src_cfg.numBuffers()));
238  }
239 
241  virtual void process(const Buffer<iScalar> &buffer, bool allow_overwrite) {
242  if (1.0 == _scale) {
243  for (size_t i=0; i<buffer.size(); i++) {
244  _buffer[i] = std::complex<oScalar>(oScalar(buffer[i]));
245  }
246  } else {
247  for (size_t i=0; i<buffer.size(); i++) {
248  _buffer[i] = std::complex<oScalar>(_scale*oScalar(buffer[i]));
249  }
250  }
251  // propergate buffer
252  this->send(_buffer.head(buffer.size()));
253  }
254 
255 protected:
257  double _scale;
260 };
261 
262 
263 
266 template <class iScalar, class oScalar>
267 class Cast : public Sink<iScalar>, public Source
268 {
269 public:
274 
275 public:
277  Cast(oScalar scale=1, iScalar shift=0)
278  : Sink<iScalar>(), Source(), _can_overwrite(false), _do_scale(false),
279  _scale(scale), _shift(shift), _buffer()
280  {
281  // pass...
282  }
283 
285  virtual void config(const Config &src_cfg) {
286  // only check type
287  if (!src_cfg.hasType()) { return; }
288  if (src_cfg.type() != Config::typeId<iScalar>()) {
289  ConfigError err;
290  err << "Can not configure Cast: Invalid input type " << src_cfg.type()
291  << ", expected " << Config::typeId<iScalar>();
292  throw err;
293  }
294 
295  // unreference buffer if non-empty
296  if (! _buffer.isEmpty()) { _buffer.unref(); }
297 
298  // allocate buffer
299  _buffer = Buffer<oScalar>(src_cfg.bufferSize());
300 
301  LogMessage msg(LOG_DEBUG);
302  msg << "Configure Cast node:" << std::endl
303  << " conversion: "<< Config::typeId<iScalar>()
304  << " -> " << Config::typeId<oScalar>() << std::endl
305  << " in-place " << (_can_overwrite ? "true" : "false") << std::endl
306  << " scale: " << _scale;
307  Logger::get().log(msg);
308 
309  _can_overwrite = sizeof(iScalar) >= sizeof(oScalar);
310  _do_scale = (_scale != oScalar(0));
311 
312  // forward config
313  this->setConfig(Config(Config::typeId<oScalar>(), src_cfg.sampleRate(),
314  src_cfg.bufferSize(), 1));
315  }
316 
318  virtual void process(const Buffer<iScalar> &buffer, bool allow_overwrite) {
319  if (allow_overwrite && _can_overwrite) {
320  _process(buffer, Buffer<oScalar>(buffer));
321  } else if (_buffer.isUnused()) {
322  _process(buffer, _buffer);
323  } else {
324 #ifdef SDR_DEBUG
325  std::cerr << "Cast: Drop buffer: Output buffer is still in use by "
326  << _buffer.refCount() << std::endl;
327 #endif
328  }
329  }
330 
332  inline double scale() const { return _scale; }
333 
335  void setScale(double scale) {
336  _scale = scale;
337  _do_scale = (0 != _scale);
338  }
339 
340 protected:
342  inline void _process(const Buffer<iScalar> &in, const Buffer<oScalar> &out) {
343  if (_do_scale) {
344  for (size_t i=0; i<in.size(); i++) {
345  out[i] = _scale*( cast<iScalar,oScalar>(in[i]) + cast<iScalar, oScalar>(_shift) );
346  }
347  } else {
348  for (size_t i=0; i<in.size(); i++) {
349  out[i] = in[i]+_shift;
350  }
351  }
352  this->send(out.head(in.size()));
353  }
354 
355 protected:
359  bool _do_scale;
361  oScalar _scale;
363  iScalar _shift;
366 };
367 
368 
369 
372 class UnsignedToSigned: public SinkBase, public Source
373 {
374 public:
376  UnsignedToSigned(float scale=1.0);
378  virtual ~UnsignedToSigned();
379 
381  virtual void config(const Config &src_cfg);
383  virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite);
384 
385 protected:
387  void _process_int8(const RawBuffer &in, const RawBuffer &out);
389  void _process_int16(const RawBuffer &in, const RawBuffer &out);
390 
391 protected:
393  void (UnsignedToSigned::*_process)(const RawBuffer &in, const RawBuffer &out);
397  float _scale;
398 };
399 
400 
401 
404 class SignedToUnsigned: public SinkBase, public Source
405 {
406 public:
410  virtual ~SignedToUnsigned();
411 
413  virtual void config(const Config &src_cfg);
415  virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite);
416 
417 protected:
419  void _process_int8(const RawBuffer &in, const RawBuffer &out);
421  void _process_int16(const RawBuffer &in, const RawBuffer &out);
422 
423 protected:
425  void (SignedToUnsigned::*_process)(const RawBuffer &in, const RawBuffer &out);
428 };
429 
430 
436 template <class Scalar>
437 class FreqShift: public Sink< std::complex<Scalar> >, public Source
438 {
439 public:
441  FreqShift(double shift, Scalar scale=1.0)
442  : Sink< std::complex<Scalar> >(), Source(),
443  _shift(shift), _scale(scale), _factor(1), _sample_rate(0), _delta(1)
444  {
445  // pass...
446  }
447 
449  virtual ~FreqShift() {
450  // pass...
451  }
452 
454  inline double shift() const { return _shift; }
455 
457  void setShift(double shift) {
458  // Update delta
459  _shift = shift;
460  _delta = exp(std::complex<double>(0,2*M_PI*_shift/_sample_rate));
461  }
462 
464  virtual void config(const Config &src_cfg) {
465  // Requires type, samplerate & buffersize
466  if ((Config::Type_UNDEFINED==src_cfg.type()) || (0==src_cfg.sampleRate()) || (0==src_cfg.bufferSize())) { return; }
467  // Assert type
468  if (src_cfg.type() != Config::typeId< std::complex<Scalar> >()) {
469  ConfigError err;
470  err << "Can not configure FreqShift node: Invalid source type " << src_cfg.type()
471  << ", expected " << Config::typeId< std::complex<Scalar> >();
472  throw err;
473  }
474  // Allocate buffer
476  // Store sample rate
477  _sample_rate = src_cfg.sampleRate();
478  // Precalc delta
479  _delta = exp(std::complex<double>(0,2*M_PI*_shift/_sample_rate));
480  // reset factor
481  _factor = 1;
482 
483  LogMessage msg(LOG_DEBUG);
484  msg << "Configure FreqShift node:" << std::endl
485  << " shift: " << _shift << std::endl
486  << " scale: " << _scale << std::endl
487  << " sample-rate: " << src_cfg.sampleRate() << std::endl
488  << " buffer-suize: " << src_cfg.bufferSize();
489  Logger::get().log(msg);
490 
491  // Propergate config
492  this->setConfig(Config(Config::typeId< std::complex<Scalar> >(), src_cfg.sampleRate(),
493  src_cfg.bufferSize(), 1));
494  }
495 
497  virtual void process(const Buffer<std::complex<Scalar> > &buffer, bool allow_overwrite) {
498  // Shift freq:
499  for (size_t i=0; i<buffer.size(); i++) {
500  _buffer[i] = (double(_scale)*_factor)*buffer[i]; _factor *= _delta;
501  }
502  // Send buffer
503  this->send(_buffer);
504  }
505 
506 protected:
510  double _shift;
512  Scalar _scale;
514  std::complex<double> _factor;
516  double _sample_rate;
518  std::complex<double> _delta;
519 };
520 
521 
524 template<class Scalar>
525 class StreamSource: public Source
526 {
527 public:
529  StreamSource(std::istream &stream, double sample_rate=1, size_t buffersize=1024)
530  : Source(), _stream(stream), _buffer(buffersize)
531  {
532  // Assemble config for stream:
533  this->_config = Config(Config::typeId<Scalar>(), sample_rate, buffersize, 1);
534  }
535 
538  void next() {
539  if(_stream.eof()) { Queue::get().stop(); return; }
540  int len = _stream.read(_buffer.ptr(), _buffer.storageSize());
541  if (len > 0) {
542  this->send(_buffer.head(len/sizeof(Scalar)));
543  }
544  }
545 
546 protected:
548  std::istream &_stream;
551 };
552 
553 
556 template <class Scalar>
557 class StreamSink: public Sink<Scalar>
558 {
559 public:
561  StreamSink(std::ostream &stream)
562  : Sink<Scalar>(), _stream(stream)
563  {
564  // pass...
565  }
566 
568  virtual void config(const Config &src_cfg) {
569  if (Config::Type_UNDEFINED == src_cfg.type()) { return; }
570  if (src_cfg.type() != Config::typeId<Scalar>()) {
571  ConfigError err;
572  err << "Can not configure StreamSink: Invalid buffer type " << src_cfg.type()
573  << ", expected " << Config::typeId<Scalar>();
574  throw err;
575  }
576  // done...
577  }
578 
580  virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
582  _stream.write(buffer.data(), buffer.size()*sizeof(Scalar));
583  }
584 
585 protected:
587  std::ostream &_stream;
588 };
589 
590 
591 
592 
595 template <class Scalar>
596 class Scale : public Sink<Scalar>, public Source
597 {
598 public:
600  Scale(float scale=1, Scalar shift=0)
601  : Sink<Scalar>(), Source(), _scale(scale), _shift(shift)
602  {
603  // pass...
604  }
605 
607  virtual ~Scale() {
608  // pass...
609  }
610 
612  virtual void config(const Config &src_cfg) {
613  // Check for type & buffer size
614  if (!src_cfg.hasType() || !src_cfg.bufferSize()) { return; }
615  // Check type
616  if (Config::typeId<Scalar>() != src_cfg.type()) {
617  ConfigError err;
618  err << "Can not configure Scale node: Invalid type " << src_cfg.type()
619  << ", expected " << Config::typeId<Scalar>();
620  throw err;
621  }
622  // Allocate buffer
623  _buffer = Buffer<Scalar>(src_cfg.bufferSize());
624  // Done, propergate config
625  this->setConfig(src_cfg);
626  }
627 
629  virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
630  if ((1 == _scale) && (Scalar(0) == _shift)) {
631  this->send(buffer, allow_overwrite);
632  } else if (allow_overwrite) {
633  // Scale inplace
634  for (size_t i=0; i<buffer.size(); i++) { buffer[i] *= _scale; }
635  this->send(buffer, allow_overwrite);
636  } else if (_buffer.isUnused()) {
637  // Scale out-of-place
638  for (size_t i=0; i<buffer.size(); i++) { _buffer[i] = _scale*_buffer[i]; }
639  this->send(_buffer.head(buffer.size()), true);
640  }
641  // else if buffer is still in use -> drop buffer...
642  }
643 
644 protected:
648  float _scale;
650  Scalar _shift;
651 };
652 
653 
654 
657 template <class Scalar>
658 class AGC: public Sink<Scalar>, public Source
659 {
660 public:
662  AGC(double tau=0.1, double target=0)
663  : Sink<Scalar>(), Source(), _enabled(true), _tau(tau), _lambda(0), _sd(0),
664  _target(target), _gain(1), _sample_rate(0)
665  {
666  if (0 == target) {
667  // Determine target by scalar type
668  switch (Config::typeId<Scalar>()) {
669  case Config::Type_u8:
670  case Config::Type_s8:
671  case Config::Type_cu8:
672  case Config::Type_cs8:
673  _target = 64; break;
674  case Config::Type_u16:
675  case Config::Type_s16:
676  case Config::Type_cu16:
677  case Config::Type_cs16:
678  _target = 16000; break;
679  case Config::Type_f32:
680  case Config::Type_f64:
681  case Config::Type_cf32:
682  case Config::Type_cf64:
683  _target = 0.5; break;
684  case Config::Type_UNDEFINED: {
685  ConfigError err; err << "Can not configure AGC node: Unsupported type."; throw err;
686  }
687  }
688  }
689  _sd = _target;
690  }
691 
693  inline bool enabled() const {
694  return _enabled;
695  }
696 
698  inline void enable(bool enabled) {
699  _enabled = enabled;
700  }
701 
703  inline float gain() const {
704  return _gain;
705  }
706 
708  inline void setGain(float gain) {
709  _gain = gain;
710  }
711 
713  inline double tau() const {
714  return _tau;
715  }
716 
718  inline void setTau(double tau) {
719  // calc decay factor
720  _tau = tau;
721  _lambda = exp(-1./(_tau*_sample_rate));
722  }
723 
725  virtual void config(const Config &src_cfg) {
726  // Need sample rate & type
727  if (!src_cfg.hasType() || !src_cfg.hasSampleRate() || !src_cfg.hasBufferSize()) { return; }
728  if (Config::typeId<Scalar>() != src_cfg.type()) {
729  ConfigError err;
730  err << "Can not configure AGC node: Invalid type " << src_cfg.type()
731  << ", expected " << Config::typeId<Scalar>();
732  throw err;
733  }
734 
735  // calc decay factor
736  _sample_rate = src_cfg.sampleRate();
737  _lambda = exp(-1./(_tau*src_cfg.sampleRate()));
738  // reset variance
739  _sd = _target;
740 
741  // Allocate buffer
742  _buffer = Buffer<Scalar>(src_cfg.bufferSize());
743 
744  LogMessage msg(LOG_DEBUG);
745  msg << "Configured AGC:" << std::endl
746  << " type: " << src_cfg.type() << std::endl
747  << " sample-rate: " << src_cfg.sampleRate() << std::endl
748  << " tau: " << _tau << std::endl
749  << " lambda [1/s]: " << pow(_lambda, src_cfg.sampleRate()) << std::endl
750  << " lambda [1/sam]: " << _lambda << std::endl
751  << " target value: " << _target;
752  Logger::get().log(msg);
753 
754  // Propergate config
755  this->setConfig(Config(Config::typeId<Scalar>(), src_cfg.sampleRate(),
756  src_cfg.bufferSize(), 1));
757  }
758 
759 
761  virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
762  // Simply forward buffer if disabled
763  if ((! _enabled) && (0 == _gain) ) {
764  this->send(buffer, allow_overwrite); return;
765  }
766  // Update signal ampl
767  for (size_t i=0; i<buffer.size(); i++) {
768  _sd = _lambda*_sd + (1-_lambda)*std::abs(buffer[i]);
769  if (_enabled) { _gain = _target/(4*_sd); }
770  _buffer[i] = _gain*buffer[i];
771  }
772  this->send(_buffer);
773  }
774 
775 
776 protected:
778  bool _enabled;
780  float _tau;
782  float _lambda;
784  float _sd;
786  float _target;
788  float _gain;
790  double _sample_rate;
793 };
794 
795 
798 template <class Scalar>
799 class DebugStore: public Sink<Scalar>
800 {
801 public:
803  DebugStore() : Sink<Scalar>(), _buffer(), _view() { }
804  virtual ~DebugStore() {
805  _buffer.unref();
806  }
807 
809  virtual void config(const Config &src_cfg) {
810  // Requires type and buffer size
811  if (!src_cfg.hasType() || !src_cfg.hasBufferSize()) { return; }
812  // Check type
813  if (Config::typeId<Scalar>() != src_cfg.type()) {
814  ConfigError err;
815  err << "Can not configure DebugStore node: Invalid input type " << src_cfg.type()
816  << ", expected " << Config::typeId<Scalar>();
817  throw err;
818  }
819  // Allocate buffer
820  _buffer = Buffer<Scalar>(src_cfg.bufferSize());
821  }
822 
824  virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
825  size_t N = std::min(buffer.size(), _buffer.size());
826  memcpy(_buffer.ptr(), buffer.data(), N*sizeof(Scalar));
827  // Store view
828  _view = _buffer.head(N);
829  }
830 
832  inline const Buffer<Scalar> &buffer() const { return _view; }
834  inline void clear() { _view = Buffer<Scalar>(); }
835 
836 public:
841 };
842 
843 
846 template <class Scalar>
847 class DebugDump: public Sink<Scalar>
848 {
849 public:
851  DebugDump(std::ostream &stream=std::cerr)
852  : Sink<Scalar>(), _stream(stream)
853  {
854  // pass...
855  }
856 
858  virtual ~DebugDump() {
859  // pass...
860  }
861 
863  virtual void config(const Config &src_cfg) {
864  // Requires type
865  if (!src_cfg.hasType()) { return; }
866  // check type
867  if (Config::typeId<Scalar>() != src_cfg.type()) {
868  ConfigError err;
869  err << "Can not configure DebugDump sink: Invalid input type " << src_cfg.type()
870  << ", expected " << Config::typeId<Scalar>();
871  throw err;
872  }
873  // Done...
874  }
875 
877  virtual void process(const Buffer<Scalar> &buffer, bool allow_overwrite) {
878  _stream << buffer << std::endl;
879  }
880 
881 protected:
883  std::ostream &_stream;
884 };
885 
888 class TextDump : public Sink<uint8_t>
889 {
890 public:
892  TextDump(std::ostream &stream=std::cerr);
894  virtual void config(const Config &src_cfg);
896  virtual void process(const Buffer<uint8_t> &buffer, bool allow_overwrite);
897 
898 protected:
900  std::ostream &_stream;
901 };
902 
903 
906 template <class Scalar>
907 class GWNSource: public Source
908 {
909 public:
911  GWNSource(double sample_rate, size_t buffer_size=1024)
912  : Source(), _sample_rate(sample_rate), _buffer_size(buffer_size), _buffer(_buffer_size),
913  _mean(0)
914  {
915  // Seed RNG
916  std::srand(std::time(0));
917  // Determine mean
918  switch (Config::typeId<Scalar>()) {
919  case Config::Type_u8:
920  case Config::Type_cu8:
921  case Config::Type_u16:
922  case Config::Type_cu16:
923  _mean = 1;
924  break;
925  default:
926  _mean = 0;
927  break;
928  }
929  // Propergate config
930  setConfig(Config(Config::typeId<Scalar>(), _sample_rate, _buffer_size, 1));
931  }
932 
934  virtual ~GWNSource() {
935  _buffer.unref();
936  }
937 
941  void next() {
942  double a,b;
943  for (size_t i=0; i<_buffer_size; i+=2) {
944  _getNormal(a,b);
945  _buffer[i] = Scalar(Traits<Scalar>::scale*(a+_mean));
946  _buffer[i+1] = Scalar(Traits<Scalar>::scale*(b+_mean));
947  }
948  if (_buffer_size%2) {
949  _getNormal(a,b); _buffer[_buffer_size-1] = Scalar(Traits<Scalar>::scale*(a+_mean));
950  }
951  this->send(_buffer, true);
952  }
953 
954 
955 protected:
957  void _getNormal(double &a, double &b) {
958  // Obtain pair of std. normal floating point values
959  double x = 2*(double(std::rand())/RAND_MAX) - 1;
960  double y = 2*(double(std::rand())/RAND_MAX) - 1;
961  double s = std::sqrt(x*x + y*y);
962  while (s >= 1) {
963  x = 2*(double(std::rand())/RAND_MAX) - 1;
964  y = 2*(double(std::rand())/RAND_MAX) - 1;
965  s = std::sqrt(x*x + y*y);
966  }
967  a = x*std::sqrt(-2*log(s)/s);
968  b = y*std::sqrt(-2*log(s)/s);
969  }
970 
971 protected:
973  double _sample_rate;
975  size_t _buffer_size;
979  double _mean;
980 };
981 
982 }
983 
984 #endif // __SDR_UTILS_HH__
void enable(bool enabled)
Enable/disable the AGC node.
Definition: utils.hh:698
virtual void process(const Buffer< iScalar > &buffer, bool allow_overwrite)
Casts the input real buffer into the complex output buffer.
Definition: utils.hh:241
Buffer< Scalar > _buffer
A pre-allocated buffer, that will hold the last data received.
Definition: utils.hh:838
void _process_int16(const RawBuffer &in, const RawBuffer &out)
Performs the cast for uint16 -> int16.
Definition: utils.cc:91
A collection of configuration information that is send by a source to all connected sinks to properga...
Definition: node.hh:35
double _sample_rate
The sample rate.
Definition: utils.hh:973
void setGain(float gain)
Resets the current gain factor.
Definition: utils.hh:708
RawBuffer _buffer
The output buffer, unused if the cast can be performed in-place.
Definition: utils.hh:395
Complex (aka I/Q) type of 32bit floats aka. std::complex.
Definition: node.hh:51
oScalar _scale
The scaling.
Definition: utils.hh:361
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Dumps the received buffer.
Definition: utils.hh:877
float gain() const
Returns the current gain factor.
Definition: utils.hh:703
virtual void config(const Config &src_cfg)
Configures the cast node.
Definition: utils.cc:117
float _tau
The time-constant of the AGC.
Definition: utils.hh:780
Base class of all buffers, represents an untyped array of bytes.
Definition: buffer.hh:32
double _scale
The scale.
Definition: utils.hh:76
void setShift(double shift)
Sets the frequency shift.
Definition: utils.hh:457
Config _config
Holds the source configuration, this can be updated by calling setConfig.
Definition: node.hh:253
void(SignedToUnsigned::* _process)(const RawBuffer &in, const RawBuffer &out)
Type-cast callback.
Definition: utils.hh:425
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Performs the amplification and adjusts the gain.
Definition: utils.hh:761
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite)
Performs the cast.
Definition: utils.cc:158
Scalar _scale
The optional scale.
Definition: utils.hh:512
double scale() const
Returns the scaling.
Definition: utils.hh:332
Cast(oScalar scale=1, iScalar shift=0)
Constructs a type-cast with optional scaleing.
Definition: utils.hh:277
virtual ~Scale()
Destructor.
Definition: utils.hh:607
Buffer< std::complex< oScalar > > _buffer
The output buffer.
Definition: utils.hh:259
Real signed 16b ints.
Definition: node.hh:44
virtual ~SignedToUnsigned()
Destructor.
Definition: utils.cc:112
Performs a reinterprete cast from an unsinged value to a singed one.
Definition: utils.hh:372
A Gaussian White Noise source.
Definition: utils.hh:907
std::ostream & _stream
The output stream.
Definition: utils.hh:900
virtual void send(const RawBuffer &buffer, bool allow_overwrite=false)
Sends the given buffer to all connected sinks.
Definition: node.cc:67
const Buffer< Scalar > & buffer() const
Retunrs a reference to the last received buffer.
Definition: utils.hh:832
static Queue & get()
Get a reference to the global instance of the queue.
Definition: queue.cc:15
DebugStore()
Constrctor.
Definition: utils.hh:803
virtual void config(const Config &src_cfg)
Configures the raw sink.
Definition: utils.hh:568
virtual void config(const Config &src_cfg)
Configures the cast node.
Definition: utils.cc:20
Typed sink.
Definition: node.hh:192
Extracts the real or imaginary part of a complex valued data stream.
Definition: utils.hh:17
Scale(float scale=1, Scalar shift=0)
Constructs the scaling node.
Definition: utils.hh:600
double _shift
The frequency shift in Hz ( ).
Definition: utils.hh:510
double _sample_rate
The current sample-rate.
Definition: utils.hh:790
Complex (aka I/Q) type of unsigned 16b ints.
Definition: node.hh:49
void setBalance(double balance)
Sets the I/Q balance.
Definition: utils.hh:153
Definition: autocast.hh:8
size_t numBuffers() const
Returns the max.
Definition: node.hh:89
bool isEmpty() const
Returns true if the buffer is invalid/empty.
Definition: buffer.hh:77
Real signed 8b ints.
Definition: node.hh:42
Definition: operators.hh:9
StreamSource(std::istream &stream, double sample_rate=1, size_t buffersize=1024)
Constructs a raw input source.
Definition: utils.hh:529
size_t storageSize() const
Returns the raw buffer size in bytes.
Definition: buffer.hh:75
Performs a frequency shift on a complex input signal, by multiplying it with .
Definition: utils.hh:437
ToComplex(double scale=1.0)
Constructor.
Definition: utils.hh:215
void stop()
Signals the queue to stop processing.
Definition: queue.cc:64
bool hasSampleRate() const
If true, the configuration has a sample rate.
Definition: node.hh:75
Generic source class.
Definition: node.hh:213
Real unsigned 8b ints.
Definition: node.hh:41
int refCount() const
Returns the reference counter.
Definition: buffer.hh:84
Explicit type cast node.
Definition: utils.hh:267
SignedToUnsigned()
Constructor with optional scaleing.
Definition: utils.cc:106
virtual void config(const Config &src_cfg)
Configures the node.
Definition: utils.hh:809
Traits< iScalar >::SScalar iSScalar
Specifies the input super scalar.
Definition: utils.hh:271
Buffer< Scalar > _buffer
The output buffer.
Definition: utils.hh:792
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Stores the given buffer.
Definition: utils.hh:824
virtual void process(const Buffer< iScalar > &buffer, bool allow_overwrite)
Performs the type-cast node.
Definition: utils.hh:318
virtual void process(const Buffer< std::complex< Scalar > > &buffer, bool allow_overwrite)
Performs the frequency shift.
Definition: utils.hh:497
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
bool hasType() const
If true, the configuration has a type.
Definition: node.hh:69
int32_t _imagFact
Scaleing factor for the imaginary part.
Definition: utils.hh:201
FreqShift(double shift, Scalar scale=1.0)
Constructs a frequency shift node with optional scaleing of the result.
Definition: utils.hh:441
std::ostream & _stream
The output stream.
Definition: utils.hh:587
void setScale(double scale)
Sets the scaling.
Definition: utils.hh:335
virtual ~DebugDump()
Destructor.
Definition: utils.hh:858
Real 64b floats aka. "double".
Definition: node.hh:46
Dumps the received uin8_t byte-stream as (ASCII) text.
Definition: utils.hh:888
char * data() const
Returns the pointer to the data of the buffer view.
Definition: buffer.hh:69
Real unsigned 16b ints.
Definition: node.hh:43
size_t _buffer_size
The size of the buffer.
Definition: utils.hh:975
AGC(double tau=0.1, double target=0)
Constructor.
Definition: utils.hh:662
virtual void setConfig(const Config &config)
Stores the configuration and propergates it if the configuration has been changed.
Definition: node.cc:98
virtual void config(const Config &src_cfg)
Configures the node.
Definition: utils.hh:222
Buffer< T > head(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:237
double _scale
The scale.
Definition: utils.hh:257
void _process_int16(const RawBuffer &in, const RawBuffer &out)
Performs the int16 -> uint16 cast.
Definition: utils.cc:181
Buffer< Scalar > _buffer
The output buffer.
Definition: utils.hh:977
GWNSource(double sample_rate, size_t buffer_size=1024)
Constructor.
Definition: utils.hh:911
double balance() const
Retunrs the balance.
Definition: utils.hh:145
double tau() const
Returns the time-constant of the AGC.
Definition: utils.hh:713
float _sd
The averaged std.
Definition: utils.hh:784
Selects the real part of a complex signal.
Definition: utils.hh:83
std::ostream & _stream
A reference to the output stream.
Definition: utils.hh:883
virtual ~UnsignedToSigned()
Destructor.
Definition: utils.cc:15
Buffer< Scalar > _buffer
The output buffer.
Definition: utils.hh:72
virtual void process(const Buffer< std::complex< Scalar > > &buffer, bool allow_overwrite)
Processes the incomming data.
Definition: utils.hh:56
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Dumps the buffer into the stream as raw data.
Definition: utils.hh:580
virtual ~IQBalance()
Destructor.
Definition: utils.hh:140
double _sample_rate
The current sample rate.
Definition: utils.hh:516
void log(const LogMessage &message)
Logs a message.
Definition: logger.cc:100
Traits< Scalar >::SScalar SScalar
The internal used compute scalar.
Definition: utils.hh:117
RealImagPart(bool select_real, double scale=1.0)
Constructor.
Definition: utils.hh:22
double _mean
The mean value of the GWN.
Definition: utils.hh:979
Type type() const
Returns the type.
Definition: node.hh:71
void _process_int8(const RawBuffer &in, const RawBuffer &out)
Performs the cast for uint8 -> int8.
Definition: utils.cc:78
Selects the imaginary part of a complex signal.
Definition: utils.hh:98
virtual void process(const Buffer< Scalar > &buffer, bool allow_overwrite)
Performs the scaleing.
Definition: utils.hh:629
Buffer< Scalar > _view
A view to the last data received.
Definition: utils.hh:840
virtual void config(const Config &src_cfg)
Configures the type-cast node.
Definition: utils.hh:285
Buffer< std::complex< Scalar > > _buffer
The output buffer.
Definition: utils.hh:508
DebugDump(std::ostream &stream=std::cerr)
Constructor.
Definition: utils.hh:851
void(UnsignedToSigned::* _process)(const RawBuffer &in, const RawBuffer &out)
Type-cast callback.
Definition: utils.hh:393
Performs a reinterprete cast from an unsinged value to a singed one.
Definition: utils.hh:404
Simple scaling node.
Definition: utils.hh:596
iScalar _shift
Another scaling, using integer shift operation (faster).
Definition: utils.hh:363
float _scale
Holds the scaleing.
Definition: utils.hh:397
A simple node, that allows to balance an IQ signal.
Definition: utils.hh:113
Buffer< std::complex< Scalar > > _buffer
The working buffer.
Definition: utils.hh:203
static Type typeId()
Returns the type-id of the template type.
double shift() const
Returns the frequency shift.
Definition: utils.hh:454
static Logger & get()
Returns the singleton instance of the logger.
Definition: logger.cc:89
Reads raw samples from an imput stream, (ie a file).
Definition: utils.hh:525
virtual void config(const Config &src_cfg)
Configures the dump-node.
Definition: utils.hh:863
Scalar _shift
Alternative formulation for the scaling, using integer shift operators.
Definition: utils.hh:650
Dumps buffers in a human readable form.
Definition: utils.hh:847
Real 32b floats aka. "float".
Definition: node.hh:45
bool _select_real
Real/Imag selection.
Definition: utils.hh:74
The configuration error class.
Definition: exception.hh:24
TextDump(std::ostream &stream=std::cerr)
Constructor.
Definition: utils.cc:193
A log message.
Definition: logger.hh:22
Traits< oScalar >::SScalar oSScalar
Specified the output super scalar.
Definition: utils.hh:273
Keeps a copy of the last buffer received.
Definition: utils.hh:799
size_t bufferSize() const
Returns the max.
Definition: node.hh:83
void next()
Samples and emits the next chunk of data.
Definition: utils.hh:941
void _process(const Buffer< iScalar > &in, const Buffer< oScalar > &out)
Internal used method to perform the type-case out-of-place.
Definition: utils.hh:342
virtual void config(const Config &src_cfg)
Configures the scaleing node.
Definition: utils.hh:612
virtual void process(const Buffer< uint8_t > &buffer, bool allow_overwrite)
Processes the input stream.
Definition: utils.cc:213
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite)
Performs the cast.
Definition: utils.cc:64
std::istream & _stream
The input stream.
Definition: utils.hh:548
Basic interface of all Sinks.
Definition: node.hh:174
float _lambda
One over the time-constant.
Definition: utils.hh:782
char * ptr() const
Returns the pointer to the data (w/o view).
Definition: buffer.hh:67
Complex (aka I/Q) type of signed 8b ints.
Definition: node.hh:48
float _scale
The scaling.
Definition: utils.hh:648
Buffer< Scalar > _buffer
The output buffer.
Definition: utils.hh:550
void clear()
Clears the buffer.
Definition: utils.hh:834
void setTau(double tau)
Sets the time-constant of the AGC.
Definition: utils.hh:718
void _process_int8(const RawBuffer &in, const RawBuffer &out)
Performs the int8 -> uint8 cast.
Definition: utils.cc:172
bool _do_scale
If true, the output gets scaled.
Definition: utils.hh:359
int32_t _realFact
Scaleing factor for the real part.
Definition: utils.hh:199
Tiny helper node to transform a real part into a complex, including a possible type-cast.
Definition: utils.hh:211
RealPart(double scale=1.0)
Constructor.
Definition: utils.hh:87
Complex (aka I/Q) type of signed 16b ints.
Definition: node.hh:50
Complex (aka I/Q) type of unsigned 8b ints.
Definition: node.hh:47
std::complex< double > _factor
The current exponental factor, gets updated for every sample.
Definition: utils.hh:514
virtual void config(const Config &src_cfg)
Configures the node.
Definition: utils.hh:29
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
bool isUnused() const
We assume here that buffers are owned by one object: A buffer is therefore "unused" if the owner hold...
Definition: buffer.hh:87
UnsignedToSigned(float scale=1.0)
Constructor with optional scaleing.
Definition: utils.cc:9
Buffer< oScalar > _buffer
The output buffer, unused if the type-cast is performed in-place .
Definition: utils.hh:365
StreamSink(std::ostream &stream)
Constructor.
Definition: utils.hh:561
bool enabled() const
Returns true, if the AGC is enabled.
Definition: utils.hh:693
std::complex< double > _delta
.
Definition: utils.hh:518
virtual void config(const Config &src_cfg)
Configures the sink.
Definition: utils.cc:200
float _target
The target level of the output signal.
Definition: utils.hh:786
Forward declaration of type tratis template.
Definition: traits.hh:20
virtual ~GWNSource()
Destructor.
Definition: utils.hh:934
Buffer< Scalar > _buffer
The output buffer, unused if the scaling is performed in-place.
Definition: utils.hh:646
float _gain
The current gain factor.
Definition: utils.hh:788
RawBuffer _buffer
The output buffer, unused if the cast is performed in-place.
Definition: utils.hh:427
bool _can_overwrite
If true, the type-cast (an scaleing) can be performed in-place.
Definition: utils.hh:357
void _process(const Buffer< std::complex< Scalar > > &in, const Buffer< std::complex< Scalar > > &out)
The actual implementation.
Definition: utils.hh:190
An automatic gain control node.
Definition: utils.hh:658
void next()
Reads the next chunk.
Definition: utils.hh:538
virtual void config(const Config &src_cfg)
Configures the frequency shift node.
Definition: utils.hh:464
virtual void config(const Config &src_cfg)
Configures the AGC node.
Definition: utils.hh:725
Serializes the incomming buffers as raw data.
Definition: utils.hh:557
virtual void process(const Buffer< std::complex< Scalar > > &buffer, bool allow_overwrite)
Processes a buffer.
Definition: utils.hh:178
ImagPart(double scale=1.0)
Constructor.
Definition: utils.hh:102
bool hasBufferSize() const
If true, the configuration has a buffer size.
Definition: node.hh:81
virtual ~FreqShift()
Destructor.
Definition: utils.hh:449
void _getNormal(double &a, double &b)
Sample two std.
Definition: utils.hh:957
Complex (aka I/Q) type of 64bit floats aka. std::complex.
Definition: node.hh:52
virtual void config(const Config &src_cfg)
Configures the node.
Definition: utils.hh:167
double sampleRate() const
Returns the sample rate.
Definition: node.hh:77
bool _enabled
If true, the automatic gain adjustment is enabled.
Definition: utils.hh:778
IQBalance(double balance=0.0)
Constructor.
Definition: utils.hh:124