Exemplo n.º 1
0
def design_sawtooth_filter(
        ntaps=40,
        decreasing=False,
        window_type=window.WIN_HAMMING,
        beta=0):
    """
    This filter has a response which increases or decreases linearly with frequency, cut at f_s/2. Its gain is 1 at frequency 0 and thus also 1 averaged over all frequencies.
    """
    window_values = window.build(window_type, ntaps, beta)
    
    # Formula provided by Olli Niemitalo in <http://dsp.stackexchange.com/a/28035/4655>.
    taps = []
    for i in xrange(0, ntaps):
        k = i - ntaps // 2  # k = 0 at middle
        if k == 0:
            # substitute limit for division by zero
            ideal_response = complex(pi, 0)
        else:
            # The real part is pi * sinc(k), but that is always zero when k != 0.
            ideal_response = complex(0, sin(pi * k) / (pi * k * k) - cos(pi * k) / k)
        taps.append(window_values[i] * ideal_response)
        
    # Compute gain at frequency 0, and divide by it so as to set the wanted gain.
    gain_factor = 1.0 / abs(sum(taps))
    for i in xrange(0, ntaps):
        taps[i] *= gain_factor
    
    # Reverse if appropriate.
    if decreasing:
        taps = taps[::-1]
    return taps
Exemplo n.º 2
0
def design_sawtooth_filter(ntaps=40,
                           decreasing=False,
                           window_type=window.WIN_HAMMING,
                           beta=0):
    """
    This filter has a response which increases or decreases linearly with frequency, cut at f_s/2. Its gain is 1 at frequency 0 and thus also 1 averaged over all frequencies.
    """
    window_values = window.build(window_type, ntaps, beta)

    # Formula provided by Olli Niemitalo in <http://dsp.stackexchange.com/a/28035/4655>.
    taps = []
    for i in six.moves.range(0, ntaps):
        k = i - ntaps // 2  # k = 0 at middle
        if k == 0:
            # substitute limit for division by zero
            ideal_response = complex(pi, 0)
        else:
            # The real part is pi * sinc(k), but that is always zero when k != 0.
            ideal_response = complex(
                0,
                sin(pi * k) / (pi * k * k) - cos(pi * k) / k)
        taps.append(window_values[i] * ideal_response)

    # Compute gain at frequency 0, and divide by it so as to set the wanted gain.
    gain_factor = 1.0 / abs(sum(taps))
    for i in six.moves.range(0, ntaps):
        taps[i] *= gain_factor

    # Reverse if appropriate.
    if decreasing:
        taps = taps[::-1]
    return taps
Exemplo n.º 3
0
    def __do_connect(self):
        itemsize = self.__itemsize

        if self.__signal_type.is_analytic():
            input_length = self.__freq_resolution
            output_length = self.__freq_resolution
            self.__after_fft = None
        else:
            # use vector_to_streams to cut the output in half and discard the redundant part
            input_length = self.__freq_resolution * 2
            output_length = self.__freq_resolution
            self.__after_fft = blocks.vector_to_streams(
                itemsize=output_length * gr.sizeof_float, nstreams=2)

        sample_rate = self.__signal_type.get_sample_rate()
        overlap_factor = int(
            math.ceil(_maximum_fft_rate * input_length / sample_rate))
        # sanity limit -- OverlapGimmick is not free
        overlap_factor = min(16, overlap_factor)

        self.__frame_rate_to_decimation_conversion = sample_rate * overlap_factor / input_length

        self.__gate = blocks.copy(itemsize)
        self.__gate.set_enabled(not self.__paused)

        overlapper = _OverlappedStreamToVector(size=input_length,
                                               factor=overlap_factor,
                                               itemsize=itemsize)

        self.__frame_dec = blocks.keep_one_in_n(
            itemsize=itemsize * input_length,
            n=max(
                1,
                int(
                    round(self.__frame_rate_to_decimation_conversion /
                          self.__frame_rate))))

        # the actual FFT logic, which is similar to GR's logpwrfft_c
        window = windows.build(self.__window_type, input_length, 6.76)
        window_power = sum(x * x for x in window)
        # TODO: use fft_vfc when applicable
        fft_block = (fft_vcc if itemsize == gr.sizeof_gr_complex else fft_vfc)(
            fft_size=input_length, forward=True, window=window)
        mag_squared = blocks.complex_to_mag_squared(input_length)
        logarithmizer = blocks.nlog10_ff(
            n=10,  # the "deci" in "decibel"
            vlen=input_length,
            k=(
                -to_dB(window_power) +  # compensate for window
                -to_dB(sample_rate)
                +  # convert from power-per-sample to power-per-Hz
                self.__power_offset  # offset for packing into bytes
            ))

        # It would make slightly more sense to use unsigned chars, but blocks.float_to_uchar does not support vlen.
        self.__fft_converter = blocks.float_to_char(
            vlen=self.__freq_resolution, scale=1.0)

        fft_sink = self.__fft_cell.create_sink_internal(
            numpy.dtype((numpy.int8, output_length)))
        scope_sink = self.__scope_cell.create_sink_internal(
            numpy.dtype(('c8', self.__time_length)))
        scope_chunker = blocks.stream_to_vector_decimator(
            item_size=gr.sizeof_gr_complex,
            sample_rate=sample_rate,
            vec_rate=self.__frame_rate,  # TODO doesn't need to be coupled
            vec_len=self.__time_length)

        # connect everything
        self.__context.lock()
        try:
            self.disconnect_all()
            self.connect(self, self.__gate, overlapper, self.__frame_dec,
                         fft_block, mag_squared, logarithmizer)
            if self.__after_fft is not None:
                self.connect(logarithmizer, self.__after_fft)
                self.connect(self.__after_fft, self.__fft_converter, fft_sink)
                self.connect(
                    (self.__after_fft, 1),
                    blocks.null_sink(gr.sizeof_float * self.__freq_resolution))
            else:
                self.connect(logarithmizer, self.__fft_converter, fft_sink)
            if self.__enable_scope:
                self.connect(self.__gate, scope_chunker, scope_sink)
        finally:
            self.__context.unlock()
