Fibonacci Stretch: Examples

by David Su

Here are some audio examples of the Fibonacci stretch algorithm in action. This notebook and its associated code are also available on GitHub.

Fibonacci Stretch is a method of time-stretching an existing audio track such that its rhythmic pulses become expanded or contracted along the Fibonacci sequence, using Euclidean rhythms as the basis for modification. Inspiration came initially from Vijay Iyer's article on Fibonacci numbers and musical rhythm as well as his trio's renditions of "Mystic Brew" and "Human Nature".

Setup

First, let's import everything we need, namely the fibonaccistretch module (which you can find here):

In [2]:
%matplotlib inline
import pardir; pardir.pardir() # Allow imports from parent directory
from fibonaccistretch import fibonacci_stretch_track

And let's also define some variables for convenience:

In [3]:
tresillo_rhythm = [1,0,0,1,0,0,1,0]

"Human Nature" stretched by a factor of 1

For our first example we'll stretch Michael Jackson's "Human Nature", off of his 1982 album Thriller.

We're using the tresillo rhythm as the original_rhythm and a stretch_factor of 1, which means [1,0,0,1,0,0,1,0] (with pulse lengths [3,3,2]) will get expanded to [1,0,0,0,0,1,0,0,0,0,1,0,0] (with pulse lengths [5,5,3]), as each pulse length is scaled along Fibonacci sequence by an index of +1:

In [4]:
# "Human Nature" stretched by a factor of 1 using default parameters
fibonacci_stretch_track("data/humannature_90s.mp3",
                        original_rhythm=tresillo_rhythm,
                        stretch_factor=1,
                        tempo=93.0)
Out[4]:

"Human Nature" stretched by a factor of 2

With a stretch_factor of 2, the tresillo rhythm [1,0,0,1,0,0,1,0] (with pulse lengths [3,3,2]) is expanded to [1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0] (with pulse lengths [8,8,5]):

In [5]:
# "Human Nature" stretched by a factor of 2
fibonacci_stretch_track("data/humannature_30s.mp3",
                        original_rhythm=tresillo_rhythm,
                        stretch_factor=2,
                        tempo=93.0,
                        overlay_clicks=True)
Out[5]:

"Chan Chan" stretched by a factor of -1

We can contract rhythms as well using negative numbers as our stretch_factor. Let's try that with "Chan Chan" by the Buena Vista Social Club:

In [6]:
# "Chan Chan" stretched by a factor of -1
fibonacci_stretch_track("data/chanchan_30s.mp3",
                        original_rhythm=tresillo_rhythm,
                        stretch_factor=-1,
                        tempo=78.5)
Out[6]:

(Note that although we do end up with a perceptible difference (the song now sounds like it's in 7/8), it should actually sound like it's in 5/8, since [1 0 0 1 0 0 1 0] is getting compressed to [1 0 1 0 1]. This is an implementation detail with the Euclidean stretch method that needs to be fixed.)

"I'm the One" stretched by a factor of 1, with custom original rhythm

In order to get musically meaningful results we generally want to supply parameters that make musical sense with our input audio (although it can certainly be interesting to try with parameters that don't!). One of the parameters that makes the most difference in results is the rhythm sequence used to represent each measure.

Here's Chance the Rapper's verse from DJ Khaled's "I'm the One", with a custom original_rhythm that matches the bassline of the song:

In [7]:
# "I'm the One" stretched by a factor of 1
fibonacci_stretch_track("data/imtheone_cropped_chance_60s.mp3",
                        original_rhythm=[1,0,0,0,0,1,0,0],
                        stretch_factor=1,
                        tempo=162)
Out[7]:

"I'm the One" expanded using custom original and target rhythms

We can define both a custom target rhythm as well. In addition, neither original_rhythm nor target_rhythm have to be Fibonacci rhythms for the stretch algorithm to work (although with this implementation they do both have to have the same number of pulses).

Let's try that out with the same verse, going from an original rhythm with 8 steps (i.e. in 4/4 meter) to a target rhythm with 10 steps (i.e. in 5/4 meter):

In [8]:
# "I'm the One" in 5/4
fibonacci_stretch_track("data/imtheone_cropped_chance_60s.mp3",
                        original_rhythm=[1,0,0,0,0,1,0,0],
                        target_rhythm=[1,0,0,0,0,1,0,0,0,0],
                        tempo=162,
                        overlay_clicks=True)
Out[8]:

"Hold Up" contracted using custom original and target rhythms

We can apply contractions simply by supplying a target rhythm that is shorter in length than the original rhythm. Here's an example with Beyonce's "Hold Up":

In [9]:
fibonacci_stretch_track("data/holdup_30s.mp3",
                        original_rhythm=[1,0,1,0,0,1,0,1],
                        target_rhythm=[1,0,0,1,0,1],
                        tempo=82)
Out[9]:

"Eine kleine Nachtmusik" stretched into a swing feel

As another example, we can give a swing feel to the first movement of Mozart's "Eine kleine Nachtmusik" (K. 525), as performed by A Far Cry:

In [10]:
# "Eine kleine Nachtmusik" with a swing feel
fibonacci_stretch_track("data/einekleinenachtmusik_30s.mp3",
                        original_rhythm=[1,0,1,1],
                        target_rhythm=[1,0,0,1,0,1],
                        tempo=130)
Out[10]:

It works pretty decently until around 0:09, at which point the assumption of a metronomically consistent tempo breaks down. (This is one of the biggest weaknesses with the current implementation, and is something I definitely hope to work on in the future.)

"Chan Chan" stretched into 5/4

Let's also hear what "Chan Chan" sounds like in 5/4:

In [11]:
# "Chan Chan" in 5/4
fibonacci_stretch_track("data/chanchan_30s.mp3",
                        original_rhythm=[1,0,0,1,0,0,0,0],
                        target_rhythm=[1,0,0,0,0,1,0,0,0,0], # Also interesting to try with [1,0,1]
                        tempo=78.5)
Out[11]:

"Pink + White" stretched from 6/8 into 4/4

We can also work with source audio in other meters. For example, Frank Ocean's "Pink + White" is in 6/8. Here I've stretched it into 4/4 using the rhythm of the bassline, but you can uncomment the other supplied parameters (or supply your own!) to hear how they sound as well:

In [12]:
# "Pink + White" stretched by a factor of 1
fibonacci_stretch_track("data/pinkandwhite_30s.mp3",
                        beats_per_measure=6,
                        tempo=160,
                        
                        # 6/8 to 4/4 using bassline rhythm
                        original_rhythm=[1,1,1,1,0,0],
                        target_rhythm=[1,1,1,0,1,0,0,0],
                        
                        # 6/8 to 4/4 using half notes
                        # original_rhythm=[1,0,0,1,0,0],
                        # target_rhythm=[1,0,0,0,1,0,0,0],
                        
                        # 6/8 to 10/8 (5/4) using Fibonacci stretch factor of 1
                        # original_rhythm=[1,0,0,1,0,0],
                        # stretch_factor=1,
                        
                        overlay_clicks=True)
Out[12]:

Download the Fibonacci stretch code from GitHub and play around with it yourself!

In [ ]: