Skip to content

Commit eec9bea

Browse files
committed
feat!: rewrite libmysofa in Rust
1 parent 62775b1 commit eec9bea

35 files changed

+5922
-462
lines changed

.github/workflows/audit-on-push.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@ on:
44
paths:
55
- '**/Cargo.toml'
66
- '**/Cargo.lock'
7+
- 'deny.toml'
8+
pull_request:
9+
paths:
10+
- '**/Cargo.toml'
11+
- '**/Cargo.lock'
12+
- 'deny.toml'
13+
schedule:
14+
- cron: '0 0 * * 0'
715
jobs:
8-
security_audit:
16+
cargo-deny:
917
runs-on: ubuntu-latest
1018
steps:
11-
- uses: actions/checkout@v1
12-
- uses: actions-rs/audit-check@v1
13-
with:
14-
token: ${{ secrets.GITHUB_TOKEN }}
19+
- uses: actions/checkout@v4
20+
- uses: EmbarkStudios/cargo-deny-action@v2

.github/workflows/general.yml

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ jobs:
1111
runs-on: ${{ matrix.os }}
1212
strategy:
1313
matrix:
14-
os: [ubuntu-latest, macOS-latest]
14+
os: [ubuntu-latest, macos-latest]
1515
rust: [stable, beta]
1616

1717
steps:
18-
- uses: hecrj/setup-rust-action@v2
19-
with:
20-
rust-version: ${{ matrix.rust }}${{ matrix.toolchain }}
21-
- uses: actions/checkout@v2
18+
- uses: actions/checkout@v4
2219
with:
2320
submodules: true
21+
- uses: dtolnay/rust-toolchain@master
22+
with:
23+
toolchain: ${{ matrix.rust }}
24+
- uses: Swatinem/rust-cache@v2.8.2
2425
- name: Install dependencies
2526
if: matrix.os == 'ubuntu-latest'
2627
run: |
27-
export DEBIAN_FRONTED=noninteractive
28+
export DEBIAN_FRONTEND=noninteractive
2829
sudo apt-get -qq update
2930
sudo apt-get install -y libasound2-dev
3031
- name: Run tests
31-
run: |
32-
cargo test --verbose --workspace --all-features
32+
run: cargo test --workspace --all-features
3333

3434
test-windows:
3535
name: Test (Windows)
@@ -39,73 +39,76 @@ jobs:
3939
rust: [stable, beta]
4040

4141
steps:
42-
- uses: hecrj/setup-rust-action@v2
43-
with:
44-
rust-version: ${{ matrix.rust }}
45-
- uses: actions/checkout@v2
42+
- uses: actions/checkout@v4
4643
with:
4744
submodules: true
48-
- uses: crazy-max/ghaction-chocolatey@v1
45+
- uses: dtolnay/rust-toolchain@master
4946
with:
50-
args: install -y pkgconfiglite --checksum 6004df17818f5a6dbf19cb335cc92702
47+
toolchain: ${{ matrix.rust }}
48+
- uses: Swatinem/rust-cache@v2.8.2
49+
- name: Install pkg-config
50+
run: choco install -y pkgconfiglite
5151
- name: Run tests
52-
run: |
53-
cargo test --verbose --workspace --all-features
52+
run: cargo test --workspace --all-features
5453

5554
fmt:
5655
name: Rustfmt
5756
runs-on: ubuntu-latest
5857
steps:
59-
- uses: actions/checkout@v2
58+
- uses: actions/checkout@v4
6059
with:
6160
submodules: true
62-
- uses: actions-rs/toolchain@v1
61+
- uses: dtolnay/rust-toolchain@stable
6362
with:
64-
toolchain: stable
65-
override: true
6663
components: rustfmt
67-
- uses: actions-rs/cargo@v1
68-
with:
69-
command: fmt
70-
args: --all -- --check
64+
- run: cargo fmt --all -- --check
7165

7266
clippy:
7367
name: Clippy
7468
runs-on: ubuntu-latest
7569
steps:
76-
- uses: actions/checkout@v2
70+
- uses: actions/checkout@v4
7771
with:
7872
submodules: true
79-
- uses: actions-rs/toolchain@v1
73+
- name: Install dependencies
74+
run: |
75+
export DEBIAN_FRONTEND=noninteractive
76+
sudo apt-get -qq update
77+
sudo apt-get install -y libasound2-dev
78+
- uses: dtolnay/rust-toolchain@stable
8079
with:
81-
toolchain: stable
82-
override: true
8380
components: clippy
84-
- uses: actions-rs/clippy-check@v1
85-
with:
86-
token: ${{ secrets.GITHUB_TOKEN }}
87-
args: -- -D warnings
81+
- uses: Swatinem/rust-cache@v2.8.2
82+
- run: cargo clippy --workspace --all-features -- -D warnings
8883

