Sync Toolbox - Python package with reference implementations for efficient, robust, and accurate music synchronization based on dynamic time warping (DTW)

Overview

Python Package using Conda Python package

Sync Toolbox

This repository contains a Python package called Sync Toolbox, which provides open-source reference implementations for full-fledged music synchronization pipelines and yields state-of-the-art alignment results for a wide range of Western music.

Using suitable feature representations and cost measures, the toolbox's core technology is based on dynamic time warping (DTW), which brings the feature sequences into temporal correspondence. To account for efficiency, robustness and, accuracy, our toolbox integrates and combines techniques such as multiscale DTW (MsDTW), memory-restricted MsDTW (MrMsDTW), and high-resolution music synchronization.

If you use the Sync Toolbox in your research, please consider the following references.

References

Meinard Müller, Henning Mattes, and Frank Kurth. An Efficient Multiscale Approach to Audio Synchronization. In Proceedings of the International Society for Music Information Retrieval Conference (ISMIR): 192–197, 2006.

Sebastian Ewert, Meinard Müller, and Peter Grosche. High Resolution Audio Synchronization Using Chroma Onset Features. In Proceedings of IEEE International Conference on Acoustics, Speech, and Signal Processing (ICASSP): 1869–1872, 2009.

Thomas Prätzlich, Jonathan Driedger, and Meinard Müller Memory-Restricted Multiscale Dynamic Time Warping. In Proceedings of the IEEE International Conference on Acoustics, Speech, and Signal Processing (ICASSP): 569–573, 2016.

Installing

If you just want to try our example notebooks, you can run them using Binder directly in your browser: Binder

To install the Sync Toolbox locally, you can use the Python package manager pip:

pip install synctoolbox

We recommend to do this inside a conda or virtual environment. Note: On some systems, you may see errors related with soundfile when calling some functions or executing our example notebooks. soundfile is a dependency of librosa, which is used by the Sync Toolbox. In case of errors, you may have to install libsndfile using your package manager, e.g., sudo apt install libsndfile1. Alternatively, you may create a conda environment, install librosa using conda and then install the Sync Toolbox with the pip command from above. See here for further information if you are experiencing these issues.

If you want to run the example notebooks locally, you must first install the Sync Toolbox to resolve all dependencies. Then, you can clone this repository using

git clone https://github.com/meinardmueller/synctoolbox.git

install Jupyter using

pip install jupyter

and then start the notebook server via

jupyter notebook

Finally, HTML exports of the example notebooks are provided under "Releases".

Usage

Fully worked examples for using the sync toolbox are provided in the accompanying Jupyter notebooks. In sync_audio_audio_simple.ipynb, we show how to use the toolbox to synchronize two recordings of the same piece of music using standard chroma features. We also compare runtimes for standard DTW and MrMsDTW. In sync_audio_audio_full.ipynb, we expand this example and demonstrate how to build a full synchronization pipeline that yields state-of-the-art results. Finally, sync_audio_score_full.ipynb shows a similar pipeline for synchronizing a music recording with the corresponding score.

There is also an API documentation for the Sync Toolbox:

https://meinardmueller.github.io/synctoolbox

Contributing

We are happy for suggestions and contributions. We would be grateful for either directly contacting us via email ([email protected]) or for creating an issue in our Github repository. Please do not submit a pull request without prior consultation with us.

Tests

We provide automated tests for each feature and different variants of MrMsDTW. These ensure that the outputs match the ground truth matrices provided in the tests/data folder.

To execute the test script, you will need to install extra requirements for testing:

pip install 'synctoolbox[tests]'
pytest tests

Licence

The code for this toolbox is published under an MIT licence. This does not apply to the data files. Schubert songs are taken from the Schubert Winterreise Dataset. The Chopin prelude example files are taken from the FMP notebooks.

Acknowledgements

The synctoolbox package builds on results, material, and insights that have been obtained in close collaboration with different people. We would like to express our gratitude to former and current students, collaborators, and colleagues who have influenced and supported us in creating this package, including Vlora Arifi-Müller, Michael Clausen, Sebastian Ewert, Christian Fremerey, and Frank Kurth. The main authors of Sync Toolbox are associated with the International Audio Laboratories Erlangen, which are a joint institution of the Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU) and Fraunhofer Institute for Integrated Circuits IIS. We also thank the German Research Foundation (DFG) for various research grants that allowed us for conducting fundamental research in music processing (in particular, MU 2686/7-2, DFG-MU 2686/14-1).

Comments
  • Unit tests fail

    Unit tests fail

    running the unit tests on python 3.8 using the proposed procedure seem to fail:

    base38 ❯ py.test tests                                                                                                (base38)
    ===================================================== test session starts =====================================================
    platform darwin -- Python 3.8.10, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
    rootdir: /Users/faro/repositories/synctoolbox
    collected 13 items
    
    tests/test_dtw.py ....                                                                                                  [ 30%]
    tests/test_features.py ....FF...                                                                                        [100%]
    
    ========================================================== FAILURES ===========================================================
    _____________________________________________________ test_pitch_features _____________________________________________________
    
        def test_pitch_features():
            audio_1, _ = librosa.load('data_music/Schubert_D911-03_HU33.wav', 22050)
            audio_2, _ = librosa.load('data_music/Schubert_D911-03_SC06.wav', 22050)
            f_pitch_1_gt = np.load('tests/data/f_pitch_1.npy')
            f_pitch_2_gt = np.load('tests/data/f_pitch_2.npy')
    
            f_pitch_1 = audio_to_pitch_features(f_audio=audio_1,
                                                Fs=22050,
                                                tuning_offset=1,
                                                feature_rate=50,
                                                verbose=False)
    
            f_pitch_2 = audio_to_pitch_features(f_audio=audio_2,
                                                Fs=22050,
                                                tuning_offset=7,
                                                feature_rate=50,
                                                verbose=False)
    
    >       assert np.allclose(f_pitch_1, f_pitch_1_gt, atol=1e-5)
    E       assert False
    E        +  where False = <function allclose at 0x7f85d8b23670>(array([[0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       ...,\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.]]), array([[0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       ...,\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.],\n       [0., 0., 0., ..., 0., 0., 0.]]), atol=1e-05)
    E        +    where <function allclose at 0x7f85d8b23670> = np.allclose
    
    tests/test_features.py:81: AssertionError
    ---------------------------------------------------- Captured stdout call -----------------------------------------------------
    ................................................................................................................................................................................
    __________________________________________________ test_pitch_onset_features __________________________________________________
    
        def test_pitch_onset_features():
            audio_1, _ = librosa.load('data_music/Schubert_D911-03_HU33.wav', 22050)
            audio_2, _ = librosa.load('data_music/Schubert_D911-03_SC06.wav', 22050)
            f_pitch_onset_1_gt = load_dict('tests/data/f_pitch_onset_1.pickle')
            f_pitch_onset_2_gt = load_dict('tests/data/f_pitch_onset_2.pickle')
    
            f_pitch_onset_1 = audio_to_pitch_onset_features(f_audio=audio_1,
                                                            Fs=22050,
                                                            tuning_offset=1,
                                                            verbose=False)
    
            f_pitch_onset_2 = audio_to_pitch_onset_features(f_audio=audio_2,
                                                            Fs=22050,
                                                            tuning_offset=7,
                                                            verbose=False)
    
    >       dict_allclose(f_pitch_onset_1, f_pitch_onset_1_gt, atol=1e-5)
    
    tests/test_features.py:101:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    tests/utils.py:26: in dict_allclose
        assert np.allclose(dict1[k], dict2[k], atol)
    <__array_function__ internals>:5: in allclose
        ???
    /opt/homebrew/Caskroom/miniconda/base/envs/base38/lib/python3.8/site-packages/numpy/core/numeric.py:2171: in allclose
        res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
    <__array_function__ internals>:5: in isclose
        ???
    /opt/homebrew/Caskroom/miniconda/base/envs/base38/lib/python3.8/site-packages/numpy/core/numeric.py:2272: in isclose
        return within_tol(x, y, atol, rtol)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    x = array([[[3.10917800e+04],
            [3.11484694e+04],
            [3.11824830e+04],
            [3.12164966e+04],
            [3.123...9819230e-09],
            [1.69793182e-09],
            [1.56447331e-09],
            [1.20539503e-09],
            [9.61932239e-10]]])
    y = array([[[3.10917800e+04],
            [3.11484694e+04],
            [3.11824830e+04],
            [3.12164966e+04],
            [3.123...7001423e-09],
            [1.67276090e-09],
            [1.54219300e-09],
            [1.18766368e-09],
            [9.48867734e-10]]])
    atol = 1e-08, rtol = 1e-05
    
        def within_tol(x, y, atol, rtol):
            with errstate(invalid='ignore'):
    >           return less_equal(abs(x-y), atol + rtol * abs(y))
    E           ValueError: operands could not be broadcast together with shapes (2,138,1) (2,136,1)
    
    /opt/homebrew/Caskroom/miniconda/base/envs/base38/lib/python3.8/site-packages/numpy/core/numeric.py:2258: ValueError
    ---------------------------------------------------- Captured stdout call -----------------------------------------------------
    ................................................................................................................................................................................21 (2, 138, 1) (2, 136, 1)
    =================================================== short test summary info ===================================================
    FAILED tests/test_features.py::test_pitch_features - assert False
    FAILED tests/test_features.py::test_pitch_onset_features - ValueError: operands could not be broadcast together with shapes ...
    ================================================ 2 failed, 11 passed in 56.14s ================================================
    

    related #5 https://github.com/openjournals/joss-reviews/issues/3434

    opened by faroit 17
  • numba error `key already in dictionary: 'index.5'` in tutorial notebook

    numba error `key already in dictionary: 'index.5'` in tutorial notebook

    Hi there,

    Thanks for making this code available!

    Just cloned the repo and tried to run the notebook sync_audio_score_full.ipynb. For cell 7 (in the section "Finding optimal shift of chroma vectors"), I'm getting an error message. Posting the complete stacktrace here. Please let me know if you require more information to address this.

    AssertionError                            Traceback (most recent call last)
    /tmp/ipykernel_25695/2527601981.py in <cell line: 3>()
          1 f_cens_1hz_audio = quantized_chroma_to_CENS(f_chroma_quantized_audio, 201, 50, feature_rate)[0]
          2 f_cens_1hz_annotation = quantized_chroma_to_CENS(f_chroma_quantized_annotation, 201, 50, feature_rate)[0]
    ----> 3 opt_chroma_shift = compute_optimal_chroma_shift(f_cens_1hz_audio, f_cens_1hz_annotation)
          4 print('Pitch shift between the audio recording and score, determined by DTW:', opt_chroma_shift, 'bins')
          5 
    
    ~/synctoolbox/synctoolbox/dtw/utils.py in compute_optimal_chroma_shift(f_chroma1, f_chroma2, chroma_transpositions, step_sizes, step_weights)
         42     for chroma_shift in chroma_transpositions:
         43         cost_matrix_tmp = cosine_distance(f_chroma1, shift_chroma_vectors(f_chroma2, chroma_shift))
    ---> 44         D, _, _ = compute_warping_path(cost_matrix_tmp, step_sizes=step_sizes, step_weights=step_weights)
         45         if D[-1, -1] < dtw_cost:
         46             dtw_cost = D[-1, -1]
    
    ~/synctoolbox/synctoolbox/dtw/core.py in compute_warping_path(C, step_sizes, step_weights, implementation)
        194                          sub_sequence=False)
        195 
    --> 196         wp = __E_to_warping_path(E=E,
        197                                  dn=dn,
        198                                  dm=dm,
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
        485                     e.patch_message('\n'.join((str(e).rstrip(), help_msg)))
        486             # ignore the FULL_TRACEBACKS config, this needs reporting!
    --> 487             raise e
        488         finally:
        489             self._types_active_call = []
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
        418         return_val = None
        419         try:
    --> 420             return_val = self.compile(tuple(argtypes))
        421         except errors.ForceLiteralArg as e:
        422             # Received request for compiler re-entry with the list of arguments
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in compile(self, sig)
        963                 with ev.trigger_event("numba:compile", data=ev_details):
        964                     try:
    --> 965                         cres = self._compiler.compile(args, return_type)
        966                     except errors.ForceLiteralArg as e:
        967                         def folded(args, kws):
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in compile(self, args, return_type)
        123 
        124     def compile(self, args, return_type):
    --> 125         status, retval = self._compile_cached(args, return_type)
        126         if status:
        127             return retval
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in _compile_cached(self, args, return_type)
        137 
        138         try:
    --> 139             retval = self._compile_core(args, return_type)
        140         except errors.TypingError as e:
        141             self._failed_cache[key] = e
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/dispatcher.py in _compile_core(self, args, return_type)
        150 
        151         impl = self._get_implementation(args, {})
    --> 152         cres = compiler.compile_extra(self.targetdescr.typing_context,
        153                                       self.targetdescr.target_context,
        154                                       impl,
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library, pipeline_class)
        691     pipeline = pipeline_class(typingctx, targetctx, library,
        692                               args, return_type, flags, locals)
    --> 693     return pipeline.compile_extra(func)
        694 
        695 
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler.py in compile_extra(self, func)
        427         self.state.lifted = ()
        428         self.state.lifted_from = None
    --> 429         return self._compile_bytecode()
        430 
        431     def compile_ir(self, func_ir, lifted=(), lifted_from=None):
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler.py in _compile_bytecode(self)
        495         """
        496         assert self.state.func_ir is None
    --> 497         return self._compile_core()
        498 
        499     def _compile_ir(self):
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler.py in _compile_core(self)
        474                     self.state.status.fail_reason = e
        475                     if is_final_pipeline:
    --> 476                         raise e
        477             else:
        478                 raise CompilerError("All available pipelines exhausted")
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler.py in _compile_core(self)
        461                 res = None
        462                 try:
    --> 463                     pm.run(self.state)
        464                     if self.state.cr is not None:
        465                         break
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler_machinery.py in run(self, state)
        351                     (self.pipeline_name, pass_desc)
        352                 patched_exception = self._patch_error(msg, e)
    --> 353                 raise patched_exception
        354 
        355     def dependency_analysis(self):
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler_machinery.py in run(self, state)
        339                 pass_inst = _pass_registry.get(pss).pass_inst
        340                 if isinstance(pass_inst, CompilerPass):
    --> 341                     self._runPass(idx, pass_inst, state)
        342                 else:
        343                     raise BaseException("Legacy pass in use")
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler_lock.py in _acquire_compile_lock(*args, **kwargs)
         33         def _acquire_compile_lock(*args, **kwargs):
         34             with self:
    ---> 35                 return func(*args, **kwargs)
         36         return _acquire_compile_lock
         37 
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler_machinery.py in _runPass(self, index, pss, internal_state)
        294             mutated |= check(pss.run_initialization, internal_state)
        295         with SimpleTimer() as pass_time:
    --> 296             mutated |= check(pss.run_pass, internal_state)
        297         with SimpleTimer() as finalize_time:
        298             mutated |= check(pss.run_finalizer, internal_state)
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/compiler_machinery.py in check(func, compiler_state)
        267 
        268         def check(func, compiler_state):
    --> 269             mangled = func(compiler_state)
        270             if mangled not in (True, False):
        271                 msg = ("CompilerPass implementations should return True/False. "
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/typed_passes.py in run_pass(self, state)
        238         pp.run(True)
        239         with fallback_context(state, msg):
    --> 240             rewrites.rewrite_registry.apply('after-inference', state)
        241         pp.remove_dels()
        242         return True
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/rewrites/registry.py in apply(self, kind, state)
         65             while work_list:
         66                 key, block = work_list.pop()
    ---> 67                 matches = rewrite.match(state.func_ir, block, state.typemap,
         68                                         state.calltypes)
         69                 if matches:
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/inline_closurecall.py in match(self, func_ir, block, typemap, calltypes)
       1339             return False
       1340         self.crnt_block = block
    -> 1341         self.new_body = guard(_inline_const_arraycall, block, func_ir,
       1342                               self.typingctx, typemap, calltypes)
       1343         return self.new_body is not None
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/ir_utils.py in guard(func, *args, **kwargs)
       1530     """
       1531     try:
    -> 1532         return func(*args, **kwargs)
       1533     except GuardException:
       1534         return None
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/inline_closurecall.py in _inline_const_arraycall(block, func_ir, context, typemap, calltypes)
       1509                 elif expr.op == 'call' and expr in calltypes:
       1510                     arr_var = inst.target
    -> 1511                     if guard(inline_array, inst.target, expr,
       1512                              state.stmts, state.list_vars, state.dels):
       1513                         state.modified = True
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/ir_utils.py in guard(func, *args, **kwargs)
       1530     """
       1531     try:
    -> 1532         return func(*args, **kwargs)
       1533     except GuardException:
       1534         return None
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/inline_closurecall.py in inline_array(array_var, expr, stmts, list_vars, dels)
       1440             index_var = ir.Var(scope, mk_unique_var("index"), loc)
       1441             index_typ = types.intp
    -> 1442             typemap[index_var.name] = index_typ
       1443             stmts.append(_new_definition(func_ir, index_var,
       1444                     ir.Const(i, loc), loc))
    
    ~/anaconda3/envs/rhythm_grammar/lib/python3.10/site-packages/numba/core/utils.py in __setitem__(self, key, value)
        373     def __setitem__(self, key, value):
        374         if key in self:
    --> 375             raise AssertionError("key already in dictionary: %r" % (key,))
        376         super(UniqueDict, self).__setitem__(key, value)
        377 
    
    AssertionError: Failed in nopython mode pipeline (step: nopython rewrites)
    key already in dictionary: 'index.5'
    
    opened by johentsch 7
  • Enable continous integration

    Enable continous integration

    to solve installation issues it could help to include a number of continuous integration tests that run

    • runs the unit tests and installs the package
    • test the package installation in a conda environment using different python versions

    https://github.com/openjournals/joss-reviews/issues/3434

    opened by faroit 7
  • Error running sync_audio_audio_full locally in macOS: Failed to execute rubberband

    Error running sync_audio_audio_full locally in macOS: Failed to execute rubberband

    I'm in a macOS Big Sur 11.2.3. The steps I followed:

    1. I created a Conda environment with Python 3.8
    2. Installed Sync Toolbox using pip install synctoolbox which worked correctly
    3. git clone https://github.com/meinardmueller/synctoolbox.git
    4. Installed Jupyter notebook
    5. Run sync_audio_audio_full

    In the following cell:

    !pip install pyrubberband
    import pyrubberband as pyrb
    
    pitch_shift_for_audio_1 = -opt_chroma_shift % 12
    if pitch_shift_for_audio_1 > 6:
        pitch_shift_for_audio_1 -= 12
    audio_1_shifted = pyrb.pitch_shift(audio_1, Fs, pitch_shift_for_audio_1)
    
    # Pyrubberband expects the warping path to be given in audio samples.
    # Here, we do the conversion and additionally clip values that are too large.
    time_map = wp.T / feature_rate * Fs
    time_map[time_map[:, 0] > len(audio_1), 0] = len(audio_1)
    time_map[time_map[:, 1] > len(audio_2), 1] = len(audio_2)
    audio_1_warped = pyrb.timemap_stretch(audio_1_shifted, Fs, time_map=time_map)
    
    stereo_sonification = np.stack([audio_1_warped, audio_2], axis=0)
    ipd.display(ipd.Audio(stereo_sonification, rate=Fs))
    
    

    I'm getting this error:

    ---------------------------------------------------------------------------
    FileNotFoundError                         Traceback (most recent call last)
    ~/miniconda3/envs/joss_review_2/lib/python3.8/site-packages/pyrubberband/pyrb.py in __rubberband(y, sr, **kwargs)
         73 
    ---> 74         subprocess.check_call(arguments, stdout=DEVNULL, stderr=DEVNULL)
         75 
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/subprocess.py in check_call(*popenargs, **kwargs)
        358     """
    --> 359     retcode = call(*popenargs, **kwargs)
        360     if retcode:
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/subprocess.py in call(timeout, *popenargs, **kwargs)
        339     """
    --> 340     with Popen(*popenargs, **kwargs) as p:
        341         try:
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors, text)
        857 
    --> 858             self._execute_child(args, executable, preexec_fn, close_fds,
        859                                 pass_fds, cwd, env,
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
       1703                         err_msg = os.strerror(errno_num)
    -> 1704                     raise child_exception_type(errno_num, err_msg, err_filename)
       1705                 raise child_exception_type(err_msg)
    
    FileNotFoundError: [Errno 2] No such file or directory: 'rubberband'
    
    The above exception was the direct cause of the following exception:
    
    RuntimeError                              Traceback (most recent call last)
    /var/folders/j_/672m867d1f30v0qyvsddt71058rw_j/T/ipykernel_27940/816051359.py in <module>
          5 if pitch_shift_for_audio_1 > 6:
          6     pitch_shift_for_audio_1 -= 12
    ----> 7 audio_1_shifted = pyrb.pitch_shift(audio_1, Fs, pitch_shift_for_audio_1)
          8 
          9 # Pyrubberband expects the warping path to be given in audio samples.
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/site-packages/pyrubberband/pyrb.py in pitch_shift(y, sr, n_steps, rbargs)
        255     rbargs.setdefault('--pitch', n_steps)
        256 
    --> 257     return __rubberband(y, sr, **rbargs)
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/site-packages/pyrubberband/pyrb.py in __rubberband(y, sr, **kwargs)
         82 
         83     except OSError as exc:
    ---> 84         six.raise_from(RuntimeError('Failed to execute rubberband. '
         85                                     'Please verify that rubberband-cli '
         86                                     'is installed.'),
    
    ~/miniconda3/envs/joss_review_2/lib/python3.8/site-packages/six.py in raise_from(value, from_value)
    
    RuntimeError: Failed to execute rubberband. Please verify that rubberband-cli is installed.
    

    It seems that librosa's users reported a similar problem here. @ahnonay @yiitozer any advice?

    openjournals/joss-reviews#3434

    opened by magdalenafuentes 3
  • Installation issues due to restrictive package versions

    Installation issues due to restrictive package versions

    installation on google colab requires a certain amounts of uninstalls to meet the requirements by the synctoolbox dependencies:

    ERROR: jupyter-console 5.2.0 has requirement prompt-toolkit<2.0.0,>=1.0.0, but you'll have prompt-toolkit 3.0.19 which is incompatible.
    ERROR: google-colab 1.0.0 has requirement ipython~=5.5.0, but you'll have ipython 7.25.0 which is incompatible.
    ERROR: libfmp 1.1.2 has requirement ipython==7.8.*, but you'll have ipython 7.25.0 which is incompatible.
    ERROR: libfmp 1.1.2 has requirement matplotlib==3.1.*, but you'll have matplotlib 3.2.2 which is incompatible.
    ERROR: libfmp 1.1.2 has requirement numpy==1.17.*, but you'll have numpy 1.19.5 which is incompatible.
    ERROR: libfmp 1.1.2 has requirement pandas==1.0.*, but you'll have pandas 1.1.5 which is incompatible.
    ERROR: libfmp 1.1.2 has requirement scipy==1.3.*, but you'll have scipy 1.4.1 which is incompatible.
    

    this is mainly caused by the frozen requirements of libfmp. To address this, a new release of libfmp on pypi should be issued (see https://github.com/meinardmueller/libfmp/issues/4) and synctoolbox should dependent only on that version (v1.1.3?)

    opened by faroit 3
  • How to evaluate alignment quality?

    How to evaluate alignment quality?

    Thanks for making this library! I'm a noob to this field, so I may be missing something obvious.

    Is there a metric returned somewhere that indicates how well two audio tracks align? My use case is determining if a song is a cover of another, e.g. a pop song to a piano or guitar cover.

    opened by platers 2
  • Issues with soundfile when installing Sync Toolbox

    Issues with soundfile when installing Sync Toolbox

    This issue arised for @lutzhamel during the JOSS review process, see also: https://github.com/openjournals/joss-reviews/issues/3434

    In some cases when installing synctoolbox via pip, one gets errors related to soundfile which is a dependency of librosa.

    We hope to have addressed this issue in the latest commits on the master branch in two ways:

    • The example notebooks can now be run inside the browser using Binder, no installation necessary.
    • We have added additional explanations for users who want to install the toolbox locally. In particular, the issues with soundfile can usually be solved by running sudo apt install libsndfile1

    Dear @lutzhamel, thanks for making us aware of this problem. Please let us know if the latest changes have solved this for you.

    opened by ahnonay 2
  • Release with Python 3.9

    Release with Python 3.9

    Just as a reminder, since the release in pip right now is not working with python 3.9. In a conda environment with that python version I'm getting:

    (joss_review) cusp-vmn244:repos mf3734$ pip install synctoolbox
    ERROR: Could not find a version that satisfies the requirement synctoolbox (from versions: none)
    ERROR: No matching distribution found for synctoolbox
    

    Related to #6

    openjournals/joss-reviews#3434

    opened by magdalenafuentes 1
  • Nits on docs and repo

    Nits on docs and repo

    Hey @ahnonay and @yiitozer thanks for creating this useful toolbox. Looks really good. I'll drop here some nits to follow JOSS guidelines and make the repo even clearer:

    • JOSS recommends to add a statement of need in the documentation as well, so maybe it's worth to add not only the API description in the docs, but also a brief description and the statement in the index.
    • I recommend you add a brief description in the about field of the GitHub repo as well as a link to the docs in the website field. It will make it quicker for people to get to the docs and also understand what the repo is about

    openjournals/joss-reviews#3434

    opened by magdalenafuentes 1
  • Unit test fix

    Unit test fix

    • Unit tests added for the filterbank and peak search
    • test_conda.yml fixed (python version)
    • scipy.signal.filtfilt function replaced with scipy.signal.sosfiltfilt due to numerical instabilities.
    opened by yiitozer 0
Releases(v1.2.1)
Users can transcribe their favorite piano recordings to MIDI files after installation

Users can transcribe their favorite piano recordings to MIDI files after installation

190 Dec 17, 2022
Python CD-DA ripper preferring accuracy over speed

Whipper Whipper is a Python 3 (3.6+) CD-DA ripper based on the morituri project (CDDA ripper for *nix systems aiming for accuracy over speed). It star

671 Jan 04, 2023
A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream).

rfsoapyfile A Python 3 script for capturing and recording a SDR stream to a WAV file (or serving it to a HTTP audio stream). The script is threaded fo

4 Dec 19, 2022
Make an audio file (really) long-winded

longwind Make an audio file (really) long-winded Daily repetitions are an illusion anyway.

Vincent Lostanlen 2 Sep 12, 2022
convert-to-opus-cli is a Python CLI program for converting audio files to opus audio format.

convert-to-opus-cli convert-to-opus-cli is a Python CLI program for converting audio files to opus audio format. Installation Must have installed ffmp

4 Dec 21, 2022
In this project we can see how we can generate automatic music using character RNN.

Automatic Music Genaration Table of Contents Project Description Approach towards the problem Limitations Libraries Used Summary Applications Referenc

Pronay Ghosh 2 May 27, 2022
Open-Source bot to play songs in your Telegram's Group Voice Chat. Powered by @Akki_ThePro

VcPlayer Telegram Voice-Chat Bot [PyTGCalls] ⇝ Requirements ⇜ Account requirements A Telegram account to use as the music bot, You cannot use regular

Akki ThePro 2 Dec 25, 2021
PyAbsorp is a python module that has the main focus to help estimate the Sound Absorption Coefficient.

This is a package developed to be use to find the Sound Absorption Coefficient through some implemented models, like Biot-Allard, Johnson-Champoux and

Michael Markus Ackermann 8 Oct 19, 2022
This is an OverPowered Vc Music Player! Will work for you and play music in Voice Chatz

VcPlayer This is an OverPowered Vc Music Player! Will work for you and play music in Voice Chatz Telegram Voice-Chat Bot [PyTGCalls] ⇝ Requirements ⇜

1 Dec 20, 2021
A voice based calculator by using termux api in Android

termux_voice_calculator This is. A voice based calculator by using termux api in Android Instagram account 👉 👈 Requirements and installation Downloa

ʕ´•ᴥ•`ʔ╠ŞĦỮβĦa̷m̷╣ʕ´•ᴥ•`ʔ 2 Apr 29, 2022
Use android as mic/speaker for ubuntu

Pulse Audio Control Panel Platforms Requirements sudo apt install ffmpeg pactl (already installed) Download Download the AppImage from release page ch

19 Dec 01, 2022
無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXのコア

無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXのコア

Hiroshiba 0 Aug 29, 2022
Sound-Equalizer- This is a Sound Equalizer GUI App Using Python's PyQt5

Sound-Equalizer- This is a Sound Equalizer GUI App Using Python's PyQt5. It gives you the ability to play, pause, and Equalize any one-channel wav audio file and play 3 different instruments.

Mustafa Megahed 1 Jan 10, 2022
cross-library (GStreamer + Core Audio + MAD + FFmpeg) audio decoding for Python

audioread Decode audio files using whichever backend is available. The library currently supports: Gstreamer via PyGObject. Core Audio on Mac OS X via

beetbox 419 Dec 26, 2022
GNU Radio – the Free and Open Software Radio Ecosystem

GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software radios. It can be used wit

GNU Radio 4.1k Jan 06, 2023
Jarvis From Basic to Advance - make a voice assistant similar to JARVIS (in iron man movie)

JARVIS (Basic to Advance) This was my attempt to make a voice assistant similar to JARVIS (in iron man movie) Let's be honest, it's not as intelligent

codesempai 17 Dec 25, 2022
Datamoshing with FFmpeg

ffmosher Datamoshing with FFmpeg Drag and drop video onto mosh.bat to create a datamoshed video. To datamosh an image, please ensure the file is in a

18 Sep 11, 2022
Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻

audius-terminal-player Terminal-based music player written in Python for the best music in the world 🎵 🎧 💻 Browse and listen to Audius from the com

Audius 21 Jul 23, 2022
Audio2midi - Automatic Audio-to-symbolic Arrangement

Automatic Audio-to-symbolic Arrangement This is the repository of the project "A

Ziyu Wang 24 Dec 05, 2022
Algorithmic Multi-Instrumental MIDI Continuation Implementation

Matchmaker Algorithmic Multi-Instrumental MIDI Continuation Implementation Taming large-scale MIDI datasets with algorithms This is a WIP so please ch

Alex 2 Mar 11, 2022