====== Signal processing ======
====== 1. Harmonický signál ======
V první ukázce vygenerujeme několik period harmonického signálu o frekvenci 1000 Hz. Pokud bychom chtěli data pohodlně přehrát na počítači, uložíme je do souboru typu ''wav''.
Asi nikoho nepřekvapí matematický popis časového průběhu harmonického signálu s frekvencí $f$ a amplitudou $A$
$y(t) = A * sin(2 * \pi * f * t)$
Protože nás zajímá digitální (tj. vzorkovaná) podoba signálu, je třeba se zabývat vlastnostmi vzorků:
* vzorkovací frekcence musí odpovídat [[https://cs.wikipedia.org/wiki/Nyquist%C5%AFv%E2%80%93Shannon%C5%AFv_vzorkovac%C3%AD_teor%C3%A9m|Nyquistově podmnínce]]. S ohledem na maximální slyšitelnou frekcenci cca 20 kHz můžeme zvolit vzorkovací frekvenci 44100 Hz, která je obvyklá v audiotechnice
* amplituda v případě uložení do souboru nemůže být být neceločíselného datového typu ''float''. Datový formát ''wav'' podporuje pouze celá kladná čísla v rozsahu 16 bit;, takže je třeba provést přeškálování (normalizaci).
import numpy as np
from matplotlib import pyplot as plt
SAMPLE_RATE = 44100 # vzorkovaci frekvence v Hz
DURATION = 5 # doba trvani
def generate_sine_wave(freq, sample_rate, duration):
x = np.linspace(0, duration, sample_rate * duration, endpoint=False)
frequencies = x * freq
# argumentem np.sin jsou radiany
y = np.sin((2 * np.pi) * frequencies)
return x, y
# 5s signalu 1kHz
x, y = generate_sine_wave(2, SAMPLE_RATE, DURATION)
plt.plot(x, y)
plt.title('Harmonicky signal 2Hz')
plt.xlabel('Cas (s)')
plt.ylabel('Amplituda')
plt.show()
===== Vytvoření zašuměného signálu =====
Pro další experiment budeme simulovat harmonický signál obsahující šum: vytvořme dva různé signály se stejnou časovou osou a rozdílnými frekvencemi, amplitudu šumového signálu potlačíme. Abychom mohli signál uložit do souboru ''wav'', provedeme normalizaci amplitudy.
_, signal = generate_sine_wave(400, SAMPLE_RATE, DURATION)
_, sum = generate_sine_wave(4000, SAMPLE_RATE, DURATION)
sum = sum * 0.3
mix = signal + sum
mix_norm = np.int16((mix / mix.max()) * 32767)
plt.plot(mix_norm[:1000])
plt.show()
K uložení do souboru použijeme vestavěnou podporu knihovny scipy
from scipy.io.wavfile import write
# SAMPLE_RATE = 44100
write("sinewave.wav", SAMPLE_RATE, mix_norm)
===== Analýza pomocí Fourierovy transformace =====
from scipy.fft import fft, fftfreq
# Number of samples in normalized_tone
N = SAMPLE_RATE * DURATION
yf = fft(mix_norm)
xf = fftfreq(N, 1 / SAMPLE_RATE)
plt.plot(xf, np.abs(yf))
plt.show()
===== Filtrace signálu ve spektru =====
# maximální frekvence je právě na polovině vzorkovací fr.
points_per_freq = len(xf) / (SAMPLE_RATE / 2)
# index v seznamu odpovídající 4000 Hz
target_idx = int(points_per_freq * 4000)
# vynulování všech položek seznamu, kromě frekvence 4k
yf[target_idx - 1 : target_idx + 2] = 0
plt.plot(xf, np.abs(yf))
plt.show()
Inverzní Fourierovou transformací pak můžeme získat filtrovaný signál
from scipy.fft import irfft
new_sig = irfft(yf)
plt.plot(new_sig[:1000])
plt.show()
Popisovaná metoda není příliš vhodná na reálné signály, protože v praxi nebudeme mít téměř nikdy čistý harmonický signál a je třeba pouřít vhodný filtr.
====== 2. Filtrace signálu pomocí FIR filtru ======