'Implement custom signal source in GNU Radio

I am trying to implement a custom signal source in GNU Radio, which must emit a band-passed white gaussian noise, centered around a frequency f, having a two-sided bandwidth BW, as shown in the pictureenter image description here

To do so, I should implement a bandpass filter and apply it to Gaussian random variables. The output of the filter reads

where the taps are the filter coefficients, and is the filter input. The taps in my case are obtained by using the Band-pass Filter Taps block of GNU Radio, and the input is set to random Gaussian variables.

To get the output of my filter, I should write a work function looking like

def work(self, input_items, output_items):
    samp_rate = self.get_samp_rate()
    f0 = self.get_f0()
    BW = self.get_BW()
    my_BP_filter = filter.fir_filter_fff(
                   1,
                   firdes.band_pass(
                       1,
                       samp_rate,
                       f0 - 0.5*BW,
                       f0 + 0.5*BW,
                       BW*1e-2,
                       firdes.WIN_HAMMING,
                       6.76
                       )
                   )
    taps = my_BP_filter.taps()
    ntaps = len(taps)

    min_array = min(output_items[0], taps, key=len)
    max_array = max(output_items[0], taps, key=len)
    min_len, max_len = len(min_array), len(max_array)

    noise = np.random.normal(loc=0.0, scale=1.0, size=min_len)

    t = 0.0
    for idx_out in range(len(output_items[0])):
        for idx_taps, val_taps in enumerate(taps):
            t += val_taps * noise[len(noise)-1-idx_taps]
        output_items[0][idx_out] = t

    return len(output_items[0])

but the code is extremely slow. How can I have a similar output to the shown picture (obtained with the following construction) ?

enter image description here



Solution 1:[1]

You Definitely (capital D) do not want to repeatedly reinstantiate a (make a new) filter in work.

Remember, work is called thousands of times, on consecutive chunks of data.

So, that's a fundamental architectural mistake there: you need one filter, which maintains its state between calls to work.

Also, you must never write signal processing that depends on the "view" of your data, i.e. how the endless stream of samples happens to arrive at your block. Imagine this very long stream of numbers:

… … -2 -1 0 1 2 3 4 5 … …

Your work gets called on a chunking of that, e.g. your first work gets the values -4000 to -2000, your second the -1999 to -1990, the third the -1989 to 2000, the fourth the 2001 to 2466, you get the idea.

Or, it goes completely different, and on the first call to work, you see -4000 to -2001, on the second -2000 to -1500, on the third -1499 to -500, on the fourth -499 to 0, on the fifth 1 to 2466.

Then, your min_aray, and max_len depend on how the signal was packaged. That is bad, as it changes the math you do.

I'd advice on what to implement, but the whole block really makes no sense to me. It is unnecessary – using an existing band-pass filter on a noise source does the same – and if I were to recommend how to do it, I'd recommend implementing the same yourself, not anything different: Two blocks, one generating the noise, a second block shaping it with a properly implemented bandpass filter, using the source code of the existing filter as example.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1