Exemplo n.º 4
0
    def __do_connect(self):
        itemsize = self.__itemsize
        
        if self.__signal_type.is_analytic():
            input_length = self.__freq_resolution
            output_length = self.__freq_resolution
            self.__after_fft = None
        else:
            # use vector_to_streams to cut the output in half and discard the redundant part
            input_length = self.__freq_resolution * 2
            output_length = self.__freq_resolution
            self.__after_fft = blocks.vector_to_streams(itemsize=output_length * gr.sizeof_float, nstreams=2)
        
        sample_rate = self.__signal_type.get_sample_rate()
        overlap_factor = int(math.ceil(_maximum_fft_rate * input_length / sample_rate))
        # sanity limit -- OverlapGimmick is not free
        overlap_factor = min(16, overlap_factor)
        
        self.__frame_rate_to_decimation_conversion = sample_rate * overlap_factor / input_length
        
        self.__gate = blocks.copy(itemsize)
        self.__gate.set_enabled(not self.__paused)
        
        overlapper = _OverlappedStreamToVector(
            size=input_length,
            factor=overlap_factor,
            itemsize=itemsize)
        
        self.__frame_dec = blocks.keep_one_in_n(
            itemsize=itemsize * input_length,
            n=max(1, int(round(self.__frame_rate_to_decimation_conversion / self.__frame_rate))))
        
        # the actual FFT logic, which is similar to GR's logpwrfft_c
        window = windows.build(self.__window_type, input_length, 6.76)
        window_power = sum(x * x for x in window)
        # TODO: use fft_vfc when applicable
        fft_block = (fft_vcc if itemsize == gr.sizeof_gr_complex else fft_vfc)(
            fft_size=input_length,
            forward=True,
            window=window)
        mag_squared = blocks.complex_to_mag_squared(input_length)
        logarithmizer = blocks.nlog10_ff(
            n=10,  # the "deci" in "decibel"
            vlen=input_length,
            k=(
                -to_dB(window_power) +  # compensate for window
                -to_dB(sample_rate) +  # convert from power-per-sample to power-per-Hz
                self.__power_offset  # offset for packing into bytes
            ))
        
        # It would make slightly more sense to use unsigned chars, but blocks.float_to_uchar does not support vlen.
        self.__fft_converter = blocks.float_to_char(vlen=self.__freq_resolution, scale=1.0)
        
        fft_sink = self.__fft_cell.create_sink_internal(numpy.dtype((numpy.int8, output_length)))
        scope_sink = self.__scope_cell.create_sink_internal(numpy.dtype(('c8', self.__time_length)))
        scope_chunker = blocks.stream_to_vector_decimator(
            item_size=gr.sizeof_gr_complex,
            sample_rate=sample_rate,
            vec_rate=self.__frame_rate,  # TODO doesn't need to be coupled
            vec_len=self.__time_length)

        # connect everything
        self.__context.lock()
        try:
            self.disconnect_all()
            self.connect(
                self,
                self.__gate,
                overlapper,
                self.__frame_dec,
                fft_block,
                mag_squared,
                logarithmizer)
            if self.__after_fft is not None:
                self.connect(logarithmizer, self.__after_fft)
                self.connect(self.__after_fft, self.__fft_converter, fft_sink)
                self.connect((self.__after_fft, 1), blocks.null_sink(gr.sizeof_float * self.__freq_resolution))
            else:
                self.connect(logarithmizer, self.__fft_converter, fft_sink)
            if self.__enable_scope:
                self.connect(
                    self.__gate,
                    scope_chunker,
                    scope_sink)
        finally:
            self.__context.unlock()