dsp/lib/fft.py

61 lines
1.6 KiB
Python
Raw Normal View History

2015-10-18 23:06:39 -07:00
import numpy as np
import scipy.signal as sig
2019-01-02 06:45:12 -08:00
from .util import lament
2017-09-21 04:04:22 -07:00
2018-03-01 04:04:27 -08:00
def magnitudes_window_setup(s, size=8192, overlap=0.661):
# note: the default overlap value is only
# optimal for a blackman-harris window.
2015-10-18 23:06:39 -07:00
L = s.shape[0]
step = np.ceil(size*(1 - overlap))
segs = np.ceil(L/step)
return step, segs
2017-09-21 04:04:22 -07:00
2019-01-02 06:45:12 -08:00
def magnitudes(s, size=8192, broken=True):
if broken:
lament("magnitudes(broken=True): DEPRECATED")
2015-10-18 23:06:39 -07:00
step, segs = magnitudes_window_setup(s, size)
L = s.shape[0]
# blindly pad with zeros for friendlier ffts and overlapping
z = np.zeros(size)
2015-11-10 04:04:41 -08:00
s = np.r_[s, z]
2015-10-18 23:06:39 -07:00
win_size = size
win = sig.blackmanharris(win_size)
2018-03-01 04:04:27 -08:00
win /= np.sqrt(np.sum(np.square(win)))
2015-10-18 23:06:39 -07:00
for i in range(0, L - 1, int(step)):
windowed = s[i:i+win_size]*win
2019-01-02 06:45:12 -08:00
if broken:
power = np.abs(np.fft.rfft(windowed, 2 * size))**2
# this scraps the nyquist value to get exactly 'size' outputs
yield power[:size]
else:
power = np.abs(np.fft.rfft(windowed, size))**2
# this scraps the 0 Hz value to get exactly size//2 outputs
yield power[1:]
2017-09-21 04:04:22 -07:00
2015-10-18 23:06:39 -07:00
2019-01-02 06:45:12 -08:00
def averfft(s, size=8192, broken=True):
2015-10-18 23:06:39 -07:00
"""calculates frequency magnitudes by fft and averages them together."""
step, segs = magnitudes_window_setup(s, size)
2019-01-02 06:45:12 -08:00
if broken:
lament("averfft(broken=True): DEPRECATED")
avg = np.zeros(size)
for power in magnitudes(s, size):
avg += power/segs
else:
avg = np.zeros(size//2)
for power in magnitudes(s, size):
avg += power/segs
2015-10-18 23:06:39 -07:00
avg_db = 10*np.log10(avg)
return avg_db