8984
coverage:
9085
name: Code coverage
9186
runs-on: ubuntu-latest
9287
steps:
93-
- name: Checkout repository
94-
uses: actions/checkout@v2
88+
- uses: actions/checkout@v4
9589
with:
9690
submodules: true
97-
98-
- name: Install alsa dev
99-
run: sudo apt-get install -y libasound2-dev
100-
101-
- name: Install stable toolchain
102-
uses: actions-rs/toolchain@v1
91+
- name: Install dependencies
92+
run: |
93+
export DEBIAN_FRONTEND=noninteractive
94+
sudo apt-get -qq update
95+
sudo apt-get install -y libasound2-dev
96+
- uses: dtolnay/rust-toolchain@stable
97+
- uses: Swatinem/rust-cache@v2.8.2
98+
- uses: taiki-e/install-action@v2
10399
with:
104-
toolchain: stable
105-
override: true
106-
100+
tool: cargo-tarpaulin
107101
- name: Run cargo-tarpaulin
108-
uses: actions-rs/tarpaulin@v0.1
102+
run: cargo tarpaulin --workspace --all-features --ignore-tests
103+
104+
wasm:
105+
name: WASM
106+
runs-on: ubuntu-latest
107+
steps:
108+
- uses: actions/checkout@v4
109+
- uses: dtolnay/rust-toolchain@stable
109110
with:
110-
version: '0.15.0'
111-
args: '--ignore-tests'
111+
targets: wasm32-unknown-unknown
112+
- uses: Swatinem/rust-cache@v2.8.2
113+
- name: Check WASM build
114+
run: cargo check --lib --target wasm32-unknown-unknown --all-features

.github/workflows/release-plz.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Release-plz
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-plz-release:
14+
name: Release
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
- uses: dtolnay/rust-toolchain@stable
21+
- uses: release-plz/action@v0.5
22+
with:
23+
command: release
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
27+
28+
release-plz-pr:
29+
name: Release PR
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
with:
34+
fetch-depth: 0
35+
- uses: dtolnay/rust-toolchain@stable
36+
- uses: release-plz/action@v0.5
37+
with:
38+
command: release-pr
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Cargo.toml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
11
[package]
22
name = "sofar"
33
version = "0.2.1"
4-
edition = "2021"
4+
edition = "2024"
55
readme = "README.md"
66
license = "MIT OR Apache-2.0"
77
authors = ["Tomasz Andrzejak <andreiltd@gmail.com>"]
88
keywords = ["libmysofa", "hrtf", "aes69"]
9-
description = "Rust bindings for the libmysofa library"
9+
description = "Pure Rust SOFA/HRTF reader and renderer"
1010
repository = "https://github.com/andreiltd/sofar"
1111
homepage = "https://github.com/andreiltd/sofar"
1212
categories = ["algorithms", "filesystem", "multimedia::audio"]
1313

1414
[features]
1515
default = ["dsp"]
1616
dsp = ["dep:realfft"]
17+
resample = ["dep:rubato", "dep:audioadapter-buffers"]
1718

1819
[workspace]
1920
members = ["libmysofa-sys"]
2021

2122
[dependencies]
22-
ffi = { package = "libmysofa-sys", version = "0.2.1", path = "libmysofa-sys" }
23+
arrayvec = "0.7.6"
24+
bitflags = "2.9.1"
25+
log = "0.4.27"
26+
miniz_oxide = "0.8.9"
2327
realfft = {version = "3.4", optional = true}
24-
thiserror = "1"
28+
rubato = {version = "1.0.1", optional = true}
29+
audioadapter-buffers = {version = "2.0", optional = true}
30+
thiserror = "2"
31+
winnow = "0.7.11"
2532

2633
[dev-dependencies]
2734
anyhow = "1.0"
35+
arc-swap = "1"
2836
assert_approx_eq = "1.1"
2937
hound = "3.5"
30-
cpal = "0.15"
38+
cpal = "0.17"
3139
criterion = "0.5"
32-
rand = "0.8"
40+
rand = "0.9"
3341
ringbuf = "0.4"
3442

3543
[[bench]]

NOTICE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
NOTICE
2+
3+
This software contains code derived from the libmysofa project.
4+
5+
libmysofa
6+
---------
7+
Copyright (c) 2016-2017, Symonics GmbH, Christian Hoene
8+
Licensed under the BSD 3-Clause License
9+
https://github.com/hoene/libmysofa
10+
11+
The following components are derived from libmysofa:
12+
13+
- HDF5 file format parser (src/hdf/)
14+
- SOFA/HRTF algorithms (src/sofa/): spatial lookup, interpolation,
15+
coordinate conversion, loudness normalization, validation
16+
17+
The KD-tree implementation is based on work by:
18+
19+
Copyright (C) 2007-2011 John Tsiombikas <nuclear@member.fsf.org>
20+
Licensed under BSD 3-Clause License

