Pro práci se signály budeme používat především knihoven Numpy, Scipy (hlavně Scipy.signal) a Matplotlib:
Nemyslím, že je potřeba k těmto knihovnám studovat zdlouhavé tutoriály, spíše používat jejich dokumentací a za chodu hledat, co je potřeba. Pokud by ale někdo přece jen chtěl, například tyto zdroje vypadají dobře:
Dále tady jen zběžně upozorním na pár věci, na které si dát v Pythonu pozor při dělání projektu.
Pro Python existuje spousta knihoven, které dokáží načíst zvukový soubor, je možné využít kteroukoli z nich. Je dobré si ale dát pozor na to, jaký interval hodnot různé tooly načítají. Narozdíl od Matlabu, kde se hodnoty přečtené z wav
souboru implicitně normalizují do intervalu −1…1, některé knihovny v Pythonu načítají hodnoty jako integer, tzn −32768…32767. Pro potřeby projektu chceme hodnoty v intervalu −1…1, je tedy třeba normalizovat podělením 215.
# scipy - potreba normalizace
from scipy.io import wavfile
fs, data = wavfile.read('music.wav')
data.min(), data.max()
(-29259, 29770)
data = data / 2**15
data.min(), data.max()
(-0.892913818359375, 0.90850830078125)
# wavio - potreba normalizace
import wavio
d = wavio.read('music.wav')
data = d.data
data.min(), data.max()
(-29259, 29770)
data = data / 2**15
data.min(), data.max()
(-0.892913818359375, 0.90850830078125)
# soundfile - neni potreba normalizace
import soundfile
data, fs = soundfile.read('music.wav')
data.min(), data.max()
(-0.892913818359375, 0.90850830078125)
Pro výpočet nul a pólů z koeficientů b,a lze využít funkce tf2zpk
z knihovny scipy.signal
, která je ekvivalentem stejnojmenné funkce v Matlabu. Funkce ze scipy
se ale od funkce z Matlabu (a toho, jak koeficienty b,a používáme v ISSku) lehce liší. Pro ekvivalentní výsledky je třeba pro scipy
zadat stejný počet koeficientů a a b - ty, kterých je méně doplnit nulami.
from scipy.signal import tf2zpk
# takto nedostaneme stejný výsledek jako v Matlabu
a1 = [1, 2.3, -0.5]
b1 = [2.3]
z1, p1, _ = tf2zpk(b1, a1)
print(f'Nuly: {z1}')
print(f'Póly: {p1}')
Nuly: [] Póly: [-2.5 0.2]
# takto dostaneme stejný výsledek jako v Matlabu a ekvivalentní tomu, jak máme b,a definované v ISS
a2 = [1, 2.3, -0.5]
b2 = [2.3, 0, 0]
z2, p2, _ = tf2zpk(b2, a2)
print(f'Nuly: {z2}')
print(f'Póly: {p2}')
Nuly: [ 0. 0.] Póly: [-2.5 0.2]
Je to kvůli tomu, že tf2zpk
ze scipy
považuje b,a za koeficienty násobící kladné mocniny z v přenosové funkci, zatímco v Matlabu jsou to koeficienty násobící záporné mocniny z. Tyto dva přístupy jsou ekvivalentní, dokud je koeficientů stejný počet.
Viz https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.tf2zpk.html a https://www.mathworks.com/help/signal/ref/tf2zpk.html
Grafy vytvořené v Matplotlibu je dobré do dokumentace vkládat ve vektorovém formátu - např. pdf nebo eps. Uložit je možné jednoduše pomocí plt.savefig
. Občas se stane, že se kolem grafu uloží do pdf i velký bílý okraj, v takovém případě zkuste pro savefig
přidat parametry bbox_inches = 'tight', pad_inches = 0
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
plt.plot(np.arange(100), np.arange(100))
plt.savefig('test.pdf')