Skip to content

docs: clarify octave band frequency resolution#48

Merged
jmrplens merged 1 commit into
mainfrom
docs/issue-47-frequency-resolution
May 9, 2026
Merged

docs: clarify octave band frequency resolution#48
jmrplens merged 1 commit into
mainfrom
docs/issue-47-frequency-resolution

Conversation

@jmrplens
Copy link
Copy Markdown
Owner

@jmrplens jmrplens commented May 9, 2026

Summary

  • Document that octavefilter is a time-domain fractional-octave filter bank, not an FFT/Welch spectrum estimator.
  • Explain standardized band spacing versus FFT bin spacing.
  • Add a Welch example that maps narrowband bins to PyOctaveBand band edges.
  • Update the quick API reference for getansifrequencies() to include nominal labels.

Verification

  • Ran git diff --check -- README.md.
  • Locally executed the README-style Welch/band-edge snippet with a synthetic signal.

Summary by Sourcery

Clarify the conceptual difference between fractional-octave filtering and FFT/Welch spectral estimation, and extend the README with guidance on standardized band definitions and their use with PyOctaveBand.

Documentation:

  • Restructure and expand the README table of contents and section headings for clearer navigation of features and theory.
  • Document that octavefilter is a time-domain fractional-octave filter bank without FFT-style frequency resolution and explain fractional-octave band spacing.
  • Add an example showing how to use Welch/FFT together with getansifrequencies band edges for tonal inspection within standardized bands.
  • Update the quick API reference for getansifrequencies() to include nominal band labels in its return values.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 9, 2026

Reviewer's Guide

Documentation-only README updates that clarify octavefilter as a time‑domain fractional‑octave filter bank, explain standardized band spacing versus FFT bin spacing with a Welch-based example, and update the quick API reference for getansifrequencies to include nominal band labels, along with corresponding TOC and section title cleanups.

Sequence diagram for Welch example using PyOctaveBand band edges

sequenceDiagram
    actor User
    participant Script
    participant pyoctaveband
    participant scipy_signal as "scipy.signal"
    participant numpy as numpy

    User ->> Script: Configure fs, x

    Script ->> pyoctaveband: octavefilter(x, fs, fraction=3, limits=[12, 20000])
    pyoctaveband -->> Script: levels, centers

    Script ->> pyoctaveband: getansifrequencies(fraction=3, limits=[12, 20000])
    pyoctaveband -->> Script: fc, fl, fu, labels

    Script ->> scipy_signal: welch(x, fs, window, nperseg, noverlap, scaling)
    scipy_signal -->> Script: freq_bins, psd

    Script ->> numpy: argmin(abs(fc - 1000.0))
    numpy -->> Script: band_index

    Script ->> Script: in_band = (freq_bins >= fl[band_index]) and (freq_bins <= fu[band_index])

    Script ->> User: Print selected label, bin spacing, and in_band Welch bins
Loading

Class diagram for updated getansifrequencies API

classDiagram
    class pyoctaveband {
        +octavefilter(x, fs, fraction, limits, sigbands) : levels, centers
        +getansifrequencies(fraction, limits) : fc, fl, fu, labels
        +normalizedfreq(fraction) : freqs
    }

    class OctaveBands {
        +fraction : int
        +limits : float[]
        +centers : float[]
        +lower_edges : float[]
        +upper_edges : float[]
        +labels : string[]
    }

    pyoctaveband ..> OctaveBands : returns data compatible with
Loading

Flow diagram for choosing octavefilter vs Welch FFT analysis

flowchart TD
    Start([Start analysis])

    Q1{Need standardized<br>fractional_octave<br>levels?}

    Start --> Q1

    Q1 -- Yes --> UseOctave[Use octavefilter<br>with fraction and limits]
    Q1 -- No --> Q2{Need narrowband<br>tonal inspection?}

    UseOctave --> Bands[Interpret results as<br>one level per<br>fractional_octave band]

    Q2 -- Yes --> UseWelch[Run Welch or FFT<br>on original signal]
    Q2 -- No --> OtherMethods[Consider other<br>analysis methods]

    UseWelch --> Edges[Call getansifrequencies<br>to obtain band centers and<br>lower_upper edges]
    Edges --> Mask[Use band edges as masks<br>to select FFT_Welch bins<br>inside each band]

    Bands --> End([End])
    Mask --> End
    OtherMethods --> End
