Please help building a signal processing block


#1

Hello,

I’m trying to build several signal processing blocks for a project that
I’m
doing using USRP2. I was going through the examples and sample code
along
with browsing the source code and I can’t seem to find exactly what I
need.
I’m trying to do an average of a vector of length N:

Input vector size N
Output vector size 1
I’m doing it for floats.


#ifndef INCLUDED_CORES_WEIGHTED_AVG_FF_H
#define INCLUDED_CORES_WEIGHTED_AVG_FF_H
#include <gr_sync_block.h>
class cores_weighted_avg_ff;

typedef boost::shared_ptr<cores_weighted_avg_ff>
cores_weighted_avg_ff_sptr;
cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff (unsigned int
vlen);

class cores_weighted_avg_ff : public gr_sync_block
{
private:
friend cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff
(unsigned
int vlen);
cores_weighted_avg_ff (unsigned int vlen); // private constructor
unsigned int d_vlen;

public:
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif

and source

#ifdef HAVE_CONFIG_H
#include “config.h”
#endif
#include <cores_weighted_avg_ff.h>
#include <gr_io_signature.h>

cores_weighted_avg_ff_sptr
cores_make_weighted_avg_ff (unsigned int vlen)
{ return cores_weighted_avg_ff_sptr (new cores_weighted_avg_ff
(vlen));}

cores_weighted_avg_ff::cores_weighted_avg_ff (unsigned int vlen)
: gr_decimator_block (“weighed_avg_ff”,
gr_make_io_signature (1, 1, sizeof (float) * vlen),
gr_make_io_signature (1, 1, sizeof (float))),
d_vlen(vlen)
{
}
int
cores_weighted_avg_ff::int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
int noi = noutput_items * d_vlen;

  for (int i = 0; i < noi; i++){
    out += in[i]*i;
  }
  out /= d_vlen;
  consume(noutput_items,d_vlen)

  return noutput_items;

}

I’m not sure if the code is correct what I want to do (input is more
than
welcome), when I compile this code I get a weird error:
cores_weighted_avg_ff.h: In function ‘PyObject*
_wrap_weighted_avg_ff(PyObject*, PyObject*)’:
cores_weighted_avg_ff.h:63: error: too few arguments to function
‘cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff(unsigned int)’
cores.cc:4326: error: at this point in file
make[4]: *** [cores.lo] Error 1

Any help would be greatly appreciated.


#2

2009/3/27 Mikhail T. removed_email_address@domain.invalid

class cores_weighted_avg_ff : public gr_sync_block
gr_vector_const_void_star &input_items,
#endif
gr_make_io_signature (1, 1, sizeof (float))),
float *out = (float *) output_items[0];

Any help would be greatly appreciated.

With gr_sync_block you only need to write work() and not general_work().
The
example at the end of this tutorial will be helpful
http://www.gnu.org/software/gnuradio/doc/howto-write-a-block.html. Also,
there is a “#endif” sitting in the middle of your code, it might be a
typo.

btw, if you are trying to get moving averages, there is a block already
available gr_moving_averages()

Karthik


#3

Thanks, but I’m trying to get weighted average specifically. I’ve looked
at
the code for moving_average… it’s close to what I need, but its 1:1
in/out
ratio, but I need N:1 ratio. That’s the part I’m particular unclear
about.


#4

along with browsing the source code and I can’t seem to find exactly what I
class cores_weighted_avg_ff;
int vlen);

cores_weighted_avg_ff_sptr
int
out += in[i]*i;
welcome), when I compile this code I get a weird error:
With gr_sync_block you only need to write work() and not general_work().

Thanks, but I’m trying to get weighted average specifically. I’ve looked at
the code for moving_average… it’s close to what I need, but its 1:1 in/out
ratio, but I need N:1 ratio. That’s the part I’m particular unclear about.

I have done something very similar in the past. I derive my block from
gr_sync_decimator to keep things simple. The value of ‘N’ is an input to
the
block and is assumed to be constant. In the myblock_ff.h file define a
std::vector d_buffer. in the myblock_ff.cc you will have a line
such
as

myblock_ff::myblock_ff(int N) :
gr_sync_decimator(“myblock”,gr_io_sig…,gr_io_sig…,N)

Here, N sets the decimation factor. In the work() function, you loop
over
all inputs and keep stuffing your inputs into d_buffer, using
d_buffer.push_back(). Once the length reaches N, you do your average or
other calculations, write an output and do d_buffer.clear(). This will
work
even if your number of inputs is not a multiple of N since your buffer
will
continue filling up from where you left the next time the work()
function is
called.

I have attached the source from my code, but it has a lot going on in
there
and isn’t really commented. Line #152 in the .cc file does exactly what
you
want to do, although in a different context. Hope this helps.

Karthik


#5

On Sat, Mar 28, 2009 at 05:35:59PM -0700, Mikhail T. wrote:

Thanks, but I’m trying to get weighted average specifically. I’ve looked at the
code for moving_average… it’s close to what I need, but its 1:1 in/out ratio,
but I need N:1 ratio. That’s the part I’m particular unclear about.

Since you’re turning 1 vector into 1 output value, you could also use a
gr_sync_block and prepend it with a gr_stream_to_vector. That
automatically takes care of aligning etc.; if you use a sync_decimator
you’re not guaranteed to get N samples every time.

This should pretty much be the simplest solution.

Cheers
MB


#6

On Mon, Mar 30, 2009 at 09:17:18AM +0200, Martin B. wrote:

On Sat, Mar 28, 2009 at 05:35:59PM -0700, Mikhail T. wrote:

Thanks, but I’m trying to get weighted average specifically. I’ve looked at the
code for moving_average… it’s close to what I need, but its 1:1 in/out ratio,
but I need N:1 ratio. That’s the part I’m particular unclear about.

Since you’re turning 1 vector into 1 output value, you could also use a
gr_sync_block and prepend it with a gr_stream_to_vector. That
automatically takes care of aligning etc.; if you use a sync_decimator
you’re not guaranteed to get N samples every time.

Actually, with a sync decimator, you’ll get a multiple of N input
samples
every time.

Eric


#7

Thank you all for help/suggestions.

I think I was most successful in implementing it the way Karthik
described
it. My code below:
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];

for (int i = 0; i < d_vlen; i++){
temp = in[i] * (i+1);
d_buffer.push_back(temp);
}
for(int j = 0; j < d_vlen; j++) {avg += d_buffer[j]; }

out[0] = avg / d_vlen;
d_buffer.clear();

It seems to work with built-in “how to…block” test script. I’ve tried
putting in a size 512 vector and received an output vector of length 1.

Regards,
Mikhail

P.S. I’ve attached my code if somebody wants a look.