Python API reference

pysofamyroom

Python interface to SofaMyRoom.

SofaMyRoom is a “shoebox” room acoustics simulator that renders binaural room impulse responses (BRIRs) with head-related transfer functions stored in SOFA files. This package drives the C library in-process and uses the same parameters, with the same names and defaults, as the setup files of the command line tool and the MATLAB structure of the MEX interface.

Example

>>> import pysofamyroom as smr
>>> setup = smr.Setup(
...     room=smr.Room(dimension=(10, 7, 4)),
...     sources=[smr.Source((8, 2.5, 1.6), (180, 0, 0), "subcardioid")],
...     receivers=[smr.Receiver.sofa("kemar.sofa", (3, 5, 1.2))],
... )
>>> brirs = smr.simulate(setup)
>>> brirs[0][0].shape          # (n_samples, n_channels)
(55125, 2)
class pysofamyroom.Options(fs=44100.0, responseduration=1.25, bandsperoctave=1, referencefrequency=125.0, airabsorption=True, distanceattenuation=True, verbose=True, simulatespecular=True, reflectionorder=(10, 10, 10), simulatediffuse=False, numberofrays=2000, diffusetimestep=0.01, rayenergyfloordB=-80.0, uncorrelatednoise=True, seed=0, outputname='output', extra=<factory>)

Bases: object

Simulation options, as in the options section of a setup file.

Parameters:
  • fs (float) – Sampling frequency in Hz.

  • responseduration (float) – Length of the impulse responses in seconds.

  • bandsperoctave (int) – Frequency resolution of the simulation, 1 to 4 bands per octave.

  • referencefrequency (float) – Reference frequency in Hz for the octave bands.

  • airabsorption (bool) – Apply air absorption (ISO 9613-1) and distance attenuation.

  • distanceattenuation (bool) – Apply air absorption (ISO 9613-1) and distance attenuation.

  • verbose (bool) – Print progress messages.

  • simulatespecular (bool) – Simulate the specular reflections with the image-source method.

  • reflectionorder (tuple of int) – Maximum reflection order along x, y and z.

  • simulatediffuse (bool) – Simulate the diffuse reflections with the diffuse-rain algorithm.

  • numberofrays (int) – Number of rays (rounded up to 20 k^2).

  • diffusetimestep (float) – Time resolution in seconds of the diffuse energy histogram.

  • rayenergyfloordB (float) – Energy threshold in dB below which a ray is dropped.

  • uncorrelatednoise (bool) – Use uncorrelated noise for the channels of a binaural response.

  • seed (int) – Seed of the random number generator; 0 selects the built-in seed of the original Roomsim.

  • outputname (str) – Base name of the output files written by the command line tool.

  • extra (dict) – Further options.* fields passed through verbatim (for example mex_saveaswav or fields of newer library versions).

class pysofamyroom.Receiver(location=(0.0, 0.0, 0.0), orientation=(0.0, 0.0, 0.0), description='omnidirectional')

Bases: Source

Receiver (microphone or listener).

Same fields as Source. A binaural receiver is described by "SOFA <file> [interp=1] [norm=1] [resampling=1] [delay=1]"; use sofa() to build that string from a path.

Parameters:
classmethod sofa(path, location, orientation=(0.0, 0.0, 0.0), *, interp=False, norm=False, resampling=False, delay=False)

Binaural receiver using the HRTFs of a SOFA file.

Parameters:
  • path (path-like) – SOFA file (SimpleFreeFieldHRIR, two receivers). Stored as an absolute path, quoted, so paths with spaces work.

  • location (array_like) – Position in metres and yaw, pitch, roll in degrees.

  • orientation (array_like) – Position in metres and yaw, pitch, roll in degrees.

  • interp (bool) – Interpolate between the measured directions instead of taking the nearest one.

  • norm (bool) – Normalise the HRTFs on loading.

  • resampling (bool) – Resample the HRTFs to the simulation sampling frequency.

  • delay (bool) – Apply the per-ear Data.Delay stored in the file.

Return type:

Receiver

class pysofamyroom.Room(dimension=(10.0, 7.0, 4.0), humidity=0.42, temperature=20.0, surface=<factory>)

Bases: object

Shoebox room.

Parameters:
  • dimension (array_like) – Width, depth and height (Lx, Ly, Lz) in metres.

  • humidity (float) – Relative humidity, 0 to 1 (used by the ISO 9613-1 air absorption).

  • temperature (float) – Temperature in degrees Celsius.

  • surface (Surface) – Absorption and diffusion of the six surfaces.

