Forum: GNU Radio Please help building a signal processing block.

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Mikhail T. (Guest)
on 2009-03-27 23:46
(Received via mailing list)
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.
Karthik (Guest)
on 2009-03-28 18:34
(Received via mailing list)
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-wri.... 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
Mikhail T. (Guest)
on 2009-03-29 03:36
(Received via mailing list)
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.
Karthik (Guest)
on 2009-03-29 12:39
(Received via mailing list)
Attachment: afm_fft2_ff.cc (0 Bytes)
Attachment: afm_fft2_ff.h (0 Bytes)
>>> 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<float> 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
Martin B. (Guest)
on 2009-03-30 11:27
(Received via mailing list)
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
Eric B. (Guest)
on 2009-03-31 10:57
(Received via mailing list)
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
Mikhail T. (Guest)
on 2009-04-02 15:01
(Received via mailing list)
Attachment: cores_weighted_avg_ff.cc (0 Bytes)
Attachment: cores_weighted_avg_ff.h (0 Bytes)
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.
This topic is locked and can not be replied to.