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!
%matplotlib inline
from pylab import *
from scipy.io import wavfile
sample_freq, whistle = wavfile.read("files/samsung_ringtone.wav")
For those that haven't heard this thing, you can hear it below:
from IPython.display import Audio, display
Audio(data = whistle, rate=sample_freq)
Visualizing the waveform¶
What does this ringtone look like if we plot its waveform?
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?
specgram(whistle, Fs=sample_freq)
xlim(0, 1.1)
ylim(0, 10000)
xlabel('time (s)')
ylabel('frequency (Hz)')
<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.
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)
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))
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!
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))
So what do you say now? You can use one of the unique $5! - 1 = 119$ other ringtones that were sitting hidden in the original ringtone and set it as your phone alert sound. Isn't that nice? :)
Bonus: reversing the sound¶
Finally, something fun to do that is remniscent of the golden age of the Beatles: play the sound backwards!
Audio(whistle[::-1], rate=sample_freq)