parent
598fe0d432
commit
855e4c3792
@ -0,0 +1,103 @@
|
||||
import paddle
|
||||
import numpy as np
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
# https://github.com/kaldi-asr/kaldi/blob/cbed4ff688/src/feat/feature-window.cc#L109
|
||||
def povey_window(frame_len:int) -> np.ndarray:
|
||||
win = np.empty(frame_len)
|
||||
a = 2 * np.pi / (frame_len -1)
|
||||
for i in range(frame_len):
|
||||
win[i] = (0.5 - 0.5 * np.cos(a * i) )**0.85
|
||||
return win
|
||||
|
||||
def hann_window(frame_len:int) -> np.ndarray:
|
||||
win = np.empty(frame_len)
|
||||
a = 2 * np.pi / (frame_len -1)
|
||||
for i in range(frame_len):
|
||||
win[i] = 0.5 - 0.5 * np.cos(a * i)
|
||||
return win
|
||||
|
||||
def sine_window(frame_len:int) -> np.ndarray:
|
||||
win = np.empty(frame_len)
|
||||
a = 2 * np.pi / (frame_len -1)
|
||||
for i in range(frame_len):
|
||||
win[i] = np.sin(0.5 * a * i)
|
||||
return win
|
||||
|
||||
def hamm_window(frame_len:int) -> np.ndarray:
|
||||
win = np.empty(frame_len)
|
||||
a = 2 * np.pi / (frame_len -1)
|
||||
for i in range(frame_len):
|
||||
win[i] = 0.54 - 0.46 * np.cos(a * i)
|
||||
return win
|
||||
|
||||
def get_window(wintype:str, winlen:int) -> np.ndarray:
|
||||
# calculate window
|
||||
if not wintype or wintype == 'rectangular':
|
||||
window = np.ones(winlen)
|
||||
elif wintype == "hann":
|
||||
window = hann_window(winlen)
|
||||
elif wintype == "hamm":
|
||||
window = hamm_window(winlen)
|
||||
elif wintype == "povey":
|
||||
window = povey_window(winlen)
|
||||
else:
|
||||
msg = f"{wintype} Not supported yet!"
|
||||
raise ValueError(msg)
|
||||
return window
|
||||
|
||||
|
||||
def dft_matrix(n_fft:int, winlen:int=None, n_bin:int=None) -> Tuple[np.ndarray, np.ndarray, int]:
|
||||
# https://en.wikipedia.org/wiki/Discrete_Fourier_transform
|
||||
# (n_bins, n_fft) complex
|
||||
if n_bin is None:
|
||||
n_bin = 1 + n_fft // 2
|
||||
if winlen is None:
|
||||
winlen = n_bin
|
||||
# https://github.com/numpy/numpy/blob/v1.20.0/numpy/fft/_pocketfft.py#L49
|
||||
kernel_size = min(n_fft, winlen)
|
||||
|
||||
n = np.arange(0, n_fft, 1.)
|
||||
wsin = np.empty((n_bin, kernel_size)) #[Cout, kernel_size]
|
||||
wcos = np.empty((n_bin, kernel_size)) #[Cout, kernel_size]
|
||||
for k in range(n_bin): # Only half of the bins contain useful info
|
||||
wsin[k,:] = -np.sin(2*np.pi*k*n/n_fft)[:kernel_size]
|
||||
wcos[k,:] = np.cos(2*np.pi*k*n/n_fft)[:kernel_size]
|
||||
w_real = wcos
|
||||
w_imag = wsin
|
||||
return w_real, w_imag, kernel_size
|
||||
|
||||
|
||||
def dft_matrix_fast(n_fft:int, winlen:int=None, n_bin:int=None) -> Tuple[np.ndarray, np.ndarray, int]:
|
||||
# (n_bins, n_fft) complex
|
||||
if n_bin is None:
|
||||
n_bin = 1 + n_fft // 2
|
||||
if winlen is None:
|
||||
winlen = n_bin
|
||||
# https://github.com/numpy/numpy/blob/v1.20.0/numpy/fft/_pocketfft.py#L49
|
||||
kernel_size = min(n_fft, winlen)
|
||||
|
||||
# https://en.wikipedia.org/wiki/DFT_matrix
|
||||
# https://ccrma.stanford.edu/~jos/st/Matrix_Formulation_DFT.html
|
||||
weight = np.fft.fft(np.eye(n_fft))[:self.n_bin, :kernel_size]
|
||||
w_real = weight.real
|
||||
w_imag = weight.imag
|
||||
return w_real, w_imag, kernel_size
|
||||
|
||||
|
||||
def hz2mel(hz):
|
||||
"""Convert a value in Hertz to Mels
|
||||
|
||||
:param hz: a value in Hz. This can also be a numpy array, conversion proceeds element-wise.
|
||||
:returns: a value in Mels. If an array was passed in, an identical sized array is returned.
|
||||
"""
|
||||
return 1127 * np.log(1+hz/700.0)
|
||||
|
||||
def mel2hz(mel):
|
||||
"""Convert a value in Mels to Hertz
|
||||
|
||||
:param mel: a value in Mels. This can also be a numpy array, conversion proceeds element-wise.
|
||||
:returns: a value in Hertz. If an array was passed in, an identical sized array is returned.
|
||||
"""
|
||||
return 700 * (np.exp(mel/1127.0)-1)
|
Loading…
Reference in new issue