README.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
<img src="docs/homer-sofar.png"/>
44

55
# Sofar
6-
Sofa Reader and Renderer
6+
Pure Rust SOFA Reader and HRTF Renderer
77

88
</div>
99

1010
## Features
11-
This crate provides high level bindings to [`libmysofa`] API allows to read
12-
`HRTF` filters from `SOFA` files (Spatially Oriented Format for Acoustics).
11+
A pure Rust implementation for reading `HRTF` filters from `SOFA` files
12+
(Spatially Oriented Format for Acoustics).
1313

1414
The [`render`] module implements uniformly partitioned convolution algorithm
1515
for rendering HRTF filters.
1616

17+
Based on the [`libmysofa`] C library by Christian Hoene / Symonics GmbH.
18+
1719
[`libmysofa`]: https://github.com/hoene/libmysofa
1820
[`render`]: `crate::render`
1921

@@ -33,7 +35,7 @@ let sofa = OpenOptions::new()
3335
let filt_len = sofa.filter_len();
3436
let mut filter = Filter::new(filt_len);
3537

36-
// Get filter at poistion
38+
// Get filter at position
3739
sofa.filter(0.0, 1.0, 0.0, &mut filter);
3840

3941
let mut render = Renderer::builder(filt_len)
@@ -42,7 +44,7 @@ let mut render = Renderer::builder(filt_len)
4244
.build()
4345
.unwrap();
4446

45-
render.set_filter(&filter);
47+
render.set_filter(&filter).unwrap();
4648

4749
let input = vec![0.0; 256];
4850
let mut left = vec![0.0; 256];
@@ -57,9 +59,18 @@ You can run `cpal` renderer example like this:
5759

5860
``` shell
5961
cargo run --example renderer -- <FILENAME-MONO.wav> libmysofa-sys/libmysofa/share/default.sofa
60-
6162
```
6263

64+
## Acknowledgments
65+
66+
This project is a Rust port of [libmysofa](https://github.com/hoene/libmysofa),
67+
a C library for reading SOFA files.
68+
69+
- **libmysofa** Copyright © 2016-2017 Symonics GmbH, Christian Hoene (BSD-3-Clause)
70+
- **KD-tree** Copyright © 2007-2011 John Tsiombikas (BSD-3-Clause)
71+
72+
See the [NOTICE](NOTICE) file for full attribution details.
73+
6374
# License
6475

6576
This project is licensed under either of

benches/renderer.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
use criterion::{criterion_group, criterion_main, Bencher, BenchmarkId, Criterion};
2-
use sofar::{reader::Filter, render::Renderer};
1+
use criterion::{Bencher, BenchmarkId, Criterion, criterion_group, criterion_main};
2+
use sofar::{filter::Filter, render::Renderer};
33

44
use rand::Rng;
55

66
fn bench_renderer(b: &mut Bencher, blocks: usize, block_len: usize, filt_len: usize) {
77
let mut filt = Filter::new(filt_len);
88

9-
rand::thread_rng().fill(&mut *filt.left);
10-
rand::thread_rng().fill(&mut *filt.right);
9+
rand::rng().fill(&mut *filt.left);
10+
rand::rng().fill(&mut *filt.right);
1111

1212
let mut input = vec![0.0; blocks * block_len];
1313
let mut left = vec![0.0; blocks * block_len];
1414
let mut right = vec![0.0; blocks * block_len];
1515

16-
rand::thread_rng().fill(input.as_mut_slice());
16+
rand::rng().fill(input.as_mut_slice());
1717

1818
let mut renderer = Renderer::builder(filt_len)
1919
.with_partition_len(block_len)

deny.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[graph]
2+
all-features = true
3+
4+
[licenses]
5+
allow = [
6+
"MIT",
7+
"Apache-2.0",
8+
"0BSD",
9+
"Zlib",
10+
"Unicode-3.0",
11+
"BSD-3-Clause",
12+
]
13+
unused-allowed-license = "allow"
14+
confidence-threshold = 0.8
15+
16+
[[licenses.clarify]]
17+
name = "libmysofa-sys"
18+
expression = "MIT"
19+
license-files = []
20+
21+
[bans]
22+
multiple-versions = "warn"
23+
wildcards = "allow"
24+
25+
[sources]
26+
unknown-registry = "deny"
27+
unknown-git = "deny"
28+
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
29+
allow-git = []

0 commit comments

Comments
 (0)