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)
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.
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.
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? :)
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)