Skip to content

Lb302 cleanup#8132

Open
rubiefawn wants to merge 30 commits intoLMMS:masterfrom
rubiefawn:refac/lb302
Open

Lb302 cleanup#8132
rubiefawn wants to merge 30 commits intoLMMS:masterfrom
rubiefawn:refac/lb302

Conversation

@rubiefawn
Copy link
Contributor

@rubiefawn rubiefawn commented Nov 13, 2025

Makes the following changes to the Lb302 plugin for increased maintainability and readability:

  • Use non-static data member initializers where possible
  • Use std::numbers::pi instead of M_PI
  • Use std::array and std::unique_ptr instead of manual memory management
  • Change plain-old-data classes with only public members to structs
  • Change some ints to f_cnt_t, fpp_t, etc. to better communicate their purpose and avoid weird implicit casting nonsense
  • Change floats to sample_t where appropriate to better communicate their purpose
  • Find suitable homes for loose constants
  • Prefix standard library math function calls with std::
  • Ensure all floating-point literals intended to be floats end in f and are not doubles to appease MSVC
  • Change uses of SIGNAL and SLOT macros to whatever they should be post-Qt6 upgrade
  • Remove cursed mutex in favor of a real-time safe queue (TODO: possible generalization for Monophonic mode on instrument plugins; portamento #6516?)
  • Optimize struct/class member layout for better locality
  • Completely conform to current code conventions

The above list is not comprehensive and is destined to expand.

@rubiefawn rubiefawn self-assigned this Nov 13, 2025
@rubiefawn
Copy link
Contributor Author

rubiefawn commented Dec 8, 2025

Figured I'd run some un-rigorous perf stat benchmarks of release builds as a sanity check to make sure I wasn't destroying performance by changing the mutex for a bunch of atomic operations and busy-wait loops.

Updated for commit 03cca1b

Before, with mutex/dynamically allocated vector:

Performance counter stats for './lmms render /home/fawn/Documents/lmms/projects/torture.mmpz -a -f flac':

   103,084,983,781      task-clock                       #    2.979 CPUs utilized             
           695,800      context-switches                 #    6.750 K/sec                     
               388      cpu-migrations                   #    3.764 /sec                      
             6,173      page-faults                      #   59.883 /sec                      
   267,717,430,944      instructions                     #    1.17  insn per cycle            
   229,289,575,609      cycles                           #    2.224 GHz                       
    61,653,273,269      branches                         #  598.082 M/sec                     
       496,591,833      branch-misses                    #    0.81% of all branches           

      34.602878156 seconds time elapsed

      93.334079000 seconds user
       9.660192000 seconds sys

After, with atomic ringbuffer/statically allocated array:

Performance counter stats for './lmms render /home/fawn/Documents/lmms/projects/torture.mmpz -a -f flac':

   104,963,456,247      task-clock                       #    3.066 CPUs utilized             
           708,920      context-switches                 #    6.754 K/sec                     
                67      cpu-migrations                   #    0.638 /sec                      
             4,237      page-faults                      #   40.366 /sec                      
   267,503,252,259      instructions                     #    1.15  insn per cycle            
   233,160,958,544      cycles                           #    2.221 GHz                       
    61,493,266,240      branches                         #  585.854 M/sec                     
       511,104,882      branch-misses                    #    0.83% of all branches           

      34.239441489 seconds time elapsed

      95.604870000 seconds user
       9.199340000 seconds sys

Project file used for said benchmarks: torture.mmp.xml

@rubiefawn rubiefawn added performance needs style review A style review is currently required for this PR needs code review A functional code review is currently required for this PR needs testing This pull request needs more testing labels Dec 8, 2025
@rubiefawn rubiefawn marked this pull request as ready for review December 8, 2025 22:38
@rubiefawn
Copy link
Contributor Author

CACHELINE and busy_wait_hint probably don't belong inside Lb302. Where is the best place for me to move these to?

@messmerd
Copy link
Member

messmerd commented Jan 8, 2026

CACHELINE and busy_wait_hint probably don't belong inside Lb302. Where is the best place for me to move these to?

Maybe add them to a new LmmsPolyfill.h header. And rename CACHELINE to lmms::hardware_destructive_interference_size to match the name the standard library uses.

Makes the following changes to the Lb302 plugin:
- Use non-static data member initializers where possible
- Find suitable homes for several loose constants
- Use std::numbers::pi instead of M_PI
- Use std::array and std::unique_ptr instead of manual memory management
- Change some plain-old-data classes with only public members to structs
- Change some ints to more descriptive types such as f_cnt_t, fpp_t, etc
- Attempt to conform any lines I touched to current code conventions
This should be the last of the functions from `<cmath>`
Begone, SIGNAL() SLOT() macro magic!!
...and move them to be inside the classes that own them
- Remove Lb302Note as it is just function parameters with extra steps
- Clean up Lb302Synth::initNote()
- Clean up Lb302Synth::process()
- Move the GET_INC() helper to an anon namespace, rename to phaseInc()
- Make computeDecayFactor() a lambda next to its only callsite
To avoid implicit casts, it's all supposed to be floats
Also don't bother checking for __ARM_ACLE
Also don't drop notes when the queue is full, busy-wait a limited
number of iterations to see if space gets freed up
- Rename CACHELINE to lmms::hardware_destructive_interference_size
- Move lmms::hardware_destructive_interference_size and busy_wait_hint() to Hardware.h
#endif


#if defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)
Copy link
Member

Choose a reason for hiding this comment

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

I would use the host architecture macros from lmmsconfig.h instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mostly resolved as of 6fccf95 (MSVC is a pain in the ass as usual)

Comment on lines +85 to +88
float vcf_c0 = 0.f; // c0=e1 on retrigger; c0*=ed every sample; cutoff=e0+c0
float vcf_e0 = 0.f; // e0 and e1 for interpolation
float vcf_e1 = 0.f;
float vcf_rescoeff; //!< Resonance coefficient [0.30, 9.54]
Copy link
Member

Choose a reason for hiding this comment

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

These could be renamed to follow the naming conventions for data members

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For stuff like this where it's all vcf_foo, vcf_bar, with coefficient names that are supposed to be lowercase, I'm considering sticking them all in a POD struct like so:

struct
{
    float c0 = 0.f; // c0 = e[1] on retrigger; c0 *='ed every sample; cutoff = e[0] + c0
    std::array<float, 2> e = { 0.f, 0.f }; // e[0] and e[1] for interpolation
    float resCoeff; //!< Resonance coefficient [0.30, 9.54]
} m_vcf;

float vcf_d1, // d1 and d2 are added back into the sample with
vcf_d2; // vcf_a and b as coefficients. IIR2 resonance
// loop.
protected:
Copy link
Member

Choose a reason for hiding this comment

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

The data members of this class could also be renamed to follow the conventions

Comment on lines +129 to +138
float kfcn;
float kp;
float kp1;
float kp1h;
float kres;
float ay1 = 0.f;
float ay2 = 0.f;
float aout = 0.f;
float lastin = 0.f;
float value;
Copy link
Member

Choose a reason for hiding this comment

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

Same here

Comment on lines 172 to 175
static constexpr float DIST_RATIO = 4.f;
static constexpr fpp_t ENVINC = 64; //!< Envelope Recalculation period
static constexpr float vca_attack = 1.f - 0.96406088f; //!< Amp attack
static constexpr float vca_a0 = 0.5f; //!< Initial amplifier coefficient
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
static constexpr float DIST_RATIO = 4.f;
static constexpr fpp_t ENVINC = 64; //!< Envelope Recalculation period
static constexpr float vca_attack = 1.f - 0.96406088f; //!< Amp attack
static constexpr float vca_a0 = 0.5f; //!< Initial amplifier coefficient
static constexpr float s_distRatio = 4.f;
static constexpr fpp_t s_envInc = 64; //!< Envelope Recalculation period
static constexpr float s_vcaAttack = 1.f - 0.96406088f; //!< Amp attack
static constexpr float s_vcaA0 = 0.5f; //!< Initial amplifier coefficient

Following the conventions for private static data members.

The other data members in this class could also be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed static members in ac820f4, the rest still todo.

- #include <new> *before* testing macro defined within it (lol)
- Make #ifdef chain for hardware_destructive_interference_size more readable
- Use LMMS_HOST_* macros from lmmsconfig.h where possible
- Move #includes for busy_wait_hint() to top of file
- Make busy_wait_hint() a function rather than a macro
- Minor formatting changes
15 is the only allowed value, so that is used regardless of whatever is
passed in
@rubiefawn
Copy link
Contributor Author

rubiefawn commented Feb 4, 2026

Ugh, I just noticed a bug I must have introduced in this PR with slide behavior. Notes continue to slide even after the toggle is disabled, but the slide-from note is whatever the last note was before the toggle was disabled.

Edit: Bug introduced in 1b563ed, is fixed by 0fc7d88. Hooray for git bisect

- Restored a line that resets the slide-from note when a slide is done,
  the accidental removal of which was the cause of a weird bug
- Actually remove initSlide() and initNote() which were supposed to be
  fully inlined
- Remove redundant `db24Toggled()` calls on init and preset load
- Move filter envelope decay stuff that does not require `recalcFilter()`
  from `filterChanged()` into new slot `decayChanged()`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement needs code review A functional code review is currently required for this PR needs style review A style review is currently required for this PR needs testing This pull request needs more testing performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants