python wrapper for rubberband

Overview

pyrubberband

PyPI Build Status Coverage Status GitHub license Documentation Status

A python wrapper for rubberband.

For now, this just provides lightweight wrappers for pitch-shifting and time-stretching.

All processing is done via the command-line through files on disk. In the future, this could be improved by directly wrapping the C library instead.

Install Rubberband on OS X

brew install https://gist.githubusercontent.com/faroit/b67c1708cdc1f9c4ddc9/raw/942bbedded22f05abab0d09b52383e7be4aee237/rubberband.rb

Example usage

>>> import soundfile as sf
>>> import pyrubberband as pyrb
>>> # Read mono wav file
>>> y, sr = sf.read("test.wav")
>>> # Play back at double speed
>>> y_stretch = pyrb.time_stretch(y, sr, 2.0)
Comments
  • Error: Please verify that rubberband-cli is installed

    Error: Please verify that rubberband-cli is installed

    Description

    I am new to this project and have been searching for time-stretching and pitch-shifting functionalities in python when I found this so, to test its working, I ran the "Example Usage" code from the pyrubberband github with one of my file but I got this error (image below).

    1 2

    I tried finding the solution to this on web, but had no leads as of now.

    Versions

    Windows-10-10.0.17134-SP0
    Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)]
    NumPy 1.16.4
    SoundFile 0.9.0
    

    Moreover

    I think the problem is with the OS (I'm using windows, but found OS X codes around the web), and by the way I also tried pip install rubberband-cli in the prompt, cuz the error said "rubberband-cli not installed" but that generated another error :-

    Collecting rubberband-cli
    ERROR: Could not find a version that satisfies the requirement rubberband-cli (from versions: none)
    ERROR: No matching distribution found for rubberband-cli
    

    Later, I downloaded rubberband cli from here and tried installing that as well but that too didn't help.

    So finally I am here, hoping to get some positive response from the community. Thanks !

    opened by srajan-jha 14
  • Added timemap stretch option

    Added timemap stretch option

    I added a function that allows users to perform the timemap stretch option of rubberband (see doc here). It is largely based on the current code.

    I've also added a test in the tests file.

    Here is an example of time map that stretches a 5 seconds audio file by: Leaving second 0 to 1 as is Speeding up seconds 1 to 3 by a factor 2. (it corresponds to seconds 1 to 2 in the stretched audio) Leaving the rest of the audio as is.

    time_map = [(0, 0), (sr, sr), (3*sr, 2*sr), (5*sr, 4*sr)]

    enhancement 
    opened by marcsarfa 13
  • replace librosa.load with pysoundfile.read

    replace librosa.load with pysoundfile.read

    I really like librosa but importing it only for the read/write capability can make things complicated. There are other libraries which only focus on audio I/O like pysoundfile and therefore have less dependencies and are more flexible.

    This PR therefore removes librosa dependency and replace it with pysoundfile. I know that pysoundfile is not optimal because it not pure python but since timestretching/pitch shifting is often applied on general audio files a library which supports a large number of input and output formats like portaudio is beneficial. Also to my knowledge there are currently no better solutions for python.

    I've also added a note howto easily install rubberband cli on mac by providing a homebrew recipe

    enhancement 
    opened by faroit 11
  • require soundfile, not pysoundfile

    require soundfile, not pysoundfile

    pysoundfile is deprecated: https://github.com/bastibe/PySoundFile

    What does this implement/fix? Explain your changes.

    The PySoundFile page on GitHub indicates that PySoundFile was renamed to SoundFile.

    The install command is now pip install soundfile.

    Any other comments?

    I had to comment out the pytest lines in setup.cfg in order to run the tests. But, the tests did pass!

    Running pytest with setup.cfg as is results in:

    ↪ pytest
    ================================================================================ test session starts ================================================================================
    platform darwin -- Python 3.6.12, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
    rootdir: /Users/nw_henderson/github.com/nwh/pyrubberband, configfile: setup.cfg
    plugins: cov-2.10.1, pep8-1.0.6
    collected 0 items / 1 error                                                                                                                                                         
    Coverage.py warning: No data was collected. (no-data-collected)
    
    ====================================================================================== ERRORS =======================================================================================
    ___________________________________________________________________________ ERROR collecting test session ___________________________________________________________________________
    Direct construction of Pep8Item has been deprecated, please use Pep8Item.from_parent.
    See https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent for more details.
    
    ---------- coverage: platform darwin, python 3.6.12-final-0 ----------
    Name                       Stmts   Miss  Cover   Missing
    --------------------------------------------------------
    pyrubberband/__init__.py       3      3     0%   4-7
    pyrubberband/pyrb.py          72     72     0%   3-257
    pyrubberband/version.py        1      1     0%   4
    --------------------------------------------------------
    TOTAL                         76     76     0%
    
    ============================================================================== short test summary info ==============================================================================
    ERROR 
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ================================================================================= 1 error in 0.09s ==================================================================================
    
    opened by nwh 4
  • add feature for parsing ableton ASD file

    add feature for parsing ableton ASD file

    Reference Issue

    N/A

    What does this implement/fix? Explain your changes.

    This adds a function ableton_asd_to_time_map for parsing Ableton .asd warp files into a time_map list to be used with pyrb.timemap_stretch.

    Any other comments?

    Example usage:

    import pyrb
    import librosa
    
    sr = 44100
    bpm = 120.
    
    y = librosa.load('song.wav', sr=sr)[0]
    time_map = pyrb.ableton_asd_to_time_map('song.wav.asd', y, sr, bpm)
    new_song = pyrb.timemap_stretch(y, sr, time_map)
    
    from scipy import io
    import scipy.io.wavfile
    io.wavfile.write('new_song.wav', sr, new_song )
    

    I wrote the code after reading https://github.com/jtxx000/extract-warp-markers. That project showed how to extract the BPM. I did some extra probing to find out how to get other fields such as loop_start, loop_end, start_marker, end_marker, loop_on. I think having that information could be really useful for other developers. Perhaps pyrubberband could handle looping one day.

    It's possible that this function could break if Ableton changes their ASD format... But I still think it's worth sharing. I'm using Ableton 10.1.30.

    opened by DBraun 3
  • Preserve original data type

    Preserve original data type

    sf.read defaults to reading files as float64, which causes pyrubberband to implicitly convert all processed audio into float64 regardless of the original data type. This change makes pyrubberband preserve the data type of the input by reading it back in the same format.

    enhancement 
    opened by joonoro 1
  • [Not a Bug] How to time_stretch without changing the pitch?

    [Not a Bug] How to time_stretch without changing the pitch?

    I followed this example that I found on Medium but it doesn't seem to work. When the playbackRate is increased, how can I correct the pitch so that it is the same as the original audio?

    Screen Shot 2021-09-21 at 7 55 27 PM

    I have also tried the following by passing the output of time_stretch to the input of pitch_shift

    # Play back at 1.5X speed
    y_stretch = pyrb.time_stretch(audioData, sampleRate, audioSpeed)
    # Play back two 1.5x tones
    y_shift = pyrb.pitch_shift(y_stretch, sampleRate, audioSpeed)
    soundfile.write(f'{tmp_name}.wav', y_shift, sampleRate, format='wav')
    
    opened by Jun711 4
  • Adding support for single valued `rbargs`

    Adding support for single valued `rbargs`

    Reference Issue

    Fixes Issue #21

    What does this implement/fix? Explain your changes.

    Arguments to CLI, parsed through rbargs can be single or dual valued, but currently breaks if it's single valued. for e.g. pyrb.pitch_shift(wav_data, n_semitones, rbargs={'--formant'}) won't work.

    This current implementation allows us to restore that functionality by parsing an empty value '' to the CLI.

    This fix allows us to parse flags through in the form of rbargs={'--flag' : ''} while retaining the kwargs format.

    Any other comments?

    I do feel that this leaves us a bit wanting for something nicer but it's just a step forward to allow some functionality for now. We can explore making the extra argument as None instead of '', but I figured this is probably just as intuitive for these occasional use-cases.

    opened by adityatb 11
  • Can't pass flags (rbargs) with keyword but no value

    Can't pass flags (rbargs) with keyword but no value

    Description

    Some flags in rubberband are not followed by a value, e.g. --no-lamination or --pitch-hq. The current implementation always expects rbargs as pairs of keyword and argument (in dict format), making it impossible to use flags that don't take values.

    Steps/Code to Reproduce

    import pyrubberband
    
    # Generate a random signal and time-stretch it
    sr = 22050
    y = np.random.randn(5 * sr)
    
    y_stretch = pyrubberband.time_stretch(y, sr, rate=1.5, rbargs={"-c": "6"})  # works
    y_stretch = pyrubberband.time_stretch(y, sr, rate=1.5, rbargs={"--pitch-hq": ""})  # fails
    y_stretch = pyrubberband.time_stretch(y, sr, rate=1.5, rbargs={"--pitch-hq": " "})  # fails
    y_stretch = pyrubberband.time_stretch(y, sr, rate=1.5, rbargs={"--pitch-hq": None})  # fails
    

    Expected Results

    Should be possible to call no-value flags such as --pitch-hq. Included some examples above of syntax that could be supported with dicts (e.g. None). Alternative dict could be replaced with e.g. tuple that can have either 1 or 2 elements.

    Actual Results

    ---------------------------------------------------------------------------
    CalledProcessError                        Traceback (most recent call last)
    <ipython-input-45-8758af91c0ad> in <module>
          5 filename = '/Users/salamon/dev/scaper/tests/data/audio/foreground/human_voice/42-Human-Vocal-Voice-all-aboard_edit.wav'
          6 audio, sr = soundfile.read(filename)
    ----> 7 audio_pitch = pyrubberband.pitch_shift(audio, sr, 1, rbargs=params)
          8 Audio(data=audio_pitch.T, rate=sr)
    
    ~/dev/miniconda3/envs/scaper35/lib/python3.5/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)
    
    ~/dev/miniconda3/envs/scaper35/lib/python3.5/site-packages/pyrubberband/pyrb.py in __rubberband(y, sr, **kwargs)
         72         arguments.extend([infile, outfile])
         73 
    ---> 74         subprocess.check_call(arguments, stdout=DEVNULL, stderr=DEVNULL)
         75 
         76         # Load the processed audio.
    
    ~/dev/miniconda3/envs/scaper35/lib/python3.5/subprocess.py in check_call(*popenargs, **kwargs)
        269         if cmd is None:
        270             cmd = popenargs[0]
    --> 271         raise CalledProcessError(retcode, cmd)
        272     return 0
        273 
    
    CalledProcessError: Command '['rubberband', '-q', '-c', '6', '--pitch-hq', ' ', '--pitch', '1', '/var/folders/j4/2cgkdym179b76zljmlm1d6yc0000gn/T/tmpu311s4a2.wav', '/var/folders/j4/2cgkdym179b76zljmlm1d6yc0000gn/T/tmpermm7whf.wav']' returned non-zero exit status 2
    

    Versions

    Darwin-18.2.0-x86_64-i386-64bit Python 3.5.6 |Anaconda, Inc.| (default, Aug 26 2018, 16:30:03) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] NumPy 1.18.2 SoundFile 0.9.0

    opened by justinsalamon 1
  • Some functions added

    Some functions added

    Reference Issue

    No reference issue

    What does this implement/fix? Explain your changes.

    Implement a function that were not wrapped: frequency multiply: To multiply all frequencies by a certain factor, helpful with some stuff that shifting by semitones cannot achieve. Is the -f option in the CLI

    tempo shift: Instead of calculating manually the ratio conversion for the tempo, use the function already included in rubberband

    enhancement 
    opened by migperfer 2
  • long window mode for signals with sr <= 210Hz

    long window mode for signals with sr <= 210Hz

    Pyrubberband will hang when faced with low-sr signals unless the --window-long flag is set. This PR adds that flag for signals below 210Hz and allows the process to complete.

    opened by markostam 8
  • Low sample rate signal hang with rubberband

    Low sample rate signal hang with rubberband

    I've noticed that when you try to use rubberband on very low-samplerate signals (anything 210Hz and below) rubberband will hang.

    These both hang:

    y = np.random.rand(1024)
    
    shifted = pyrubberband.pitch_shift(y=y, sr=210, n_steps=2)
    stretched = pyrubberband.time_stretch(y=y, sr=210, rate=0.5)
    

    These both work

    y = np.random.rand(1024)
    
    shifted = pyrubberband.pitch_shift(y=y, sr=211, n_steps=2)
    stretched = pyrubberband.time_stretch(y=y, sr=211, rate=0.5)
    

    The rubberband CLI has the same behavior; it hangs during the first studying pass at 99% CPU until you send it a break:

    $ rubberband -d3 -t 2.0 /tmp/tmpzGl2Zt.wav /tmp/tmpzGl2Zt_2.wav
    Using crispness level: 5 (Crisp monophonic instrumental)
    Using time ratio 2 and frequency ratio 1
    RubberBandStretcher::Impl::Impl: rate = 125, options = 16
    configure: effective ratio = 2
    configure: analysis window size = 8, synthesis window size = 8, fft size = 8, increment = 0 (approx output increment = 0)
    configure: outbuf size = 8192
    Window area: 0.5; synthesis window area: 0.5
    FFT::FFT(8): using implementation: fftw
    Not real time mode: prefilling
    configure: effective ratio = 2
    configure: analysis window size = 8, synthesis window size = 8, fft size = 8, increment = 0 (approx output increment = 0)
    configure: outbuf size = 8192
    Not real time mode: prefilling
    configure: effective ratio = 2
    configure: analysis window size = 8, synthesis window size = 8, fft size = 8, increment = 0 (approx output increment = 0)
    configure: outbuf size = 8192
    Pass 1: Studying...
    

    Interestingly, this only seems to be an issue when rate for time_stretch < 1 or when n_steps for pitch_shift > 0, otherwise it runs fine.

    I haven't had time to dig into the rubberband source and likely will not any time soon but I've noticed that passing the --window-long flag will allow it to run to completion. IE these both run fine:

    y = np.random.rand(1024)
    
    shifted = pyrubberband.pitch_shift(y=y, sr=210, n_steps=2, rbargs={"-q":"--window-long"})
    stretched = pyrubberband.time_stretch(y=y, sr=210, rate=0.5, rbargs={"-q":"--window-long"})
    

    It's hacky, but would it make sense to simply add a conditional that would add the --window-long flag to any sr <= 210?

    opened by markostam 0
