Room Simulation

Room

The three main classes are pyroomacoustics.room.Room, pyroomacoustics.soundsource.SoundSource, and pyroomacoustics.beamforming.MicrophoneArray. On a high level, a simulation scenario is created by first defining a room to which a few sound sources and a microphone array are attached. The actual audio is attached to the source as raw audio samples. The image source method (ISM) is then used to find all image sources up to a maximum specified order and room impulse responses (RIR) are generated from their positions. The microphone signals are then created by convolving the audio samples associated to sources with the appropriate RIR. Since the simulation is done on discrete-time signals, a sampling frequency is specified for the room and the sources it contains. Microphones can optionally operate at a different sampling frequency; a rate conversion is done in this case.

Simulating a Shoebox Room

We will first walk through the steps to simulate a shoebox-shaped room in 3D.

Create the room

So-called shoebox rooms are pallelepipedic rooms with 4 or 6 walls (in 2D and 3D, respectiely), all at right angles. They are defined by a single vector that contains the lengths of the walls. They have the advantage of being simple to define and very efficient to simulate. A 9m x 7.5m x 3.5m room is simply defined like this

import pyroomacoustics as pra
room = pra.ShoeBox([9, 7.5, 3.5], fs=16000, absorption=0.35, max_order=17)

The second argument is the sampling frequency at which the RIR will be generated. Note that the default value of fs is 8 kHz. The third argument is the absorption of the walls, namely reflections are multiplied by (1 - absorption) for every wall they hit. The fourth argument is the maximum number of reflections allowed in the ISM.

The relationship between absorption/max_order and reverberation time (the T60 or RT60 in the acoustics literature) is not straightforward. Sabine’s formula can be used to some extent to set these parameters.

Add sources and microphones

Sources are fairly straighforward to create. They take their location as single mandatory argument, and a signal and start time as optional arguments. Here we create a source located at [2.5, 3.73, 1.76] within the room, that will utter the content of the wav file speech.wav starting at 1.3 s into the simulation.

# import a mono wavfile as the source signal
# the sampling frequency should match that of the room
from scipy.io import wavfile
_, audio = wavfile.read('speech.wav')

my_source = pra.SoundSource([2.5, 3.73, 1.76], signal=audio, delay=1.3)

# place the source in the room
room.add_source(my_source)

The locations of the microphones in the array should be provided in a numpy nd-array of size (ndim, nmics), that is each column contains the coordinates of one microphone. This array is used to construct a pyroomacoustics.beamforming.MicrophoneArray object, together with the sampling frequency for the microphone. Note that it can be different from that of the room, in which case resampling will occur. Here, we create an array with two microphones placed at [6.3, 4.87, 1.2] and [6.3, 4.93, 1.2].

# define the location of the array
import numpy as np
R = np.c_[
    [6.3, 4.87, 1.2],  # mic 1
    [6.3, 4.93, 1.2],  # mic 2
    ]

# the fs of the microphones is the same as the room
mic_array = pra.MicrophoneArray(R, room.fs)

# finally place the array in the room
room.add_microphone_array(mic_array)

A number of routines exist to create regular array geometries in 2D.

Create the Room Impulse Response

At this point, the RIRs are simply created by invoking the ISM via pyroomacoustics.room.Room.image_source_model(). This function will generate all the images sources up to the order required and use them to generate the RIRs, which will be stored in the rir attribute of room. The attribute rir is a list of lists so that the outer list is on microphones and the inner list over sources.

room.compute_rir()

# plot the RIR between mic 1 and source 0
import matplotlib.pyplot as plt
plt.plot(room.rir[1][0])
plt.show()

Simulate sound propagation

By calling pyroomacoustics.room.Room.simulate(), a convolution of the signal of each source (if not None) will be performed with the corresponding room impulse response. The output from the convolutions will be summed up at the microphones. The result is stored in the signals attribute of room.mic_array with each row corresponding to one microphone.

room.simulate()

# plot signal at microphone 1
plt.plot(room.mic_array.signals[1,:])

Example

import numpy as np
import matplotlib.pyplot as plt
import pyroomacoustics as pra

# Create a 4 by 6 metres shoe box room
room = pra.ShoeBox([4,6])

# Add a source somewhere in the room
room.add_source([2.5, 4.5])

# Create a linear array beamformer with 4 microphones
# with angle 0 degrees and inter mic distance 10 cm
R = pra.linear_2D_array([2, 1.5], 4, 0, 0.04)
room.add_microphone_array(pra.Beamformer(R, room.fs))

# Now compute the delay and sum weights for the beamformer
room.mic_array.rake_delay_and_sum_weights(room.sources[0][:1])

# plot the room and resulting beamformer
room.plot(freq=[1000, 2000, 4000, 8000], img_order=0)
plt.show()
class pyroomacoustics.room.Room(walls, fs=8000, t0=0.0, max_order=1, sigma2_awgn=None, sources=None, mics=None)

Bases: object

