12 Commits

Author SHA1 Message Date
Fawn
5e3a67c9d1 Improve lmms::fastRand() and use it instead of std::rand() (#7741) 2026-01-15 17:12:04 -07:00
Fawn
bfa04c987d Centralize standard LMMS plugin logo (#8124)
* Centralize standard LMMS plugin logo

Previously, every single plugin would have its own copy of this image.
Now, these plugins pull it from the theme. I'm not sure it's valuable
for this to be themeable, but AFAIK it's the place all the other
non-plugin resources are stored, so that's where it goes for now.
2025-11-23 13:23:08 -05:00
cyberrumor
41093efcbe Revert "Fix PeakController attack/decay (#7566)" (#7871)
Prior to commit b5de1d50e, audible zipper artifacts were present when
using the PeakController on a bus to control the volume of another bus
for sidechain compression. The bus that had its volume reduced was the
one which produced audible artifacts.

Commit b5de1d50e introduced LERP to PeakController to smooth out its
signal, which eliminated the zipper artifacts. However, this had the
side effect of increased latency even when both attack and decay
settings were set to zero.

Until a more robust solution is implemented, reverting this change
eliminates the latency by eliminating the lerp, but reintroduces audible
zipper artifacts.
2025-05-02 11:04:47 -04:00
cyberrumor
b5de1d50e1 Fix PeakController attack/decay, use linear interpolation between samples (#7566)
Historically, the PeakController has had issues like attack/decay knobs
acting like on/off switches, and audio artifacts like buzzing or
clicking. This patch aims to address those issues.

The PeakController previously used lerp (linear interpolation) when
looping through the sample buffer, which was in updateValueBuffer. This
lerp utilized attack/decay values from control knobs. This is not the
correct place to utilize attack/decay because the only temporal data
available to the function is the frame and sample size. Therefore the
coefficient should simply be the sample rate instead.

Between each sample, processImpl would set m_lastSample to the RMS
without any sort of lerp. This resulted in m_lastSample producing
stair-like patterns over time, rather than a smooth line.

For context, m_lastSample is used to set the value of whatever is
connected to the PeakController. The basic lerp formula is:

m_lastSample = m_lastSample + ((1 - attack) * (RMS - m_lastSample))

This is useful because an attack of 0 sets m_lastSample to RMS, whereas
an attack of 1 would set m_lastSample to m_lastSample. This means our
attack/decay knobs can be used on a range from "snap to the next value
immediately" to "never stray from the last value".

* Remove attack/decay from PeakController frame lerp.
* Set frame lerp coefficient to 100.0 / sample_rate to fix buzzing.
* Add lerp between samples for PeakController to fix stairstep bug.
* The newly added lerp utilizes (1 - attack or decay) as the
  coefficient, which means the knobs actually do something now.
2024-10-28 15:01:08 -04:00
Dalton Messmer
18252088ba Refactor Effect processing (#7484)
* Move common effect processing code to wrapper method

- Introduce `processImpl` and `sleepImpl` methods, and adapt each effect
plugin to use them
- Use double for RMS out sum in Compressor and LOMM
- Run `checkGate` for GranularPitchShifterEffect
- Minor changes to LadspaEffect
- Remove dynamic allocations and VLAs from VstEffect's process method
- Some minor style/formatting fixes

* Fix VstEffect regression

* GranularPitchShifterEffect should not call `checkGate`

* Apply suggestions from code review

Co-authored-by: saker <sakertooth@gmail.com>

* Follow naming convention for local variables

* Add `MAXIMUM_BUFFER_SIZE` and use it in VstEffect

* Revert "GranularPitchShifterEffect should not call `checkGate`"

This reverts commit 67526f0ffe.

* VstEffect: Simplify setting "Don't Run" state

* Rename `sleepImpl` to `processBypassedImpl`

* Use `MAXIMUM_BUFFER_SIZE` in SetupDialog

* Pass `outSum` as out parameter; Fix LadspaEffect mutex

* Move outSum calculations to wrapper method

* Fix Linux build

* Oops

* Apply suggestions from code review

Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: saker <sakertooth@gmail.com>

---------

Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
2024-09-20 20:00:36 -04:00
Dominic Clark
851c884f58 Re-enable disabled GCC warnings where possible (#7379) 2024-07-21 22:34:34 +01:00
Michael Gregorius
286e62adf5 Simplify sample frame operations (make it a class) (#7156)
* Remove the struct StereoSample

Remove the struct `StereoSample`. Let `AudioEngine::getPeakValues` return a `sampleFrame` instead.

Adjust the calls in `Mixer`  and `Oscilloscope`.

* Simplify AudioEngine::getPeakValues

* Remove surroundSampleFrame

Some code assumes that `surroundSampleFrame` is interchangeable with `sampleFrame`. Thus, if the line `#define LMMS_DISABLE_SURROUND` is commented out in `lmms_basics.h` then the code does not compile anymore because `surroundSampleFrame` now is defined to be an array with four values instead of two. There also does not seem to be any support for surround sound (four channels instead of two) in the application. The faders and mixers do not seem to support more that two channels and the instruments and effects all expect a `sampleFrame`, i.e. stereo channels. It therefore makes sense to remove the "feature" because it also hinders the improvement of `sampleFrame`, e.g. by making it a class with some convenience methods that act on `sampleFrame` instances.

All occurrences of `surroundSampleFrame` are replaced with `sampleFrame`.

The version of `BufferManager::clear` that takes a `surroundSampleFrame` is removed completely.

The define `SURROUND_CHANNELS` is removed. All its occurrences are replaced with `DEFAULT_CHANNELS`.

Most of the audio devices classes, i.e. classes that inherit from `AudioDevice`, now clamp the configuration parameter between two values of `DEFAULT_CHANNELS`. This can be improved/streamlined later.

`BYTES_PER_SURROUND_FRAME` has been removed as it was not used anywhere anyway.

* Make sampleFrame a class

Make `sampleFrame` a class with several convenience methods. As a first step and demonstration adjust the follow methods to make use of the new functionality:
* `AudioEngine::getPeakValues`: Much more concise now.
* `lmms::MixHelpers::sanitize`: Better structure, better readable, less dereferencing and juggling with indices.
* `AddOp`, `AddMultipliedOp`, `multiply`: Make use of operators. Might become superfluous in the future.

* More operators and methods for sampleFrame

Add some more operators and methods to `sampleFrame`:
* Constructor which initializes both channels from a single sample value
* Assignment operator from a single sample value
* Addition/multiplication operators
* Scalar product

Adjust some more plugins to the new functionality of `sampleFrame`.

* Adjust DelayEffect to methods in sampleFrame

* Use composition instead of inheritance

Using inheritance was the quickest way to enable adding methods to `sampleFrame` without having to reimpement much of `std::array`s interface.

This is changed with this commit. The array is now a member of `sampleFrame` and the interface is extended with the necessary methods `data` and the index operator.

An `average` method was added so that no iterators need to be implemented (see changes in `SampleWaveform.cpp`).

* Apply suggestions from code review

Apply Veratil's suggestions from the code review

Co-authored-by: Kevin Zander <veratil@gmail.com>

* Fix warnings: zeroing non-trivial type

Fix several warnings of the following form:

Warnung: »void* memset(void*, int, size_t)« Säubern eines Objekts von nichttrivialem Typ »class lmms::sampleFrame«; use assignment or value-initialization instead [-Wclass-memaccess]

* Remove unnecessary reinterpret_casts

Remove some unnecessary reinterpret_casts with regards to `sampleFrame` buffers.

`PlayHandle::m_playHandleBuffer` already is a `sampleFrame*` and does not need a reinterpret_cast anymore.

In `LadspaEffect::processAudioBuffer` the `QVarLengthArray` is now directly initialized as an array of `sampleFrame` instances.

I guess in both places the `sampleFrame` previously was a `surroundSampleFrame` which has been removed.

* Clean up zeroSampleFrames code

* Fix warnings in RemotePlugin

Fix some warnings related to calls to `memcpy` in conjunction with`sampleFrame` which is now a class.

Add the helper functions `copyToSampleFrames` and `copyFromSampleFrames` and use them. The first function copies data from a `float` buffer into a `sampleFrame` buffer and the second copies vice versa.

* Rename "sampleFrame" to "SampleFrame"

Uppercase the name of `sampleFrame` so that it uses UpperCamelCase convention.

* Move SampleFrame into its own file

Move the class `SampleFrame` into its own class and remove it from `lmms_basics.h`.

Add forward includes to all headers where possible or include the `SampleFrame` header if it's not just referenced but used.

Add include to all cpp files where necessary.

It's a bit surprising that the `SampleFrame` header does not need to be included much more often in the implementation/cpp files. This is an indicator that it seems to be included via an include chain that at one point includes one of the headers where an include instead of a forward declaration had to be added in this commit.

* Return reference for += and *=

Return a reference for the compound assignment operators `+=` and `-=`.

* Explicit float constructor

Make the  constructor that takes a `float` explicit.

Remove the assignment operator that takes a `float`. Clients must use the
explicit `float` constructor and assign the result.

Adjust the code in "BitInvader" accordingly.

* Use std::fill in zeroSampleFrames

* Use zeroSampleFrames in sanitize

* Replace max with absMax

Replace `SampleFrame::max` with `SampleFrame::absMax`.

Use `absMax` in `DelayEffect::processAudioBuffer`. This should also fix
a buggy implementation of the peak computation.

Add the function `getAbsPeakValues`. It  computes the absolute peak
values for a buffer.

Remove `AudioEngine::getPeakValues`. It's not really the business of the
audio engine. Let `Mixer` and `Oscilloscope` use `getAbsPeakValues`.

* Replace scalarProduct

Replace the rather mathematical method `scalarProduct` with
`sumOfSquaredAmplitudes`. It was always called on itself anyway.

* Remove comment/TODO

* Simplify sanitize

Simplify the `sanitize` function by getting rid of the `bool found` and
by zeroing the buffer as soon as a problem is found.

* Put pointer symbols next to type

* Code review adjustments

* Remove "#pragme once"
* Adjust name of include guard
* Remove superfluous includes (leftovers from previous code changes)

---------

Co-authored-by: Kevin Zander <veratil@gmail.com>
2024-06-30 20:21:19 +02:00
Dominic Clark
f10277715f Classier enums (#6760) 2023-08-24 19:16:02 +01:00
saker
9a0add49fb Core Refactor: Replace `QVector with std::vector` (#6477)
* Replace QVector with std::vector in AudioEngine

* Replace QVector with std::vector in AudioEngineWorkerThread

* Replace QVector with std::vector in AudioJack

* Replace QVector with std::vector in AutomatableModel

* Replace QVector with std::vector in AutomationClip

* Replace QVector with std::vector in AutomationEditor

* Replace QVector with std::vector in ConfigManager

* Replace QVector with std::vector in Controller

* Replace QVector with std::vector in ControllerConnection

* Replace QVector with std::vector in EffectChain

* Replace QVector with std::vector in EnvelopeAndLfoParameters

* Replace QVector with std::vector in InstrumentFunctions

* Replace QVector with std::vector in MidiClient

* Replace QVector with std::vector in Mixer

* Replace QVector with std::vector in Note

* Replace QVector with std::vector in PeakController

* Replace QVector with std::vector in PianoRoll

* Replace QVector with std::vector in PluginFactory

* Replace QVector with std::vector in RenderManager

* Replace QVector with std::vector in StepRecorder

* Replace QVector with std::vector in Track

* Replace QVector with std::vector in TrackContainer

* Replace QVector with std::vector in Song

* Adapt QVector to std::vector changes in ControllerConnectionDialog

* Phase 2: Use std::abs in panning.h
Without this, the QVector changes will make the code not compile.

* Phase 2: Replace QVector with std::vector in PeakControllerEffect

* Phase 2: Replace QVector with std::vector in AutomatableModel

* Phase 2: Replace QVector with std::vector in AutomationClip

* Phase 2: Replace QVector with std::vector in ControllerConnection

* Phase 2: Replace QVector with std::vector in EffectChain

* Phase 2: Replace QVector with std::vector in Mixer

* Phase 2: Replace QVector with std::vector in PeakController

* Phase 2: Replace QVector with std::vector in RenderManager

* Phase 2: Replace QVector with std::vector in Song

* Phase 2: Replace QVector with std::vector in StepRecorder

* Phase 2: Replace QVector with std::vector in Track

* Phase 2: Replace QVector with std::vector in TrackContainer

* Phase 2: Adapt QVector changes in EffectRackView

* Phase 2: Adapt QVector changes in AutomationClipView

* Phase 2: Adapt QVector changes in ClipView

* Phase 2: Adapt QVector changes in AutomationEditor

* Phase 2: Adapt QVector changes in PianoRoll

* Phase 2: Adapt QVector changes in TrackContainerView

* Phase 2: Adapt QVector changes in TrackContentWidget

* Phase 2: Adapt QVector changes in InstrumentTrack

* Phase 2: Adapt QVector changes in MidiClip

* Phase 2: Adapt QVector changes in SampleTrack

* Fix segmentation fault in ConfigManager::value

* Fix unintended faulty std::vector insert in AutomationClip::resolveAllIDs

* Resolve trailing whitespace in src/core/StepRecorder.cpp

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Use std::next and std::prev in EffectChain::moveUp/moveDown

* Introduce static "combineAllTracks" function in AutomationClip

* Adjust variable name in Song::automatedValuesAt

* Adjust removal of long step notes in StepRecorder::removeNotesReleasedForTooLong

* Iterate over m_chords by const reference in src/core/InstrumentFunctions.cpp

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Fix StepRecorder::removeNotesReleasedForTooLong again

* Combine the ConfigManager::value overloads using std::optional

* Revise StepRecorder::removeNotesReleasedForTooLong

* Remove redundant std::optional in ConfigManager::value

* Remove trailing whitespace in ConfigManager::value

* Fix: Prevent incorrect use of std::distance when element not found

* Chore: Remove trailing whitespace in edited files

* Only set the id attribute if the controller was found

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Remove extra indents from 84b8fe8a559855ed263b74cc582eab3655250c5f

* Fix compilation issues

* Add LMMS_ prefix for header guard in Track.h

* Undo changes made to MixerView::deleteUnusedChannels

* Simplify code to handle failure of finding tracks
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Split ternary operator into separate if statement
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>

* Undo changes to indentation in MixerRoute

* Do general clean-up
Some of the changes made:
+ Use auto where benefical
+ Fix bug in AutomatableModel::globalAutomationValueAt (for loop should be looping over clips variable, not clipsInRange)
+ Undo out of focus whitespace changes

* Always assign to m_steps regardless if clip is found or not
Even when the clip is not found (i.e., currentClip is -1), m_steps still
gets assigned to.

* Insert at the end of tracks vector in src/core/Mixer.cpp

Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

* Insert at the end of tracks vector in src/core/Mixer.cpp (2)

Co-authored-by: Dominic Clark <mrdomclark@gmail.com>

* Remove redundant template parameter

* Use std::array for zoomLevels

---------

Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
2023-08-22 12:08:56 +09:00
Dominic Clark
96df9b006c Clean up macros a bit (#6444)
* Prefix `STRINGIFY` and `STR` macros with `LMMS_`

* Fix include guard macro names

* Remove unused macros
2022-06-23 12:20:05 +01:00
Levin Oehlmann
7227c89847 Namespace lmms (#6174)
This PR places all LMMS symbols into namespaces to eliminate any potential future name collisions between LMMS and third-party modules.

Also, this PR changes back `LmmsCore` to `Engine`, reverting c519921306 .

Co-authored-by: allejok96 <allejok96@gmail.com>
2022-06-19 20:08:46 +02:00
Johannes Lorenz
f6bad88ad3 Fix casing of filenames and code in plugins/ (#6350)
No functional changes! No changes to savefiles/presets!

Fixes casing of everything that is currently lowercase but should
be uppercase.

Fixes also some other plugin strings, especially:

* opl2 -> OpulenZ (see 289887f4fc)
* calf -> veal (see ae291e0709)
* ladspa_effect -> LadspaEffect (see 9c9372f0c8)
* remove flp_import (see 2d1813fb64)
2022-04-03 13:26:12 +02:00