Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapper function for private 1st and 2nd order allpass implementations #571

Merged
merged 9 commits into from Apr 26, 2024

Conversation

hoyer-a
Copy link
Contributor

@hoyer-a hoyer-a commented Apr 8, 2024

Wrapper function for allpass implementation #527

I probably should add a test for the filter properties to test_filter.py. Any ideas for a smart way of checking if the filter is doing what it's supposed to do?

Link to docs:
https://pyfar--571.org.readthedocs.build/en/571/modules/pyfar.dsp.filter.html#pyfar.dsp.filter.allpass

Copy link
Member

@f-brinkmann f-brinkmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the effort. This is a very food first Pull. I made a suggestion for testing the functionality of the filter at the beginning of the test_allpass function

pyfar/dsp/filter/_audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/_audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved

.. math:: A(s_n) = \\frac{1-\\frac{a_i}{\\omega_c} s_n+\\frac{b_i}
{\\omega_c^2} s_n^2}{1+\\frac{a_i}{\\omega_c} s_n
+\\frac{b_i}{\\omega_c^2} s_n^2}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can write s in stead of s_n and add below \omega_c = 2 \pi f_c with the cut-off frequency f_c and s=\sigma + \mathrm{i} \omega

pyfar/dsp/filter/audiofilter.py Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
# We thus only test the functionality not the results

fc = 1000
orders = [1, 2]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cleaner to use pytest.parametrize here: @pytest.parametrize('order', (1, 2))` (actual syntax might be slightly different you can search for it in the pyfar code)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also prove more arguments in parametrize. For example you do
@pytest.parametrize('order, group_delay, frequency', ([1, group_delay_1, frequency_1], [2, group_delay_2, frequency_2])) and use this to test if the group delay of the allpass is close to group_delay below frequency

Copy link
Contributor Author

@hoyer-a hoyer-a Apr 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tip.

Now i'm testing the group delay $T_{gr}$ at fc for $T_{gr}(f_c) = T_{gr}(f_0) * \frac{1}{\sqrt{2}}$ according to the definition in Tietze/Schenk.

And the difference between $T_{gr}(f_0)$ and $T_{gr}(f_c)$ is my tolerance for frequencies below fc.
Hope that makes any sense :D

tests/test_filter.py Show resolved Hide resolved
Copy link
Member

@ahms5 ahms5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing! Just small comments

pyfar/dsp/filter/audiofilter.py Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Show resolved Hide resolved
@hoyer-a hoyer-a requested a review from ahms5 April 14, 2024 12:30
@hoyer-a hoyer-a self-assigned this Apr 16, 2024
ahms5
ahms5 previously approved these changes Apr 17, 2024
f-brinkmann
f-brinkmann previously approved these changes Apr 25, 2024
@@ -85,48 +96,33 @@ def allpass(signal, frequency, order, coefficients=None, sampling_rate=None):
# check if coefficients match filter order
if coefficients is not None and (
(order == 1 and np.isscalar(coefficients) is False)
or (order == 2 and (
type(coefficients) is not list or len(coefficients) != 2))):
or (order == 2 and (isinstance(coefficients, (list, np.ndarray))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using not isinstance(...) instead of isinstance(...) is False is more common and easier to reade

Comment on lines 144 to 145
freqs = sig_filt.frequencies
idx = np.argmin(abs(freqs - fc))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Signal class already has a find_nearest_frequency method that you can use here :)


def test_allpass_warnings(impulse, fc=1000):
# test ValueError
with pytest.raises(ValueError):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually test if the expected error is thrown using the match. Can you add this here and below?

Suggested change
with pytest.raises(ValueError):
with pytest.raises(ValueError, match='some text'):

# test ValueError
with pytest.raises(ValueError):
# pass signal and sampling rate
x = pfilt.allpass(impulse, fc, 1, sampling_rate=44100)
_ = pfilt.allpass(impulse, fc, 1, sampling_rate=44100)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simplfiy this here and below:

Suggested change
_ = pfilt.allpass(impulse, fc, 1, sampling_rate=44100)
pfilt.allpass(impulse, fc, 1, sampling_rate=44100)

Copy link
Member

@mberz mberz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of small things

pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
pyfar/dsp/filter/audiofilter.py Outdated Show resolved Hide resolved
hoyer-a and others added 4 commits April 26, 2024 12:26
Remove real part from laplace variable in docstring

Co-authored-by: Marco Berzborn <mberz@users.noreply.github.com>
Co-authored-by: Marco Berzborn <mberz@users.noreply.github.com>
Co-authored-by: Marco Berzborn <mberz@users.noreply.github.com>
@f-brinkmann f-brinkmann changed the base branch from main to develop April 26, 2024 11:39
@f-brinkmann f-brinkmann dismissed stale reviews from ahms5 and themself April 26, 2024 11:39

The base branch was changed.

@f-brinkmann f-brinkmann merged commit 8f2634a into develop Apr 26, 2024
9 checks passed
@f-brinkmann f-brinkmann deleted the allpass-filter branch April 26, 2024 14:55
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.

None yet

4 participants