|
|
@ -98,6 +98,22 @@ def dft_matrix_fast(n_fft:int, winlen:int=None, n_bin:int=None) -> Tuple[np.ndar
|
|
|
|
return w_real, w_imag, kernel_size
|
|
|
|
return w_real, w_imag, kernel_size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def bin2hz(bin:Union[List[int], np.ndarray], N:int, sr:int)->List[float]:
|
|
|
|
|
|
|
|
"""FFT bins to Hz.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
http://practicalcryptography.com/miscellaneous/machine-learning/intuitive-guide-discrete-fourier-transform/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
bins (List[int] or np.ndarray): bin index.
|
|
|
|
|
|
|
|
N (int): the number of samples, or FFT points.
|
|
|
|
|
|
|
|
sr (int): sampling rate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
List[float]: Hz's.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
hz = bin * float(sr) / N
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def hz2mel(hz):
|
|
|
|
def hz2mel(hz):
|
|
|
|
"""Convert a value in Hertz to Mels
|
|
|
|
"""Convert a value in Hertz to Mels
|
|
|
|
|
|
|
|
|
|
|
@ -106,6 +122,7 @@ def hz2mel(hz):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
return 1127 * np.log(1+hz/700.0)
|
|
|
|
return 1127 * np.log(1+hz/700.0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mel2hz(mel):
|
|
|
|
def mel2hz(mel):
|
|
|
|
"""Convert a value in Mels to Hertz
|
|
|
|
"""Convert a value in Mels to Hertz
|
|
|
|
|
|
|
|
|
|
|
@ -113,3 +130,72 @@ def mel2hz(mel):
|
|
|
|
:returns: a value in Hertz. If an array was passed in, an identical sized array is returned.
|
|
|
|
: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)
|
|
|
|
return 700 * (np.exp(mel/1127.0)-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rms_to_db(rms: float):
|
|
|
|
|
|
|
|
"""Root Mean Square to dB.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
rms ([float]): root mean square
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
float: dB
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return 20.0 * math.log10(max(1e-16, rms))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rms_to_dbfs(rms: float):
|
|
|
|
|
|
|
|
"""Root Mean Square to dBFS.
|
|
|
|
|
|
|
|
https://fireattack.wordpress.com/2017/02/06/replaygain-loudness-normalization-and-applications/
|
|
|
|
|
|
|
|
Audio is mix of sine wave, so 1 amp sine wave's Full scale is 0.7071, equal to -3.0103dB.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dB = dBFS + 3.0103
|
|
|
|
|
|
|
|
dBFS = db - 3.0103
|
|
|
|
|
|
|
|
e.g. 0 dB = -3.0103 dBFS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
rms ([float]): root mean square
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
float: dBFS
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return rms_to_db(rms) - 3.0103
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def max_dbfs(sample_data: np.ndarray):
|
|
|
|
|
|
|
|
"""Peak dBFS based on the maximum energy sample.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
sample_data ([np.ndarray]): float array, [-1, 1].
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
float: dBFS
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Peak dBFS based on the maximum energy sample. Will prevent overdrive if used for normalization.
|
|
|
|
|
|
|
|
return rms_to_dbfs(max(abs(np.min(sample_data)), abs(np.max(sample_data))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mean_dbfs(sample_data):
|
|
|
|
|
|
|
|
"""Peak dBFS based on the RMS energy.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
sample_data ([np.ndarray]): float array, [-1, 1].
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
float: dBFS
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return rms_to_dbfs(
|
|
|
|
|
|
|
|
math.sqrt(np.mean(np.square(sample_data, dtype=np.float64))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def gain_db_to_ratio(gain_db: float):
|
|
|
|
|
|
|
|
"""dB to ratio
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
gain_db (float): gain in dB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
float: scale in amp
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return math.pow(10.0, gain_db / 20.0)
|