Skip to content

move compressor to TG menu and add parameters#973

Closed
soyersoyer wants to merge 4 commits intoprobonopd:mainfrom
soyersoyer:tgcompressor
Closed

move compressor to TG menu and add parameters#973
soyersoyer wants to merge 4 commits intoprobonopd:mainfrom
soyersoyer:tgcompressor

Conversation

@soyersoyer
Copy link
Contributor

@soyersoyer soyersoyer commented Jul 30, 2025

Summary by Sourcery

Introduce per-tone generator compressor controls by adding enable, pregain, attack, release, threshold, and ratio parameters to performance configuration, synthesizer engine, and the UI, and move compressor settings from global effects to the TG menu.

New Features:

  • Add per-TG compressor parameters (enable, pregain, attack, release, threshold, ratio) to CPerformanceConfig and CMiniDexed
  • Expose compressor controls in the UI under a dedicated TG submenu with custom formatting for dB, ms, and ratio values

Enhancements:

  • Move compressor settings from the global effects menu into the tone generator menu for individual TG configuration
  • Provide compatibility handling for the legacy global compressor enable flag in performance loading

@sourcery-ai
Copy link

sourcery-ai bot commented Jul 30, 2025

Reviewer's Guide

This PR refactors the compressor from a single global toggle to fully configurable per‐tone-generator, introducing six new TG parameters (enable, pre-gain, attack, release, threshold, ratio) and propagating them through the config loader/saver, the synth engine, and the UI menu, with backward compatibility for existing global settings.

Class diagram for updated compressor configuration in CPerformanceConfig and CMiniDexed

classDiagram
    class CPerformanceConfig {
        +bool GetCompressorEnable(unsigned nTG) const
        +int GetCompressorPreGain(unsigned nTG) const
        +unsigned GetCompressorAttack(unsigned nTG) const
        +unsigned GetCompressorRelease(unsigned nTG) const
        +int GetCompressorThresh(unsigned nTG) const
        +unsigned GetCompressorRatio(unsigned nTG) const
        +void SetCompressorEnable(bool, unsigned nTG)
        +void SetCompressorPreGain(int, unsigned nTG)
        +void SetCompressorAttack(unsigned, unsigned nTG)
        +void SetCompressorRelease(unsigned, unsigned nTG)
        +void SetCompressorThresh(int, unsigned nTG)
        +void SetCompressorRatio(unsigned, unsigned nTG)
        -bool m_bCompressorEnable[CConfig::AllToneGenerators]
        -int m_nCompressorPreGain[CConfig::AllToneGenerators]
        -unsigned m_nCompressorAttack[CConfig::AllToneGenerators]
        -unsigned m_nCompressorRelease[CConfig::AllToneGenerators]
        -int m_nCompressorThresh[CConfig::AllToneGenerators]
        -unsigned m_nCompressorRatio[CConfig::AllToneGenerators]
    }

    class CMiniDexed {
        +void SetCompressorEnable(bool, unsigned nTG)
        +void SetCompressorPreGain(int, unsigned nTG)
        +void SetCompressorAttack(unsigned, unsigned nTG)
        +void SetCompressorRelease(unsigned, unsigned nTG)
        +void SetCompressorThresh(int, unsigned nTG)
        +void SetCompressorRatio(unsigned, unsigned nTG)
        -bool m_bCompressorEnable[CConfig::AllToneGenerators]
        -int m_nCompressorPreGain[CConfig::AllToneGenerators]
        -unsigned m_nCompressorAttack[CConfig::AllToneGenerators]
        -unsigned m_nCompressorRelease[CConfig::AllToneGenerators]
        -int m_nCompressorThresh[CConfig::AllToneGenerators]
        -unsigned m_nCompressorRatio[CConfig::AllToneGenerators]
    }

    CPerformanceConfig <.. CMiniDexed : uses
Loading

Class diagram for updated CUIMenu compressor menu and parameter handling

classDiagram
    class CUIMenu {
        +static const TMenuItem s_TGMenu[]
        +static const TMenuItem s_EditCompressorMenu[]
        +static const TParameter s_TGParameter[]
        +static std::string TodB(int nValue)
        +static std::string ToMillisec(int nValue)
        +static std::string ToRatio(int nValue)
    }

    class TMenuItem {
    }
    class TParameter {
    }

    CUIMenu o-- TMenuItem
    CUIMenu o-- TParameter
Loading

File-Level Changes

Change Details Files
Migrate compressor state into per-TG arrays in PerformanceConfig
  • Replaced single m_bCompressorEnable with arrays for enable, preGain, attack, release, thresh, ratio
  • Updated Load() and Save() loops to iterate over all TGs for each compressor parameter
  • Added compatibility block to map old global compressor flag to per-TG disables
  • Removed old global Get/SetCompressorEnable and declared new per-TG getters/setters in header
performanceconfig.cpp
performanceconfig.h
Extend CMiniDexed to support and persist TG compressor parameters
  • Initialized new compressor defaults in constructor
  • Removed global compressor code paths in SetParameter and DoSavePerformance
  • Added SetCompressor*/GetCompressor* methods with bounds checks, synth engine callbacks, and UI notifications
  • Extended TGParameter switch cases to handle all six compressor parameters
  • Updated performance save/load integration in DoSavePerformance and LoadPerformanceParameters
