Skip to content

Commit 295f5a6

Browse files
committed
Added a vector operation mode to the moving average
This allows users to average per-element. Might be very useful for spectrum "condensing" and such.
1 parent 34933ac commit 295f5a6

File tree

5 files changed

+102
-23
lines changed

5 files changed

+102
-23
lines changed

gr-blocks/grc/blocks_moving_average_xx.xml

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<name>Moving Average</name>
99
<key>blocks_moving_average_xx</key>
1010
<import>from gnuradio import blocks</import>
11-
<make>blocks.moving_average_$(type.fcn)($length, $scale, $max_iter)</make>
11+
<make>blocks.moving_average_$(type.fcn)($length, $scale, $max_iter, $vlen)</make>
1212
<callback>set_length_and_scale($length, $scale)</callback>
1313
<param>
1414
<name>Type</name>
@@ -57,12 +57,21 @@
5757
<value>4000</value>
5858
<type>int</type>
5959
</param>
60+
<param>
61+
<name>Length of Vectors</name>
62+
<key>vlen</key>
63+
<value>1</value>
64+
<type>int</type>
65+
</param>
66+
<check>$vlen &gt; 0</check>
6067
<sink>
6168
<name>in</name>
6269
<type>$type</type>
70+
<vlen>$vlen</vlen>
6371
</sink>
6472
<source>
6573
<name>out</name>
6674
<type>$type</type>
75+
<vlen>$vlen</vlen>
6776
</source>
6877
</block>

gr-blocks/include/gnuradio/blocks/moving_average_XX.h.t

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- c++ -*- */
22
/*
3-
* Copyright 2008,2013 Free Software Foundation, Inc.
3+
* Copyright 2008,2013,2017 Free Software Foundation, Inc.
44
*
55
* This file is part of GNU Radio
66
*
@@ -48,9 +48,11 @@ namespace gr {
4848
* \param scale scale factor for the result.
4949
* \param max_iter limits how long we go without flushing the accumulator
5050
* This is necessary to avoid numerical instability for float and complex.
51+
* \param vlen When > 1, do a per-vector-element moving average
5152
*/
5253
static sptr make(int length, @O_TYPE@ scale,
53-
int max_iter = 4096);
54+
int max_iter = 4096,
55+
unsigned int vlen = 1);
5456

