Open an interactive online version by clicking the badge Binder badge or download the notebook.

pyfar challenge#

The pyfar developers
pyfar.org
Contact: info@pyfar.org

This assignment will familiarize you with some of the basic pyfar functionality. For help visit the pyfar documentation

Audience: People, who are new to pyfar.

Requirements: No previous knowledge required. Minimal numpy skills are advantageous.

Duration: 45 Minutes

Dependencies
pip install pyfar>=0.8 sounddevice ipympl ipykernel watermark
[ ]:
import pyfar as pf
import numpy as np
import sounddevice as sd
import matplotlib.pyplot as plt
from IPython.display import Audio, display
%matplotlib ipympl

1. pyfar Signals#

pyfar Signal objects store audio data that can be converted between the time and frequency domain. They also contain useful meta data such as the sampling rate or the frequencies at which the spectrum is available. See their documentation for more information

Generate a Signal with a sampling rate of 48 kHz and the time data [0, 2, 0, 0].

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

Inspect your Signal by printing the sampling rate, time data, the times at which the data is available, and the number of samples.

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

You entered time data into the Signal, but you can also access the frequency domain data because the Signal can do the Fourier transform for you. Print the complex spectrum, the frequencies at which the spectrum is available, and the number of frequencies.

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

Generate a second Signal with the same sampling rate and the time data [0, -1, 0, 0] with the variable name signal_2. Add this Signal to the one that you generated above and print the time data of the result. See the arithmetics operations examples for more details on this.

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

2. Plotting#

Visually inspecting Signals is a common task and pyfar contains different plot functions for this purpose. In the background, pyfar uses Matplotlib for plotting. If you are using an interactive Matplotlib backend, which is the case for this tutorial, you can use the pyfar plotting shortcuts for example to quickly switch between different plots, zoom into an axis, or change the unit of the axis.

Run the cell below to create an interactive plot. Then use pyfar keybord shortcuts to modify the plot below to:

  • show the time in samples on the x-axis,

  • zoom in to see x-axis to see only the first 50 samples,

  • show magnitude spectrum in dB,

  • zoom in to the y-axis to see only therange of +/- 6 dB, and

  • show the group delay in samples.

Hint: You might need to activate the plot by clicking on it to make the shortcuts work.

[ ]:
# this uses the pyfar plot style. Without this the figure created in the next
# line would use the Matplotlib plot style.
pf.plot.use()
plt.figure()
pf.plot.time(pf.signals.impulse(1024, 10))
plt.show()

3. Signal Processing#

Pyfar contains many functions for processing Signals in the dsp module and the dsp.filter submodule. Lets start by loading a speech signal to play with

[ ]:
speech = pf.signals.files.speech()

Filter the speech Signal into octaves between 63 Hz and 16 kHz using the fractional octaves filter bank.

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

How many channels does the speech signal have before and after filtering? Hint: there is a property of the Signal class that tells you the so called channel shape of a Signal.

[ ]:
# YOUR CODE HERE
raise NotImplementedError()

Lets again plot the result and explore some more shortcuts. Can you find out how to switch between showing all channels of a Signal and cycle between single channels?

[ ]:
plt.figure()
pf.plot.freq(speech_filtered)
plt.show()

Lets compute the RMS power of each octave and plot the result. For this you need to get the center frequencies of the octaves and find out about FrequencyData objects.

[ ]:
# compute the RMS power
# YOUR CODE HERE
raise NotImplementedError()

# get third octave center frequencies
# YOUR CODE HERE
raise NotImplementedError()

# make FrequencyData object for plotting
# YOUR CODE HERE
raise NotImplementedError()

# plot the result
plt.figure()
pf.plot.freq(rms_frequency_data)
plt.show()

4. Audio IO#

Besides visual inspection, it is often useful to listen to audio signals. Listen to a single channel of the filtered speech Signal. There are at least two option for listening to audio data:

  • sd.play is a quick solution that directly plays the audio using your default device. It needs a numpy array containing the audio channels of the Signal in the columns of a numpy array (or a float array).

  • The iPyhton.display.Audio widget creates an audio player, which is nice for comparing multiple signals. It also uses the default output device and needs a numpy array containing the audio channels in the rows of a numpy array (or a flat array)

[ ]:
# select an octave center frequency to listen to
idx = 3
print(f"listening to {frequencies[idx]:.0f} Hz octave signal")

# YOUR CODE HERE
raise NotImplementedError()

5. Coordinates#

In many cases, we don’t only have one signal but many signals acquired at different positions in space. pyfar’s Coordinate class can store points in space in many different coordinate systems. It can also convert between coordinate systems and help you to find a specific point or set of points.

Generate a coordinate objects with azimuth angles of 0, 1, 2, …, 359 degree, elevation angles of zero degree and radii of 1.5 meter. Which Coordinate system is the best for this task?

[ ]:
# store the data in the variable `coordinates`
# YOUR CODE HERE
raise NotImplementedError()

# verify you coordinates object by plotting the points it contains
coordinates.show()
plt.show()

Find and plot the three points that are closest to the azimuth angle of zero degree. The Coordinate class has different find functions, which one should you use?

[ ]:
# get the indices of the points described above
# YOUR CODE HERE
raise NotImplementedError()

# plot the result. Hint: `idx` are the indices of the desired points returned
# by the `find_` function of the Coordinates class
coordinates.show(list(idx))
plt.show()

Last, rotate the points 90 degree about the x-axis and plot the result.

[ ]:
# start by making a copy to make sure the original coordinates are not changed.
# Most pyfar classes have a `copy` function that can do this
rotated = coordinates.copy()

# now rotate around the x-axis
# YOUR CODE HERE
raise NotImplementedError()


# as always, lets end with a quick visual inspection
rotated.show()
plt.show()

Congratulations,#

you are now a pyfarian. If this got you interested, visit the examples of the pyfar documentation to find out what else you can do with pyfar and related packages.

License notice#

This notebook © 2025 by the pyfar developers is licensed under CC BY 4.0

Watermark#

The following watermark might help others to install specific package versions that might be required to run the notebook. Please give at least the versions of Python, IPython, numpy , and scipy, major third party packagers (e.g., pytorch), and all used pyfar packages.

[ ]:
%load_ext watermark
%watermark -v -m -p numpy,scipy,pyfar,sounddevice,nbgrader,watermark
Python implementation: CPython
Python version       : 3.13.4
IPython version      : 9.1.0

numpy      : 2.3.3
scipy      : 1.17.1
pyfar      : 0.8.0
sounddevice: 0.5.2
nbgrader   : 0.9.5
watermark  : 2.5.0

Compiler    : Clang 14.0.6
OS          : Darwin
Release     : 25.3.0
Machine     : arm64
Processor   : arm
CPU cores   : 8
Architecture: 64bit