Releases(0.3.0)
Owner
Brian McFee
Assistant Professor of Music Technology and Data Science
Brian McFee
A simple voice detection system which can be applied practically for designing a device with capability to detect a baby’s cry and automatically turning on music

Auto-Baby-Cry-Detection-with-Music-Player A simple voice detection system which can be applied practically for designing a device with capability to d

2 Dec 15, 2021
This Bot can extract audios and subtitles from video files

Send any valid video file and the bot shows you available streams in it that can be extracted!!

TroJanzHEX 56 Nov 22, 2022
A rofi-blocks script that searches youtube and plays the selected audio on mpv.

rofi-ytm A rofi-blocks script that searches youtube and plays the selected audio on mpv. To use the script, run the following command rofi -modi block

Cliford 26 Dec 21, 2022
A useful tool to generate chord progressions according to melody MIDIs

Auto chord generator, pure python package that generate chord progressions according to given melodies

Billy Yi 53 Dec 30, 2022
Audio library for modelling loudness

Loudness Loudness is a C++ library with Python bindings for modelling perceived loudness. The library consists of processing modules which can be casc

Dominic Ward 33 Oct 02, 2022
Python game programming in Jupyter notebooks.

Jupylet Jupylet is a Python library for programming 2D and 3D games, graphics, music and sound synthesizers, interactively in a Jupyter notebook. It i