5557
/*!
5658
* Get the length used in the avaraging calculation.

gr-blocks/lib/moving_average_XX_impl.cc.t

+42-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- c++ -*- */
22
/*
3-
* Copyright 2008,2010,2013 Free Software Foundation, Inc.
3+
* Copyright 2008,2010,2013,2017 Free Software Foundation, Inc.
44
*
55
* This file is part of GNU Radio
66
*
@@ -33,24 +33,30 @@ namespace gr {
3333
namespace blocks {
3434

3535
@NAME@::sptr
36-
@NAME@::make(int length, @O_TYPE@ scale, int max_iter)
36+
@NAME@::make(int length, @O_TYPE@ scale, int max_iter, unsigned int vlen)
3737
{
3838
return gnuradio::get_initial_sptr
39-
(new @NAME_IMPL@(length, scale, max_iter));
39+
(new @NAME_IMPL@(length, scale, max_iter, vlen));
4040
}
4141

42-
@NAME_IMPL@::@NAME_IMPL@(int length, @O_TYPE@ scale, int max_iter)
42+
@NAME_IMPL@::@NAME_IMPL@(int length, @O_TYPE@ scale, int max_iter, unsigned int vlen)
4343
: sync_block("@NAME@",
44-
io_signature::make(1, 1, sizeof(@I_TYPE@)),
45-
io_signature::make(1, 1, sizeof(@O_TYPE@))),
44+
io_signature::make(1, 1, sizeof(@I_TYPE@)*vlen),
45+
io_signature::make(1, 1, sizeof(@O_TYPE@)*vlen)),
4646
d_length(length),
4747
d_scale(scale),
4848
d_max_iter(max_iter),
49+
d_vlen(vlen),
4950
d_new_length(length),
5051
d_new_scale(scale),
5152
d_updated(false)
5253
{
5354
set_history(length);
55+
//we don't have C++11's <array>, so initialize the stored vector instead
56+
//we store this vector so that work() doesn't spend its time allocating and freeing vector storage
57+
if(d_vlen > 1) {
58+
d_sum = std::vector<@I_TYPE@>(d_vlen);
59+
}
5460
}
5561

5662
@NAME_IMPL@::~@NAME_IMPL@()
@@ -95,18 +101,37 @@ namespace gr {
95101
const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0];
96102
@O_TYPE@ *out = (@O_TYPE@ *)output_items[0];
97103

98-
@I_TYPE@ sum = 0;
99-
int num_iter = (noutput_items>d_max_iter) ? d_max_iter : noutput_items;
100-
for(int i = 0; i < d_length-1; i++) {
101-
sum += in[i];
102-
}
103-
104-
for(int i = 0; i < num_iter; i++) {
105-
sum += in[i+d_length-1];
106-
out[i] = sum * d_scale;
107-
sum -= in[i];
104+
unsigned int num_iter = (unsigned int)((noutput_items>d_max_iter) ? d_max_iter : noutput_items);
105+
if(d_vlen == 1) {
106+
@I_TYPE@ sum = 0;
107+
for(unsigned int i = 0; i < d_length-1; i++) {
108+
sum += in[i];
109+
}
110+
111+
for(unsigned int i = 0; i < num_iter; i++) {
112+
sum += in[i+d_length-1];
113+
out[i] = sum * d_scale;
114+
sum -= in[i];
115+
}
116+
117+
} else { // d_vlen > 1
118+
//TODO: VOLKize this zeroing?
119+
std::fill(d_sum.begin(), d_sum.end(), (@I_TYPE@)0);
120+
121+
for(unsigned int i = 0; i < d_length - 1; i++) {
122+
for(unsigned int elem = 0; elem < d_vlen; elem++) {
123+
d_sum[elem] += in[i*d_vlen + elem];
124+
}
125+
}
126+
127+
for(unsigned int i = 0; i < num_iter; i++) {
128+
for(unsigned int elem = 0; elem < d_vlen; elem++) {
129+
d_sum[elem] += in[(i+d_length-1)*d_vlen + elem];
130+
out[i*d_vlen + elem] = d_sum[elem] * d_scale;
131+
d_sum[elem] -= in[i*d_vlen + elem];
132+
}
133+
}
108134
}
109-
110135
return num_iter;
111136
}
112137

gr-blocks/lib/moving_average_XX_impl.h.t

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* -*- c++ -*- */
22
/*
3-
* Copyright 2008,2013 Free Software Foundation, Inc.
3+
* Copyright 2008,2013,2017 Free Software Foundation, Inc.
44
*
55
* This file is part of GNU Radio
66
*
@@ -25,6 +25,8 @@
2525
#ifndef @GUARD_NAME_IMPL@
2626
#define @GUARD_NAME_IMPL@
2727

28+
#include <vector>
29+
#include <algorithm>
2830
#include <gnuradio/blocks/@[email protected]>
2931

3032
namespace gr {
@@ -36,18 +38,23 @@ namespace gr {
3638
int d_length;
3739
@O_TYPE@ d_scale;
3840
int d_max_iter;
41+
unsigned int d_vlen;
42+
std::vector<@I_TYPE@> d_sum;
43+
3944

4045
int d_new_length;
4146
@O_TYPE@ d_new_scale;
4247
bool d_updated;
4348

4449
public:
4550
@NAME_IMPL@(int length, @O_TYPE@ scale,
46-
int max_iter = 4096);
51+
int max_iter = 4096,
52+
unsigned int vlen = 1);
4753
~@NAME_IMPL@();
4854

4955
int length() const { return d_new_length; }
5056
@O_TYPE@ scale() const { return d_new_scale; }
57+
unsigned int vlen() const { return d_vlen; }
5158

5259
void set_length_and_scale(int length, @O_TYPE@ scale);
5360
void set_length(int length);

gr-blocks/python/blocks/qa_moving_average.py

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
#
3-
# Copyright 2013 Free Software Foundation, Inc.
3+
# Copyright 2013,2017 Free Software Foundation, Inc.
44
#
55
# This file is part of GNU Radio
66
#
@@ -87,5 +87,41 @@ def test_02(self):
8787
# make sure result is close to zero
8888
self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
8989

90+
def test_03(self):
91+
tb = self.tb
92+
93+
print "setting up"
94+
vlen = 5
95+
N = 10*vlen
96+
seed = 0
97+
data = make_random_float_tuple(N, 2**10)
98+
data = [int(d*1000) for d in data]
99+
print "making blocks"
100+
src = blocks.vector_source_i(data, False)
101+
one_to_many = blocks.stream_to_streams(gr.sizeof_int, vlen)
102+
one_to_vector = blocks.stream_to_vector(gr.sizeof_int, vlen)
103+
many_to_vector = blocks.streams_to_vector(gr.sizeof_int, vlen)
104+
isolated = [ blocks.moving_average_ii(100, 1) for i in range(vlen)]
105+
dut = blocks.moving_average_ii(100, 1, vlen=vlen)
106+
dut_dst = blocks.vector_sink_i(vlen=vlen)
107+
ref_dst = blocks.vector_sink_i(vlen=vlen)
108+
109+
print "connecting"
110+
tb.connect(src, one_to_many)
111+
tb.connect(src, one_to_vector, dut, dut_dst)
112+
tb.connect(many_to_vector, ref_dst)
113+
for idx, single in enumerate(isolated):
114+
tb.connect((one_to_many,idx), single, (many_to_vector,idx))
115+
116+
117+
print "running"
118+
tb.run()
119+
120+
print "comparing"
121+
dut_data = dut_dst.data()
122+
ref_data = ref_dst.data()
123+
124+
# make sure result is close to zero
125+
self.assertTupleEqual(dut_data, ref_data)
90126
if __name__ == '__main__':
91127
gr_unittest.run(test_moving_average, "test_moving_average.xml")

0 commit comments

Comments
 (0)