6.15. Filtriranje i spektrogrami¶
Filtriranje, izglađivanje i spektri magnitude poslovi su susjedni sirovom FFT-u: izglađivanje ili pojasno filtriranje toka uzoraka, izračunavanje spektara magnitude u petlji za tok podataka bez dodjele memorije te ponovno tumačenje sirovih međuspremnika periferije kao polja s pomičnim zarezom. Dostupni alati:
sosfilt()– digitalni filtar primijenjen putem kaskadno povezanih sekcija drugog reda.spectrogram()– magnitudaabs(fft(...))bez međudodjela memorije.from_int16_buffer()i ostali pomoćniciulab.utilsfrom_*_buffer– izvuku polje s pomičnim zarezom iz međuspremnika čiji dtype ugrađenifrombuffer()ne pokriva.
6.15.1. Filtriranje s sosfilt¶
sosfilt() primjenjuje digitalni filtar beskonačnog impulsnog odziva (IIR) kao kaskadu sekcija drugog reda (SOS) – numerički robustan oblik. sos je niz sekcija duljine 6; x je 1-D ulaz:
from ulab import numpy as np
from ulab import scipy as sp
x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
sos = [[1, 2, 3, 1, 5, 6],
[1, 2, 3, 1, 5, 6]]
y = sp.signal.sosfilt(sos, x)
Svaki redak polja sos sadrži šest koeficijenata [b0, b1, b2, a0, a1, a2] za jednu biquad sekciju. Polje sos obično se unaprijed izračunava na računalu pomoću scipy.signal.iirfilter(..., output='sos') i kopira u skriptu kamere kao Python literal.
Neobavezna ključna riječ zi= prenosi stanje filtra preko međuspremnika. Proslijedite početno stanje oblika (n_sections, 2) i funkcija vraća (y, zf) – filtrirani izlaz i konačno stanje – tako da konačno stanje jednog međuspremnika napaja početno stanje sljedećeg:
y0, zf0 = sp.signal.sosfilt(sos, buffer0, zi=zi)
y1, zf1 = sp.signal.sosfilt(sos, buffer1, zi=zf0)
# ...
Ovo je standardni obrazac za streaming filtar na međuspremljenim podacima – ulaz mikrofona čitan po 1024 uzorka odjednom, ADC uzorci akumulirani u DMA-pogonjenim dijelovima, IMU očitanja prikupljena tijekom prozora.
6.15.2. Spektrogrami¶
spectrogram() izračunava magnitudu Fourierove transformacije. Konceptualno je istovjetna s np.sqrt(real * real + imag * imag) nakon poziva fft(), ali sažima posao u jedan poziv – bez zadržavanja međurezultata real * real, imag * imag, zbroja ili eksplicitnog polja magnitude u RAM-u u bilo kojem trenutku. To je čini pravim alatom u svakoj petlji u kojoj se spektri izračunavaju iznova i iznova:
from ulab import numpy as np
from ulab import utils
x = np.linspace(0, 10, num=1024)
spectrum = utils.spectrogram(x)
Oblik argumenata zrcali fft(): jedno realno polje ili par (real, imag) kada ulaz ima imaginarni dio.
Tri ključna argumenta pomažu kod dodjele memorije:
scratchpad=None– 1-D gusto polje s pomičnim zarezom duljine2 * len(signal)kojespectrogram()koristi kao radni prostor.out=None– 1-D polje s pomičnim zarezom u koje se zapisuje rezultat.log=False– kada jeTrue, prije vraćanja uzimalog()magnitude, sažeto u isti poziv.
Obrazac za tok podataka jest sve dodijeliti jednom i nikada više ne dodjeljivati:
from ulab import numpy as np
from ulab import utils
N = 1024
scratch = np.zeros(2 * N)
out = np.zeros(N)
while True:
signal = read_samples(N)
utils.spectrogram(signal, out=out, scratchpad=scratch,
log=True)
# out now holds the log-magnitude spectrum for this window ...
Usporedite s očitom, ali rasipnom inačicom:
while True:
signal = read_samples(N)
spectrum = np.log(utils.spectrogram(signal)) # two allocations
Obje proizvode iste brojeve, ali prva inačica ništa ne dodjeljuje unutar petlje – kamera u svakoj iteraciji koristi istu memoriju, a petlja se izvodi brže.
6.15.3. Međuspremnici periferije širi od 16 bita¶
frombuffer() obrađuje samo dtypeove koje numpy sam definira (uint8 / int8, uint16 / int16, float). Kada periferija proizvodi 32-bitne cjelobrojne uzorke – 24-bitni ili 32-bitni ADC, mikrofon visoke razlučivosti – ulab.utils izlaže eksplicitne pomoćnike za pretvorbu:
Svaki uzima međuspremnik nalik bajtovima i vraća ndarray s pomičnim zarezom:
from ulab import utils
buf = bytearray([1, 1, 0, 0, 0, 0, 0, 255])
utils.from_uint32_buffer(buf)
# array([257.0, 4278190080.0])
Funkcije prihvaćaju iste regulatore za uštedu memorije kao spectrogram():
count=ioffset=za preskakanje zaglavlja ili ograničavanje čitanja.out=za zapisivanje u unaprijed dodijeljeno polje s pomičnim zarezom.byteswap=Truekada se periferija ne slaže s MCU-om oko redoslijeda bajtova.
Kombinirani obrazac – jedan poziv from_int32_buffer() izravno u jedan poziv spectrogram(), oba s out= međuspremnicima izvan petlje – pravi je predložak za streaming analizator spektra koji radi na mikrofonu visoke razlučivosti.