minidexed.cpp
minidexed.h
Expose compressor controls in the TG menu and add formatting helpers
  • Inserted “Compressor” submenu under TG menu with entries for each parameter
  • Extended CUIMenu parameter arrays to include new TG compressor entries with appropriate ranges and formatter pointers
  • Implemented TodB, ToMillisec, ToRatio helpers for UI display
  • Removed legacy global compressor menu entry
uimenu.cpp
uimenu.h

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

Copy link

@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 @soyersoyer - I've reviewed your changes - here's some feedback:

  • The repeated loops of PropertyName.Format/GetNumber and SetNumber for each compressor parameter suggest a helper or data‐driven approach would reduce boilerplate and risk of mismatches.
  • Maintaining six parallel arrays for compressor state across CPerformanceConfig and CMiniDexed is error‐prone—consider bundling them into a struct or small class to improve cohesion.
  • The new TodB/ToMillisec/ToRatio formatters in CUIMenu could be moved into a shared formatting utility to keep the menu class focused solely on navigation and rendering logic.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The repeated loops of PropertyName.Format/GetNumber and SetNumber for each compressor parameter suggest a helper or data‐driven approach would reduce boilerplate and risk of mismatches.
- Maintaining six parallel arrays for compressor state across CPerformanceConfig and CMiniDexed is error‐prone—consider bundling them into a struct or small class to improve cohesion.
- The new TodB/ToMillisec/ToRatio formatters in CUIMenu could be moved into a shared formatting utility to keep the menu class focused solely on navigation and rendering logic.

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.

@github-actions
Copy link

Build for testing:
MiniDexed_1275_2025-07-30-b879934_32bit
MiniDexed_1275_2025-07-30-b879934_64bit
Use at your own risk.

@github-actions
Copy link

Build for testing:
MiniDexed_1276_2025-07-30-eaf2223_32bit
MiniDexed_1276_2025-07-30-eaf2223_64bit
Use at your own risk.

@Banana71
Copy link

I'm impressed. 👍

It's only possible to set the compressor for TG1. I can't access the compressor for TG2 - TG8. When you try to control the compressor via the TG2 - TG8 UI, it always jumps directly to TG1. The shortcut (pressing and turning the encoder) doesn't work in the compressor menu either.

The compressor itself works really well :-)

@Banana71
Copy link

I still have a few questions:

  • Does the compressor only work with an RPi 4 or higher, or also with the RPi 2, RPi Zero 2, and RPi 3?
  • Is your goal to combine multiple parts (TG9 - TG16, TG17 - TG24) and the dynamic extension?
  • What about compressed layered sounds? Would compressor groups perhaps be better (e.g., route TG1 - TG4 to compressor A, TG5 to compressor B, TG6 & TG7 to compressor C, etc.)

@probonopd
Copy link
Owner

As we still have a comprehensive FX patch waiting to become ready, I'm hesitant to merge this. Also I guess this would break the performance format?

@github-actions
Copy link

Build for testing:
MiniDexed_1278_2025-07-30-92c3927_64bit
MiniDexed_1278_2025-07-30-92c3927_32bit
Use at your own risk.

@soyersoyer
Copy link
Contributor Author

soyersoyer commented Jul 30, 2025

It's only possible to set the compressor for TG1.

This surprised me, I fixed it. Thanks.

Does the compressor only work with an RPi 4 or higher, or also with the RPi 2, RPi Zero 2, and RPi 3?

Just like before, from RPi1 as well. Only the configurability of the compressors has changed.

Is your goal to combine multiple parts (TG9 - TG16, TG17 - TG24) and the dynamic extension?

Not necessarily like that. Part2, Part3 PR was more of a demo to see if it was worth doing something like that. It would be nice to somehow link the TGs together, to find a solution that would be good for larger Performances, Unison, Part things.

What about compressed layered sounds? Would compressor groups perhaps be better (e.g., route TG1 - TG4 to compressor A, TG5 to compressor B, TG6 & TG7 to compressor C, etc.)

This is also a good idea. We'll keep that in mind when linking to TGs.

Also I guess this would break the performance format?

This can open the current format, thus disabling all compressors if CompressorEnable is set and its value is 0.
However, previous MiniDexed versions will not catch the new parameters and a default compressor will be enabled. (even it is disabled for some or all TGs)

But this can be improved, CompressorEnable=0 can be written for older MiniDexeds if all compressors are disabled. But I don't know if it's worth the hassle.

As we still have a comprehensive FX patch waiting to become ready, I'm hesitant to merge this.

Will jnonis still work on it? The compressor is also used by the fx-full code, this change will be basically compatible with it.

@github-actions
Copy link

Build for testing:
MiniDexed_1279_2025-07-30-db09f37_32bit
MiniDexed_1279_2025-07-30-db09f37_64bit
Use at your own risk.

@github-actions
Copy link

