FRidh's blog

Discovery consists of seeing what everybody has seen and thinking what nobody has thought -- Albert Szent-Gyorgyi

Auralization: Doppler effect

The goal of the project that I'm working on is to develop a tool to synthesize how it sounds when an aircraft flies over an urban environment. One part of the project deals with the propagation model, which also includes the Doppler shift. Let's have a look now at how we can include the Doppler shift in auralizations.

Doppler shift equation

The following equation is likely known to you. $$ f = \frac{c + v_r}{c + v_s} f_0 $$ You put in the emission frequency $f_0$, the speed of sound $c$, and the velocity of respectively receiver and source $v_r$ and $v_s$. What you get out is the Doppler shifted frequency.

In the time-domain the Doppler shift is implicitly included when considering the propagation delay between source and receiver. It takes $d = s/c$ seconds to travel the source-receiver distance $s$ at the speed of sound $c$. When the distance changes over time, the emission is Doppler shifted.

Applying the Doppler shift to a tone

As an example we will now apply the Doppler shift to a pure tone. Let's start of with some imports.

In [1]:
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from acoustics import Signal
from IPython.display import Audio
import warnings
warnings.filterwarnings('ignore')

As you can see I'm importing the Signal class from the acoustics package. This package is mainly a collection of tools that could be useful to acousticians, and I started this package because I need many of these tools for my research, and I'm sure others can use it as well. The code base is still a bit messy though, and things do break occasionally.

We start with generating a pure tone.

In [2]:
duration = 10.0
fs = 44100.0
frequency = 5000.0

samples = int(fs*duration)
times = np.arange(samples) / fs

signal = Signal(np.sin(2.0*np.pi*frequency*times), fs=fs)

As I wrote before the Signal class can be found in the acoustics package. This class is a subclass of the np.ndarray and requires besides the array also a sample frequency. The class has some methods for common operations, like calculating different types of spectra and plotting them, as well as calculating other acoustic quantities like the equivalent sound pressure level.

In [3]:
Audio(signal, rate=signal.fs)
Out[3]: