Skip to content

[FEATURE] add pytta.sofa to read and write SOFA files (AES69) - #83

Open
aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-sofa
Open

aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-sofa

Conversation

@aguirreSL

@aguirreSL aguirreSL commented Oct 31, 2026 •

Copy link
Copy Markdown

Adds pytta.sofa to read and write SOFA files (AES69-2022, SOFA version 2.1), as ita_read_sofa and ita_write_sofa in the ITA-Toolbox. The ITA code was read for its semantics only and nothing was copied. SOFA is netCDF-4, which is HDF5 with dimension scales, so the module uses h5py and adds no dependency.

  1. read(path) returns a dict with:

    • 'signal': a list with one SignalObj per measurement, with the receivers as channels. ITA maps the data the same way. A single SignalObj with every measurement as a channel would be transposed by SignalObj for a typical HRIR set, which has more channels than samples.
    • 'ir': Data.IR as an array (M, R, N), 'fs' and 'delay' as stored. The delay is returned and not applied.
    • the source, listener, receiver and emitter positions, each with its values, Type and Units, and the global attributes.

    Any convention with Data.IR can be read.

  2. write(path, signal, source_positions, convention='SimpleFreeFieldHRIR', **attributes) writes every mandatory item of SimpleFreeFieldHRIR 1.0 or GeneralFIR 1.0. The source positions are spherical for SimpleFreeFieldHRIR and cartesian for GeneralFIR. The other positions take the defaults of the convention, and mandatory text attributes not given are written empty. The layout of dimensions and attributes follows what MATLAB writes, so the files open with the netCDF tools.

The conventions are taken from the convention tables of the SOFA Toolbox (SimpleFreeFieldHRIR_1.0.csv and GeneralFIR_1.0.csv) and from sofaconventions.org.

The tests in tests/test_sofa.py:

  1. A round trip of a GeneralFIR file (3 measurements, 4 receivers, 64 samples) keeps the data, the sampling rate and the positions exactly.
  2. A SimpleFreeFieldHRIR file has every mandatory item of the convention table: 16 global attributes, 9 variables with their dimensions and 11 Type and Units attributes.
  3. A file written by MATLAB R2026b with its own netCDF functions (tests/golden/make_sofa.m) is read by pytta.sofa.read with the same arrays that ncread returns, with a difference of 0. The files written by this module were also opened in MATLAB with ncinfo and ncread. The golden .sofa file is 60 KB, almost all of it netCDF header, for 384 bytes of data.

Writing SingleRoomSRIR, version 1.2 of SimpleFreeFieldHRIR (AES69-2025) and string variables are left out.

Checked with Python 3.12, numpy 1.26 and scipy 1.17. The 7 failures of development (3 in test_h5io.py, 4 in test_pyttasave.py) are the same with and without this change.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

New module pytta/sofa.py reads and writes impulse responses in SOFA
(AES69-2022, SOFA 2.1) with h5py only. The writer creates the netCDF-4
dimension scales and attributes itself, so the files open with MATLAB
ncinfo/ncread and other netCDF tools.

read(path) returns one SignalObj per measurement with the receivers as
channels, the float64 Data.IR, fs, Data.Delay, the source, listener,
receiver and emitter positions with Type and Units, and the global
attributes. Any convention with Data.IR can be read.

write(path, signal, source_positions, convention, **attributes) writes
every mandatory attribute and variable of SimpleFreeFieldHRIR 1.0 or
GeneralFIR 1.0.

Tests: exact write/read round trip, presence and shape of all mandatory
SimpleFreeFieldHRIR items, and parity with MATLAB ncread on a small
golden file written by tests/golden/make_sofa.m.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant