kupix / bungee

Audio time stretch and pitch shift library. Enables music tempo adjustment, transposition, "smooth scrub" and "live pause".
https://bungee.parabolaresearch.com/
Mozilla Public License 2.0
96 stars 3 forks source link
audio-processing audio-speed music-tempo phase-vocoder pitch-shifter

actions workflow

🎵 Bungee: Audio Time Stretch and Pitch Shift C++ Library

Bungee is a real-time library for stretching audio. It can:

Bungee is unique in its controllability, allowing continually changing pitch and position with seamless support of zero and negative playback speeds. So it can be used for a "smooth scrub" or for rendering life-like audio for slow-motion videos.

Features

Getting started

Bungee's dependencies are managed as git submodules; so clone like this:

git clone --recurse-submodules https://github.com/kupix/bungee

Use CMake to configure and build the bungee library and command-line executable:

cd bungee
mkdir build && cd build
cmake ..
cmake --build .

After a successful build, run the bungee executable

./bungee --help

Using Bungee from your own code

Bungee operates on discrete, overlapping "grains" of audio, typically processing around 100 grains per second. Parameters such as position and pitch are provided on a per-grain basis so that they can be changed continuously as audio rendering progresses. This means that only minimal parameters are required for instantiation.

For a working example of this API, see cmd/main.cpp.

Instantiation

To instantiate, include the bungee/Bungee.h header file, create a Stretcher<Basic> object and initialise a Request object:

#include "Bungee.h"
#include <cmath>

const int sampleRate = 44100;

Bungee::Stretcher<Bungee::Basic> stretcher({sampleRate, sampleRate}, 2);

Bungee::Request request{};

// Set pitch, this example shows an upward transposition of one semitone.
request.pitch = std::pow(2., 1. / 12.);

// Set initial speed, this example shows how to achieve constant 75% output speed.
request.speed = 0.75;

// Set initial starting position at 0.5 seconds offset from the start of the input buffer.
request.position = 0.5;

// This call adjusts request.position so that stretcher's pipeline will be fully initialised by the
// time it reaches the starting position of 0.5 seconds offset.
stretcher.preroll(request);

Granular loop

Stretcher's processing functions are typically called from within a loop, each iteration of which corresponds to a grain of audio. For each grain, the functions Stretcher<Basic>::specifiyGrain, Stretcher<Basic>::analyseGain and Stretcher<Basic>::synthesiseGrain should be called in sequence.

while (true)
{
    // ...
    // Change request's members, for example, position, speed or pitch, as required here.
    // ...

    auto inputChunk = stretcher.specifyGrain(request);

    // ...
    // Examine inputChunk and retrieve the segment of input audio that the stretcher requires here.
    // Set data and channelStride to point to the input data.
    // ...

    stretcher.analyseGrain(data, channelStride);

    Bungee::OutputChunk outputChunk;
    stretcher.synthesiseGrain(outputChunk);

    // ...
    // Output the audio buffer indicated by outputChunk here.
    // ...

    // Prepare request for the next grain (modifies request.position according to request.speed)
    stretcher.next(request);
}

Things to note

Dependencies

The Bungee library gratefully depends on:

The sample bungee command-line utility also uses:

See this repo's .gitmodules for versioned links to these projects.

Bungee Pro

Bungee Pro is a closed-source commercial audio library built on Bungee's API and core philosophy. It uses novel algorithms for sharp and clear professional-grade audio and runs at least as fast as Bungee, thanks to platform-specific performance optimisations.

Try Bungee Pro now in your browser, see a comparison with other techniques and consider licensing if your app would benefit from: