Block with N inputs and M outputs (M>=N)

I am trying to write a block that takes N inputs at a time
and produces M outputs at a time.
Since M>=N this is an interpolator.
However, M/N is not neccesarily an integer.

Is there an elegant way to force the work() function to
process a multiple number of N input samples every time it is called?

Thanks
Achilleas

Let’s assume you’re working with 1 input and output stream.

If the interpolator block doesn’t do it for you (I think it does, so try
to inherit from that code), use “set_output_multiple(M)”, then make sure
your “forecast()” function sets the input stream’s required items
correctly (to a multiple of N). “forecast()” will always be called with
“noutput” being a multiple of “M”, which makes finding the required
items simple (#in = #out * M / N). You should do an “assert(M % N ==
0)” before before the divide just to be sure it’s OK.

Hope this helps! - MLD

On Mon, 10 Apr 2006 09:36:51 -0400, “Achilleas A.”
[email protected] said:

I am trying to write a block that takes N inputs at a time
and produces M outputs at a time.
Since M>=N this is an interpolator.
However, M/N is not neccesarily an integer.

Is there an elegant way to force the work() function to
process a multiple number of N input samples every time it is called?

Michael D.
[email protected]

Just a quick additive note, all from my testing of
“set_output_multiple()”:

“set_output_multiple (M)” will work so long as M isn’t too big.
Anything up to 100 or so seems to work OK; even 1000 or so usually
works. 5000 or higher generally doesn’t work, though I’m sure there
are specific values which would work (e.g. powers of 2 are more likely
than prime numbers). Unless your M and N are “small enough”, then
you’ll likely need to inherit from “gr_block” directory and use
“general_work()”. Using a finite-state machine (FSM; e.g. the GMSK
packet sink), if your task can be broken down into parts as well as
picked up from available “history”, would allow for a much more robust
implementation - taking in whatever input data is available, not just a
given multiple of some number, and producing whatever it can from that
data. The trade-off is that "forecast()"ing the number of input items
required for a given number of output items is potentially more
challenging … could depend on the amount of accumulated history, what
state the FSM is in, etc… - MLD

Michael,

Thanks for the info.
Indeed I am looking into small numbers of M,N (order of 10)
so this should work.

Can I ask for a clarification here:

If the interpolator block doesn’t do it for you (I think it does, so try
to inherit from that code),

Since my overall interpolator block is an M/N-interpolator, even if I
inherit from interpolator, it does not force output_multiple to M,
but rather multiples of (M/N), which is not what I want.
I guess I have to inherit from block and do that manually using
set_output_multiple(M), as you suggested.

am I right?

[email protected] said:

I am trying to write a block that takes N inputs at a time
and produces M outputs at a time.
Since M>=N this is an interpolator.
However, M/N is not neccesarily an integer.

Is there an elegant way to force the work() function to
process a multiple number of N input samples every time it is called?


Achilleas A.
Associate Professor
EECS Department Voice : (734)615-4024
UNIVERSITY OF MICHIGAN Fax : (734)763-8041
Ann Arbor, MI 48109-2122 E-mail: [email protected]
URL: U-M Web Hosting


Achilleas - I did not have the gr_sync_interpolator code in front of
me when I wrote originally, so it was a guess … which was not
entirely correct (the interpolation must be an -integer- value, while
yours is not guaranteed to be so). Thus, yes, you will need to
inherit from “gr_block” and, since M and N are reasonably small, you
can use “set_output_multiple(M)” to guarantee a multiple of N input
items when you use write “forecast()” to handle this. For example,
if “d_M” and “d_N” are the values of M and N at instantiation, then …

  1. In your instantiator, include:
    +++
    // Set the approximate output rate / input rate
    set_relative_rate (1.0 * d_M / ((double) d_N));
    // Set the output multiple to guarantee a multiple of M
    set_output_multiple (d_M);
    +++
  2. In forecast (), include:
    +++
    // Check that the number of requested output items is a multiple of M
    assert (noutput_items % d_M == 0);
    // find the number of input items required to
    // generate the requested number of output items
    int ninput_items = d_N * noutput_items / d_M;
    // set all streams’ input requirements
    unsigned ninputs = ninput_items_required.size ();
    for (unsigned i = 0; i < ninputs; i++)
    ninput_items_required[i] = ninput_items;
    +++
  3. In general_work (), include:
    +++
    // Check that the number of requested output items is a multiple of M
    assert (noutput_items % d_M == 0);
    // find the number of input items required to
    // generate the requested number of output items
    int ninput_items = d_N * noutput_items / d_M;
    +++
    to get the number of input items as make sure it really is a multiple
    of N (via that the # of output items is a multiple of M). You can,
    of course, choose other means for doing this which are more in your
    coding style. And the asserts can be dropped (I use #if’s) once
    you’re happy that it’s all working as you want. Hope this is clear!
  • MLD

I would take a look at gr_rational_resampler. The forecasting and all
of the control stuff should be useful for you.

Matt