An ambulance siren sounds higher as it comes toward you and lower once it has passed. The siren never changes its note. Its motion squeezes the sound waves ahead of it and stretches the ones behind. Push the source faster than sound and the waves pile into a shock cone that sweeps the ground as a sonic boom. The same squeeze, applied to radio waves and light, catches speeders and measures how fast galaxies move.
Sound is a ripple of air pressure that spreads out in rings at a fixed speed, the speed of sound c. A siren sends out a fixed number of ripples per second, its frequency f, measured in hertz (Hz). Your ear hears frequency as pitch. When the siren moves, each new ring starts a little farther along the road, so the rings bunch up in front and spread out behind. Drag the green listener anywhere, change the speeds, and press play to hear the pitch drop.
How to read this: Top: the road seen from above. Each green ring is one burst of sound spreading out from where the siren was when it made it. Bottom: the pitch you hear over time. The animation runs faster than real time.
Try this: Press "Play the pass" and listen. Then drag the green dot far from the road and play again: the drop becomes a slow slide.
Sound starts only when you press play. Volume is low; it stops if you switch tabs.
vs is the siren's speed and θ the angle between its direction of travel and the line to you, measured when the sound you hear now left it. vo is your speed and φ the angle between your motion and the line to the siren. Head-on, cos θ = 1 and the pitch is highest. Going away, cos θ = −1 and it is lowest.
Warm air has faster molecules, so sound travels faster: at , at .
If you stood in the middle of the road, the pitch would jump straight from high to low as the siren went through you. Standing to the side, the angle θ sweeps smoothly from 0° to 180°, so the pitch slides down. The farther you stand from the road, the slower the slide. Drag the listener away from the road and watch the curve flatten.
The model is idealized: still air, a point source, straight-line motion. Wind adds to the speed of sound in one direction and subtracts in the other.
import math def sound_speed(T_c): # dry air, m/s; T_c in °C return 331.3 * math.sqrt(1 + T_c / 273.15) def heard(f, t, vs, vo, lx, ly, c): """Pitch heard at time t. Siren at (vs*t, 0), listener at (lx + vo*t, ly). Units: m, s, Hz.""" xl = lx + vo * t # sound emitted at te reaches you at t: c*(t - te) = distance gap = lambda te: c * (t - te) - math.hypot(xl - vs * te, ly) lo = t - 2 * math.hypot(xl - vs * t, ly) / (c - abs(vs)) - 1 hi = t for _ in range(64): # bisection for te mid = (lo + hi) / 2 if gap(mid) > 0: lo = mid else: hi = mid dx = xl - vs * lo cos_t = dx / math.hypot(dx, ly) # cos θ at emission return f * (c - vo * cos_t) / (c - vs * cos_t) c = sound_speed(20) # 343.2 m/s f, vs = 700, 30 print(f * c / (c - vs)) # approaching: 767.0 Hz print(f * c / (c + vs)) # receding: 643.7 Hz print(heard(f, 0.0, vs, 0, 40, 60, c)) # the curve in the lab
The Mach number M is the source's speed divided by the speed of sound. Below Mach 1 the rings still outrun the source, only bunched up in front. At Mach 1 the source keeps pace with its own sound and the rings stack into a single wall of pressure. Above Mach 1 the source outruns every ring it makes. The rings overlap only along a cone trailing behind it, and that cone is the shock wave. When the cone's edge sweeps over you on the ground, you hear the boom.
How to read this: Each green ring is sound made a moment ago by the amber dot (the aircraft). Above Mach 1 the rings overlap only along the red V: that is the shock cone, and μ is the angle between its edge and the flight line.
How to read this: Top: the aircraft seen from the side, dragging its red shock cone. Bottom: the ground seen from above, with the aircraft flying along the dashed line. The red curve is the boom sweeping across the ground; everyone in the red-shaded area has already heard it. The scene is sped up (time-lapse) so you don't wait minutes.
Try this: Pick "Mach 1.2, high" and check the "Boom reaches ground in real air?" readout. Then compare "Mach 2 cruise".
In time t the aircraft flies v·t while a ring it made at the start grows to radius c·t. The cone touches every ring, so its half-angle obeys sin μ = c·t / (v·t) = 1/M. At Mach 2 that is 30°.
Directly under the flight path, the cone's edge reaches you after the aircraft has flown h·√(M² − 1) past the overhead point. Off to the side you are farther from the aircraft, so the boom comes later. The boom front on the ground is a curve called a hyperbola, drawn in red in the top view.
The cone and the delay assume air with one temperature, using the speed of sound at the aircraft's altitude from the standard atmosphere ( at the ground, cooling 3.6°F per 1,000 ft up to 36,000 ft). Real air is warmer near the ground, so sound travels faster there and the shock bends upward. If the aircraft's speed is below the ground-level speed of sound, about Mach 1.15 at cruise height, the boom never reaches the ground. The bending also limits how wide the boom carpet is: a common rule of thumb is about 1 mile of width per 1,000 ft of altitude, shaded in the top view.
The boom is not a one-time event at the moment of "breaking" the barrier. A supersonic aircraft drags its cone along the whole time, so everyone under the carpet hears a boom as it passes.
import math def sound_speed(T_c): return 331.3 * math.sqrt(1 + T_c / 273.15) def isa_temp(h): # standard atmosphere, °C, h in m return 15 - 0.0065 * h if h < 11000 else -56.5 M, h = 1.6, 12000 # Mach number, altitude in m c = sound_speed(isa_temp(h)) # 295.1 m/s up there v = M * c # 472 m/s mu = math.degrees(math.asin(1 / M)) # Mach angle: 38.7° delay = h * math.sqrt(M**2 - 1) / v # 31.7 s after overhead ahead = v * delay # 15.0 km past you reaches = v > sound_speed(15) # True: faster than sound at ground def boom_time(y): # y = sideways distance from the track return math.hypot(y, h) * math.sqrt(M**2 - 1) / v
Radio waves and light obey the same squeeze. A police radar gun sends out radio waves at a known frequency. A car driving toward it hits the waves more often than they arrive, and the echo comes back shifted up. The gun mixes the echo with its own signal. The difference, called the beat frequency Δf, is a few thousand hertz, which is low enough to count. Light from a galaxy moving away from us is stretched toward red, which astronomers call redshift.
How to read this: The "Measured shift" slider sets what the gun measures; the page works out the car's speed from it. The gold wave at the bottom is the beat the gun counts.
Try this: Raise "Beam angle" and watch the gun's reading fall below the true speed as the red "Cosine error" grows.
The beat frequency is in the range you can hear. Press play to listen; it follows the slider.
How to read this: Each bright bar is a color hydrogen always gives off (Hα, Hβ, Hγ and Hδ are just their names). The strip runs from violet on the left to red on the right. Top row: where the bars sit in a lab. Bottom row: where we see them in the galaxy's light. Shifted right (redder) means moving away; shifted left (bluer) means coming closer.
The shift is doubled because it happens twice: the moving car receives the wave at a higher frequency, then re-emits it as a moving source. At a K-band gun sees a shift of 4,833 Hz on top of 24.15 billion, about 2 parts in 10 million.
The gun measures only the speed along its beam, v cos θ. Aim at an angle and it reads low, an error that always favors the driver.
Weather radars such as the US NEXRAD network transmit between 2.7 and 3.0 GHz and measure the shift from raindrops as a phase change between successive pulses. The physics is the same, and it is how forecasters see the spinning wind of a tornado. Try it in the radar lab of W01 · Tornadoes.
For light the waves need no air, so only the relative speed matters and relativity sets the exact formula. Below a few percent of light speed, z ≈ v/c is accurate to better than 1%.
import math C = 299_792_458 # speed of light, m/s f = 24.150e9 # K-band radar gun, Hz df = 4830 # measured beat frequency, Hz theta = 10 # beam angle to the road, degrees v_beam = C * df / (2 * f) # 29.98 m/s along the beam v_true = v_beam / math.cos(math.radians(theta)) # 30.44 m/s v = 6.0e6 # galaxy moving away, m/s z_approx = v / C # 0.0200 z_exact = math.sqrt((1 + v/C) / (1 - v/C)) - 1 # 0.0202 print(656.28 * (1 + z_exact)) # H-alpha at 669.5 nm
Related: S00 · Waves & harmonics · S02 · The Fourier transform (how a gun finds Δf) · W09 · Sky color