Nir Aides 178 Dec 09, 2022
Gateware for the Terasic/Arrow DECA board, to become a USB2 high speed audio interface

DECA USB Audio Interface DECA based USB 2.0 High Speed audio interface Status / current limitations enumerates as class compliant audio device on Linu

Hans Baier 16 Mar 21, 2022
Muzic: Music Understanding and Generation with Artificial Intelligence

Muzic is a research project on AI music that empowers music understanding and generation with deep learning and artificial intelligence.

Microsoft 2.6k Dec 30, 2022
Python interface to the WebRTC Voice Activity Detector

py-webrtcvad This is a python interface to the WebRTC Voice Activity Detector (VAD). It is compatible with Python 2 and Python 3. A VAD classifies a p

John Wiseman 1.5k Dec 22, 2022
Music bot of # Owner

Pokimane-Music Music bot of # Owner How To Host The easiest way to deploy this Bot Support Channel :- TeamDlt Support Group :- TeamDlt Please fork thi

5 Dec 23, 2022
Code to work with wave files!

Code to work with wave files!

Mohammad Dori 3 Jul 15, 2022
Basically Play Pauses the song when it is safe to do so. when you die in a round

Basically Play Pauses the song when it is safe to do so. when you die in a round

AG_1436 1 Feb 13, 2022
PianoPlayer - Automatic fingering generator for piano scores