Loading

File-Level Changes

Change Details Files
Restructured and corrected the README table of contents to match current section headings and hierarchy.
  • Switched from a simple numbered list to a nested bullet list anchored from the top-level PyOctaveBand heading
  • Updated section titles (e.g., Gallery of Filter Bank Responses, Theoretical Background) and added/moved subsections such as RMS vs Peak Levels and Filter Bank Design & Numerical Stability
  • Escaped special characters in anchors (e.g., & to &) and added an Author link at the end of the TOC
README.md
Updated the quick API reference for getansifrequencies to document the nominal IEC label output.
  • Changed the documented call signature of getansifrequencies to return a fourth value, labels
  • Documented labels as the IEC nominal frequency labels alongside center, lower, and upper band-edge frequencies
README.md
Added a new theoretical subsection clarifying fractional-octave band frequency resolution versus FFT bin spacing, including a Welch-based example that maps FFT bins to standardized band edges.
  • Explained that octavefilter is a time-domain fractional-octave filter bank and does not have fs/nfft-style frequency resolution
  • Documented how third-octave bands are defined via standardized center, lower, and upper edges, including a numeric 1 kHz band example
  • Provided a code snippet using getansifrequencies and scipy.signal.welch to map narrowband PSD bins into PyOctaveBand-defined bands and inspect Welch bin spacing
  • Clarified how sigbands=True can be used to obtain filtered waveforms for diagnostic FFT/Welch analysis without conflating band levels with FFT bins
README.md

Possibly linked issues

  • #Question regarding frequency resolution: Yes. The PR’s new docs explicitly answer the issue’s question about octavefilter frequency resolution versus FFT bin spacing.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Warning

Rate limit exceeded

@jmrplens has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 30 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 842ad11e-1c1f-45cd-ad18-029c8117a25c

📥 Commits

Reviewing files that changed from the base of the PR and between 6fd5eb1 and 7f913ea.

📒 Files selected for processing (1)
  • README.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/issue-47-frequency-resolution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jmrplens jmrplens merged commit bc50b21 into main May 9, 2026
