Skip to content

Commit

Permalink
fix hybrid_cqt scaling. should resolve #341
Browse files Browse the repository at this point in the history
modified unit test for hybrid-cqt continuity

simplified unit test for hybrid-cqt continuity

strengthened hybrid_cqt continuity tests
  • Loading branch information
bmcfee committed May 4, 2016
1 parent 486b2ea commit 594e504
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
35 changes: 28 additions & 7 deletions librosa/core/constantq.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,21 @@ def hybrid_cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84,
filter_scale=filter_scale,
norm=norm,
sparsity=sparsity)

# Compute the scaling factor for the pseudo-cqt
Q = float(filter_scale) / (2.0**(1. / bins_per_octave) - 1)

filter_cutoff = (freqs[-(n_bins_pseudo+1)] *
(1 + filters.window_bandwidth('hann') / Q))

n_octaves = int(np.ceil(float(n_bins - n_bins_pseudo) / bins_per_octave))

downsample_count = __early_downsample_count(sr/2,
filter_cutoff,
hop_length,
n_octaves)

my_pseudo_cqt *= 2.0**(downsample_count - 1)
cqt_resp.append(my_pseudo_cqt)

n_bins_full = int(np.sum(~pseudo_filters))
Expand Down Expand Up @@ -586,20 +601,26 @@ def __variable_hop_response(y, n_fft, hop_length, min_filter_length,
return my_cqt


def __early_downsample(y, sr, hop_length, res_type, n_octaves,
nyquist, filter_cutoff):
'''Perform early downsampling on an audio signal, if it applies.'''

if res_type != 'kaiser_fast':
return y, sr, hop_length
def __early_downsample_count(nyquist, filter_cutoff, hop_length, n_octaves):
'''Compute the number of early downsampling operations'''

downsample_count1 = int(np.ceil(np.log2(audio.BW_FASTEST * nyquist /
filter_cutoff)) - 1)
num_twos = __num_two_factors(hop_length)
downsample_count2 = max(0, num_twos - n_octaves + 1)
downsample_count = min(downsample_count1, downsample_count2)

if downsample_count > 0:
return min(downsample_count1, downsample_count2)


def __early_downsample(y, sr, hop_length, res_type, n_octaves,
nyquist, filter_cutoff):
'''Perform early downsampling on an audio signal, if it applies.'''

downsample_count = __early_downsample_count(nyquist, filter_cutoff,
hop_length, n_octaves)

if downsample_count > 0 and res_type == 'kaiser_fast':
downsample_factor = 2.0**(downsample_count)

assert hop_length % downsample_factor == 0
Expand Down
28 changes: 28 additions & 0 deletions tests/test_constantq.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,31 @@ def test_cqt_fail_short_late():
y = np.zeros(64)
librosa.cqt(y, sr=22050, real=False)


def test_hybrid_cqt_scale():
# Test to resolve issue #341
def __test(sr, hop_length, y):

hcqt = librosa.hybrid_cqt(y=y, sr=sr, hop_length=hop_length)

max_response = np.max(np.abs(hcqt), axis=1)

# Test that peak-energy deviation is bounded
assert np.std(max_response) < 1e-2

ref_response = np.max(max_response)
continuity = np.abs(np.diff(max_response)) / ref_response

# Test that continuity is never violated by more than 20% point-wise energy
assert np.max(continuity) < 2e-1, continuity


for sr in [22050, 32000]:
# Generate an impulse
x = np.zeros(16384)

for hop_length in [64, 128, 384, 512, 1024]:
# Center the impulse response on a frame
center = (len(x) / (2 * float(hop_length))) * hop_length
x[center] = 1
yield __test, sr, hop_length, x

0 comments on commit 594e504

Please sign in to comment.