From 0268cc553f6774eb6f046bff0b5d85aa2a6eaebc Mon Sep 17 00:00:00 2001 From: Brian McFee Date: Wed, 17 Aug 2016 10:51:10 -0400 Subject: [PATCH 1/4] implemented #398 --- librosa/beat.py | 4 +-- librosa/cache.py | 52 +++++++++++++++++++++++++-------------- librosa/core/audio.py | 9 +++---- librosa/core/constantq.py | 7 +++--- librosa/core/pitch.py | 2 +- librosa/core/spectrum.py | 12 ++++----- librosa/decompose.py | 4 +-- librosa/display.py | 1 - librosa/feature/utils.py | 4 +-- librosa/filters.py | 12 ++++----- librosa/onset.py | 2 +- librosa/segment.py | 5 ++-- librosa/util/utils.py | 17 +++---------- tests/test_cache.py | 8 +++--- 14 files changed, 71 insertions(+), 68 deletions(-) diff --git a/librosa/beat.py b/librosa/beat.py index fc0e41b2e9..45d7833922 100644 --- a/librosa/beat.py +++ b/librosa/beat.py @@ -182,7 +182,7 @@ def beat_track(y=None, sr=22050, onset_envelope=None, hop_length=512, return (bpm, beats) -@cache +@cache(level=30) def estimate_tempo(onset_envelope, sr=22050, hop_length=512, start_bpm=120, std_bpm=1.0, ac_size=4.0, duration=90.0, offset=0.0): """Estimate the tempo (beats per minute) from an onset envelope @@ -297,7 +297,7 @@ def estimate_tempo(onset_envelope, sr=22050, hop_length=512, start_bpm=120, return start_bpm -@cache +@cache(level=30) def __beat_tracker(onset_envelope, bpm, fft_res, tightness, trim): """Internal function that tracks beats in an onset strength envelope. diff --git a/librosa/cache.py b/librosa/cache.py index 7bd7b83810..d38950513a 100644 --- a/librosa/cache.py +++ b/librosa/cache.py @@ -15,35 +15,51 @@ class CacheManager(Memory): field, thereby allowing librosa.cache to act as a decorator function. ''' - def __call__(self, function): - '''Decorator function. Adds an input/output cache to - the specified function.''' + def __init__(self, cachedir, level=0, **kwargs): + super().__init__(cachedir, **kwargs) + # The level parameter controls which data we cache + # smaller numbers mean less caching + self.level = level - from decorator import FunctionMaker + def __call__(self, level): + '''Example usage: - def decorator_apply(dec, func): - """Decorate a function by preserving the signature even if dec - is not a signature-preserving decorator. + @cache(level=2) + def semi_important_function(some_arguments): + ... + ''' + def wrapper(function): + '''Decorator function. Adds an input/output cache to + the specified function.''' - This recipe is derived from - http://micheles.googlecode.com/hg/decorator/documentation.html#id14 - """ + from decorator import FunctionMaker - return FunctionMaker.create( - func, 'return decorated(%(signature)s)', - dict(decorated=dec(func)), __wrapped__=func) + def decorator_apply(dec, func): + """Decorate a function by preserving the signature even if dec + is not a signature-preserving decorator. - if self.cachedir is not None: - return decorator_apply(self.cache, function) + This recipe is derived from + http://micheles.googlecode.com/hg/decorator/documentation.html#id14 + """ + + return FunctionMaker.create( + func, 'return decorated(%(signature)s)', + dict(decorated=dec(func)), __wrapped__=func) + + if self.cachedir is not None and self.level >= level: + return decorator_apply(self.cache, function) + + else: + return function + return wrapper - else: - return function # Instantiate the cache from the environment CACHE = CacheManager(os.environ.get('LIBROSA_CACHE_DIR', None), mmap_mode=os.environ.get('LIBROSA_CACHE_MMAP', None), compress=os.environ.get('LIBROSA_CACHE_COMPRESS', False), - verbose=int(os.environ.get('LIBROSA_CACHE_VERBOSE', 0))) + verbose=int(os.environ.get('LIBROSA_CACHE_VERBOSE', 0)), + level=int(os.environ.get('LIBROSA_CACHE_LEVEL', 0))) # Override the module's __call__ attribute sys.modules[__name__] = CACHE diff --git a/librosa/core/audio.py b/librosa/core/audio.py index 455d255ca5..bc623621e8 100644 --- a/librosa/core/audio.py +++ b/librosa/core/audio.py @@ -152,7 +152,7 @@ def load(path, sr=22050, mono=True, offset=0.0, duration=None, return (y, sr) -@cache +@cache(level=20) def to_mono(y): '''Force an audio signal down to mono. @@ -186,7 +186,7 @@ def to_mono(y): return y -@cache +@cache(level=20) def resample(y, orig_sr, target_sr, res_type='kaiser_best', fix=True, scale=False, **kwargs): """Resample a time series from orig_sr to target_sr @@ -355,7 +355,7 @@ def get_duration(y=None, sr=22050, S=None, n_fft=2048, hop_length=512, return float(n_samples) / sr -@cache +@cache(level=20) def autocorrelate(y, max_size=None, axis=-1): """Bounded auto-correlation @@ -422,7 +422,7 @@ def autocorrelate(y, max_size=None, axis=-1): return autocorr -@cache +@cache(level=20) def zero_crossings(y, threshold=1e-10, ref_magnitude=None, pad=True, zero_pos=True, axis=-1): '''Find the zero-crossings of a signal `y`: indices `i` such that @@ -543,7 +543,6 @@ def zero_crossings(y, threshold=1e-10, ref_magnitude=None, pad=True, constant_values=pad) -@cache def clicks(times=None, frames=None, sr=22050, hop_length=512, click_freq=1000.0, click_duration=0.1, click=None, length=None): """Returns a signal with the signal `click` placed at each specified time diff --git a/librosa/core/constantq.py b/librosa/core/constantq.py index 96f46fbff1..682f238c4d 100644 --- a/librosa/core/constantq.py +++ b/librosa/core/constantq.py @@ -20,7 +20,7 @@ __all__ = ['cqt', 'hybrid_cqt', 'pseudo_cqt'] -@cache +@cache(level=20) def cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, bins_per_octave=12, tuning=None, filter_scale=1, norm=1, sparsity=0.01, real=util.Deprecated()): @@ -232,7 +232,7 @@ def cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, return __trim_stack(cqt_resp, n_bins) -@cache +@cache(level=20) def hybrid_cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, bins_per_octave=12, tuning=None, filter_scale=1, norm=1, sparsity=0.01): @@ -349,7 +349,7 @@ def hybrid_cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, return __trim_stack(cqt_resp, n_bins) -@cache +@cache(level=20) def pseudo_cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, bins_per_octave=12, tuning=None, filter_scale=1, norm=1, sparsity=0.01): @@ -432,6 +432,7 @@ def pseudo_cqt(y, sr=22050, hop_length=512, fmin=None, n_bins=84, return fft_basis.dot(D) +@cache(level=10) def __cqt_filter_fft(sr, fmin, n_bins, bins_per_octave, tuning, filter_scale, norm, sparsity, hop_length=None): '''Generate the frequency domain constant-Q filter basis.''' diff --git a/librosa/core/pitch.py b/librosa/core/pitch.py index dcb442914e..30364899fc 100644 --- a/librosa/core/pitch.py +++ b/librosa/core/pitch.py @@ -162,7 +162,7 @@ def pitch_tuning(frequencies, resolution=0.01, bins_per_octave=12): return tuning[np.argmax(counts)] -@cache +@cache(level=30) def piptrack(y=None, sr=22050, S=None, n_fft=2048, hop_length=None, fmin=150.0, fmax=4000.0, threshold=0.1): '''Pitch tracking on thresholded parabolically-interpolated STFT diff --git a/librosa/core/spectrum.py b/librosa/core/spectrum.py index d068c4e5ba..49c79d6a72 100644 --- a/librosa/core/spectrum.py +++ b/librosa/core/spectrum.py @@ -21,7 +21,7 @@ 'fmt'] -@cache +@cache(level=20) def stft(y, n_fft=2048, hop_length=None, win_length=None, window=None, center=True, dtype=np.complex64): """Short-time Fourier transform (STFT) @@ -186,7 +186,7 @@ def stft(y, n_fft=2048, hop_length=None, win_length=None, window=None, return stft_matrix -@cache +@cache(level=20) def istft(stft_matrix, hop_length=None, win_length=None, window=None, center=True, dtype=np.float32): """ @@ -510,7 +510,6 @@ def magphase(D): return mag, phase -@cache def phase_vocoder(D, rate, hop_length=None): """Phase vocoder. Given an STFT matrix D, speed up by a factor of `rate` @@ -598,7 +597,7 @@ def phase_vocoder(D, rate, hop_length=None): return d_stretch -@cache +@cache(level=30) def logamplitude(S, ref_power=1.0, amin=1e-10, top_db=80.0): """Log-scale the amplitude of a spectrogram. @@ -702,7 +701,7 @@ def logamplitude(S, ref_power=1.0, amin=1e-10, top_db=80.0): return log_spec -@cache +@cache(level=30) def perceptual_weighting(S, frequencies, **kwargs): '''Perceptual weighting of a power spectrogram: @@ -770,7 +769,7 @@ def perceptual_weighting(S, frequencies, **kwargs): return offset + logamplitude(S, **kwargs) -@cache +@cache(level=30) def fmt(y, t_min=0.5, n_fmt=None, kind='cubic', beta=0.5, over_sample=1, axis=-1): """The fast Mellin transform (FMT) [1]_ of a uniformly sampled signal y. @@ -970,7 +969,6 @@ def fmt(y, t_min=0.5, n_fmt=None, kind='cubic', beta=0.5, over_sample=1, axis=-1 return result[idx] * np.sqrt(n) / n_fmt -@cache def _spectrogram(y=None, S=None, n_fft=2048, hop_length=512, power=1): '''Helper function to retrieve a magnitude spectrogram. diff --git a/librosa/decompose.py b/librosa/decompose.py index 20e5ae1c9e..55764dac79 100644 --- a/librosa/decompose.py +++ b/librosa/decompose.py @@ -186,7 +186,7 @@ def decompose(S, n_components=None, transformer=None, sort=False, fit=True, **kw return components, activations -@cache +@cache(level=30) def hpss(S, kernel_size=31, power=2.0, mask=False, margin=1.0): """Median-filtering harmonic percussive source separation (HPSS). @@ -371,7 +371,7 @@ def hpss(S, kernel_size=31, power=2.0, mask=False, margin=1.0): return ((S * mask_harm) * phase, (S * mask_perc) * phase) -@cache +@cache(level=30) def nn_filter(S, rec=None, aggregate=None, axis=-1, **kwargs): '''Filtering by nearest-neighbors. diff --git a/librosa/display.py b/librosa/display.py index 8298339b2e..009fa1ac85 100644 --- a/librosa/display.py +++ b/librosa/display.py @@ -187,7 +187,6 @@ def __call__(self, x, pos=None): r'M3$_x$', r'M3$_y$']) -@cache def cmap(data, robust=True, cmap_seq='magma', cmap_bool='gray_r', cmap_div='coolwarm'): '''Get a default colormap from the given data. diff --git a/librosa/feature/utils.py b/librosa/feature/utils.py index 30153066d3..4f55bfee66 100644 --- a/librosa/feature/utils.py +++ b/librosa/feature/utils.py @@ -11,7 +11,7 @@ __all__ = ['delta', 'stack_memory'] -@cache +@cache(level=40) def delta(data, width=9, order=1, axis=-1, trim=True): r'''Compute delta features: local estimate of the derivative of the input data along the selected axis. @@ -111,7 +111,7 @@ def delta(data, width=9, order=1, axis=-1, trim=True): return delta_x -@cache +@cache(level=40) def stack_memory(data, n_steps=2, delay=1, **kwargs): """Short-term history embedding: vertically concatenate a data vector or matrix with delayed copies of itself. diff --git a/librosa/filters.py b/librosa/filters.py index d7c6989eb8..c760f1badb 100644 --- a/librosa/filters.py +++ b/librosa/filters.py @@ -49,7 +49,7 @@ 'window_bandwidth'] -@cache +@cache(level=10) def dct(n_filters, n_input): """Discrete cosine transform (DCT type-III) basis. @@ -99,7 +99,7 @@ def dct(n_filters, n_input): return basis -@cache +@cache(level=10) def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False): """Create a Filterbank matrix to combine FFT bins into Mel-frequency bins @@ -189,7 +189,7 @@ def mel(sr, n_fft, n_mels=128, fmin=0.0, fmax=None, htk=False): return weights -@cache +@cache(level=10) def chroma(sr, n_fft, n_chroma=12, A440=440.0, ctroct=5.0, octwidth=2, norm=2, base_c=True): """Create a Filterbank matrix to convert STFT to chroma @@ -342,7 +342,7 @@ def _wrap(n, *args, **kwargs): return _wrap -@cache +@cache(level=10) def constant_q(sr, fmin=None, n_bins=84, bins_per_octave=12, tuning=0.0, window=None, filter_scale=1, pad_fft=True, norm=1, **kwargs): @@ -494,7 +494,7 @@ def constant_q(sr, fmin=None, n_bins=84, bins_per_octave=12, tuning=0.0, return filters, np.asarray(lengths) -@cache +@cache(level=10) def constant_q_lengths(sr, fmin, n_bins=84, bins_per_octave=12, tuning=0.0, window='hann', filter_scale=1): r'''Return length of each filter in a constant-Q basis. @@ -565,7 +565,7 @@ def constant_q_lengths(sr, fmin, n_bins=84, bins_per_octave=12, return lengths -@cache +@cache(level=10) def cq_to_chroma(n_input, bins_per_octave=12, n_chroma=12, fmin=None, window=None, base_c=True): '''Convert a Constant-Q basis to Chroma. diff --git a/librosa/onset.py b/librosa/onset.py index 109996d9b7..2ec9f6e0c6 100644 --- a/librosa/onset.py +++ b/librosa/onset.py @@ -287,7 +287,7 @@ def onset_strength(y=None, sr=22050, S=None, lag=1, max_size=1, return odf_all[0] -@cache +@cache(level=30) def onset_strength_multi(y=None, sr=22050, S=None, lag=1, max_size=1, detrend=False, center=True, feature=None, aggregate=None, channels=None, **kwargs): diff --git a/librosa/segment.py b/librosa/segment.py index 761ceafdae..d0208f4240 100644 --- a/librosa/segment.py +++ b/librosa/segment.py @@ -46,7 +46,7 @@ 'subsegment'] -@cache +@cache(level=30) def recurrence_matrix(data, k=None, width=1, metric='euclidean', sym=False, sparse=False, mode='connectivity', bandwidth=None, axis=-1): @@ -499,7 +499,6 @@ def timelag_filter(function, pad=True, index=0): >>> plt.tight_layout() ''' - @cache def __my_filter(wrapped_f, *args, **kwargs): '''Decorator to wrap the filter''' # Map the input data into time-lag space @@ -516,7 +515,7 @@ def __my_filter(wrapped_f, *args, **kwargs): return decorator(__my_filter, function) -@cache +@cache(level=30) def subsegment(data, frames, n_segments=4, axis=-1): '''Sub-divide a segmentation by feature clustering. diff --git a/librosa/util/utils.py b/librosa/util/utils.py index f6d8ec9e05..97dce7c540 100644 --- a/librosa/util/utils.py +++ b/librosa/util/utils.py @@ -99,7 +99,7 @@ def frame(y, frame_length=2048, hop_length=512): return y_frames -@cache +@cache(level=20) def valid_audio(y, mono=True): '''Validate whether a variable contains valid, mono audio data. @@ -212,7 +212,6 @@ def valid_intervals(intervals): return True -@cache def pad_center(data, size, axis=-1, **kwargs): '''Wrapper for np.pad to automatically center an array prior to padding. This is analogous to `str.center()` @@ -286,7 +285,6 @@ def pad_center(data, size, axis=-1, **kwargs): return np.pad(data, lengths, **kwargs) -@cache def fix_length(data, size, axis=-1, **kwargs): '''Fix the length an array `data` to exactly `size`. @@ -433,7 +431,6 @@ def fix_frames(frames, x_min=0, x_max=None, pad=True): return np.unique(frames).astype(int) -@cache def axis_sort(S, axis=-1, index=False, value=None): '''Sort an array along its rows or columns. @@ -531,7 +528,7 @@ def axis_sort(S, axis=-1, index=False, value=None): return S[sort_slice] -@cache +@cache(level=40) def normalize(S, norm=np.inf, axis=0): '''Normalize the columns or rows of a matrix @@ -628,7 +625,6 @@ def normalize(S, norm=np.inf, axis=0): return S / length -@cache def match_intervals(intervals_from, intervals_to): '''Match one set of time intervals to another. @@ -693,7 +689,6 @@ def match_intervals(intervals_from, intervals_to): return output -@cache def match_events(events_from, events_to): '''Match one set of events to another. @@ -773,7 +768,6 @@ def match_events(events_from, events_to): return output -@cache def localmax(x, axis=0): """Find local maxima in an array `x`. @@ -823,7 +817,6 @@ def localmax(x, axis=0): return (x > x_pad[inds1]) & (x >= x_pad[inds2]) -@cache def peak_pick(x, pre_max, post_max, pre_avg, post_avg, delta, wait): '''Uses a flexible heuristic to pick peaks in a signal. @@ -994,7 +987,7 @@ def peak_pick(x, pre_max, post_max, pre_avg, post_avg, delta, wait): return np.array(peaks) -@cache +@cache(level=40) def sparsify_rows(x, quantile=0.01): ''' Return a row-sparse matrix approximating the input `x`. @@ -1083,7 +1076,6 @@ def sparsify_rows(x, quantile=0.01): return x_sparse.tocsr() -@cache def roll_sparse(x, shift, axis=0): '''Sparse matrix roll @@ -1246,7 +1238,7 @@ def index_to_slice(idx, idx_min=None, idx_max=None, step=None, pad=True): return [slice(start, end, step) for (start, end) in zip(idx_fixed, idx_fixed[1:])] -@cache +@cache(level=40) def sync(data, idx, aggregate=None, pad=True, axis=-1): """Synchronous aggregation of a multi-dimensional array between boundaries @@ -1374,7 +1366,6 @@ def sync(data, idx, aggregate=None, pad=True, axis=-1): return data_agg -@cache def softmask(X, X_ref, power=1, split_zeros=False): '''Robustly compute a softmask operation. diff --git a/tests/test_cache.py b/tests/test_cache.py index f55fc1cc93..a191e234e9 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -7,8 +7,8 @@ import os import sys import tempfile -import numpy as np import shutil +import numpy as np import matplotlib matplotlib.use('Agg') @@ -16,7 +16,7 @@ # Disable any initial cache settings -for key in ['DIR', 'MMAP', 'COMPRESS', 'VERBOSE']: +for key in ['DIR', 'MMAP', 'COMPRESS', 'VERBOSE', 'LEVEL']: try: os.environ.pop('LIBROSA_CACHE_{:s}'.format(key)) except KeyError: @@ -47,7 +47,7 @@ def test_cache_disabled(): sys.modules.pop('librosa.cache', None) import librosa.cache - func_cache = librosa.cache(func) + func_cache = librosa.cache(level=-10)(func) # When there's no cache directory in the environment, # librosa.cache is a no-op. @@ -61,7 +61,7 @@ def test_cache_enabled(): import librosa.cache librosa.cache.clear() - func_cache = librosa.cache(func) + func_cache = librosa.cache(level=-10)(func) # The cache should be active now assert func_cache != func From 2037add7d83d57f8f7ce09c3fc905e023b2b94c9 Mon Sep 17 00:00:00 2001 From: Brian McFee Date: Wed, 17 Aug 2016 10:52:25 -0400 Subject: [PATCH 2/4] changed default cache level to 10 --- librosa/cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librosa/cache.py b/librosa/cache.py index d38950513a..18c6a80a28 100644 --- a/librosa/cache.py +++ b/librosa/cache.py @@ -15,7 +15,7 @@ class CacheManager(Memory): field, thereby allowing librosa.cache to act as a decorator function. ''' - def __init__(self, cachedir, level=0, **kwargs): + def __init__(self, cachedir, level=10, **kwargs): super().__init__(cachedir, **kwargs) # The level parameter controls which data we cache # smaller numbers mean less caching @@ -59,7 +59,7 @@ def decorator_apply(dec, func): mmap_mode=os.environ.get('LIBROSA_CACHE_MMAP', None), compress=os.environ.get('LIBROSA_CACHE_COMPRESS', False), verbose=int(os.environ.get('LIBROSA_CACHE_VERBOSE', 0)), - level=int(os.environ.get('LIBROSA_CACHE_LEVEL', 0))) + level=int(os.environ.get('LIBROSA_CACHE_LEVEL', 10))) # Override the module's __call__ attribute sys.modules[__name__] = CACHE From 442a169b94430bcdf048dd701fab14be9d23b906 Mon Sep 17 00:00:00 2001 From: Brian McFee Date: Wed, 17 Aug 2016 11:06:28 -0400 Subject: [PATCH 3/4] updated documentation for new caching features --- docs/cache.rst | 96 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/docs/cache.rst b/docs/cache.rst index a1496940aa..21cbfcec9a 100644 --- a/docs/cache.rst +++ b/docs/cache.rst @@ -37,61 +37,93 @@ The default configuration can be overridden by setting the following environment - `LIBROSA_CACHE_MMAP` : optional memory mapping mode `{None, 'r+', 'r', 'w+', 'c'}` - `LIBROSA_CACHE_COMPRESS` : flag to enable compression of data on disk `{0, 1}` - `LIBROSA_CACHE_VERBOSE` : controls how much debug info is displayed. `{int, non-negative}` + - `LIBROSA_CACHE_LEVEL` : controls the caching level: the larger this value, the more data is cached. `{int}` Please refer to the `joblib.Memory` `documentation `_ for a detailed explanation of these parameters. + +Cache levels +------------ + +Cache levels operate in a fashion similar to logging levels. +For small values of `LIBROSA_CACHE_LEVEL`, only the most important (frequently used) data are cached. +As the cache level increases, broader classes of functions are cached. +As a result, application code may run faster at the expense of larger disk usage. + +The caching levels are described as follows: + + - 10: filter bases, independent of audio data (dct, mel, chroma, constant-q) + - 20: low-level features (cqt, stft, zero-crossings, etc) + - 30: high-level features (tempo, beats, decomposition, recurrence, etc) + - 40: post-processing (delta, stack_memory, normalize, sync) + +The default cache level is 10. + + Example ------- To demonstrate how to use the cache, we'll first call an example script twice without caching:: - [~/git/librosa/examples]$ time ./estimate_tuning.py ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 - Loading ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 + $ time -p ./estimate_tuning.py ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Loading ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg Separating harmonic component ... Estimating tuning ... - +6.00 cents - - real 0m4.369s - user 0m4.065s - sys 0m0.350s - - [~/git/librosa/examples]$ time ./estimate_tuning.py ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 - Loading ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 + +9.00 cents + real 6.74 + user 6.03 + sys 1.09 + + $ time -p ./estimate_tuning.py ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Loading ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg Separating harmonic component ... Estimating tuning ... - +6.00 cents - - real 0m4.414s - user 0m4.013s - sys 0m0.440s - + +9.00 cents + real 6.68 + user 6.04 + sys 1.05 + Next, we'll enable caching to `/tmp/librosa`:: - [~/git/librosa/examples]$ export LIBROSA_CACHE_DIR=/tmp/librosa + $ export LIBROSA_CACHE_DIR=/tmp/librosa + +and set the cache level to 50:: + + $ export LIBROSA_CACHE_LEVEL=50 And now we'll re-run the example script twice. The first time, there will be no cached values, so the time should be similar to running without cache. The second time, we'll be able to reuse intermediate values, so it should be significantly faster.:: - [~/git/librosa/examples]$ time ./estimate_tuning.py ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 - Loading ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 + $ time -p ./estimate_tuning.py ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Loading ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg Separating harmonic component ... Estimating tuning ... - +6.00 cents - - real 0m4.859s - user 0m4.471s - sys 0m0.429s - - [~/git/librosa/examples]$ time ./estimate_tuning.py ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 - Loading ../librosa/example_data/Kevin_MacLeod_-_Vibe_Ace.mp3 + +9.00 cents + real 7.60 + user 6.79 + sys 1.15 + + $ time -p ./estimate_tuning.py ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Loading ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg Separating harmonic component ... Estimating tuning ... - +6.00 cents - - real 0m0.931s - user 0m0.862s - sys 0m0.112s + +9.00 cents + real 1.64 + user 1.30 + sys 0.74 +Reducing the cache level to 20 yields an intermediate acceleration:: + + $ export LIBROSA_CACHE_LEVEL=50 + + $ time -p ./estimate_tuning.py ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Loading ../librosa/util/example_data/Kevin_MacLeod_-_Vibe_Ace.ogg + Separating harmonic component ... + Estimating tuning ... + +9.00 cents + real 4.98 + user 4.17 + sys 1.22 From a3fbbf8239faedaf2ca98d9159d66efa8e11f124 Mon Sep 17 00:00:00 2001 From: Brian McFee Date: Wed, 17 Aug 2016 11:12:03 -0400 Subject: [PATCH 4/4] fixed a py2vs3 bug in cache --- librosa/cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librosa/cache.py b/librosa/cache.py index 18c6a80a28..92c8030706 100644 --- a/librosa/cache.py +++ b/librosa/cache.py @@ -16,7 +16,7 @@ class CacheManager(Memory): ''' def __init__(self, cachedir, level=10, **kwargs): - super().__init__(cachedir, **kwargs) + super(CacheManager, self).__init__(cachedir, **kwargs) # The level parameter controls which data we cache # smaller numbers mean less caching self.level = level