-
Notifications
You must be signed in to change notification settings - Fork 102
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
Add Configurable DSP with Parametric Equalizer #1795
Conversation
Wow, just wow. I was kind of hoping someone would pick up the glove for this (as I did prepare a few hooks for this in the code). You just did. Amazing! I will give this a proper review tomorrow. First impression: Super nice work! |
I'm thinking, maybe this PR (or another PR in the same release) should also add a Tone Controls Filter? Then we can easily migrate the CONF_EQ_BASS, CONF_EQ_MID and CONF_EQ_TREBLE settings by:
Otherwise it would be more difficult to handle this case:
Let me know, if I should put this in this set of PRs or open another one. |
Let me first start off by saying 'Amazing work'. Really love the amount of detail you put into this PR. I only really have one suggestion. Personally I think it makes sense to put the filter calculations inside the model classes themselves. This avoids quite some logic in the So, for example, instead of using an class PeakParametricEQBand:
....
def get_filter(sample_rate: int) -> str:
b0 = 1 + alpha * a
b1 = -2 * math.cos(w_0)
b2 = 1 - alpha * a
a0 = 1 + alpha / a
a1 = -2 * math.cos(w_0)
a2 = 1 - alpha / a
return f"biquad=b0={b0}:b1={b1}:b2={b2}:a0={a0}:a1={a1}:a2={a2}" Then, in ...
# Process each DSP filter sequentially
for f in dsp.filters:
if not f.enabled:
continue
if isinstance(f, ParametricEQFilter):
for b in f.bands:
if not b.enabled:
continue
filter = b.get_filter(sample_rate)
filter_params.append(filter) What do you and @marcelveldt think? |
I was kind of wondering the same - the models that we have defined in our separate repo/package are basically models that are shared between client and server (we handle serialization and some validation there as well) but these seem to be server-side models only, its pretty much self-contained data and logic. So yeah it could make sense to make these server side models (actual classes and not dataclasses) but you can even have a mix of both worlds, it perfectly fine to add some helper methods to the dataclasses, for instance to create this filter config with a simple helper method within the model class. I'm fine either way but if this logic is server-side only I'd vote for moving them to the servercode instead of the shared models package. |
Yes, it sounds good to consolidate the old simple tone controls to EQ by either just drop them or write a small migration function. |
That was my thought too.
Another solution is to move this logic to a new |
I made the following changes:
The migration will be performed once someone plays music. |
3c12d29
to
109efa6
Compare
109efa6
to
5608b6a
Compare
Sorry for the late review. I have been busy last 2 weeks with other (HA) stuff so there was no more time left for MA. |
No problem. Let me know if some changes are necessary. |
This method is analogous to `on_player_config_change`, but just restarts the playback. Since resuming playback restarts ffmpeg, the DSP configuration is reloaded.
DSP configuration is now handled separately from player configuration. This has a few advantages: - Applying changes can be speed up, since main player configuration stays the same - Changing DSP does not require to resend Player options as dictated by the provider - Later filters like convolution require special handling for the IR wav file - This allows saving/loading presets without chaning the players configuration
Some FFMPEG filters like biquad require knowing the sample rate.
This commit add Parametric Equalizer support to Music Assistant. By using Biquad Filters, this implementation uses minimal CPU usage and supports all common filter types typically found in Room/Headphone correction scenarios.
The new DSP System replaces those old options, while supporting more in depth configuration.
5608b6a
to
b1ce9b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
I will also do a release of the frontend and then release a beta with this feature included later today or tomorrow! |
@maximmaxim345 I haven't had a chance to play with this awesomeness much but one small thing. Can the toggles change to blue when on to match the rest of the UI? |
This comment was marked as outdated.
This comment was marked as outdated.
Just tried it. Unfortunately, when using dark mode, using the primary color clashes with the background, resulting in a contrast that's too low for my liking: |
Good point! I've experimented with tweaking the background colors while keeping the same blue. Here's what I came up with: Dark Mode:Light Mode:What do you think about these adjustments? |
Yeah i think that looks great and a separator would look good. |
Overview
This Pull Request introduces a sophisticated multi-stage Digital Signal Processing (DSP) system to Music Assistant, featuring a highly-flexible Parametric Equalizer as its core component.
To replace the old existing EQ, this PR also adds a Filter "Tone Controls" with automatic migration.
Screenshot
For me, the main feature missing from Music Assistant was the lack of a Parametric Equalizer, therefore I added one.
Related Changes
This PR is to be viewed in conjunction with music-assistant/frontend#756 and music-assistant/models#18.
This PR depends on music-assistant/models#18.
Future Filters
This modular system allows the addition of other filters in the future, that I will add in future PRs including:
Implementation Details
DSP Configuration is saved in a separate key compared to all other player configuration.
This has the following advantages:
stays the same
the provider
file
configuration
DSP should function with all player providers as I understand, since
get_raw_player_config_value
is used regardless of the underlying provider.Tested with DLNA, Chromecast and Sonos.