dsp/lib/windowing.py
2019-01-02 04:04:21 -08:00

100 lines
2.5 KiB
Python

import numpy as np
def _deco_win(f):
# gives scipy compatibility
def deco(N, *args, sym=True, **kwargs):
if N < 1:
return np.array([])
if N == 1:
return np.ones(1)
odd = N % 2
if not sym and not odd:
N = N + 1
w = f(N, *args, **kwargs)
if not sym and not odd:
return w[:-1]
return w
return deco
def _gen_hamming(*a):
L = len(a)
a += (0, 0, 0, 0, 0) # pad so orders definition doesn't error
orders = [
lambda fac: 0,
lambda fac: a[0],
lambda fac: a[0] - a[1]*np.cos(1*fac),
lambda fac: a[0] - a[1]*np.cos(1*fac) + a[2]*np.cos(2*fac),
lambda fac: a[0] - a[1]*np.cos(1*fac) + a[2]*np.cos(2*fac)
- a[3]*np.cos(3*fac),
lambda fac: a[0] - a[1]*np.cos(1*fac) + a[2]*np.cos(2*fac)
- a[3]*np.cos(3*fac) + a[4]*np.cos(4*fac),
]
f = orders[L]
return lambda N: f(np.arange(0, N)*2*np.pi/(N - 1))
def _normalize(*args):
a = np.asfarray(args)
return a/np.sum(a)
def _h(*args):
return _deco_win(_gen_hamming(*args))
blackman_inexact = _h(0.42, 0.5, 0.08)
blackman = _h(0.42659, 0.49656, 0.076849)
blackman_nuttall = _h(0.3635819, 0.4891775, 0.1365995, 0.0106411)
blackman_harris = _h(0.35875, 0.48829, 0.14128, 0.01168)
nuttall = _h(0.355768, 0.487396, 0.144232, 0.012604)
flattop = _h(*_normalize(1, 1.93, 1.29, 0.388, 0.028)) # FTSRS
# flattop_weird = _h(*_normalize(1, 1.93, 1.29, 0.388, 0.032)) # ??? wtf
flattop_weird = _h(0.2156, 0.4160, 0.2781, 0.0836, 0.0069) # ??? scipy crap
hann = _h(0.5, 0.5)
hamming_inexact = _h(0.54, 0.46)
hamming = _h(0.53836, 0.46164)
@_deco_win
def triangular(N):
if N % 2 == 0:
return 1 - np.abs((2*np.arange(N) + 1)/N - 1)
else:
return 1 - np.abs(2*(np.arange(N) + 1)/(N + 1) - 1)
@_deco_win
def parzen(N):
odd = N % 2
n = np.arange(N/2)
if not odd:
n += 0.5
center = 1 - 6*(2*n/N)**2*(1 - 2*n/N)
outer = 2*(1 - 2*n/N)**3
center = center[:len(center)//2]
outer = outer[len(outer)//2:]
if not odd:
return np.r_[outer[::-1], center[::-1], center, outer]
else:
return np.r_[outer[::-1], center[::-1], center[1:], outer]
@_deco_win
def cosine(N):
return np.sin(np.pi*(np.arange(N) + 0.5)/N)
@_deco_win
def welch(N):
return 1 - (2*np.arange(N)/(N - 1) - 1)**2
# TODO: rename or something
@_deco_win
def sinc(N):
return np.sinc((np.arange(N) - (N - 1)/2)/2)