We use cookies on this website to distinguish you from other users.
We use this data to improve our content experience and for targeted advertising.
By continuing to use this website you consent to our use of cookies.
For more information, please see our
Cookie Policy.
Source code for spafe.fbanks.bark_fbanks
"""
- Description : Bark filter banks implementation.
- Copyright (c) 2019-2024 Ayoub Malek.
This source code is licensed under the terms of the BSD 3-Clause License.
For a copy, see <https://github.com/SuperKogito/spafe/blob/master/LICENSE>.
"""
from typing import Optional
import numpy as np
from ..utils.converters import hz2bark, bark2hz, BarkConversionApproach
from ..utils.exceptions import ParameterError, ErrorMsgs
from ..utils.filters import scale_fbank, ScaleType
[docs]def Fm(fb: float, fc: float) -> float:
"""
Compute a Bark filter around a certain center frequency in bark [Hermansky]_.
Args:
fb (float): frequency in Bark.
fc (float): center frequency in Bark.
Returns:
(float) : associated Bark filter value/amplitude.
"""
if (fb - fc < -1.3) or (2.5 < fb - fc):
return 0
elif -1.3 <= fb - fc <= -0.5:
return 10 ** (2.5 * (fb - fc + 0.5))
elif -0.5 < fb - fc < 0.5:
return 1
else:
# if 0.5 <= fb - fc <= 2.5:
return 10 ** (-1 * (fb - fc - 0.5))
[docs]def bark_filter_banks(
nfilts: int = 24,
nfft: int = 512,
fs: int = 16000,
low_freq: float = 0,
high_freq: Optional[float] = None,
scale: ScaleType = "constant",
conversion_approach: BarkConversionApproach = "Wang",
):
"""
Compute Bark filter banks. The filters are stored in the rows, the columns
correspond to fft bins.
Args:
nfilts (int) : the number of filters in the filter bank.
(Default is 20).
nfft (int) : the FFT size.
(Default is 512).
fs (int) : sample rate/ sampling frequency of the signal.
(Default 16000 Hz).
low_freq (float) : lowest band edge of mel filters.
(Default 0 Hz).
high_freq (float) : highest band edge of mel filters.
(Default is fs/2).
scale (str) : monotonicity behavior of the filter banks.
(Default is "constant").
conversion_approach (str) : bark scale conversion approach.
(Default is "Wang").
Returns:
(tuple) :
- (numpy.ndarray) : array of size nfilts * (nfft/2 + 1) containing filter bank. Each row holds 1 filter.
- (numpy.ndarray) : array of center frequencies
Raises:
ParameterError
- if low_freq < 0 OR high_freq > (fs / 2)
Tip:
- :code:`scale` : can take the following options ["constant", "ascendant", "descendant"].
- :code:`conversion_approach` : can take the following options ["Tjomov","Schroeder", "Terhardt", "Zwicker", "Traunmueller", "Wang"].
Note that the use of different options than the ddefault can lead to unexpected behavior/issues.
References:
.. [Hermansky] Hermansky, H. “Perceptual linear predictive (PLP) analysis of speech.”
The Journal of the Acoustical Society of America 87 4 (1990): 1738-52
doi: 10.1121/1.399423. PMID: 2341679.
Examples:
.. plot::
import numpy as np
from spafe.utils.converters import bark2hz
from spafe.utils.vis import show_fbanks
from spafe.fbanks.bark_fbanks import bark_filter_banks
# init var
fs = 8000
nfilt = 7
nfft = 1024
low_freq = 0
high_freq = fs / 2
# compute freqs for xaxis
bhz_freqs = np.linspace(low_freq, high_freq, nfft //2+1)
for scale, label in [("constant", ""), ("ascendant", "Ascendant "), ("descendant", "Descendant ")]:
# bark fbanks
bark_fbanks_mat, bark_freqs = bark_filter_banks(nfilts=nfilt,
nfft=nfft,
fs=fs,
low_freq=low_freq,
high_freq=high_freq,
scale=scale)
# visualize filter bank
show_fbanks(
bark_fbanks_mat,
[bark2hz(freq) for freq in bark_freqs],
bhz_freqs,
label + "Bark Filter Bank",
ylabel="Weight",
x1label="Frequency / Hz",
x2label="Frequency / bark",
figsize=(14, 5),
fb_type="bark",
)
See Also:
- :py:func:`spafe.fbanks.gammatone_fbanks.gammatone_filter_banks`
- :py:func:`spafe.fbanks.linear_fbanks.linear_filter_banks`
- :py:func:`spafe.fbanks.mel_fbanks.mel_filter_banks`
"""
# init freqs
high_freq = high_freq or fs / 2
# run checks
if low_freq < 0:
raise ParameterError(ErrorMsgs["low_freq"])
if high_freq > (fs / 2):
raise ParameterError(ErrorMsgs["high_freq"])
# compute points evenly spaced in Bark scale (points are in Bark)
low_bark = hz2bark(low_freq, conversion_approach)
high_bark = hz2bark(high_freq, conversion_approach)
bark_center_freqs = np.linspace(low_bark, high_bark, nfilts)
# we use fft bins, so we have to convert from Bark to fft bin number
bins = np.floor(
np.array(
[
(nfft + 1) * (bark2hz(freq, conversion_approach) / fs)
for freq in bark_center_freqs
]
)
)
fbank = np.zeros([nfilts, nfft // 2 + 1])
for j in range(0, nfilts):
for i in range(int(bins[0]), int(bins[nfilts - 1])):
fc = bark_center_freqs[j]
fb = hz2bark((i * fs) / (nfft + 1), conversion_approach)
fbank[j, i] = Fm(fb, fc)
# compute scaling
scaling = scale_fbank(scale=scale, nfilts=nfilts)
fbank = fbank * scaling
return fbank, bark_center_freqs