-
Notifications
You must be signed in to change notification settings - Fork 98
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
base: dev
Are you sure you want to change the base?
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
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.
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.