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)
What does this ringtone look like if we plot its waveform?
figure(figsize=(10, 6)) t = arange(whistle.shape, 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)')
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))