class pysofamyroom.Setup(room=<factory>, options=<factory>, sources=<factory>, receivers=<factory>)

Bases: object

Complete description of one simulation run.

Parameters:
to_text()

Setup file text understood by the command line tool.

Return type:

str

classmethod from_text(text)

Parse the text of a setup file (comments allowed).

Parameters:

text (str)

Return type:

Setup

classmethod from_file(path)

Read a setup file.

Parameters:

path (str | PathLike)

Return type:

Setup

save(path)

Write the setup file.

Parameters:

path (str | PathLike)

Return type:

None

simulate()

Run the simulation, see pysofamyroom.simulate().

Return type:

list[list[ndarray]]

exception pysofamyroom.SofaMyRoomError

Bases: RuntimeError

Raised when the simulator rejects a setup or fails while running.

class pysofamyroom.Source(location=(0.0, 0.0, 0.0), orientation=(0.0, 0.0, 0.0), description='omnidirectional')

Bases: object

Sound source.

Parameters:
  • location (array_like) – Position (x, y, z) in metres.

  • orientation (array_like) – Yaw, pitch and roll in degrees.

  • description (str) – Directivity: "omnidirectional", "cardioid", "subcardioid", "supercardioid", "hypercardioid", "bidirectional", "hemisphere", "dipole" or "SOFA <file> [options]".

class pysofamyroom.Surface(frequency=<factory>, absorption=<factory>, diffusion=None)

Bases: object

Frequency-dependent absorption and diffusion of the six surfaces.

Parameters:
  • frequency (array_like) – Centre frequencies in Hz of the bands in which the coefficients are given. Default: 125 Hz to 4 kHz in octaves.

  • absorption (array_like) – Absorption coefficients, shape (6, n_bands) in the order of SURFACES. A 1-D array is used for all six surfaces.

  • diffusion (array_like or None) – Scattering coefficients, same layout. None (default) uses 0.5 everywhere.

pysofamyroom.clear_sensors()

Drop the sources and receivers (SOFA files) cached between calls.

Return type:

None

pysofamyroom.library_version()

Version string of the underlying SofaMyRoom C library.

Return type:

str

pysofamyroom.read_setup(path)

Read a setup file (same as Setup.from_file()).

Parameters:

path (str | PathLike)

Return type:

Setup

pysofamyroom.set_log(callback)

Choose where the simulator’s status messages go.

Parameters:

callback (callable or None) – Called with each message as bytes. None sends the messages to the C standard output. The default writes to sys.stdout.

Return type:

None

pysofamyroom.simulate(setup)

Simulate the room impulse responses of a setup.

Parameters:

setup (Setup, path-like or str) – A Setup, the path of a setup file, or the text of one.

Returns:

list of list of numpy.ndarray – brirs[s][r] is the response of source s at receiver r, shape (n_samples, n_channels), float64, sampled at setup.options.fs. Same layout as the MEX cell array.

Raises:

SofaMyRoomError – If the setup is invalid or the simulation fails.

Return type:

list[list[ndarray]]

Notes

The library is single-threaded and keeps global state (a cache of the loaded SOFA files), so calls are serialised with a lock. Use processes, not threads, to simulate several rooms in parallel.

pysofamyroom.SURFACES = ('x0', 'x1', 'y0', 'y1', 'floor', 'ceiling')

Built-in immutable sequence.

If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.

If the argument is a tuple, the return value is the same object.

pysofamyroom.vast

Generate annotated BRIR datasets in the VAST format.

VAST (Virtual Acoustic Space Traveler, Gaultier et al. 2017) stores binaural room impulse responses together with the room, receiver and source parameters that produced them. This module is a port of matlab/VAST/VASTGeneration.m: for each RoomCondition the source positions are the measurement grid of the SOFA file, shifted to the receiver and clipped to the room, one BRIR is simulated per position, and all conditions end up in one VAST object that can be saved as a MATLAB-compatible .mat file with the layout of the original dataset.

Example

