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

Fix: [Spectrogram] fix cropping and scaling issues #3796

Merged
merged 2 commits into from
Dec 23, 2024

Conversation

jonom
Copy link
Contributor

@jonom jonom commented Jul 22, 2024

Short description

Resolves #3663, #3140

Implementation details

I've attempted to address some issues with the spectrogram rendering creating an image of the wrong height for the target container, causing it to be too tall or short to fill the area, and meaning the frequency labels do not line up with data in the image. There are some magic numbers in here (E.g. division by 2 or 4) I don't understand so appreciate if someone else can vet this!

(Marked as draft for now as I'm running tests locally but it's taking quite a while.)

Separate to this I've implemented some caching of the result of getFrequencies() as well as the rendered bitmaps as this can be quite slow, and for my use case we allow zooming in and out so I wanted to speed up the rendering. If this is something you'd like included I can add to this PR or open another one later.

How to test it

Screenshots

Checklist

  • This PR is covered by e2e tests
  • It introduces no breaking API changes

Summary by CodeRabbit

  • New Features
    • Enhanced audio playback quality with an updated sample rate.
    • Added new configuration options for the Spectrogram, including frequency range and scale settings.
  • Bug Fixes
    • Improved error handling for color map validation.
  • Refactor
    • Streamlined frequency scaling and rendering logic in the Spectrogram plugin.

@katspaugh
Copy link
Owner

@jonom thanks for the PR! How did your tests go, did it solve those issues for you?

@jonom
Copy link
Contributor Author

jonom commented Aug 9, 2024

I'm not exactly sure how the e2e tests are supposed to be ran - after a while I worked out I could run them manually, but I didn't see snapshots to compare with expected results.

One thing I have found since is that setting sampleRate on the ws instance doesn't seem to affect rendering, except that if it's too small, the upper range of the spectrogram may be missing. So I've been setting it to 88200 and then it seems to always work 🤷‍♂️

@katspaugh
Copy link
Owner

I've commented out Spectrogram tests for now, they mysteriously always fail on GitHub Actions but work locally.

@jonom jonom force-pushed the spectrogram-fixes branch from ccd8362 to 2b9bb14 Compare December 18, 2024 00:47
Copy link

coderabbitai bot commented Dec 18, 2024

Walkthrough

The pull request introduces modifications to the Spectrogram plugin in WaveSurfer.js, focusing on enhancing the frequency analysis and visualization capabilities. The changes include updating the sample rate, adjusting frequency scaling parameters, and improving the rendering logic of the spectrogram. The modifications aim to provide more flexible and accurate spectrogram generation across different audio sample rates and FFT sample sizes.

Changes

File Change Summary
examples/spectrogram.js - Updated sampleRate from 22050 to 44100
- Added Spectrogram plugin configuration parameters: scale, frequencyMax, frequencyMin, fftSamples, labelsBackground
src/plugins/spectrogram.ts - Modified frequency scaling logic
- Updated frequencyMax calculation
- Added getWidth() method
- Improved error handling and rendering logic

Assessment against linked issues

Objective Addressed Explanation
fftSamples shouldn't scale spectrogram height [#3663] Partial implementation - requires further verification of consistent image height across different FFT sample sizes

Poem

🎵 Spectrogram waves dance and sway,
Frequencies mapped in a digital play,
From low to high, pixels align,
WaveSurfer's magic, sound design!
🎧 Rabbit's code leaps with delight! 🐰

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@jonom jonom marked this pull request as ready for review December 21, 2024 00:43
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (7)
src/plugins/spectrogram.ts (7)

339-340: Default height of 200 px may be too small for some use cases.
If the user’s container is large, consider making the default scale more adaptive. This might also address potential visual issues.


352-352: Explain the 4x downsampling of fftSamples for Mel filters.
The new logic sets numMelFilters to fftSamples / 4. If the intention is to reduce computational load, consider documenting or making this configurable to allow different channel granularity.


463-463: Ensure canvas width is appropriately recalculated.
Calling “this.getWidth()” multiple times is fine, but be mindful of reflows if the container changes size often or if the plugin is continuously redrawn. Caching the width might be more performant.

