Skip to content

Commit

Permalink
Prepare new release
Browse files Browse the repository at this point in the history
* CI: removes python 3.7, adds 3.11 and 3.12

* switches to "build" package to build the package in CI.

* fixes bdist_wheel build

* Replaces the brittle crossing-based point-in-polygon (2D) algorithm by Dan Sunday's robust winding based algorithm.

* Fixes a bug with releasing the GIL and python 3.12 in the rir builder part of libroom. Related to wjakob/nanobind#377
  • Loading branch information
fakufaku authored Apr 25, 2024
1 parent e753328 commit f869ef2
Show file tree
Hide file tree
Showing 39 changed files with 134 additions and 113 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 @@ -40,17 +45,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
3 changes: 0 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
1 change: 1 addition & 0 deletions examples/adaptive_filter_stft_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
In this example, we will run adaptive filters for system
identification, but in the frequeny domain.
"""

from __future__ import division, print_function

import matplotlib.pyplot as plt
Expand Down
1 change: 1 addition & 0 deletions examples/adaptive_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
In this example, we will run adaptive filters for system identification.
"""

from __future__ import division, print_function

import matplotlib.pyplot as plt
Expand Down
1 change: 1 addition & 0 deletions examples/beamforming_delay_and_sum.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
This example shows how to create delay and sum beamformers
"""

from __future__ import division, print_function

import matplotlib.pyplot as plt
Expand Down
1 change: 1 addition & 0 deletions examples/bss_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
This script requires the `mir_eval` to run, and `tkinter` and `sounddevice` packages for the GUI option.
"""

import time

import numpy as np
Expand Down
1 change: 1 addition & 0 deletions examples/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Example of the basic operations with ``pyroomacoustics.datasets.Dataset``
and ``pyroomacoustics.datasets.Sample`` classes
"""

from pyroomacoustics.datasets import Dataset, Sample

# Prepare a few artificial samples
Expand Down
1 change: 1 addition & 0 deletions examples/raytracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This example program demonstrates the use of ray tracing
for the simulation of rooms of different sizes.
"""

from __future__ import print_function

import argparse
Expand Down
1 change: 1 addition & 0 deletions examples/room_L_shape_3d_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
The simulation is done using the hybrid ISM/RT simulator.
"""

from __future__ import print_function

import time
Expand Down
1 change: 1 addition & 0 deletions examples/room_complex_wall_materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
2022 (c) @noahdeetzers, @fakufaku
"""

import matplotlib.pyplot as plt
import numpy as np

Expand Down
1 change: 1 addition & 0 deletions examples/room_from_rt60.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
The simulation is pure image source method.
The audio sample with the reverb added is saved back to `examples/samples/guitar_16k_reverb.wav`.
"""

import argparse

import matplotlib.pyplot as plt
Expand Down
1 change: 1 addition & 0 deletions examples/room_from_stl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
The STL file was kindly provided by Diego Di Carlo (@Chutlhu).
"""

import argparse
import os
from pathlib import Path
Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/adaptive/lms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Implementations of adaptive filters from the LMS class. These algorithms have a
low complexity and reliable behavior with a somewhat slower convergence.
"""

from __future__ import absolute_import, division, print_function

import numpy as np
Expand Down
1 change: 0 additions & 1 deletion pyroomacoustics/adaptive/subband_lms.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@


class SubbandLMS:

"""
Frequency domain implementation of LMS. Adaptive filter for each
subband.
Expand Down
1 change: 0 additions & 1 deletion pyroomacoustics/beamforming.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ def circular_microphone_array_xyplane(


class MicrophoneArray(object):

"""Microphone array class."""

def __init__(self, R, fs, directivity=None):
Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/datasets/cmu_arctic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
URL: http://www.festvox.org/cmu_arctic/
"""

import os

import numpy as np
Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/datasets/tests/test_corpus_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Example of the basic operations with ``pyroomacoustics.datasets.Dataset``
and ``pyroomacoustics.datasets.Sample`` classes
"""

from pyroomacoustics.datasets import Dataset, Sample


Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/doa/grid.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Routines to perform grid search on the sphere
"""

from __future__ import absolute_import, division, print_function

from abc import ABCMeta, abstractmethod
Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/doa/plotters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
A collection of functions to plot maps and points on circles and spheres.
"""

import numpy as np


Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/doa/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module contains useful functions to compute distances and errors on on
circles and spheres.
"""

from __future__ import division

import numpy as np
Expand Down
1 change: 1 addition & 0 deletions pyroomacoustics/experimental/signals.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
A few test signals like sweeps and stuff.
"""

from __future__ import division, print_function

import numpy as np
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 f869ef2

Please sign in to comment.