A Room object has as attributes a collection of pyroomacoustics.wall.Wall objects, a pyroomacoustics.beamforming.MicrophoneArray array, and a list of pyroomacoustics.soundsource.SoundSource. The room can be two dimensional (2D), in which case the walls are simply line segments. A factory method pyroomacoustics.room.Room.from_corners() can be used to create the room from a polygon. In three dimensions (3D), the walls are two dimensional polygons, namely a collection of points lying on a common plane. Creating rooms in 3D is more tedious and for convenience a method pyroomacoustics.room.Room.extrude() is provided to lift a 2D room into 3D space by adding vertical walls and a parallel $B!H(Bceiling$B!I(B (see Figure 4b).

The Room is sub-classed by :py:obj:pyroomacoustics.room.ShoeBox` which creates a rectangular (2D) or parallelepipedic (3D) room. Such rooms benefit from an efficient algorithm for the image source method.

Attribute walls:
 (Wall array) list of walls forming the room
Attribute fs:(int) sampling frequency
Attribute t0:(float) time offset
Attribute max_order:
 (int) the maximum computed order for images
Attribute sigma2_awgn:
 (float) ambient additive white gaussian noise level
Attribute sources:
 (SoundSource array) list of sound sources
Attribute mics:(MicrophoneArray) array of microphones
Attribute normals:
 (numpy.ndarray 2xN or 3xN, N=number of walls) array containing normal vector for each wall, used for calculations
Attribute corners:
 (numpy.ndarray 2xN or 3xN, N=number of walls) array containing a point belonging to each wall, used for calculations
Attribute absorption:
 (numpy.ndarray size N, N=number of walls) array containing the absorption factor for each wall, used for calculations
Attribute dim:(int) dimension of the room (2 or 3 meaning 2D or 3D)
Attribute wallsId:
 (int dictionary) stores the mapping “wall name -> wall id (in the array walls)”
add_microphone_array(micArray)
add_source(position, signal=None, delay=0)
check_visibility_for_all_images(source, p, use_libroom=True)

Checks visibility from a given point for all images of the given source.

This function tests visibility for all images of the source and returns the results in an array.

Parameters:
  • source – (SoundSource) the sound source object (containing all its images)
  • p – (np.array size 2 or 3) coordinates of the point where we check visibility
Returns:

(int array) list of results of visibility for each image -1 : unchecked (only during execution of the function) 0 (False) : not visible 1 (True) : visible

compute_rir()

Compute the room impulse response between every source and microphone

convex_hull()

Finds the walls that are not in the convex hull

direct_snr(x, source=0)

Computes the direct Signal-to-Noise Ratio

extrude(height, v_vec=None, absorption=0.0)

Creates a 3D room by extruding a 2D polygon. The polygon is typically the floor of the room and will have z-coordinate zero. The ceiling

Parameters:
  • height (float) – The extrusion height
  • v_vec (array-like 1D length 3, optionnal) – A unit vector. An orientation for the extrusion direction. The ceiling will be placed as a translation of the floor with respect to this vector (The default is [0,0,1]).
  • absorption (float or array-like) – Absorption coefficients for all the walls. If a scalar, then all the walls will have the same absorption. If an array is given, it should have as many elements as there will be walls, that is the number of vertices of the polygon plus two. The two last elements are for the floor and the ceiling, respectively. (default 1)
first_order_images(source_position)
classmethod from_corners(corners, absorption=0.0, fs=8000, t0=0.0, max_order=1, sigma2_awgn=None, sources=None, mics=None)

Creates a 2D room by giving an array of corners.

Parameters:
  • corners – (np.array dim 2xN, N>2) list of corners, must be antiClockwise oriented
  • absorption – (float array or float) list of absorption factor for each wall or single value for all walls
Returns:

(Room) instance of a 2D room

get_bbox()

Returns a bounding box for the room

get_wall_by_name(name)

Returns the instance of the wall by giving its name.

Parameters:name – (string) name of the wall
Returns:(Wall) instance of the wall with this name
image_source_model(use_libroom=True)
is_inside(p, include_borders=True)

Checks if the given point is inside the room.

Parameters:
  • p (array_like, length 2 or 3) – point to be tested
  • include_borders (bool, optional) – set true if a point on the wall must be considered inside the room
Returns:

Return type:

True if the given point is inside the room, False otherwise.

is_obstructed(source, p, imageId=0)

Checks if there is a wall obstructing the line of sight going from a source to a point.

Parameters:
  • source – (SoundSource) the sound source (containing all its images)
  • p – (np.array size 2 or 3) coordinates of the point where we check obstruction
  • imageId – (int) id of the image within the SoundSource object
Returns:

(bool) False (0) : not obstructed True (1) : obstructed

is_visible(source, p, imageId=0)

Returns true if the given sound source (with image source id) is visible from point p.

Parameters:
  • source – (SoundSource) the sound source (containing all its images)
  • p – (np.array size 2 or 3) coordinates of the point where we check visibility
  • imageId – (int) id of the image within the SoundSource object
Returns:

(bool) False (0) : not visible True (1) : visible

make_c_room()

Wrapper around the C libroom

plot(img_order=None, freq=None, figsize=None, no_axis=False, mic_marker_size=10, **kwargs)

Plots the room with its walls, microphones, sources and images

plot_rir(FD=False)
print_wall_sequences(source)
simulate(recompute_rir=False)

Simulates the microphone signal at every microphone in the array

class pyroomacoustics.room.ShoeBox(p, fs=8000, t0=0.0, absorption=0.0, max_order=1, sigma2_awgn=None, sources=None, mics=None)

Bases: pyroomacoustics.room.Room

This class extends room for shoebox room in 3D space.

extrude(height)

Overload the extrude method from 3D rooms