Preciso filtrar todo (ou pelo menos um pouquinho) o sinal toda vez que chegam algumas amostras novas ou existe uma maneira (como a DFT deslizante) em que é possível determinar com eficiência a nova parte do filtro filtrado sinal?
Os filtros digitais não funcionam assim - basicamente, o FIR ou IIR clássico pode funcionar em cada nova amostra . Você realmente deve ler sobre o que são esses filtros e como as pessoas os modelam.
Eu gostaria de usar um filtro butterworth
Bem, há muitas implementações disso por aí,
Atualmente, estou usando manteiga e filtro de scipy
dos quais você já conhece um!
Agora, um filtro butterworth é uma coisa recursiva; portanto, para calcular a próxima parte do sinal amostrado, você precisará do último estado. Esse é exatamente o "estado de atraso do filtro zi" que lfilter
retorna e pode receber a próxima chamada como zi
parâmetro.
mas não sei como usá-lo para obter um sinal constante.
Eu acho que você quer dizer "alcançar filtragem contínua".
Agora, dito isso, o ponto é que você está se preparando para escrever sua própria arquitetura de streaming. Eu não faria isso. Use uma estrutura existente. Por exemplo, há o GNU Radio, que permite definir gráficos de fluxo de processamento de sinal em Python, e também é inerentemente multithread, usa implementações de algoritmos altamente otimizadas, possui muitas facilidades de entrada e saída e vem com uma enorme biblioteca de blocos de processamento de sinal , que pode ser escrito em Python ou C ++, se você precisar fazer isso.
Por exemplo, um gráfico de fluxo que coleta amostras de uma placa de som, filtra-as com butterworth e as grava em um arquivo é:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Butterworth Test
# Generated: Mon Feb 8 16:17:18 2016
##################################################
from gnuradio import audio
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import filter
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser
class butterworth_test(gr.top_block):
def __init__(self):
gr.top_block.__init__(self, "Butterworth Test")
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 48000
##################################################
# Blocks
##################################################
# taps from scipy.butter!
self.iir_filter_xxx_0 = filter.iir_filter_ffd(([1.0952627450621233e-05, 0.00013143152940745496, 0.0007228734117410033, 0.0024095780391366808, 0.005421550588057537, 0.008674480940892064, 0.010120227764374086, 0.008674480940892081, 0.005421550588057554, 0.0024095780391366955, 0.0007228734117410089, 0.00013143152940745594, 1.0952627450621367e-05]), ([1.0, -4.4363862740719835, 10.215121830052535, -15.374408118154847, 16.57333784740102, -13.325056987818655, 8.133543488903097, -3.77641064765334, 1.3181452681671835, -0.3361758629961047, 0.05930166356243964, -0.0064815521348275, 0.00033130678123743994]), False)
self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_float*1, "", False)
self.blocks_file_sink_0.set_unbuffered(False)
self.audio_source_0 = audio.source(samp_rate, "", True)
##################################################
# Connections
##################################################
self.connect((self.audio_source_0, 0), (self.iir_filter_xxx_0, 0))
self.connect((self.iir_filter_xxx_0, 0), (self.blocks_file_sink_0, 0))
def main(top_block_cls=butterworth_test, options=None):
tb = top_block_cls()
tb.start()
try:
raw_input('Press Enter to quit: ')
except EOFError:
pass
tb.stop()
tb.wait()
if __name__ == '__main__':
main()
Observe que esse código foi gerado automaticamente a partir de um gráfico de fluxo gráfico que eu apenas cliquei usando o gnuradio-companion
programa:
Se você quiser saber mais sobre como implementar gráficos de fluxo de processamento de sinal em Python, vá para os tutoriais guiados por rádio da GNU .
EDIT : Gostei bastante da resposta da @ Fat32! O que ele descreve como uma arquitetura de buffer duplo é bem parecido com o que o GNU Radio faz:
Um bloco upstream produz amostras em pedaços de tamanhos arbitrários, grava-os no buffer do anel de saída (que é representado como uma seta na figura acima) e notifica seus blocos downstream de que há novos dados.
O bloco downstream é notificado, verifica se há espaço suficiente em seu buffer de saída para processar as amostras que estão em seu buffer de anel de entrada (que é o mesmo que o buffer de saída do bloco upstream), processa-os. Quando finalizado, informa o (s) bloco (s) a montante que utilizou o buffer do anel de entrada (que pode ser reutilizado pelos blocos a montante como saída) e os blocos a jusante sobre a disponibilidade de novas amostras.
Agora, com o GNU Radio sendo multiencadeado, o bloco upstream já pode estar produzindo amostras novamente; em um aplicativo normal do GNU Radio, quase todos os blocos estão "ativos" simultaneamente e as coisas se adaptam muito bem em máquinas com várias CPUs.
Portanto, a principal tarefa do GNU Radio é fornecer a você essa infraestrutura de buffer, a limpeza de notificações e encadeamentos, a API clara do bloco de processamento de sinal e algo para definir como tudo está conectado, para que você não precise escrever o que o Fat32 descreve nela. publique-se! Observe que não é tão fácil fazer a organização do fluxo de amostra, e o GNU Radio elimina a dureza e permite que você se concentre no que você quer fazer: DSP.