Variations on the Samsung whistle ringtone

Update October 1, 2014: I made a YouTube video from the content of this post! You can find more details about how I made the video using the great Python movie library MoviePy in the dedicated repository.

There's this ringtone. Everyone has it. Especially here, in Korea. It's a whistling. A really cool whistling sound. And you know what? I'm bored so we're gonna have some fun with this tune!

In [1]:
%matplotlib inline
from pylab import *
In [2]:
from scipy.io import wavfile
In [3]:
sample_freq, whistle = wavfile.read("files/samsung_ringtone.wav")

For those that haven't heard this thing, you can hear it below:

In [4]:
from IPython.display import Audio, display
Audio(data = whistle, rate=sample_freq)
Out[4]:

Visualizing the waveform

What does this ringtone look like if we plot its waveform?

In [5]:
figure(figsize=(10, 6))
t = arange(whistle.shape[0], dtype=float32) / sample_freq
subplot(211)
plot(t, whistle)
xlabel("time (s)")
title('waveform of the whistling ringtone')
grid(True)

As one can see, the plot clearly shows the 5 tones that are whistled.

Visualizing the spectrogram

When you listen closely to that sound, you can hear that the 4th note is a sort of sliding tone. Can we plot a spectrogram and actually show this?

In [6]:
specgram(whistle, Fs=sample_freq)
xlim(0, 1.1)
ylim(0, 10000)
xlabel('time (s)')
ylabel('frequency (Hz)')
Out[6]:
<matplotlib.text.Text at 0x5788f30>

Indeed, we can see that the fourth sound is not very horizontal, but rather sloped upwards: I would say it's a slide from a note to another.

Fun with ringtones and permutations

Until now everything we did was fun. But what do you do when you're in Korea and everyone use the original ringtone with his phone? You surely would like to stand out and be original, right?

Below, we'll develop a recipe for being original: first we segment the ringtone in its components and then we recreate all the possible permuations of the ringtone with these components. So that in the end, it sounds just like the real thing, but different. Let's get started!

First, we plot the times at which the ringtone is split into chunks.

In [7]:
chunk_times = [0., 0.22, 0.38, 0.5, 0.92, 1.2]

specgram(whistle, Fs=sample_freq)
xlim(0, 1.1)
ylim(0, 10000)
xlabel('time (s)')
ylabel('frequency (Hz)')

for time in chunk_times[:-1]:
    vlines(time, 0, 10000)
In [8]:
from scipy.signal import get_window

chunks = []
for start, end in zip(chunk_times[:-1], chunk_times[1:]):
    chunks.append(whistle[(t > start) & (t < end)] * get_window('hamming', t[(t > start) & (t < end)].size))
In [9]:
for chunk in chunks:
    display(Audio(chunk, rate=sample_freq))

Now that we have the individual chunks, we can permute all of them and rebuild the new ones!

In [10]:
from itertools import permutations

for p in permutations((0, 1, 2, 3, 4)):
    out = []
    for elem in p:
        if len(out) == 0:
            out = chunks[elem].copy() 
        else:
            out = concatenate((out, chunks[elem].copy()))
    display(Audio(out, rate=sample_freq))