2015-10-18 23:06:39 -07:00
|
|
|
from . import rfft
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
import scipy.signal as sig
|
|
|
|
|
2017-09-21 04:04:22 -07:00
|
|
|
|
2015-10-18 23:06:39 -07:00
|
|
|
def magnitudes_window_setup(s, size=8192):
|
|
|
|
L = s.shape[0]
|
|
|
|
overlap = 0.661
|
|
|
|
step = np.ceil(size*(1 - overlap))
|
|
|
|
segs = np.ceil(L/step)
|
|
|
|
return step, segs
|
|
|
|
|
2017-09-21 04:04:22 -07:00
|
|
|
|
2015-10-18 23:06:39 -07:00
|
|
|
def magnitudes(s, size=8192):
|
|
|
|
import scipy.linalg as linalg
|
|
|
|
|
|
|
|
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)
|
|
|
|
win /= linalg.norm(win)
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
for i in range(0, L - 1, int(step)):
|
|
|
|
windowed = s[i:i+win_size]*win
|
|
|
|
power = np.abs(rfft(windowed, size))**2
|
2015-10-18 23:33:46 -07:00
|
|
|
# this scraps the nyquist value to get exactly 'size' outputs
|
2015-10-18 23:06:39 -07:00
|
|
|
yield power[0:size]
|
|
|
|
count += 1
|
|
|
|
|
2017-09-21 04:04:22 -07:00
|
|
|
# assert(segs == count) # this is probably no good in a generator
|
|
|
|
|
2015-10-18 23:06:39 -07:00
|
|
|
|
|
|
|
def averfft(s, size=8192):
|
|
|
|
"""calculates frequency magnitudes by fft and averages them together."""
|
|
|
|
step, segs = magnitudes_window_setup(s, size)
|
|
|
|
|
|
|
|
avg = np.zeros(size)
|
|
|
|
for power in magnitudes(s, size):
|
|
|
|
avg += power/segs
|
|
|
|
|
|
|
|
avg_db = 10*np.log10(avg)
|
|
|
|
return avg_db
|