musescore / musescore/MuseScore

Mixer: manual volume resets to 0 dB after enabling Solo and playing back

Open
#34,673 0 comments 0 reactions 1 assignee View on GitHub

@RomanPudashkin is already working on this.

Since Aug 25, 2026.

P1 Pre-release feature issue regression MS4 UX/interaction
Dominant language
C++
Stars
15.1k
Forks
3.3k
Avg merge
2d 2h
Merged PRs (30d)
91

Description

Issue type

UX/Interaction bug (incorrect behaviour)

Description with steps to reproduce

Manually setting an instrument's volume in the Mixer gets silently discarded and reset to the default (0 dB) shortly after playback runs — even when no volume-automation curve was ever drawn on that track.

Steps to reproduce:

  1. Open the Mixer.
  2. Set an instrument's volume to -6 dB.
  3. Enable Solo on that instrument.
  4. Close the Mixer.
  5. Start playback, let it play 1-2 measures, then stop.
  6. Reopen the Mixer.

Actual behaviour:
The instrument's volume has reset to 0 dB (default), discarding the manual adjustment made in step 2.

Expected behaviour:
The manually set volume (-6 dB) should be preserved across playback, regardless of Solo/Mute state changes or automation.

Supporting files, videos and screenshots

https://github.com/user-attachments/assets/0d6c84e2-f29a-400c-a1a5-c0d18c12843b

In which versions of MuseScore Studio is this issue present?

MS 5 current main branch

Regression

Yes, this used to work in a previous version of MuseScore 4.x

Operating system

macos 26.2

Additional context

This appears to be an unintended side effect of the new Volume/Pan automation feature (PR #34474), not related to automation curve evaluation itself.

Code analysis (as of main):

  • PlaybackController::updateSoloMuteStates() (src/playback/internal/playbackcontroller.cpp, ~line 1629) is triggered by the Solo/Mute toggle. It rebuilds control params by calling trackOutputParams(), which returns the value stored in IProjectAudioSettings::trackOutputParams() — i.e. the persisted value — rather than whatever the user last set live in the Mixer.
  • MixerChannelItem::setVolumeLevel() / mixerpanelmodel.cpp (controlParamsChanged handlers, ~lines 520/578/616) only push the new value to the live audio engine via playback()->setControlParams(...). They never call IProjectAudioSettings::setTrackOutputParams() to persist it — unlike fx-chain parameters, which ARE persisted correctly via a dedicated subscription in PlaybackController::subscribeOnAudioParamsChanges() (~lines 1491-1541).
  • As a result, any later call to updateSoloMuteStates() (or resendAutomatedControlParams(), triggered by tempo/duration changes) re-sends the stale/default persisted value and overwrites the manual fader setting.
  • I verified this is NOT related to automation curve evaluation: trackControlParams() only builds an automation envelope when explicitly asked to rebuild (rebuildVolume/rebuildPan = true), and updateSoloMuteStates() calls it with both flags false. No automation curve was drawn in the reproduction steps above, confirming the automation engine itself is not involved.
  • The PR #34474 description mentioned an intent to "restore manual values when automation ends," but I could not find this restoration logic currently implemented in mixerchannelitem.cpp.

Suggested fix scope (not yet attempted, for information only):
Add a call to IProjectAudioSettings::setTrackOutputParams(instrumentTrackId, params) inside the controlParamsChanged handlers in mixerpanelmodel.cpp (~lines 520, 578, 616), alongside the existing live playback()->setControlParams(...) call, so manual Mixer changes are persisted at the moment they're made. This setter already exists and is used elsewhere (fx-chain persistence) — no new engine-side plumbing appears to be required.

Checklist
  • This report follows the guidelines for reporting bugs and issues
  • I have verified that this issue has not been logged before, by searching the issue tracker for similar issues
  • I have attached all requested files and information to this report
  • I have attempted to identify the root problem as concisely as possible, and have used minimal reproducible examples where possible

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.