Also applies to: 468-468


555-557: Confirm safe usage of “offsetWidth”.
“offsetWidth” returns an integer that excludes margins. If the element has non-zero margins or is inside a flex container, the actual content width might be different. For more precise sizing, consider “clientWidth” or a bounding rectangle.


563-563: Defaulting “frequencyMax” to samplerate/4.
Be cautious that some usage might require the full Nyquist range. If this is truly the intended new default, highlight it in release notes or usage docs for clarity.


689-690: Protect label drawing with boundary checks.
The label position clamp is a good approach, but multiple computations might cause “flickering” if the spectrogram height changes over time. Consider caching layout data or injecting a stable reference.

Also applies to: 691-692


707-707: Potential repeated measurement with “getWidth()”.
Same comment as line 463 and 468: consider storing the width in a local variable to avoid repeated layout calculations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8368928 and ba25bfe.

📒 Files selected for processing (2)
  • examples/spectrogram.js (2 hunks)
  • src/plugins/spectrogram.ts (9 hunks)
🔇 Additional comments (6)
src/plugins/spectrogram.ts (4)

469-469: Validate shift from samplerate/2 to samplerate/4.
The line “freqFrom = this.buffer.sampleRate / 4” could limit your spectrogram to half of the typical Nyquist range. Verify that you actually intend to skip the higher frequencies.


486-486: Offset expression might invert frequency axis unintentionally.
“(bitmapHeight / 2 - j)” suggests half-based vertical offset. Confirm if the design requires a mirrored view or if there’s a user-facing reason for the inverted indexing.


677-685: Validate frequency scale transitions.
Ensure that switching from “mel” scale to a “linear” scale preserves consistent label spacing. Also check numeric rounding for high frequencies.


250-250: Clarify “samplerate/4” usage in docstring.
The updated comment suggests setting the max frequency to “samplerate/4” to draw the “whole range” of the spectrogram. Typically, the Nyquist frequency is samplerate/2. If you intend to visualize the entire Nyquist range, consider double-checking this value and updating the docstring accordingly.

Run the following script to find all docstring references to “samplerate/4” or “samplerate/2” and confirm whether they need updating:

examples/spectrogram.js (2)

12-12: Check interplay between “sampleRate=44100” and actual audio sampling.
Browsers often ignore custom sampleRate during decoding and might resample internally. If you’re relying on 44100 for display math, confirm that the actual decoded data sample rate matches.


21-25: Helpful additions for advanced spectrogram customization.
The new options (scale, frequencyMax, frequencyMin, fftSamples, labelsBackground) give users more granular control. Just ensure your docs or example usage describe their interactions clearly (especially how “frequencyMax=8000” relates to “sampleRate=44100”).

Comment on lines +480 to +481
const bitmapHeight = pixels[0].length
const imageData = new ImageData(width, bitmapHeight)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Check potential out-of-bounds index.
Accessing “pixels[0]” might fail if “pixels” is empty. Ensure “frequenciesData[c]” is never empty or handle errors gracefully.

src/plugins/spectrogram.ts Show resolved Hide resolved
@jonom
Copy link
Contributor Author

jonom commented Dec 21, 2024

@katspaugh sorry for the slow reply, I didn't realise the Mel scale had been added and the fixes I supplied previously only worked for the Linear scale. I've worked with @lucastheis to update the fixes and the Mel scale should work a lot better now, being rendered at the appropriate height and also fixing a few bugs with the scale labels.

If you could let me know what I would need to do to get this over the line that would be great. No rush - I'll be off until the new year now. If you're taking some time off as well, happy holidays!

image

Copy link
Owner

@katspaugh katspaugh left a comment

Choose a reason for hiding this comment

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

Amazing, thank you! Happy holidays to you as well!

@katspaugh katspaugh merged commit 6543bf1 into katspaugh:main Dec 23, 2024
3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Dec 25, 2024
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.

fftSamples shouldn't scale the spectrogram image
2 participants