Lọc tín hiệu số trực tuyến trong thời gian thực bằng python


7

Tôi hiện đang cố gắng áp dụng bộ lọc thông dải cho tín hiệu trong thời gian thực. Có những mẫu đến với tốc độ lấy mẫu không đổi và tôi muốn tính toán tín hiệu được lọc băng thông tương ứng.

cách nào tốt nhất để làm việc này? Tôi có phải lọc toàn bộ (hoặc ít nhất một chút rất lớn) tín hiệu mỗi khi có một vài mẫu mới xuất hiện hoặc có cách nào (như DFT trượt) trong đó có thể xác định hiệu quả phần mới của bộ lọc tín hiệu?

Tôi muốn sử dụng bộ lọc butterworth (để phân tích ngoại tuyến, tôi hiện đang sử dụng bơ và lfilter của scipy). Tôi biết rằng chức năng này có thể trả về độ trễ của bộ lọc, nhưng tôi không biết cách sử dụng nó để có được tín hiệu không đổi.

Câu trả lời:


1

Các cơ chế cơ bản của việc thực hiện xử lý auido kỹ thuật số thời gian thực trong nền tảng PC cho mục đích chung dựa trên X-windows dựa trên việc sử dụng nhóm kiến ​​trúc đệm đôi.

Trong kiến ​​trúc này, âm thanh phát ra từ mic / line-in trước tiên được chuyển đổi thành các mẫu thông qua ADC soundcard và sau đó nó được điền vào bộ đệm đầu vào ở tốc độ lấy mẫu Fs do người dùng chọn. Khi bộ đệm này đầy, đầu tiên phần cứng soundcard sẽ thông báo cho hệ điều hành và sau đó hệ điều hành sẽ thông báo cho chương trình của bạn. Và chương trình của bạn sau đó có thể truy cập vào khối và có thể bắt đầu xử lý các mẫu trong khối đó.

Tuy nhiên, đồng thời bận rộn với khối hiện tại, chương trình của bạn đã cung cấp một bộ đệm (thứ hai) khác để được lấp đầy bởi thẻ âm thanh với các mẫu đang đến trong khi bạn xử lý bộ đệm được điền đầy đủ. Khi bộ đệm hiện có này được xử lý hoàn toàn, bạn cần bắt đầu xử lý bộ đệm tiếp theo ngay lập tức mà không có bất kỳ độ trễ nào, đây là điều cần thiết cơ bản để phát lại âm thanh mượt mà không cần nhấp chuột. Theo cách đệm đôi này, bạn có cơ hội tạo ra một âm thanh mượt mà mà không bị trục trặc và nứt vỡ.

Ngoài ra, cho dù bạn sẽ thực hiện lọc dựa trên FIR hay IIR, bạn có thể lọc toàn bộ bộ đệm cùng một lúc như trường hợp FIR hoặc lấy mẫu đệ quy theo mẫu cho trường hợp IIR.

Kích thước của bộ đệm rất quan trọng đối với độ trễ ban đầu của quá trình. Vì vậy, nếu bạn lấy nó quá lớn, bạn phải đợi cho đến khi cả hai bộ đệm được lấp đầy trước khi xuất ra bất cứ thứ gì. Trên tay otehr nếu bạn lấy bộ đệm quá ngắn, thì hệ thống sẽ bị choáng ngợp bởi các ngắt đến.

Một lựa chọn tối ưu là từ 128 đến 1024 mẫu. Các độ dài bộ đệm này phù hợp để xử lý loại FFT sau này. Ngoài ra số lượng bộ đệm có thể được tăng lên cho thông lượng mạnh mẽ hơn trong các điều kiện tải hệ thống khác nhau. Nhưng ít nhất hai bộ đệm được yêu cầu.


2
Mặc dù tôi đang xử lý tín hiệu EEG nhưng tôi hoàn toàn có thể áp dụng điều này, cảm ơn bạn!
BStadlbauer

1
Nhân tiện, đó chính xác là mô tả về kiến ​​trúc bộ đệm xếp tầng của GNU Radio.
Marcus Müller

1
Tôi đã giải quyết bài viết của bạn trong phần mở rộng cho câu trả lời của tôi, @ Fat32; Tôi hy vọng bạn thích nó :)
Marcus Müller

@ MarcusMüller; Cảm ơn vi sự hợp tac. Tôi đánh giá cao;)
Fat32

5

Tôi có phải lọc toàn bộ (hoặc ít nhất một chút rất lớn) tín hiệu mỗi khi có một vài mẫu mới xuất hiện hoặc có cách nào (như DFT trượt) trong đó có thể xác định hiệu quả phần mới của bộ lọc tín hiệu?

Các bộ lọc kỹ thuật số không hoạt động như vậy - về cơ bản, FIR hoặc IIR cổ điển có thể hoạt động trên mọi mẫu mới . Bạn thực sự nên đọc về những bộ lọc này là gì và cách mọi người mô hình hóa chúng.

Tôi muốn sử dụng bộ lọc butterworth

Vâng, có rất nhiều triển khai đó,

Tôi hiện đang sử dụng bơ và lfilter của scipy

trong đó bạn đã biết một!

Bây giờ, bộ lọc butterworth là một thứ đệ quy, vì vậy để tính phần tiếp theo của tín hiệu được lấy mẫu của bạn, bạn sẽ cần trạng thái cuối cùng. Đó chính xác là "trạng thái trễ của bộ lọc zi" lfiltertrả về và có thể thực hiện cuộc gọi tiếp theo dưới dạng zitham số.

nhưng tôi không biết làm thế nào để sử dụng nó để có được tín hiệu liên tục.

Tôi nghĩ bạn có nghĩa là "để đạt được lọc liên tục".