12 checks passed
@jmrplens jmrplens deleted the docs/issue-47-frequency-resolution branch May 9, 2026 11:33
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="README.md" line_range="29" />
<code_context>
+    - [Gallery of Filter Bank Responses](#gallery-of-filter-bank-responses)
+  - [🔊 Acoustic Weighting (A, C, Z)](#-acoustic-weighting-a-c-z)
+  - [⏱️ Time Weighting and Integration](#️-time-weighting-and-integration)
+  - [⚡ Performance: Multichannel \& Vectorization](#-performance-multichannel-vectorization)
+  - [🔍 Filter Usage and Examples](#-filter-usage-and-examples)
+    - [1. Butterworth (`butter`)](#1-butterworth-butter)
</code_context>
<issue_to_address>
**issue (bug_risk):** The updated anchor for the Performance section likely no longer matches the generated heading ID, which can break the TOC link.

Previously this link used `#-performance-multichannel--vectorization`, but now has only one hyphen between `multichannel` and `vectorization`. For a heading like `⚡ Performance: Multichannel & Vectorization`, the generated ID is usually `-performance-multichannel--vectorization`. Please either restore the previous anchor or verify the actual generated ID so the TOC link continues to work.
</issue_to_address>

### Comment 2
<location path="README.md" line_range="46" />
<code_context>
+    - [Octave Band Frequencies (ANSI S1.11 / IEC 61260)](#octave-band-frequencies-ansi-s111-iec-61260)
+    - [Frequency Resolution vs FFT Bin Spacing](#frequency-resolution-vs-fft-bin-spacing)
+    - [Magnitude Responses |H(jw)|](#magnitude-responses-hjw)
+    - [Filter Bank Design \& Numerical Stability](#filter-bank-design-numerical-stability)
+    - [Weighting Curves (IEC 61672-1)](#weighting-curves-iec-61672-1)
     - [Time Integration](#time-integration)
</code_context>
<issue_to_address>
**issue (bug_risk):** The anchor for the "Filter Bank Design & Numerical Stability" section may not match the heading’s generated ID.

For this heading, GitHub’s generated ID is likely `filter-bank-design--numerical-stability` (double hyphen for the `&`), but the TOC uses `#filter-bank-design-numerical-stability`. Please confirm the actual generated ID and update the link so it matches.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread README.md
- [Gallery of Filter Bank Responses](#gallery-of-filter-bank-responses)
- [🔊 Acoustic Weighting (A, C, Z)](#-acoustic-weighting-a-c-z)
- [⏱️ Time Weighting and Integration](#️-time-weighting-and-integration)
- [⚡ Performance: Multichannel \& Vectorization](#-performance-multichannel-vectorization)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): The updated anchor for the Performance section likely no longer matches the generated heading ID, which can break the TOC link.

Previously this link used #-performance-multichannel--vectorization, but now has only one hyphen between multichannel and vectorization. For a heading like ⚡ Performance: Multichannel & Vectorization, the generated ID is usually -performance-multichannel--vectorization. Please either restore the previous anchor or verify the actual generated ID so the TOC link continues to work.

Comment thread README.md
- [Octave Band Frequencies (ANSI S1.11 / IEC 61260)](#octave-band-frequencies-ansi-s111-iec-61260)
- [Frequency Resolution vs FFT Bin Spacing](#frequency-resolution-vs-fft-bin-spacing)
- [Magnitude Responses |H(jw)|](#magnitude-responses-hjw)
- [Filter Bank Design \& Numerical Stability](#filter-bank-design-numerical-stability)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): The anchor for the "Filter Bank Design & Numerical Stability" section may not match the heading’s generated ID.

For this heading, GitHub’s generated ID is likely filter-bank-design--numerical-stability (double hyphen for the &), but the TOC uses #filter-bank-design-numerical-stability. Please confirm the actual generated ID and update the link so it matches.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request significantly enhances the documentation in README.md by reorganizing the Table of Contents, updating the getansifrequencies API reference, and adding a comprehensive explanation of frequency resolution in filter banks compared to FFT methods. Review feedback identified several technical improvements for the documentation, including fixing broken Markdown anchor links caused by ampersand slugging, defining missing variables in code snippets to ensure they are runnable, and using more robust methods to determine signal length for multichannel support in examples.

Comment thread README.md
- [Gallery of Filter Bank Responses](#gallery-of-filter-bank-responses)
- [🔊 Acoustic Weighting (A, C, Z)](#-acoustic-weighting-a-c-z)
- [⏱️ Time Weighting and Integration](#️-time-weighting-and-integration)
- [⚡ Performance: Multichannel \& Vectorization](#-performance-multichannel-vectorization)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The anchor link for this header is likely broken. In GitHub's Markdown renderer, the ampersand (&) is removed, and the spaces surrounding it are converted to dashes, resulting in a double dash (--). Also, escaping the ampersand with a backslash (\&) is unnecessary and may cause the backslash to be rendered literally in some environments.

Suggested change
- [⚡ Performance: Multichannel \& Vectorization](#-performance-multichannel-vectorization)
- [⚡ Performance: Multichannel & Vectorization](#-performance-multichannel--vectorization)

Comment thread README.md
Comment on lines +43 to 48
- [Octave Band Frequencies (ANSI S1.11 / IEC 61260)](#octave-band-frequencies-ansi-s111-iec-61260)
- [Frequency Resolution vs FFT Bin Spacing](#frequency-resolution-vs-fft-bin-spacing)
- [Magnitude Responses |H(jw)|](#magnitude-responses-hjw)
- [Filter Bank Design \& Numerical Stability](#filter-bank-design-numerical-stability)
- [Weighting Curves (IEC 61672-1)](#weighting-curves-iec-61672-1)
- [Time Integration](#time-integration)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

These sub-items in the Theoretical Background section are missing their anchor links. Additionally, the link for 'Filter Bank Design & Numerical Stability' should account for the double dash generated by the ampersand slugging.

Suggested change
- [Octave Band Frequencies (ANSI S1.11 / IEC 61260)](#octave-band-frequencies-ansi-s111-iec-61260)
- [Frequency Resolution vs FFT Bin Spacing](#frequency-resolution-vs-fft-bin-spacing)
- [Magnitude Responses |H(jw)|](#magnitude-responses-hjw)
- [Filter Bank Design \& Numerical Stability](#filter-bank-design-numerical-stability)
- [Weighting Curves (IEC 61672-1)](#weighting-curves-iec-61672-1)
- [Time Integration](#time-integration)
- [Octave Band Frequencies (ANSI S1.11 / IEC 61260)](#octave-band-frequencies-ansi-s111-iec-61260)
- [Frequency Resolution vs FFT Bin Spacing](#frequency-resolution-vs-fft-bin-spacing)
- [Magnitude Responses |H(jw)|](#magnitude-responses-hjw)
- [Filter Bank Design & Numerical Stability](#filter-bank-design--numerical-stability)
- [Weighting Curves (IEC 61672-1)](#weighting-curves-iec-61672-1)
- [Time Integration](#time-integration)

Comment thread README.md
from pyoctaveband import octavefilter, getansifrequencies

fs = 100_000
x = pressure_signal_pa # 1D pressure signal in Pa
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The variable pressure_signal_pa is not defined in this snippet, which prevents the example from being runnable as-is. Providing a synthetic signal generation step makes the documentation more helpful for users.

Suggested change
x = pressure_signal_pa # 1D pressure signal in Pa
x = np.random.randn(fs) # Example 1D pressure signal in Pa

Comment thread README.md
fc, fl, fu, labels = getansifrequencies(fraction=3, limits=[12, 20_000])

# Narrowband Welch estimate on the original signal.
nperseg = min(2**15, len(x))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using len(x) on a NumPy array returns the size of the first dimension. If the input signal is multichannel (2D), this would return the number of channels instead of the number of samples, leading to an incorrect nperseg for the Welch estimate. Using x.shape[-1] or x.size (for 1D) is more robust.

Suggested change
nperseg = min(2**15, len(x))
nperseg = min(2**15, x.shape[-1])

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 9, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

CI Results 🚀

Test Summary

Python Version Tests Failures Coverage Status
macos-latest-3.13 111 0 99.5% ✅ Passed
ubuntu-latest-3.13 111 0 99.5% ✅ Passed
windows-latest-3.13 111 0 99.5% ✅ Passed

Technical Benchmark Summary

📊 View Benchmark Details

PyOctaveBand: Technical Benchmark Report

Generated: 2026-05-09 11:37:08

1. Test Signal Parameters

  • Sample Rate: 96.0 kHz
  • Duration: 10.0 seconds
  • Signal Types: White Noise (Stability) / Pure Sine (Precision)
  • Precision: 64-bit Floating Point

2. Crossover (Linkwitz-Riley)

Crossover

  • Flatness Error: 0.000000 dB (Target < 0.01)

3. Precision & Isolation

Precision

Type Error (dB) Isolation Ripple GD Std (ms)
butter 2.46e-03 31.3 dB 0.2705 dB 2847.826
cheby1 3.38e-03 40.5 dB 0.1000 dB 3551.677
cheby2 3.26e-03 57.8 dB 29.4187 dB 4790.013
ellip 9.41e-03 54.2 dB 0.1000 dB 4700.881
bessel 5.20e-01 32.5 dB 5.9845 dB 1380.212

4. Performance

Performance

Channels Exec Time (s) Speedup
1 0.629 1.00x
2 1.230 1.02x
4 2.437 1.03x
8 4.850 1.04x
16 9.664 1.04x

View Full Artifacts

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.

1 participant