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
:sound: Play and Record Sound with Python :snake:

Play and Record Sound with Python This Python module provides bindings for the PortAudio library and a few convenience functions to play and record Nu

spatialaudio.net 750 Dec 31, 2022
Audio spatialization over WebRTC and JACK Audio Connection Kit

Audio spatialization over WebRTC Spatify provides a framework for building multichannel installations using WebRTC.

Bruno Gola 34 Jun 29, 2022
Full LAKH MIDI dataset converted to MuseNet MIDI output format (9 instruments + drums)

LAKH MuseNet MIDI Dataset Full LAKH MIDI dataset converted to MuseNet MIDI output format (9 instruments + drums) Bonus: Choir on Channel 10 Please CC

Alex 6 Nov 20, 2022
PatrikZero's CS:GO Hearing protection

Program that lowers volume when you die and get flashed in CS:GO. It aims to lower the chance of hearing damage by reducing overall sound exposure. Uses game state integration. Anti-cheat safe.

Patrik Žúdel 224 Dec 04, 2022
A music player designed for a University Project.

A music player designed for a University Project. Very flexibe and easy to use, a real life working application with user friendly controls. Hope u enjoy!!

Aditya Johorey 1 Nov 19, 2021
PianoPlayer - Automatic fingering generator for piano scores

PianoPlayer - Automatic fingering generator for piano scores

Marco Musy 571 Jan 02, 2023
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
Cobra is a highly-accurate and lightweight voice activity detection (VAD) engine.

On-device voice activity detection (VAD) powered by deep learning.

Picovoice 88 Dec 16, 2022
Omniscient Mozart, being able to transcribe everything in the music, including vocal, drum, chord, beat, instruments, and more.

OMNIZART Omnizart is a Python library that aims for democratizing automatic music transcription. Given polyphonic music, it is able to transcribe pitc

MCTLab 1.3k Jan 08, 2023
A simple python script to play bell sound in your system infinitely, just for fun and experimental purposes

A simple python script to play bell sound in your system infinitely, just for fun and experimental purposes

نافع الهلالي 1 Oct 29, 2021
Bot Music Pintar. Created by Rio

🎶 Rio Music 🎶 Kalo Fork Star Ya Bang Hehehe Requirements 📝 FFmpeg NodeJS nodesource.com Python 3.8+ or 3.7 PyTgCalls Generate String Using Replit ⤵

RioProjectX 7 Jun 15, 2022
Mousai is a simple application that can identify song like Shazam

Mousai is a simple application that can identify song like Shazam. It saves the artist, album, and title of the identified song in a JSON file.

Dave Patrick 662 Jan 07, 2023
GiantMIDI-Piano is a classical piano MIDI dataset contains 10,854 MIDI files of 2,786 composers

GiantMIDI-Piano is a classical piano MIDI dataset contains 10,854 MIDI files of 2,786 composers

Bytedance Inc. 1.3k Jan 04, 2023
A tool for retrieving audio in the past

Rewinder A tool for retrieving audio in the past. Ever felt like, I need to remember that discussion which happened 10 min back. Now you can! Rewind a

Bharat 1 Jan 24, 2022
An audio digital processing toolbox based on a workflow/pipeline principle

AudioTK Audio ToolKit is a set of audio filters. It helps assembling workflows for specific audio processing workloads. The audio workflow is split in

Matthieu Brucher 238 Oct 18, 2022
Implementation of "Slow-Fast Auditory Streams for Audio Recognition, ICASSP, 2021" in PyTorch

Auditory Slow-Fast This repository implements the model proposed in the paper: Evangelos Kazakos, Arsha Nagrani, Andrew Zisserman, Dima Damen, Slow-Fa

Evangelos Kazakos 57 Dec 07, 2022
python script for getting mp3 files from yaoutube playlist

mp3-from-youtube-playlist python script for getting mp3 files from youtube playlist. Do your non-tech brown relatives ask you for downloading music fr

Shuhan Mirza 7 Oct 19, 2022
OpenClubhouse - A third-part web application based on flask to play Clubhouse audio.

OpenClubhouse - A third-part web application based on flask to play Clubhouse audio.

1.1k Jan 05, 2023
Generating a structured library of .wav samples with Python.

sample-library Scripts for generating a structured sample library with Python Requires Docker about Samples are written to wave files in lib/. Differe

Ben Mangold 1 Nov 11, 2021
Synchronize a local directory of songs' (MP3, MP4) metadata (genre, ratings) and playlists with a Plex server.

PlexMusicSync Synchronize a local directory of songs' (MP3, MP4) metadata (genre, ratings) and playlists (m3u, m3u8) with a Plex server. The song file

Tom Goetz 9 Jul 07, 2022