Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
fakufaku committed May 7, 2024
2 parents 3984eaa + fa064c2 commit 20e4106
Show file tree
Hide file tree
Showing 24 changed files with 351 additions and 242 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.8
python-version: 3.9

- name: Install Python dependencies
run: pip install black flake8 isort
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ jobs:
fail-fast: false
max-parallel: 12
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.7, 3.8, 3.9, "3.10"]
os: [ubuntu-latest, macos-13, macos-latest, windows-latest]
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
exclude:
- os: macos-latest
python-version: 3.8
- os: macos-latest
python-version: 3.9
steps:
- uses: actions/checkout@v3
- name: Checkout submodules
Expand Down Expand Up @@ -41,17 +46,17 @@ jobs:
python -m pip install -e .
- name: Test with pytest
run: |
pip install -U pytest setuptools wheel twine
pip install -U pytest setuptools build wheel twine
pytest
- name: Test the universal wheels
if: matrix.os == 'ubuntu-latest'
run: |
python setup.py sdist
python -m build --sdist
twine check dist/*
- name: Test the binary wheels
if: matrix.os != 'ubuntu-latest'
run: |
python setup.py bdist_wheel
python -m build --wheel
twine check dist/*
- name: Publish sdist to pypi
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v') && matrix.os == 'ubuntu-latest'
Expand Down
35 changes: 35 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.12"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"

# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true

# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub

# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt
49 changes: 37 additions & 12 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ adheres to `Semantic Versioning <http://semver.org/spec/v2.0.0.html>`_.
Added
~~~~~

- Simulation with measured directivity responses in SOFA format (limited file types) is
possible with the image source model.
- New implementation of fast RIR builder function in the ``libroom`` C++
extentsion to replace the current cython code. Advantages are: 1) only one
compiled extension, 2) multithreading support
- New global parameter ``sinc_lut_granularity`` that controls the number of points used
in the look-up table for the sinc interpolation. Accessible via ``parameters.constants.get``.
- New global parameter ``num_threads`` that controls the number of threads used in
multi-threaded code (rir builder only at the moment). The number of threads can also
be controlled via the environement variable ``PRA_NUM_THREADS``
- New global parameters to control the octave bands used for simulation.
* ``octave_bands_base_freq``: the base frequency used for the octave bands (default ``125 ``),
note that together with the sampling frequency this will determine the number of sub-bands
Expand All @@ -37,15 +27,49 @@ Added
Changed
~~~~~~~

- Removed the broken ``get_rir`` method of the class ``SoundSource``
- In ray tracing, the histograms are now linearly interpolated between
the bins to obtain smoother RIR

`0.7.4`_ - 2024-04-25
---------------------

Added
~~~~~

- Simulation with measured directivity responses in SOFA format (limited file types) is
possible with the image source model.
- New implementation of fast RIR builder function in the ``libroom`` C++
extension to replace the current cython code. Advantages are: 1) only one
compiled extension, 2) multithreading support
- New global parameter ``sinc_lut_granularity`` that controls the number of
points used in the look-up table for the sinc interpolation. Accessible via
``parameters.constants.get``.
- New global parameter ``num_threads`` that controls the number of threads
used in multi-threaded code (rir builder only at the moment). The number of
threads can also be controlled via the environement variable
``PRA_NUM_THREADS``
- Adds package build support for Python 3.11 and 3.12. - Adds package build for
new Apple M1 architecture

Changed
~~~~~~~

- Removed the broken ``get_rir`` method of the class ``SoundSource``
- Removes package build support for Python 3.7 (EOL)

Bugfix
~~~~~~

- Fixes a bug when using randomized image source model with a 2D room (#315) by
@hrosseel
- Fixes a bug when setting the air absorption coefficients to custom values (#191),
adds a test, and more details in the doc
- Fixes a bug in the utilities.angle_function in the calculation of the
colatitude (#329) by @fabiodimarco
- Replaces the crossing-based point-in-polygon algorithm in the C++ code with
the more robust winding number algorithm (#345)
- Fixes usage of deprecated hann window with new version of scipy in
`metrics.py` (#344) by @mattpitkin

`0.7.3`_ - 2022-12-05
---------------------
Expand Down Expand Up @@ -551,7 +575,8 @@ Changed
``pyroomacoustics.datasets.timit``


.. _Unreleased: https://github.com/LCAV/pyroomacoustics/compare/v0.7.3...master
.. _Unreleased: https://github.com/LCAV/pyroomacoustics/compare/v0.7.4...master
.. _0.7.4: https://github.com/LCAV/pyroomacoustics/compare/v0.7.3...v0.7.4
.. _0.7.3: https://github.com/LCAV/pyroomacoustics/compare/v0.7.2...v0.7.3
.. _0.7.2: https://github.com/LCAV/pyroomacoustics/compare/v0.7.1...v0.7.2
.. _0.7.1: https://github.com/LCAV/pyroomacoustics/compare/v0.7.0...v0.7.1
Expand Down
8 changes: 5 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
.. image:: https://github.com/LCAV/pyroomacoustics/raw/master/logo/pyroomacoustics_logo_horizontal.png
:scale: 80 %
:alt: Pyroomacoustics logo
:align: left

------------------------------------------------------------------------------

.. image:: https://travis-ci.org/LCAV/pyroomacoustics.svg?branch=pypi-release
:target: https://travis-ci.org/LCAV/pyroomacoustics
.. image:: https://readthedocs.org/projects/pyroomacoustics/badge/?version=pypi-release
:target: http://pyroomacoustics.readthedocs.io/en/pypi-release/
:alt: Documentation Status
Expand Down Expand Up @@ -218,6 +215,11 @@ A comprehensive set of examples covering most of the functionalities
of the package can be found in the ``examples`` folder of the `GitHub
repository <https://github.com/LCAV/pyroomacoustics/tree/master/examples>`_.

A `video introduction to pyroomacoustics <https://www.youtube.com/watch?v=c3DTtc--_F4>`_.

A `video tutorial series on using pyroomacoustics <https://youtube.com/playlist?list=PL6QnpHKwdPYgxLV_Ijr6K_3Gdyfhk0SHg&si=gsSuUm9Yw2_sjYhr>`_
covering many advanced topics.

Authors
-------

Expand Down
2 changes: 1 addition & 1 deletion docs/pyroomacoustics.bss.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Algorithms
pyroomacoustics.bss.sparseauxiva
pyroomacoustics.bss.common
pyroomacoustics.bss.fastmnmf
pytoomacoustics.bss.fastmnmf2
pyroomacoustics.bss.fastmnmf2
4 changes: 2 additions & 2 deletions docs/pyroomacoustics.doa.normmusic.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pyroomacoustics.doa.normmusic module
====================================
NormMUSIC
=========

.. automodule:: pyroomacoustics.doa.normmusic
:members:
Expand Down
1 change: 1 addition & 0 deletions docs/pyroomacoustics.doa.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Algorithms
pyroomacoustics.doa.cssm
pyroomacoustics.doa.frida
pyroomacoustics.doa.music
pyroomacoustics.doa.normmusic.rst
pyroomacoustics.doa.srp
pyroomacoustics.doa.tops
pyroomacoustics.doa.waves
Expand Down
117 changes: 60 additions & 57 deletions pyroomacoustics/libroom_src/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,55 @@ Eigen::Vector3f cross(Eigen::Vector3f v1, Eigen::Vector3f v2)
return v1.cross(v2);
}

bool on_segment(const Eigen::Vector2f &c1, const Eigen::Vector2f &c2, const Eigen::Vector2f &p) {
// Given three collinear points c1, c2, p, the function checks if
// point p lies on line segment c1 <-> c2

float x_down, x_up, y_down, y_up;
x_down = fminf(c1.coeff(0), c2.coeff(0));
x_up = fmaxf(c1.coeff(0), c2.coeff(0));
y_down = fminf(c1.coeff(1), c2.coeff(1));
y_up = fmaxf(c1.coeff(1), c2.coeff(1));
return (x_down <= p.coeff(0) && p.coeff(0) <= x_up && y_down <= p.coeff(1) && p.coeff(1) <= y_up);
}

int is_inside_2d_polygon(const Eigen::Vector2f &p,
inline int is_left(const Eigen::Vector2f &P0, const Eigen::Vector2f &P1, const Eigen::Vector2f &P2)
{
// isLeft(): tests if a point is Left|On|Right of an infinite line.
// on the line is defined as within epsilon
// Input: three points P0, P1, and P2
// Return: >0 for P2 left of the line through P0 and P1
// =0 for P2 on the line
// <0 for P2 right of the line
// See: Algorithm 1 "Area of Triangles and Polygons"
float test_value = (
(P1.coeff(0) - P0.coeff(0)) * (P2.coeff(1) - P0.coeff(1))
- (P2.coeff(0) - P0.coeff(0)) * (P1.coeff(1) - P0.coeff(1))
);

if (fabsf(test_value) < libroom_eps)
return 0;
else if (test_value > 0)
return 1;
else
return -1;
}

int is_inside_2d_polygon(const Eigen::Vector2f &p_test,
const Eigen::Matrix<float,2,Eigen::Dynamic> &corners)
{
/*
Checks if a given point is inside a given polygon in 2D.
Checks if a given point is inside a given polygon in 2D using the winding
number method.
This function checks if a point (defined by its coordinates) is inside
a polygon (defined by an array of coordinates of its corners) by counting
the number of intersections between the borders and a segment linking
the given point with a computed point outside the polygon.
A boolean is also returned to indicate if a point is on a border of the
polygon (the point is still considered inside), which can be useful for
limit cases computations.
the number of left intersections between the edges and a half-line starting from
the test point.
This is Dave Sunday's winding number algorithm described here:
http://profs.ic.uff.br/~anselmo/cursos/CGI/slidesNovos/Inclusion%20of%20a%20Point%20in%20a%20Polygon.pdf
It was modified to explicitely check for points on the edges of the polygon.
p: (array size 2) coordinates of the point
corners: (array size 2xN, N>2) coordinates of the corners of the polygon
Expand All @@ -257,67 +292,35 @@ int is_inside_2d_polygon(const Eigen::Vector2f &p,
0 : the point is inside
1 : the point is on the boundary
*/

