The old US ringtone is the combination of two frequencies (440 and 480 Hz). This notebook shows how to create the audio for this ringtone.
Sympy
Audio
Matplotlib
Python
Author
Scott Wied
Published
November 28, 2022
1 Introduction
The Bell telphone ringtone was a two second tone composed of the frequencies 440 Hz and 480 Hz. The tone was followed by a four second pause, and then repeated. This ringtone continues to be used in the US with most mobile/landline carriers, and PBX systems. Read more about this, and other international ringtones, at https://en.wikipedia.org/wiki/Ringing_tone.
You can download a recording of the US ringtone, which is now in the public domain. Shown below is a demonstration of how to play this sound file within a Jupyter notebook.
from IPython.display import display, HTML, AudioHTML("""<p>Ringtone Recording:</p> <audio controls> <source type="audio/mp3" src="resources/US_ringback_tone.mp3"> <source type="audio/ogg" src="resources/US_ringback_tone.ogg"> <p>Your browser cannot play this audio</p> </audio>""")
Ringtone Recording:
2 Basics of audio frequencies
Let’s start with some basics before jumping into recreating this ringtone.
Where, \(t\) is the time value, and \(f\) = wave frequency (Hertz).
2.1 Symbolic equations in Python
If you are exploring a problem it can be helpful to start with symbolic computation. The Sympy package in Python allows you to operate on and simplify algebraic equations. Then, when you are ready, you can easily convert your equations into numerical formats (e.q., a Python list, or a Numpy array).
Define sinusoidal waveform equation as a symbolic equation.
import sympy as s# Define variables as Sympy symbolst, f = s.symbols('t f')# Define Sympy equationy = s.sin(2*s.pi*t*f)print(f"y = {y}")
y = sin(2*pi*f*t)
2.2 Musical notes
As a first example let’s explore a couple of pure tones: 440 Hz (A4), and 480 Hz (B4).
# Substitue these frequencies in for fy_at_440_hz = y.subs(f, 440)y_at_480_hz = y.subs(f, 480)
# Show the new equationsprint(f"y_at_440_hz = {y_at_440_hz}")print(f"y_at_480_hz = {y_at_480_hz}")
Let’s plot these example frequencies together on a graph. Note that we don’t have to transform our equations into numerical lists before plotting them. Sympy does this for us. We just need to provide a plot range.
plot_range = (t, 0, 1/440)# Plot the curve for A4p = s.plot( y_at_440_hz, plot_range, line_color='gray', title=f'Frequencies 440Hz, and 480Hz', show=False)# Add the curve for B4 to the graphp.extend(s.plot( y_at_480_hz, plot_range, line_color='green', show=False, adaptive=False))# Format the graph and display itp.size = (6,5)p.show()
2.4 Convert Sympy equations into Python lists
In order to listen to these two notes we need to convert the equations into numerical time series.
# Define numeric values for f1, and f2f_440, f_480 = (440, 480)# Number of samples per cyclen =50# Number of seconds of play timeplay_time =3# Sampling period in micro-secondst_440_delta =int(1e6/n/f_440)t_480_delta =int(1e6/n/f_480) # Total play time in micro-secondst_max =int(play_time*1e6)
# Iterators for each time seriests_440_range =range(0, t_max, t_440_delta)ts_480_range =range(0, t_max, t_480_delta)# Generate numeric lists from lambda# functions. Note: time (t) values have # to be converted back into seconds.ts_440 = [lambda_y_440(t/1e6) for t in ts_440_range]ts_480 = [lambda_y_480(t/1e6) for t in ts_480_range]
2.5 Play sounds for A4 and B4
Audio(ts_440, rate=f_440*n)
Audio(ts_480, rate=f_480*n)
3 Recreate the US ringtone
In the United States, the ringtone has historically been a two second tone composed of the frequencies 440 Hz and 480 Hz. The tone is followed by a four second pause, and then repeated until the call is answered.
3.1 Acoustic Equations
When multiple sound waves overlap, their amplitudes add together. This is called superposition.
\(y_{super}(t) = sin \left({ 2 \pi f_1 t }\right) + sin \left({ 2 \pi f_2 t }\right)\)
Plot the superpositioned frequencies along with the curve for the beat frequency.
plot_range = (t, 0, 2/f_beat)# Plot the superpositioned waveform in grayp = s.plot( y_super, plot_range, line_color='gray', title=f'Superposition {f1}Hz, and {f2}Hz', show=False, adaptive=False)# Plot, on the same graph, the beat frequency # function in green.p.extend( s.plot(y_beat, plot_range, line_color='green', show=False, adaptive=False))p.size = (6,5)p.show()
# Number of samples per cyclen =50# Number of seconds of play timeplay_time =2# Sampling period in micro-secondst_delta =int(1e6/n/max(f1,f2))# Total play time in micro-secondst_max =int(play_time*1e6)
# Create the time series as a listts_ringtone = [ lambda_y_ringtone(t/1e6) for t inrange(0,t_max, t_delta)]pause_4sec = [0.0for t inrange(0,2*t_max,t_delta)]