Build for testing:
MiniDexed_1281_2025-07-30-ca6e0ac_32bit
MiniDexed_1281_2025-07-30-ca6e0ac_64bit
Use at your own risk.

@github-actions
Copy link

Build for testing:
MiniDexed_1282_2025-07-30-630c523_32bit
MiniDexed_1282_2025-07-30-630c523_64bit
Use at your own risk.

@soyersoyer
Copy link
Contributor Author

Changed the preGrain range to -20 .. 20 dB and threshold to -60 .. 0 dBFS.

@github-actions
Copy link

Build for testing:
MiniDexed_1283_2025-07-30-2f49a26_32bit
MiniDexed_1283_2025-07-30-2f49a26_64bit
Use at your own risk.

@github-actions
Copy link

Build for testing:
MiniDexed_1284_2025-07-30-0db753a_32bit
MiniDexed_1284_2025-07-30-0db753a_64bit
Use at your own risk.

@Banana71
Copy link

Hey, hey, hey, the compressor is fun.
You can control it really well and it does whatever you want. Great.
If the ratio is set to 1:1, you can easily adjust the drums to a reasonable volume using pre-gain.
Saving and loading performances also works perfectly with the compressor parameters.

Crying over nothing serious: A ratio of 5:1 is more of a limiter than a musical compressor. I think a starting value of 2:1 is more suitable.

Just a thought: Since I like to overdo it sometimes, a warning about clipping would be helpful. Is it possible to evaluate the volume and, if the volume exceeds, say, -3 dB, set a digital output for a warning LED?

Peter

@soyersoyer
Copy link
Contributor Author

Good to hear! :)

A ratio of 5:1 is more of a limiter than a musical compressor. I think a starting value of 2:1 is more suitable.

This site said that 5:1 is the 'medium' ratio, so I think that's fine.

Since I like to overdo it sometimes, a warning about clipping would be helpful. Is it possible to evaluate the volume and, if the volume exceeds, say, -3 dB, set a digital output for a warning LED?

I'll look for a limiter at the end of the chain, and I think that can solve it. But the warning may also appear on the display for a short time.

@soyersoyer
Copy link
Contributor Author

The compressor in Synth_Dexed could be placed after MasterVolume and parameterized to act as a limiter. Is this a good idea?

Could it be parameterized in the Performance files also?

@Banana71
Copy link

The parameterizable compressor that you have integrated into the TGs, is it technically the same as the one we have always known as a limiter under effects?

The compressor in Synth_Dexed could be placed after MasterVolume and parameterized to act as a limiter. Is this a good idea?

Could it be parameterized in the Performance files also?

Yes and yes, absolutely agree. The best way to protect your ears from unwanted happy little accidents :-) 🙉

@Banana71
Copy link

Banana71 commented Aug 4, 2025

The compressor is well implemented, and I wish it were adopted for this project. Then I could bring all the performances to the same volume level. The performances would work on older versions without a compressor.

Peter

@soyersoyer
Copy link
Contributor Author

The parameterizable compressor that you have integrated into the TGs, is it technically the same as the one we have always known as a limiter under effects?

Yes, it's the same. Look at this current implementation: if you enable the compressor in the Effects menu, it will enable all TG compressors.

The compressor is well implemented, and I wish it were adopted for this project. Then I could bring all the performances to the same volume level.

That's sounds good! With 32 TGs, layering of performances is also possible.

I'm going to add a limiter at the end of the chain.

@Banana71
Copy link

Banana71 commented Aug 5, 2025

I'm going to add a limiter at the end of the chain.

If it were possible for you, a fully parameterizable compressor would be ideal (with the default parameters as a limiter)

@soyersoyer
Copy link
Contributor Author

soyersoyer commented Aug 5, 2025

I added the limiter before MasterVolume.

Parameters:

  • LimiterEnable (default: 1)
  • LimiterPreGain (default: 0 dB)
  • LimiterAttack (default: 5 ms)
  • LimiterRelease (default: 5 ms)
  • LimiterThresh (default: -3 dBFS)
  • LimiterRatio (default: 20:1)
  • LimiterHPFilterEnable (default: 0)

@github-actions
Copy link

github-actions bot commented Aug 5, 2025

Build for testing:
MiniDexed_1294_2025-08-05-0052a28_32bit
MiniDexed_1294_2025-08-05-0052a28_64bit
Use at your own risk.

@Banana71
Copy link

Banana71 commented Aug 5, 2025

Thank you @soyersoyer ,
that's perfect 👍This way, you can give each sound the desired punch.

Peter

@soyersoyer
Copy link
Contributor Author

Then we just have to wait for the integration :)

@soyersoyer
Copy link
Contributor Author

@probonopd What do you think? Do you need else in this?

@Banana71
Copy link

Banana71 commented Aug 6, 2025

I could offer to extend the wiki after the merge.🤖

@Banana71
Copy link

Banana71 commented Aug 6, 2025

I tested something else: Performance saving and loading works great.

Peter

@soyersoyer soyersoyer closed this Aug 12, 2025
@soyersoyer soyersoyer deleted the tgcompressor branch December 3, 2025 22:25
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.

3 participants