Skip to content

Commit

Permalink
Merge 93a99cd into 707ffd1
Browse files Browse the repository at this point in the history
  • Loading branch information
dpwe committed Apr 9, 2017
2 parents 707ffd1 + 93a99cd commit 0f9730f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 12 deletions.
18 changes: 14 additions & 4 deletions librosa/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ def dct(n_filters, n_input):


@cache(level=10)
def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False,
norm=1):
"""Create a Filterbank matrix to combine FFT bins into Mel-frequency bins
Parameters
Expand All @@ -178,6 +179,11 @@ def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
htk : bool [scalar]
use HTK formula instead of Slaney
norm : {None, 1, np.inf} [scalar]
if 1, divide the triangular mel weights by the width of the mel band
(area normalization). Otherwise, leave all the triangles aiming for
a peak value of 1.0
Returns
-------
M : np.ndarray [shape=(n_mels, 1 + n_fft/2)]
Expand Down Expand Up @@ -220,6 +226,9 @@ def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
if fmax is None:
fmax = float(sr) / 2

if norm is not None and norm != 1 and norm != np.inf:
raise ParameterError('Unsupported norm: {}'.format(repr(norm)))

# Initialize the weights
n_mels = int(n_mels)
weights = np.zeros((n_mels, int(1 + n_fft // 2)))
Expand All @@ -241,9 +250,10 @@ def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False):
# .. then intersect them with each other and zero
weights[i] = np.maximum(0, np.minimum(lower, upper))

# Slaney-style mel is scaled to be approx constant energy per channel
enorm = 2.0 / (mel_f[2:n_mels+2] - mel_f[:n_mels])
weights *= enorm[:, np.newaxis]
if norm == 1:
# Slaney-style mel is scaled to be approx constant energy per channel
enorm = 2.0 / (mel_f[2:n_mels+2] - mel_f[:n_mels])
weights *= enorm[:, np.newaxis]

# Only check weights if f_mel[0] is positive
if not np.all((mel_f[:-2] == 0) | (weights.max(axis=1) > 0)):
Expand Down
Binary file added tests/data/feature-melfbnorm-001.mat
Binary file not shown.
Binary file added tests/data/feature-melfbnorm-002.mat
Binary file not shown.
Binary file added tests/data/feature-melfbnorm-003.mat
Binary file not shown.
41 changes: 33 additions & 8 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ def __test_to_octs(infile):

def test_melfb():

def __test(infile):
def __test_default_norm(infile):
DATA = load(infile)

wts = librosa.filters.mel(DATA['sr'][0],
DATA['nfft'][0],
n_mels=DATA['nfilts'][0],
fmin=DATA['fmin'][0],
fmax=DATA['fmax'][0],
htk=DATA['htk'][0])
wts = librosa.filters.mel(DATA['sr'][0, 0],
DATA['nfft'][0, 0],
n_mels=DATA['nfilts'][0, 0],
fmin=DATA['fmin'][0, 0],
fmax=DATA['fmax'][0, 0],
htk=DATA['htk'][0, 0])

# Our version only returns the real-valued part.
# Pad out.
Expand All @@ -107,7 +107,32 @@ def __test(infile):
assert np.allclose(wts, DATA['wts'])

for infile in files('data/feature-melfb-*.mat'):
yield (__test, infile)
yield (__test_default_norm, infile)

def __test_with_norm(infile):
DATA = load(infile)
# if DATA['norm'] is empty, pass None.
if DATA['norm'].shape[-1] == 0:
norm = None
else:
norm = DATA['norm'][0, 0]
wts = librosa.filters.mel(DATA['sr'][0, 0],
DATA['nfft'][0, 0],
n_mels=DATA['nfilts'][0, 0],
fmin=DATA['fmin'][0, 0],
fmax=DATA['fmax'][0, 0],
htk=DATA['htk'][0, 0],
norm=norm)
# Pad out.
wts = np.pad(wts, [(0, 0),
(0, int(DATA['nfft'][0]//2 - 1))],
mode='constant')

eq_(wts.shape, DATA['wts'].shape)
assert np.allclose(wts, DATA['wts'])

for infile in files('data/feature-melfbnorm-*.mat'):
yield (__test_with_norm, infile)


def test_mel_gap():
Expand Down

0 comments on commit 0f9730f

Please sign in to comment.