Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_feedforward_agc_cc.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gr_feedforward_agc_cc.h>
28 #include <gr_io_signature.h>
29 #include <stdexcept>
30
31 gr_feedforward_agc_cc_sptr
32 gr_make_feedforward_agc_cc(int nsamples, float reference)
33 {
34   return gr_feedforward_agc_cc_sptr(new gr_feedforward_agc_cc (nsamples, reference));
35 }
36
37 gr_feedforward_agc_cc::gr_feedforward_agc_cc (int nsamples, float reference)
38   : gr_sync_block ("gr_feedforward_agc_cc",
39                    gr_make_io_signature (1, 1, sizeof (gr_complex)),
40                    gr_make_io_signature (1, 1, sizeof (gr_complex))),
41     d_nsamples(nsamples), d_reference(reference)
42 {
43   if (nsamples < 1)
44     throw std::invalid_argument("gr_feedforward_agc_cc: nsamples must be >= 1");
45   
46   set_history(nsamples);
47 }
48
49 gr_feedforward_agc_cc::~gr_feedforward_agc_cc()
50 {
51 }
52
53 inline static float
54 mag_squared(gr_complex x)
55 {
56   return x.real() * x.real() + x.imag() * x.imag();
57 }
58
59 // approximate sqrt(x^2 + y^2)
60 inline static float
61 envelope(gr_complex x)
62 {
63   float r_abs = std::fabs(x.real());
64   float i_abs = std::fabs(x.imag());
65
66   if (r_abs > i_abs)
67     return r_abs + 0.4 * i_abs;
68   else
69     return i_abs + 0.4 * r_abs;
70 }
71
72 int
73 gr_feedforward_agc_cc::work(int noutput_items,
74                             gr_vector_const_void_star &input_items,
75                             gr_vector_void_star &output_items)
76 {
77   const gr_complex *in = (const gr_complex *) input_items[0];
78   gr_complex *out = (gr_complex *) output_items[0];
79   int   nsamples = d_nsamples;
80   float gain;
81   
82   for (int i = 0; i < noutput_items; i++){
83     //float max_env = 1e-12;    // avoid divide by zero
84     float max_env = 1e-4;       // avoid divide by zero, indirectly set max gain
85     for (int j = 0; j < nsamples; j++)
86       max_env = std::max(max_env, envelope(in[i+j]));
87     gain = d_reference / max_env;
88     out[i] = gain * in[i];
89   }
90   return noutput_items;
91 }