Skip to content

Clean up the audio_filters directory - #15087

Open
priya-sundaram-dev wants to merge 2 commits into
TheAlgorithms:masterfrom
priya-sundaram-dev:audio-filters-tlc
Open

Clean up the audio_filters directory#15087
priya-sundaram-dev wants to merge 2 commits into
TheAlgorithms:masterfrom
priya-sundaram-dev:audio-filters-tlc

Conversation

@priya-sundaram-dev

Copy link
Copy Markdown

Describe your change:

This cleans up the audio_filters/ directory as requested in #15081. Working through the checklist from that thread:

  • Restore equal_loudness_filter.py. The file was disabled (.broken.txt) because it imported the third-party yulewalker package, which isn't a project dependency. I replaced that import with a dependency-free yulewalk() implementation of the modified Yule-Walker method that uses only numpy and scipy (both already in pyproject.toml). The restored EqualLoudnessFilter now constructs and processes samples again, and the designed filter is verified stable in a doctest.
  • Look for bugs and add tests for corner cases. Fixed two real bugs in IIRFilter.set_coefficients: the "leave out a_0" branch (len(a_coeffs) < self.order) never triggered, and the b_coeffs length-error message reported len(a_coeffs). Added doctests covering both valid and erroneous inputs (coefficient-length ValueErrors, yulewalk input validation for mismatched lengths and non-increasing frequencies), plus doctests for the new helpers.
  • Add Wikipedia URLs. Added Wikipedia links to the docstrings that lacked them (butterworth_filter.py, equal_loudness_filter.py, show_response.py).
  • Clean up README.md. Rewrote it to describe every file and every filter in the directory, with a runnable "Try it out" example and links encouraging readers to learn more.
  • EXTRA CREDIT: two new audio filters. Added make_notch (band-reject, e.g. for mains hum) and make_bandpass_peak (the constant-0 dB-peak-gain band-pass variant from the RBJ Audio EQ Cookbook), both with type hints and doctests.

All modules pass python -m pytest --doctest-modules audio_filters/, ruff check, and ruff format --check. Credit for the original equal-loudness filter design remains with David Robinson (2001), as noted in the docstring.

Closes part of the maintenance exercise in #15081.

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms include at least one URL that points to Wikipedia or another similar explanation.

- Restore equal_loudness_filter.py: replace the third-party 'yulewalker'
  dependency with a dependency-free 'yulewalk' implementation (numpy + scipy
  only, both already project dependencies) so the filter works again.
- Fix two bugs in iir_filter.set_coefficients: the a0-omitted branch never
  triggered, and the b_coeffs length error reported len(a_coeffs).
- Add doctests covering valid and erroneous inputs (coefficient-length errors,
  yulewalk input validation).
- Add Wikipedia URLs to the docstrings that were missing them.
- Add two new RBJ Audio EQ Cookbook filters: make_notch and make_bandpass_peak.
- Rewrite audio_filters/README.md to document every file and filter.
@cclauss

cclauss commented Aug 26, 2026

Copy link
Copy Markdown
Member

@fJpmjZdgpD, @dredonjaquana26 Your reviews, please.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR cleans up and re-enables the audio_filters/ directory by restoring the equal-loudness filter without third-party dependencies, expanding filter offerings, and improving documentation and doctest coverage for filter APIs.

Changes:

  • Restores equal_loudness_filter.py with an in-module yulewalk() implementation using numpy/scipy.
  • Fixes and extends IIRFilter.set_coefficients() doctests and error handling, and adds two new RBJ-cookbook-derived filter designs.
  • Improves discoverability via README updates and module-level documentation links.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
audio_filters/show_response.py Adds a module docstring with a reference URL for frequency response.
audio_filters/README.md Rewrites README to enumerate modules/filters and provide a runnable example.
audio_filters/iir_filter.py Fixes a0-omission handling and improves doctest coverage for coefficient validation.
audio_filters/equal_loudness_filter.py.broken.txt Removes the previously-disabled equal loudness implementation.
audio_filters/equal_loudness_filter.py Restores equal-loudness filter and introduces dependency-free yulewalk() plus helpers.
audio_filters/butterworth_filter.py Adds Wikipedia link and introduces make_notch() and make_bandpass_peak() designs with doctests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread audio_filters/iir_filter.py Outdated
Comment on lines 73 to 76
if len(a_coeffs) < self.order + 1:
a_coeffs = [1.0, *a_coeffs]

if len(a_coeffs) != self.order + 1:
Comment on lines +100 to +102
if np.any(np.diff(frequencies) < 0):
msg = "frequencies must be in increasing order"
raise ValueError(msg)
Comment on lines +175 to +177
# pad the data to nyquist
curve_freqs = np.array(data["frequencies"] + [max(20000.0, samplerate / 2)])
curve_gains = np.array(data["gains"] + [140])
return filt


def make_notch(

@cclauss cclauss Aug 26, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we move make_notch() and make_bandpass_peak() to their own files? Or is there some reason that they should remain in this file?

make_notch() contains many short, cryptic variable names that make the algorithm read like a chemistry formula. Experts might be comfortable with that, but it might be difficult for new developers to understand. Can any of these be renamed to more self-documenting variable names that would help visitors follow the complexity?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Moving them to a new file is not necessary. I now see that this file contains lots of filters, so we can continue that approach.

…set_coefficients guard

- Add a shared notation guide to butterworth_filter so the single-letter
  RBJ-cookbook names (w0/alpha/a0..a2/b0..b2) are self-explanatory across
  every filter instead of diverging in one function.
- Comment make_notch's feed-forward/feed-back sections in plain English.
- set_coefficients only fills the optional a_0 when exactly one coefficient
  is missing, so genuinely too-short inputs raise with their real length
  (new regression doctest).
@priya-sundaram-dev

Copy link
Copy Markdown
Author

Thanks @cclauss — pushed in 764c115.

On the make_notch naming: those single-letter names (w0, alpha, a0..a2, b0..b2) aren't ad-hoc — they're the notation from the RBJ Audio EQ Cookbook that every filter in this file already uses, and a*/b* map one-to-one onto IIRFilter.set_coefficients(a_coeffs, b_coeffs) and the standard biquad transfer function. Renaming them in just one function would make make_notch read differently from its ten siblings, which I think would confuse a reader more than help.

So instead of diverging locally, I made the shared notation self-documenting:

  • Added a short notation guide to the module docstring explaining w0, alpha, and the a/b (feed-back / feed-forward) coefficients once, benefiting every filter here.
  • Commented make_notch's two coefficient blocks in plain English (zeros on the notch frequency cancel it; matching poles keep the band narrow and the surrounding gain flat).

Happy to go further and rename across the whole file if you'd prefer full self-documenting names everywhere — I just didn't want to touch the other filters unasked in this PR.

Also addressed the Copilot review while I was in there: set_coefficients now only fills the optional leading a_0 when exactly one coefficient is missing, so a genuinely too-short a_coeffs raises with its real length instead of the padded one (added a regression doctest). All doctests + ruff green.

@cclauss cclauss left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Very impressive. Thanks.

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.

3 participants