>>> import pysofamyroom as smr
>>> from pysofamyroom import vast
>>> conditions = [
...     vast.RoomCondition("small", smr.Room((4.5, 3.5, 2.6)),
...                        receiver_location=(1.2, 1.7, 1.5)),
...     vast.RoomCondition("large", smr.Room((9.0, 7.0, 3.5)),
...                        receiver_location=(3.0, 2.5, 1.5)),
... ]
>>> dataset = vast.generate(conditions, "kemar.sofa", fs=16000)
>>> dataset.save("vast_kemar.mat")
class pysofamyroom.vast.VAST(fs, frequency, duration, rir_left, rir_right, room_size, rt60_bands, rt60_global, absorption, diffusion, receiver_position, receiver_orientation, hrtf_fs, hrtf_left, hrtf_right, source_azimuth, source_elevation, source_distance, source_position)

A VAST dataset in memory.

Responses are stored as columns, n is the number of responses, n_bands the number of frequency bands. The attribute names follow the MATLAB structure of vast.rst.

Parameters:
property n_responses: int

Number of stored responses.

extend(other)

Append the responses of other (same fs, bands and HRTF).

Parameters:

other (VAST)

Return type:

VAST

to_dict()

Nested dictionary with the MATLAB field names of VAST.

Return type:

dict

save(path)

Write a .mat file holding the structure VAST.

Parameters:

path (str | PathLike)

Return type:

None

classmethod load(path)

Read a .mat file written by save() (or by MATLAB).

Parameters:

path (str | PathLike)

Return type:

VAST

class pysofamyroom.vast.RoomCondition(name, room=<factory>, receiver_location=(1.0, 1.0, 1.5), receiver_yaw=0.0)

One acoustic condition: a room and a receiver inside it.

Parameters:
  • name (str) – Label of the condition (not stored in the .mat file).

  • room (Room) – Room dimensions, absorption, diffusion, humidity and temperature.

  • receiver_location (array_like) – Receiver position (x, y, z) in metres.

  • receiver_yaw (float) – Receiver orientation in degrees around the vertical axis, 0 facing +x. The source grid turns with the receiver, so the direction of every source relative to the head is the one of the SOFA grid.

pysofamyroom.vast.WALLS = ('WestWall', 'EastWall', 'SouthWall', 'NorthWall', 'Floor', 'Ceiling')

VAST wall names in the row order of pysofamyroom.SURFACES (x = 0, x = Lx, y = 0, y = Ly, floor, ceiling).

pysofamyroom.vast.generate(conditions, sofa, *, fs=16000.0, duration=1.25, margin=0.2, step=1, options=None, interp=True, norm=True, resampling=True, chunk=32, workers=1, verbose=False, progress=None)

Simulate a VAST dataset for one or more room conditions.

Parameters:
  • conditions (RoomCondition or sequence of RoomCondition) – Rooms and receivers; the responses of all conditions are stacked in one dataset.

  • sofa (path-like) – SOFA file with the HRTFs of the listener. Its measurement grid, centred on the receiver, gives the source positions.

  • fs (float) – Sampling frequency of the stored responses. The simulation runs at the sampling frequency of the HRTFs and the result is resampled, as in the MATLAB generator.

  • duration (float) – Length of the responses in seconds.

  • margin (float) – Grid points closer than this (metres) to a wall are skipped.

  • step (int) – Use every step-th grid point (1 = all points).

  • options (Options or None) – Simulation options; fs and responseduration are overridden. Default: the VAST settings (bands per octave 1, specular order 10, 2000 rays, diffuse rain on, uncorrelated noise).

  • interp (bool) – Flags of the SOFA receiver (see Receiver.sofa()).

  • norm (bool) – Flags of the SOFA receiver (see Receiver.sofa()).

  • resampling (bool) – Flags of the SOFA receiver (see Receiver.sofa()).

  • chunk (int) – Number of sources per call of the simulator (bounds memory use).

  • workers (int) – Number of processes simulating chunks in parallel (1 = run in this process). The result does not depend on it: every chunk is seeded from its own setup. Each worker loads the SOFA file once. Worker processes are started with the spawn method on macOS and Windows, so a script calling generate(..., workers=n) must keep that call under if __name__ == "__main__":.

  • verbose (bool) – Print the simulator’s messages.

  • progress (callable or None) – Called as progress(condition_name, done, total) after each chunk.

Returns:

VAST

Return type:

VAST

pysofamyroom.vast.rt60(room)

Norris-Eyring reverberation time per frequency band.

Port of Room2RT60 in VASTGeneration.m (air absorption after Roomsim’s estimateRT60.m). Returns zeros for an anechoic room.

Parameters:

room (Room) – Room dimensions, absorption per surface and band, humidity and temperature.

Returns:

numpy.ndarray – RT60 in seconds, one value per band of room.surface.frequency.

Return type:

ndarray