Bây giờ, điều đó đang được nói, vấn đề là bạn đang tự thiết lập để viết kiến ​​trúc phát trực tuyến của riêng bạn. Tôi sẽ không làm điều đó. Sử dụng một khung hiện có. Ví dụ, có GNU Radio, cho phép bạn xác định biểu đồ luồng xử lý tín hiệu trong Python và cũng là đa luồng, sử dụng các triển khai thuật toán được tối ưu hóa cao, có nhiều phương tiện đầu vào và đầu ra, đi kèm với một thư viện khối xử lý tín hiệu khổng lồ , có thể được viết bằng Python hoặc C ++, nếu bạn cần phải làm điều đó.

Ví dụ: biểu đồ luồng lấy mẫu từ card âm thanh, butterworth lọc chúng và ghi chúng vào tệp là:

#!/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()

Lưu ý rằng mã này được tạo tự động từ biểu đồ luồng đồ họa mà tôi vừa nhấp vào bằng gnuradio-companionchương trình:

biểu đồ dòng chảy như được thiết kế trong GRC

Nếu bạn muốn biết thêm về cách triển khai biểu đồ luồng xử lý tín hiệu trong Python, hãy tìm Hướng dẫn có hướng dẫn của Radio Radio .

EDIT : Tôi thích câu trả lời của @ Fat32 khá nhiều! Những gì ông mô tả là một kiến ​​trúc bộ đệm đôi khá gần với những gì GNU Radio làm:

Một khối ngược dòng tạo ra các mẫu trong các khối mẫu có kích thước tùy ý, ghi chúng vào bộ đệm vòng đầu ra (được biểu thị như một mũi tên trong hình trên) và thông báo cho các khối xuôi dòng của nó có dữ liệu mới.

Khối hạ lưu được thông báo, kiểm tra xem có đủ không gian trong bộ đệm đầu ra để xử lý các mẫu trong bộ đệm vòng đầu vào của nó không (giống như bộ đệm đầu ra của khối ngược dòng), xử lý các mẫu này. Khi kết thúc, nó thông báo cho (các) khối ngược dòng rằng nó đã sử dụng hết bộ đệm vòng đầu vào (sau đó có thể được các khối ngược dòng sử dụng làm đầu ra) và các khối hạ lưu về các mẫu mới có sẵn.

Bây giờ, GNU Radio là đa luồng, khối ngược dòng có thể đã tạo ra các mẫu một lần nữa; trong một ứng dụng GNU Radio bình thường, gần như tất cả các khối đều "hoạt động" đồng thời và mọi thứ có quy mô khá tốt trên các máy đa CPU.

Vì vậy, công việc chính của GNU Radio là cung cấp cho bạn cơ sở hạ tầng bộ đệm này, thông báo và quản lý luồng, API khối xử lý tín hiệu rõ ràng và một cái gì đó để xác định cách mọi thứ được kết nối, vì vậy bạn không phải viết những gì Fat32 mô tả trong anh ấy / anh ấy tự đăng bài! Lưu ý rằng thực hiện việc sắp xếp luồng mẫu không dễ thực hiện đúng cách và GNU Radio sẽ loại bỏ độ cứng của nó và cho phép bạn tập trung vào những gì bạn muốn làm: DSP.


Cảm ơn bạn! Tôi đã xem xét GNU Radio nhưng vì tôi sẽ xử lý Tín hiệu EEG, tôi sẽ phải xây dựng mô-đun của riêng mình để sử dụng biểu đồ luồng bởi vì mọi mẫu đều có dấu thời gian phải theo dõi toàn bộ quá trình lọc.
BStadlbauer

Bạn không cần một khối cho điều đó. Các mẫu là liên tiếp và với tốc độ lấy mẫu cố định, thời gian có sẵn trực tiếp như tỷ lệ mẫu hiện tại
Marcus Müller

@ MarcusMüller; Kiến trúc GNU Radio này, mà bạn mô tả, thực sự là những gì triết lý hiện đại cung cấp để sử dụng. Tính linh hoạt, dễ mã hóa và quan trọng nhất là có thể tập trung vào mục tiêu cốt lõi của bạn (xử lý DSP), thay vì làm thế nào để đạt được điều đó bằng cách sử dụng các chi tiết cấp thấp phức tạp (như những gì xảy ra khi bạn cố gắng thực hiện kỹ thuật đệm đôi bằng các lệnh gọi Win32 API !)
Fat32

@ Fat32 chúng ta nên giảm bớt phong cách tiếp thị nhưng: Vâng, thực sự, và tất cả cùng với việc cung cấp một kiến ​​trúc bộ đệm không sao chép hiệu quả và một thư viện rộng lớn các khối sử dụng mã được tối ưu hóa bằng tay trên x86, đó là MMX, SSE, Các phần mở rộng SSE2, AVX và NEON của ARM khi áp dụng bằng Thư viện tối ưu hóa vectơ VOLK :)
Marcus Müller

@ MarcusMüller Hôm qua tôi có thời gian rảnh rỗi nên tôi đã tìm hiểu sâu hơn về GNU Radio và nó có vẻ khá hữu ích, chỉ tôi không hiểu làm thế nào tôi có thể "tự tay" đưa các mẫu vào khối sp, bởi vì (tất cả) được làm cho các nguồn âm thanh đến từ một thiết bị phần cứng. Bạn không biết nơi tôi có thể tìm thấy một sân khấu, vv để tự đẩy các mẫu vào chuỗi? PS Các mẫu EEG đến từ một lớp đặc biệt (LSL - Lớp phát trực tuyến phòng thí nghiệm) và có khoảng 64 kênh trên mỗi mẫu
BStadlbauer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.