bool is_inside = false; // initialize point not in the polygon
int c1c2p, c1c2p0, pp0c1, pp0c2;
int n_corners = corners.cols();

// find a point outside the polygon
int i_min;
corners.row(0).minCoeff(&i_min);
Eigen::Vector2f p_out;
p_out.resize(2);
p_out.coeffRef(0) = corners.coeff(0,i_min) - 1;
p_out.coeffRef(1) = p.coeff(1);

// Now count intersections
int wn = 0; // the winding number counter
// loop through all edges of the polygon
for (int i = 0, j = n_corners-1 ; i < n_corners ; j=i++)
{

// Check first if the point is on the segment
// We count the border as inside the polygon
c1c2p = ccw3p(corners.col(i), corners.col(j), p);
if (c1c2p == 0)
if (ccw3p(corners.col(j), corners.col(i), p_test) == 0 && on_segment(corners.col(j), corners.col(i), p_test))
{
// Here we know that p is co-linear with the two corners
float x_down, x_up, y_down, y_up;
x_down = fminf(corners.coeff(0,i), corners.coeff(0,j));
x_up = fmaxf(corners.coeff(0,i), corners.coeff(0,j));
y_down = fminf(corners.coeff(1,i), corners.coeff(1,j));
y_up = fmaxf(corners.coeff(1,i), corners.coeff(1,j));
if (x_down <= p.coeff(0) && p.coeff(0) <= x_up && y_down <= p.coeff(1) && p.coeff(1) <= y_up)
return 1;
// point is on the edge, we consider it inside
return 1;
}

// Now check intersection with standard method
c1c2p0 = ccw3p(corners.col(i), corners.col(j), p_out);
if (c1c2p == c1c2p0) // no intersection
continue;

pp0c1 = ccw3p(p, p_out, corners.col(i));
pp0c2 = ccw3p(p, p_out, corners.col(j));
if (pp0c1 == pp0c2) // no intersection
continue;

// at this point we are sure there is an intersection

// the second condition takes care of horizontal edges and intersection on vertex
float c_max = fmaxf(corners.coeff(1,i), corners.coeff(1,j));
if (p.coeff(1) + libroom_eps < c_max)
{
is_inside = !is_inside;
if (corners.coeff(1,j) <= p_test.coeff(1)) { // start y <= P.y
if (corners.coeff(1,i) > p_test.coeff(1)) { // an upward crossing
if (is_left(corners.col(j), corners.col(i), p_test) > 0) // P left of edge
++wn; // have a valid up intersect
}
} else { // start y > P.y (no test needed)
if (corners.coeff(1, i) <= p_test.coeff(1)) { // a downward crossing
if (is_left(corners.col(j), corners.col(i), p_test) < 0) // P right of edge
--wn; // have a valid down intersect
}
}

}

// for a odd number of intersections, the point is in the polygon
if (is_inside)
return 0; // point strictly inside
if (wn == 0)
return -1;
else
return -1; // point is outside
return 0;
}


float area_2d_polygon(const Eigen::Matrix<float, 2, Eigen::Dynamic> &corners)
{
/*
Expand Down
9 changes: 3 additions & 6 deletions pyroomacoustics/libroom_src/libroom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,7 @@ PYBIND11_MODULE(libroom, m) {
m.def("dist_line_point", &dist_line_point,
"Computes the distance between a point and an infinite line");

m.def("rir_builder", &rir_builder, "RIR builder",
py::call_guard<py::gil_scoped_release>());
m.def("delay_sum", &delay_sum, "Delay and sum",
py::call_guard<py::gil_scoped_release>());
m.def("fractional_delay", &fractional_delay, "Fractional delays",
py::call_guard<py::gil_scoped_release>());
m.def("rir_builder", &rir_builder, "RIR builder");
m.def("delay_sum", &delay_sum, "Delay and sum");
m.def("fractional_delay", &fractional_delay, "Fractional delays");
}
Loading

0 comments on commit 20e4106

Please sign in to comment.