PianoPlayer - Automatic fingering generator for piano scores

Marco Musy 571 Jan 02, 2023
a library for audio and music analysis

aubio aubio is a library to label music and sounds. It listens to audio signals and attempts to detect events. For instance, when a drum is hit, at wh

aubio 2.9k Dec 30, 2022
Python tools for the corpus analysis of popular music.

CATCHY Corpus Analysis Tools for Computational Hook discovery Python tools for the corpus analysis of popular music recordings. The tools can be used

Jan VB 20 Aug 20, 2022
TONet: Tone-Octave Network for Singing Melody Extraction from Polyphonic Music

TONet Introduction The official implementation of "TONet: Tone-Octave Network for Singing Melody Extraction from Polyphonic Music", in ICASSP 2022 We

Knut(Ke) Chen 29 Dec 01, 2022
A python library for working with praat, textgrids, time aligned audio transcripts, and audio files.

praatIO Questions? Comments? Feedback? A library for working with praat, time aligned audio transcripts, and audio files that comes with batteries inc

Tim 224 Dec 19, 2022
pedalboard is a Python library for adding effects to audio.

pedalboard is a Python library for adding effects to audio. It supports a number of common audio effects out of the box, and also allows the use of VST3® and Audio Unit plugin formats for third-party

Spotify 3.9k Jan 02, 2023
Official implementation of A cappella: Audio-visual Singing VoiceSeparation, from BMVC21

Y-Net Official implementation of A cappella: Audio-visual Singing VoiceSeparation, British Machine Vision Conference 2021 Project page: ipcv.github.io

Juan F. Montesinos 12 Oct 22, 2022
A Quick Music Player Made Fully in Python

Quick Music Player Made Fully In Python. Pure Python, cross platform, single function module with no dependencies for playing sounds. Installation & S

1 Dec 24, 2021