* Render fader levels in code with a gradient
Render the fader level in code using a gradient instead of using pixmaps. The problem with the pixmaps is that they don't "know" how a fader instance is configured with regards to the minimum and maximum value. This means that the display can give quite a wrong impression.
The rendering of levels has been unified in the method `paintLevels`. It can render using dbFS and linear scale. The method `paintLinearLevels` has been removed completely, i.e. there's no more code that renders using pixmaps.
Much of the previous code relied on the size of the background image `fader_background.png`, e.g. the initialization of the size. For now the `Fader` widget is initially resized to the size of that background image as it is present in the default and classic theme (see `Fader::init`). All rendering uses the size of the widget itself to determine where to draw what. This means that the widget is prepared to be resizable.
The method `paintLevels` first renders the background of the level indicators and uses these as clipping paths for all other rendering operations, e.g. for the rendering of the levels themselves. Levels are rendered using a gradient which is defined with the following stops:
* Two stops for the ok levels.
* One stop for warning levels.
* One stop for clipping levels.
Peak indicators do not use the three distinct colors anymore but instead use the color of the gradient at that position of the peak. This makes everything look "smooth".
The code now also renders a marker at unity position, i.e. at position 1.0 in linear levels and 0 dbFS in dbFS scale.
The painting code makes lots of use of the class `PaintHelper`. This class is configured with a minimum and maximum value and can then return linear factors for given values. There are two supported modes:
* Map min to 0 and max to 1
* Map min to 1 and max to 0
It can also compute rectangles that correspond to a given value. These methods can be given rectangles that are supposed to represent the span from min to max. The returned result is then a rectangle that fills the lower part of the source rectangle according to the given value with regards to min and max (`getMeterRect`). Another method returns a rectangle of height 1 which lies inside the given source rectangle at the corresponding level (`getPersistentPeakRect`).
The method `paintLevels` uses a mapping function to map the amplitude values (current peak value, persistent peak, etc.) to the display values. There's one mapper that keeps the original value and it is used to display everything in a linear scale. Another mapper maps everything to dbFS and uses these values as display everything in a dbFS scale. The following values must be mapped for the left and right channel to make this work:
* Min and max display values (min and max peak values)
* The current peak value
* The persistent peak value
* The value for unity, i.e. 1.0 in linear levels and 0 dbFS in dbFS scale.
Remove the method `calculateDisplayPeak` which was used in the old method to render linear levels.
`Fader::setPeak` now uses `std::clamp` instead of doing "manual" comparisons.
The LMMS plugins Compressor, EQ and Delay are still configured to use linear displays. It should be considered to switch them to dbFS/logarithmic displays as well and to remove the code that renders linearly.
* Remove unused pixmaps from `Fader`
Remove the now unused pixmaps for the background and the LEDs from the `Fader` class and remove the files from the default and classic theme directories.
* Rename peak properties and use them to render levels
Rename the peak properties as follows:
* peakGreen -> peakOk
* peakRed -> peakClip
* peakYellow -> peakWarn
The reasoning is that a style might for example use a different color than green to indicate levels that are ok.
Use the properties to initialize the gradient that is used to render the levels.
Initialize the properties to the colors of the current default theme so that it's not mandatory to set them in a style sheet. Up until now they have all been initialized as black.
* Always render the knob in the middle of the fader
Render the knob in the middle of the fader regardless of the width. The previous implementation was dependent on the fader pixmap having a matching width because it always rendered at x=0.
* Set size policy of fader to minimum expanding
Set the size policy of the fader to minimum expanding in both directions. This will make the fader grow in layouts if there is space.
* Default dbFS levels and better peak values
Default to dbFS levels for all faders and set some better minimum and maximum peak values.
* Fix faders of Crossover EQ
Fix the faders of the Crossover EQ which were initialized and rendered much too wide and with a line at unity. The large width also resulted in the knobs being rendered outside of view.
Resize the fader to the minimum size so that it is constructed at a sane default.
Introduce a property that allows to control if the unity line is rendered. The property is available in style sheets and defaults to the unity lines being rendered. Adjust the paint code to evaluate the property.
Initialize the faders of the Crossover EQ such that the unity line is not drawn.
* Remove EqFader constructor with pixmaps
Remove the constructor of `EqFader` that takes the pixmaps to the fader background, leds and knob. The background and leds pixmaps are not used by the base class `Fader` for rendering anymore to make the `Fader` resizable. A pixmap is still used to render the knob but the constructor that takes the knob as an argument does not do anything meaningful with it, i.e. all faders are rendered with the default knob anyway.
Remove the resources for the fader background, leds and knob as they are not used and the knob was the same image as the default knob anyway.
Remove the static pixmaps from the constructor of `EqControlsDialog`. Switch the instantiations of the EQ's faders to use the remaining constructor of `EqFader`. This constructor sets a different fixed size of (23, 116) compared to the removed constructor which set a size of (23, 80). Therefore all faders that used the removed constructor are now set explicitly to a fixed size of (23, 80).
The constructor that's now used also calls a different base constructor than the removed one. The difference between the two base constructors of `Fader` is that one of them sets the member `m_conversionFactor` to 100.0 whereas the other one keeps the default of 1.0. The adjusted faders in `EqControlsDialog` are thus now constructed with the conversion factor set to 100. However, all of them already call `setDisplayConversion` with `false` after construction which results in the conversion factor being reset to 1.0. So the result should be the same as before the changes.
* Remove background and LEDs pixmap from Fader constructor
Remove the parameters for the background and LEDs pixmap from the second `Fader` constructor. Make the knob pixmap parameter in the constructor a const reference. Assign the reference to the knob pixmap of the `Fader` itself. This enables clients to use their own fader knobs as is the case with the Crossover EQ. The EQ now renders using it's own knobs again.
Make the second constructor delegate to the first one. This will additionally set the conversion factor to 100 but this is not a problem with the current code because the only user of the second constructor, the Crossover EQ, already calls `setDisplayConversion` with the parameter set to `false`, hence reinstating a conversion factor of 1.
Remove the resources for the background and LEDs from the Crossover EQ as they are not used anymore. Remove the three QPixmap members from `CrossoverEQControlDialog` as they are not needed. The background and LEDs are not used anyway and the knob is passed in as a constant reference which is copied. Hence we can use a local variable in the constructor of `CrossoverEQControlDialog`.
* Remove the init method from Fader
Remove the `init` method from `Fader` as it is not needed anymore due to the constructor delegation. Tidy up the parameter lists and use of spaces in the constructor.
* Introduce range with solid warn color
Introduce a second point in the gradient for the warn colors so that we get a certain range with the full/solid warn color.
The colors are distributed as follows now. The solid ok range goes from -inf dbFS to -12 dbFS. The warn range goes from -6 dbFS to 0 dbFS. In between the colors are interpolated. Values above 0 dbFS interpolate from the warn color to the clip color.
This is now quite similar to the previous implementation.
# Analysis of the previous pixmap implementation
The pixmap implementation used pixmaps with a height of 116 pixels to map 51 dbFS (-42 dbFS to 9 dbFS) across the whole height. The pixels of the LED pixmap were distributed as follows along the Y-axis:
* Margin: 4
* Red: 18
* Yellow: 14
* Green: 76
* Margin: 4
Due to the margins the actual red, yellow and green areas only represent a range of (1 - (4+4) / 116) * 51 ~ 47,48 dbFS. This range is distributed as follows across the colors:
Red: 7.91 dbFS
Yellow: 6.16 dbFS
Green: 33.41 dbFS
The borders between the colors are located along the following dbFS values:
* Red/yellow: 9 - (4 + 18) / 116 * 51 dbFS ~ -0.67 dbFS
* Yellow/green: 9 - (4 + 18 + 14) / 116 * 51 dbFS ~ -6.83 dbFS
* The green marker is rendered for values above -40.24 dbFS.
* Remove unused method Fader::clips
* Fader: Correctly render arbitrary ranges
Adjust the `Fader` so that it can correctly render arbitrary ranges of min and max peak values, e.g. that it would render a display range of [-12 dbFS, -42 dbFS] correctly.
Until now the gradient was defined to start at the top of the levels rectangle and end at the bottom. As a result the top was always rendered in the "clip" color and the bottom in the "ok" color. However, this is wrong, e.g. if we configure the `Fader` with a max value of -12 dbFS and a min value of -42 dbFS. In that case the whole range of the fader should be rendered with the "ok" color.
The fix is to compute the correct window coordinates of the start and end point of gradient using from the "window" of values that the `Fader` displays and then to map the in-between colors accordingly. See the added comments in the code for more details.
Add the templated helper class `LinearMap` to `lmms_math.h`. The class defines a linear function/map which is initialized using two points. With the `map` function it is then possible to evaluate arbitrary X-coordinates.
* Remove unused methods in PaintHelper
Remove the now unused mapping methods from `PaintHelper`. Their functionality has been replaced with the usage of `LinearMap` in the code.
* Fix some builds
Include `cassert` for some builds that otherwise fail.
* Opaque unity marker with styling option
Make the unity marker opaque by default and enable to style it with the style sheets. None of the two style sheets uses this option though.
* Darker default color for the unity line
* Move code
Move the computation of most mapped values at the top right after the definition of the mapper so that it is readily available in all phases of the painting code.
* Render unity lines in background
Render the unity lines before rendering the levels so that they get overdrawn and do not stick out when they are crossed.
* Don't draw transparent white lines anymore
Don't draw the transparent white lines anymore as they were mostly clipped anyway and only create "smudge".
* Full on clip color at unity
Adjust the gradient so that the full on clip color shows starting at unity. There is only a very short transition from the end of warning to clipping making it look like a solid color "standing" on top of a gradient.
* Fix discrepancy between levels and unity markers
This commit removes the helper class `PaintHelper` and now uses two lambdas to compute the rectangles for the peak indicators and levels. It uses the linear map which maps the peak values (in dbFS or linear) to window coordinates of the widget.
The change fixes a discrepancy in the following implementation for which the full on clip rectangle rendered slightly below the unity marker.
* Fix fader display for Equalizer shelves and peaks
The peak values for the shelves and peaks of the Equalizer plugin are computed in `EqEffect::peakBand`. The previous implementation evaluated the bins of the corresponding frequency spectrum and determined the "loudest" one. The value of this bin was then converted to dbFS and mapped to the interval [0, inf[ where all values less or equal to -60 dbFS were mapped to 0 and a value of 40 dbFS was mapped to 1. So effectively everything was mapped somewhere into [0, 1] yet in a quite "distorted" way because a signal of 40 dbFS resulted in being displayed as unity in the fader.
This commit directly returns the value of the maximum bin, i.e. it does not map first to dbFS and then linearize the result anymore. This should work because the `Fader` class assumes a "linear" input signal and if the value of the bin was previously mapped to dbFS it should have some "linear" character. Please note that this is still somewhat of a "proxy" value because ideally the summed amplitude of all relevant bins in the frequency range would be shown and not just the "loudest" one.
## Other changes
Rename `peakBand` to `linearPeakBand` to make more clear that a linear value is returned.
Handle a potential division by zero by checking the value of `fft->getEnergy()` before using it.
Index into `fft->m_bands` so that no parallel incrementing of the pointer is needed. This also enables the removal of the local variable `b`.
* Improve the rendering of the levels
The levels rendering now more explicitly distinguished between the rendering of the level outline/border and the level meters. The level rectangles are "inset" with regards to the borders so that there is a margin between the level borders and the meter readings. This margin is now also applied to the top and bottom of the levels. Levels are now also rendered as rounded rectangles similar to the level borders.
Only render the levels and peaks if their values are greater than the minimum level.
Make the radius of the rounded rectangles more pronounced by increasing its value from 1 to 2.
Decrease the margins so that the level readings become wider, i.e. so that they are rendered with more pixels.
Add the lambda `computeLevelMarkerRect` so that the rendering of the level markers is more decoupled from the rendering of the peak markers.
* Reduce code repetition
Reduce code repetition in `EqEffect::setBandPeaks` by introducing a lambda. Adjust code formatting.
* Code review changes
Code review changes in `Fader.cpp`. Mostly whitespace adjustments.
Split up the calculation of the meter width to make it more understandable. This also reduces the number of parentheses.
* Use MEMBER instead of READ/WRITE
Use `MEMBER` instead of `READ`/`WRITE` for some properties that are not called explicitly from outside of the class.
* Use default member initializers for Fader
Use default member initializers for the members in `Fader` that have previously been initialized in the constructor list.
* Make code clearer
Make code clearer in `Fader::FadermouseDoubleClickEvent`. Only divide if the dialog was accepted with OK.
Adjust and rename the function `pointSize` so that it sets the font size in pixels. Rename `pointSize` to `adjustedToPixelSize` because that's what it does now. It returns a font adjusted to a given pixel size. Rename `fontPointer` to `font` because it's not a pointer but a copy. Rename `fontSize` to simply `size`.
This works if the intended model is that users use global fractional scaling. In that case pixel sized fonts are also scaled so that they should stay legible for different screen sizes and pixel densities.
## Adjust plugins with regards to adjustedToPixelSize
Adjust the plugins with regards to the use of `adjustedToPixelSize`.
Remove the explicit setting of the font size of combo boxes in the following places to make the combo boxes consistent:
* `AudioFileProcessorView.cpp`
* `DualFilterControlDialog.cpp`
* `Monstro.cpp` (does not even seem to use text)
* `Mallets.cpp`
Remove calls to `adjustedToPixelSize` in the following places because they can deal with different font sizes:
* `LadspaBrowser.cpp`
Set an explicit point sized font size for the "Show GUI" button in `ZynAddSubFx.cpp`
Increase the font size of the buttons in the Vestige plugin and reduce code repetition by introducing a single variable for the font size.
I was not able to find out where the font in `VstEffectControlDialog.cpp` is shown. So it is left as is for now.
## Adjust the font sizes in the area of GUI editors and instruments.
Increase the font size to 10 pixels in the following places:
* Effect view: "Controls" button and the display of the effect name at the bottom
* Automation editor: Min and max value display to the left of the editor
* InstrumentFunctionViews: Labels "Chord:", "Direction:" and "Mode:"
* InstrumentMidiIOView: Message display "Specify the velocity normalization base for MIDI-based instruments at 100% note velocity."
* InstrumentSoundShapingView: Message display "Envelopes, LFOs and filters are not supported by the current instrument."
* InstrumentTuningView: Message display "Enables the use of global transposition"
Increase the font size to 12 pixels in the mixer channel view, i.e. the display of the channel name.
Render messages in system font size in the following areas because there should be enough space for almost all sizes:
* Automation editor: Message display "Please open an automation clip by double-clicking on it!"
* Piano roll: Message display "Please open a clip by double-clicking on it!"
Use the application font for the line edit that can be used to change the instrument name.
Remove overrides which explicitly set the font size for LED check boxes in:
* EnvelopeAndLfoView: Labels "FREQ x 100" and "MODULATE ENV AMOUNT"
Remove overrides which explicitly set the font size for combo boxes in:
* InstrumentSoundShapingView: Filter combo box
## Adjust font sizes in widgets
Adjust the font sizes in the area of the custom GUI widgets.
Increase and unify the pixel font size to 10 pixels in the following classes:
* `ComboBox`
* `GroupBox`
* `Knob`
* `LcdFloatSpinBox`
* `LcdWidget`
* `LedCheckBox`
* `Oscilloscope`: Display of "Click to enable"
* `TabWidget`
Shorten the text in `EnvelopeAndLfoView` from "MODULATE ENV AMOUNT" to "MOD ENV AMOUNT" to make it fit with the new font size of `LedCheckBox`.
Remove the setting of the font size in pixels from `MeterDialog` because it's displayed in a layout and can accommodate all font sizes. Note: the dialog can be triggered from a LADSPA plugin with tempo sync, e.g. "Allpass delay line". Right click on the time parameter and select "Tempo Sync > Custom..." from the context menu.
Remove the setting of the font size in `TabBar` as none of the added `TabButton` instances displays text in the first place.
Remove the setting of the font size in `TabWidget::addTab` because the font size is already set in the constructor. It would be an unexpected size effect of setting a tab anyway. Remove a duplicate call to setting the font size in `TabWidget::paintEvent`.
Remove unnecessary includes of `gui_templates.h` wherever this is possible now.
## Direct use of setPixelSize
Directly use `setPixelSize` when drawing the "Note Velocity" and "Note Panning" strings as they will likely never be drawn using point sizes.
* clang-tidy: Apply cppcoreguidelines-init-variables everywhere (treating NaNs as zeros)
* Initialize msec and tick outside switch
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Use initialization with =
* Use tabs
* Use static_cast
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Do not use tabs for alignment in src/core/DrumSynth.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Move x variable inside loop
* Use ternary operator for b variable
* Revert "Use tabs"
This reverts commit 07afd8a83f58b539c3673310b2aad4b63c9198a0.
* Remove unnecessary variables in XpressiveView
* Simplify initialization in Plugin
* Combine declaration and initialization in EqCurve
* Combine declaration and initialization in Song
* Combine declaration and initialization in AudioAlsa
* Combine declaration and initialization in EqCurve (again)
* Missed some
* Undo changes made to non-LMMS files
* Undo indentation changes in SidInstrument.cpp
* Combine declaration with assignment in IoHelper
* Combine declaration with assignment using auto in Carla
* Combine declaration with assignment
* Combine declaration with assignment in BasicFilters
* Simplify assignments in AudioFileProcessorWaveView::zoom
* Simplify out sample variable in BitInvader
* Remove sampleLength variable in DelayEffect
* Move gain variable in DynamicsProcessor
* Combine peak variable declaration with assignment in EqSpectrumView
* Move left/right lfo variables in for loop in FlangerEffect
* Use ternary operator for group variable in LadspaControlDialog
* Combine declaration with assignment in Lb302
* Combine declaration with assignment in MidiExport
* Combine declaration with assignment in MidiFile
* Combine declaration with assignment in MidiImport
* Use ternary operator for vel_adjusted variable in OpulenZ
* Move tmpL and dcblkL variables in for loop in ReverbSC
* Combine declaration with initialization in SlicerT
* Combine declaration with assignment in SaSpectrumView
* Combine declaration with assignment in SaWaterfallView
* Combine declaration with assignment in StereoEnhancerEffect
* Combine declaration with assignment in VibratingString
* Combine declaration with assignment in VstEffectControls
* Combine declaration with assignment in Xpressive
* Combine declaration with assignment in AutomatableModel
* Combine declaration with assignment in AutomationClip
* Move sample variable in for loop in BandLimitedWave
* Combine declaration with assignment in DataFile
* Combine declaration with assignment in DrumSynth
* Combine declaration with assignment in Effect
* Remove redundant assignment to nphsLeft in InstrumentPlayHandle
* Combine declaration with assignment in LadspaManager
* Combine declaration with assignment in LinkedModelGroups
* Combine declaration with assignment in MemoryHelper
* Combine declaration with assignment in AudioAlsa
* Combine declaration with assignment in AudioFileOgg
* Combine declaration with assignment in AudioPortAudio
* Combine declaration with assignment in AudioSoundIo
* Combine declaration with assignment in Lv2Evbuf
* Combine declaration with assignment in Lv2Proc
* Combine declaration with assignment in main
* Combine declaration with assignment in MidiAlsaRaw
* Combine declaration with assignment in MidiAlsaSeq
* Combine declaration with assignment in MidiController
* Combine declaration with assignment in MidiJack
* Combine declaration with assignment in MidiSndio
* Combine declaration with assignment in ControlLayout
* Combine declaration with assignment in MainWindow
* Combine declaration with assignment in ProjectNotes
* Use ternary operator for nextValue variable in AutomationClipView
* Combine declaration with assignment in AutomationEditor
* Move length variable in for-loop in PianoRoll
* Combine declaration with assignment in ControllerConnectionDialog
* Combine declaration with assignment in Graph
* Combine declaration with assignment in LcdFloatSpinBox
* Combine declaration with assignment in TimeDisplayWidget
* Remove currentNote variable in InstrumentTrack
* Combine declaration with assignment in DrumSynth (again)
* Use ternary operator for factor variable in BitInvader
* Use ternary operator for highestBandwich variable in EqCurve
Bandwich?
* Move sum variable into for loop in Graph
* Fix format in MidiSndio
* Fixup a few more
* Cleanup error variables
* Use ternary operators and combine declaration with initialization
* Combine declaration with initialization
* Update plugins/LadspaEffect/LadspaControlDialog.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/OpulenZ/OpulenZ.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/SpectrumAnalyzer/SaProcessor.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/midi/MidiAlsaRaw.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/MainWindow.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/clips/AutomationClipView.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/editors/AutomationEditor.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/widgets/Fader.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Move static_cast conversion into separate variable
* Use real index when interpolating
* Remove empty line
* Make helpBtn a private member
* Move controller type into separate variable
* Fix format of DrumSynth::waveform function
* Use tabs and static_cast
* Remove redundant if branch
* Refactor using static_cast/reinterpret_cast
* Add std namespace prefix
* Store repeated conditional into boolean variable
* Cast to int before assigning to m_currentLength
* Rename note_frames to noteFrames
* Update src/core/Controller.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/widgets/Graph.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Revert changes that initialized variables redudantly
For situations where the initialization is
more complex or passed into a function
by a pointer, we dont need to do
initialization ourselves since it is
already done for us, just in a different way.
* Remove redundant err variable
* Remove explicit check of err variable
* Clean up changes and address review
* Do not initialize to 0/nullptr when not needed
* Wrap condition in parentheses for readability
---------
Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* remove the gui_templates header where functions not used
* refactor and replace template with function argument
* refactor: merge pointSizeF function with pointSize
* removed template per michael's review
* use std::max for more readability
* remove the QDesktopWidget header
* cleanup arguments and remove parentheses from return
* replace QRegExp with QRegularExpression (find n replace)
* follow up to fix errors
* removed rpmalloc
* Fix compilation for qt5, to be fixed when qt6 fully supported.
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Added QtGlobal header for version finding fix
* Use the other syntax to try fix compilation.
* Check for 5.12 instead.
* Fix the header
* Attempt at fixing it further.
* Use version checks properly in header file
* Use QT_VERSION_CHECK macro in sources
* Apply suggestions from messmerd's review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
---------
Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Fix several NaNs in the context of the basic filters and the Equalizer.
The coefficients of the `BiQuad` were not initialized which seems to have led to NaNs down the line.
Fix a division by zero in `EqEffect::peakBand` and `EqSpectrumView::paintEvent` if the energy is zero.
The condition `m_peakSum <= 0` was removed from `EqSpectrumView::paintEvent` because the value is initialized to 0 down the line and later only potentially positive values are added.
Removes `MemoryManager` and the use of rpmalloc in favor of the `new` and `delete` operators found in C++.
---------
Co-authored-by: Veratil <veratil@gmail.com>
* Fix crash in Audio File Processor
Fix a crash in the Audio File Processor that occurs when an Audio File Processor with a reversed sample is loaded from a save file and then the plugin window is opened.
The problem was caused by a call to `AudioFileProcessorWaveView::slideSampleByFrames` during the execution of constructor of `AudioFileProcessorWaveView`. In that situation the three `knob` members were all `nullptr` because for some reason there was an explicit setter for them which was only called after construction. This is fixed by passing and setting the knobs in the constructor.
Another question is if it's not a problem in the first place that the knobs are given to the `AudioFileProcessorWaveView` instead of their underlying models.
On plugin instantiation failure, `Lv2Proc::m_valid` was being set to false. However, `Lv2Proc::run` did not evaluate `m_valid` and still called `lilv_instance_run`, which caused undefined behavior, including crashes.
This bug fixes this by not even create such zombie classes, and instead `throw`s right away. The throws are caught in `lmms_plugin_main`, as suggested in the PR discussion and as the VST3 approach.
* Add private setters for "from" and "to"
Add private setters for the "from" and "to" values in `AudioFileProcessorWaveView`. When being used the setters will ensure that the bounds are respected.
Also add a `range` method because this computation was done repeatedly throughout the code.
Fixes#7068 but masks some of the original problems with the code that computes out-of-bounds values for "from" and "to" like the `slide` method. Problematic code can still be found by temporarily adding the following assertions to the setters:
* `assert (to <= m_sample->sampleSize());` in `setTo`
* `assert (from >= 0);` in `setFrom`
* Remove superfluous calls to qMax and qMin
## Extract views
Extract the classes `AudioFileProcessorWaveView` and `AudioFileProcessorView` into their own files.
Reformat the new classes by removing unnecessary whitespace and underscores. Add spaces to if-statements.
Cleanup the includes.
## Remove friend relationship
Remove the friend relationship between `AudioFileProcessor` and `AudioFileProcessorView`.
Introduce getters for entities that the view is interested in.
* Handle divisions by 0 in Lb302
Handle potential division by 0 which in turn lead to floating point exceptions in Lb302. The division can occur in the `process` method if it is called with the member `vco_inc` still initialized to 0. This seems to happen then the Lb302 processes with no notes actually being played.
The offending call is `BandLimitedWave::pdToLen(vco_inc)` which is now prevented when the increment is 0. In the latter case a sample of 0 is produced. This works because in all other cases the Lb302 instance should process a note which in turn sets the increments to something different from 0.
* Fix FPEs in Monstro
Fix some floating point exceptions in `MonstroSynth::renderOutput` that occurred due to calling `BandLimitedWave::pdToLen` with a value of 0. This happened when one of the phase deltas was set to 0, i.e. `pd_l` or `pd_r`. These cases are now checked and produce silence in the corresponding components if the phase delta is set to 0.
* Fix uninitialized variables
Initialize the local variables `len_l` and `len_r` to 0. This fixes compiler warnings a la "error: 'len_r' may be used uninitialized in this function" which are treated as errors on the build server.
* Adjust whitespace of touched code
Fix the peak update of the LMMS equalizer which accidentally used the same sample twice.
Simplify the `gain` method by removing repeated deferences which made the code hard to read.
Use `std::max` to update the peak values to the maximum of the buffer.
Remove the code which computes a minimum height for the LADSPA dialogs. It was intended to make sure that no scrollbar is shown in most cases. However, doing so came at the cost that the computed height was the minimum height as well. Therefore the dialogs took a lot of space on low-res displays and could not be made smaller.
After the removal the behavior is still sane. Small dialogs are shown in full and dialogs which are larger, e.g. "Calf Equalizer 12 Band LADSPA", seem to be sized around half the height of the workspace and show scrollbars.
* Add refactored SampleBuffer
* Add Sample
* Add SampleLoader
* Integrate changes into AudioSampleRecorder
* Integrate changes into Oscillator
* Integrate changes into SampleClip/SamplePlayHandle
* Integrate changes into Graph
* Remove SampleBuffer include from SampleClipView
* Integrate changes into Patman
* Reduce indirection to sample buffer from Sample
* Integrate changes into AudioFileProcessor
* Remove old SampleBuffer
* Include memory header in TripleOscillator
* Include memory header in Oscillator
* Use atomic_load within SampleClip::sample
* Include memory header in EnvelopeAndLfoParameters
* Use std::atomic_load for most calls to Oscillator::userWaveSample
* Revert accidental change on SamplePlayHandle L.111
* Check if audio file is empty before loading
* Add asserts to Sample
* Add cassert include within Sample
* Adjust assert expressions in Sample
* Remove use of shared ownership for Sample
Sample does not need to be wrapped around a std::shared_ptr.
This was to work with the audio thread, but the audio thread
can instead have their own Sample separate from the UI's Sample,
so changes to the UI's Sample would not leave the audio worker thread
using freed data if it had pointed to it.
* Use ArrayVector in Sample
* Enforce std::atomic_load for users of std::shared_ptr<const SampleBuffer>
* Use requestChangesGuard in ClipView::remove
Fixes data race when deleting SampleClip
* Revert only formatting changes
* Update ClipView::remove comment
* Revert "Remove use of shared ownership for Sample"
This reverts commit 1d452331d1.
In some cases, you can infact do away with shared ownership
on Sample if there are no writes being made to either of them,
but to make sure changes are reflected to the object in cases
where writes do happen, they should work with the same one.
* Fix heap-use-after-free in Track::loadSettings
* Remove m_buffer asserts
* Refactor play functionality (again)
The responsibility of resampling the buffer
and moving the frame index is now in Sample::play, allowing the removal
of both playSampleRangeLoop and playSampleRangePingPong.
* Change copyright
* Cast processingSampleRate to float
Fixes division by zero error
* Update include/SampleLoader.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update include/SampleLoader.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Format SampleLoader.h
* Remove SampleBuffer.h include in SampleRecordHandle.h
* Update src/core/Oscillator.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Use typeInfo<float> for float equality comparison
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Use std::min in Sample::visualize
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Move in result to m_data
* Use if block in playSampleRange
* Pass in unique_ptr to SampleClip::setSampleBuffer
* Return const QString& from SampleBuffer::audioFile
* Do not pass in unique_ptr by r-value reference
* Use isEmpty() within SampleClipView::updateSample
* Remove use of atomic_store and atomic_load
* Remove ArrayVector comment
* Use array specialization for unique_ptr when managing DrumSynth data
Also made it so that we don't create result
before checking if we failed to decode the file,
potentially saving us an allocation.
* Don't manually delete Clip if it has a Track
* Clean up generateAntiAliasUserWaveTable function
Also, make it so that we actually call this function
when necessary in TripleOscillator.
* Set user wave, even when value is empty
If the value or file is empty, I think showing a
error popup here is ideal.
* Remove whitespace in EnvelopeAndLfoParameters.cpp L#121
* Fix error in c5f7ccba49
We still have to delete the Clip's, or else we would just be eating
up memory. But we should first make sure that the Track's no longer
see this Clip in their m_clips vector. This has to happen
as it's own operation because we have to wait for the audio thread(s)
first. This would ensure that Track's do not create
PlayHandle's that would refer to a Clip that is currently
being destroyed. After that, then we call deleteLater on the Clip.
* Convert std::shared_ptr<Sample> to Sample
This conversion does not apply to Patman as there seems to be issues
with it causing heap-use-after-free issues, such as with
PatmanInstrument::unloadCurrentPatch
* Fix segfault when closing LMMS
Song should be deleted before AudioEngine.
* Construct buffer through SampleLoader in FileBrowser's previewFileItem function
+ Remove const qualification in SamplePlayHandle(const QString&)
constructor for m_sample
* Move guard out of removeClip and deleteClips
+ Revert commit 1769ed517d since
this would fix it anyway
(we don't try to lock the engine to
delete the global automation track when closing LMMS now)
* Simplify the switch in play function for loopMode
* Add SampleDecoder
* Add LMMS_HAVE_OGGVORBIS comment
* Fix unused variable error
* Include unordered_map
* Simplify SampleDecoder
Instead of using the extension (which could be wrong) for the file,
we simply loop through all the decoders available. First sndfile because
it covers a lot of formats, then the ogg decoder for the few cases where sndfile
would not work for certain audio codecs, and then the DrumSynth decoder.
* Attempt to fix Mac builds
* Attempt to fix Mac builds take 2
* Add vector include to SampleDecoder
* Add TODO comment about shared ownership with clips
Calls to ClipView::remove may occur at any point, which can cause
a problem when the Track is using the clip about to be removed.
A suitable solution would be to use shared ownership between the Track
and ClipView for the clip. Track's can then simply remove the shared
pointer in their m_clips vector, and ClipView can call reset on the
shared pointer on calls to ClipView::remove.
* Adjust TODO comment
Disregard the shared ownership idea. Since we would be modifying
the collection of Clip's in Track when removing the Clip, the Track
could be iterating said collection while this happens,
causing a bug. In this case, we do actually
want a synchronization mechanism.
However, I didn't mention another separate issue in the TODO comment
that should've been addressed: ~Clip should not be responsible for
actually removing the itself from it's Track. With calls to removeClip,
one would expect that to already occur.
* Remove Sample::playbackSize
Inside SampleClip::sampleLength, we should be using Sample::sampleSize
instead.
* Fix issues involving length of Sample's
SampleClip::sampleLength should be passing the Sample's sample rate to
Engine::framesPerTick.
I also changed sampleDuration to return a std::chrono::milliseconds
instead of an int so that the callers know what time interval
is being used.
* Simplify if condition in src/gui/FileBrowser.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Simplify if condition in src/core/SampleBuffer.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update style in include/Oscillator.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Format src/core/SampleDecoder.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Set the sample rate to be that of the AudioEngine by default
I also removed some checks involving the state of the SampleBuffer.
These functions should expect a valid SampleBuffer each time.
This helps to simplify things since we don't have to validate it
in each function.
* Set single-argument constructors in Sample and SampleBuffer to be explicit
* Do not make a copy when reading result from the decoder
* Add constructor to pass in vector of sampleFrame's directly
* Do a pass by value and move in SampleBuffer.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Pass vector by value in SampleBuffer.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Make Sample(std::shared_ptr) constructor explicit
* Properly draw sample waveform when reversed
* Collect sample not found errors when loading project
Also return empty buffers when trying to load
either an empty file or empty Base64 string
* Use std::make_unique<SampleBuffer> in SampleLoader
* Fix loop modes
* Limit sample duration to [start, end] and not the entire buffer
* Use structured binding to access buffer
* Check if GUI exists before displaying error
* Make Base64 constructor pass in the string instead
* Remove use of QByteArray::fromBase64Encoding
* Inline simple functions in SampleBuffer
* Dynamically include supported audio file types
* Remove redundant inline specifier
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Translate file types
* Cache calls to SampleDecoder::supportedAudioTypes
* Fix translations in SampleLoader (again)
Also ensure that all the file types are listed first.
Also simplified the generation of the list a bit.
* Store static local variable for supported audio types instead of in the header
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Clamp frame index depending on loop mode
* Inline member functions of PlaybackState
* Do not collect errors in SampleLoader when loading projects
Also fix conflicts with surrounding codebase
* Default construct shared pointers to SampleBuffer
* Simplify and optimize Sample::visulaize()
* Remove redundant gui:: prefix
* Rearrange Sample::visualize after optimizations by DanielKauss
* Apply amplification when visualizing sample waveforms
* Set default min and max values to 1 and -1
* Treat waveform as mono signal when visualizing
* Ensure visualization works when framesPerPixel < 1
* Simplify Sample::visualize a bit more
* Fix CPU lag in Sample by using atomics (with relaxed ordering)
Changing any of the frame markers originally took a writer
lock on a mutex.
The problem is that Sample::play took a reader lock first before
executing. Because Sample::play has to wait on the writer, this
created a lot of lag and raised the CPU meter. The solution
would to be to use atomics instead.
* Fix errors from merge
* Fix broken LFO controller functionality
The shared_ptr should have been taken by reference.
* Remove TODO
* Update EnvelopeAndLfoView.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update src/gui/clips/SampleClipView.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update plugins/SlicerT/SlicerT.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update plugins/SlicerT/SlicerT.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Store shortest relative path in SampleBuffer
* Tie up a few loose ends
* Use sample_rate_t when storing sample rate in SampleBuffer
* Add missing named requirement functions and aliases
* Use sampledata attribute when loading from Base64 in AFP
* Remove initializer for m_userWave in the constructor
* Do not use trailing return syntax when return is void
* Move decoder functionality into unnamed namespace
* Remove redundant gui:: prefix
* Use PathUtil::toAbsolute to simplify code in SampleLoader::openAudioFile
* Fix translations in SampleLoader::openAudioFile
Co-authored-by: DomClark <mrdomclark@gmail.com>
* Fix formatting for ternary operator
* Remove redundant inlines
* Resolve UB when decoding from Base64 data in SampleBuffer
* Fix up SampleClip constructors
* Add AudioResampler, a wrapper class around libsamplerate
The wrapper has only been applied to Sample::PlaybackState for now.
AudioResampler should be used by other classes in the future that do
resampling with libsamplerate.
* Move buffer when moving and simplify assignment functions in Sample
* Move Sample::visualize out of Sample and into the GUI namespace
* Initialize supportedAudioTypes in static lambda
* Return shared pointer from SampleLoader
* Create and use static empty SampleBuffer by default
* Fix header guard in SampleWaveform.h
* Remove use of src_clone
CI seems to have an old version of libsamplerate and does not have this method.
* Include memory header in SampleBuffer.h
* Remove mutex and shared_mutex includes in Sample.h
* Attempt to fix string operand error within AudioResampler
* Include string header in AudioResampler.cpp
* Add LMMS_EXPORT for SampleWaveform class declaration
* Add LMMS_EXPORT for AudioResampler class declaration
* Enforce returning std::shared_ptr<const SampleBuffer>
* Restrict the size of the memcpy to the destination size, not the source size
* Do not make resample const
AudioResampler::resample, while seemingly not changing the data of the resampler, still alters its internal state and therefore should not be const.
This is because libsamplerate manages state when
resampling.
* Initialize data.end_of_input
* Add trailing new lines
* Simplify AudioResampler interface
* Fix header guard prefix to LMMS_GUI instead of LMMS
* Remove Sample::resampleSampleRange
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
Co-authored-by: Daniel Kauss <daniel.kauss.serna@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: DomClark <mrdomclark@gmail.com>
Fix a floating point exception in the Spectrum Analyzer which occurs if the amplitude is 0. The amplitude is used in the calculation of a logarithm which is not defined for values smaller or equal to 0.
The fix is to replace a value of 0 with the minimum positive float value. Negative values are not handled because it seems that only values greater or equal to 0 are fed into the method. This assumption is asserted in case this ever changes.
* Replace knobFModel with std::vector
* Create QPixmap's on the stack
* Assign parent for QGraphicsScene
A call to QGraphicsView::setScene does not make
the view take ownership of the scene.
* Do not allocate QList on the heap
* Use static QPixmap's
The QPixmap's need to be created within the constructor, and not outside
where they are defined, since it can't find them otherwise.
I'm not too sure why.
* Clear m_vi2->knobFModel in destructor
* Use local static QPixmap's
* Do not allocate QPixmap with new in AudioFileProcessor
* Do not allocate QPixmap with new in Nes
* Do not allocate QPixmap with new in Organic
* Do not allocate QPixmap with new in SaControlsDialog
* Do not allocate QPixmap with new in Vestige
* Do not allocate QPixmap with new for FileBrowser
* Do not allocate QPixmap with new in MixerLine
* Do not allocate QPixmap with new in SendButtonIndicator
* Do not allocate QPixmap with new in AutomationClipView
* Do not allocate QPixmap with new in MidiClipView
* Do not allocate QPixmap with new in AutomationEditor
* Do not allocate QPixmap with new in PianoRoll
* Do not allocate QPixmap with new in TimeLineWidget
* Do not allocate QPixmap with new in EnvelopeAndLfoView
* Do not allocate QPixmap with new in PianoView
* Do not allocate QPixmap with new in ComboBox
* Do not allocate QPixmap with new in Fader
* Do not allocate QPixmap with new for LcdWidget
* Do not allocate QPixmap with new for LedCheckbox
* Use m_ as prefix for members
* Use uniform initialization
I already started using uniform initialization for the QPixmap changes
for some reason, so I'm finishing that up.
* Uniform initiaization
* And then he realized he was making copies...
* Do not call QPixmap copy constructor
* Do not call QPixmap copy constructor in SaControlsDialog
* Do not make pixmap's static for Lcd's and Led's
* Initialize pixmaps in-class
* Fix few mistakes and formatting
* Initial Commit
Starts implementing Note Types. The two available types are
RegularNote and StepNote. PianoRoll now paints the color with a
different color for StepNotes. Pattern::addStep now sets the type of the
note to StepNote.
Negative size is still used to signal a step note.
* Update Pattern.cpp to account for the Note::Type
Updates the methods noteAtStep(), addStepNote() and checkType()
from Pattern.cpp to account for the note type and not the note length.
* Update PatternView::paintEvent to draw step notes
PatternView::paintEvent now draws the pattern if the pattern
type is BeatPattern and TCOs aren't fixed (Song Editor). Color used is
still the BeatPattern color (grey) and the conditional doesn't look very
nice and can be improved.
Pattern::beatPatternLength was also updated so it accounts for
the note type not note length. Review this method, as it looks a bit
weird (particularly the second conditional).
* Implements StepNotes setting a NPH with 0 frames
Now, instead of TimePos returning 0 for negative lengths, we
create a NotePlayHandle with 0 frames when the note type is StepNote on
InstrumentTrack::play.
* Improves PatternView::paintEvent conditional
Improves a conditional inside PatternView::paintEvent by
reversing the order in which they are executed.
* Adds upgrade method for backwards compatibility
Adds an upgrade method that converts notes with negative length
to StepNotes, so old projects can be loaded properly.
Explicitly set the Note::RegularNote value as 0.
Make the default "type" value "0", so notes without a type are
loaded as RegularNotes.
* Addresses Veratil's review
- Changes "addStepNote" so "checkType" isn't called twice in a
row.
- Changes style on a one line conditional.
* Uses ternary expression on statement
Reduces number of lines by using ternary expression.
* Addresses PR review (sakertooth)
- Changes class setter to inline
- Uses enum class instead of enum
- Uses auto and const where appropriate
* Finished changes from review (sakertooth)
- Used std::max instead of qMax
- Fixed style on lines changed in the PR
* Uses std::find_if to save codelines
As suggested by sakertooth, by using std::find_if we are able to
simplify the checkType method to two lines.
* Addresses review from sakertooth
- Reverts m_detuning in-class initialization
- Removes testing warning
- Removes unnecessary comment
* Addresses DomClark's review
- Rename the Note Types enum to avoid redundancy
- Uses std::all_of instead of std::find_if on MidiClip checkType
- Rewrites addStepNote so it sets the note type before adding it
to the clip, avoiding having to manually change the type of the clip
after adding the note
* Updates MidiExport to use Note Types
- Now MidiExport is updated to use note types instead of relying
on negative length notes.
- For that change it was necessary to find a way of letting
MidiExport know how long step notes should be. The solution found was to
add an attribute to the Instrument XML called "beatlen", which would
hold the number of frames of the instrument's beat. That would be
converted to ticks, so we could calculate how long the MIDI notes would
have to be to play the whole step note. If the attribute was not found,
the default value of 16 ticks would be used as a length of step notes,
as a fallback.
* Fixes ambiguity on enum usage
Due to changes in the name of enum classes, there was an
ambiguity caused in NotePlayHandle.cpp. That was fixed.
* Addresses new code reviews
- Addresses code review from PhysSong and Messmerd
* Fixes note drawing on Song Editor
- Notes were not being draw on the song editor for BeatClips.
This commit fixes this.
* Adds cassert header to TimePos.cpp
- Adds header to use assert() on TimePos.cpp
* Apply suggestions from code review
Fixes style on some lines
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Reverts some changes on MidiExport
- Some changes were reverted on MidiExport and InstrumentTrack.
We were storing the beat length on the XML of Instrument Tracks, but in
reality the beat length is a per note attribute, and some instruments
could run into a segmentation fault when calling beat length without a
NotePlayHandle (i.e.: AFP). Because of that I reverted this change, so
the beat length is not stored on the XML anymore, and instead we have a
magic number on the MidiExport class that holds a default beat length
which is actually an upper limit for the MIDI notes of step notes. In
the future we can improve this by finding a way to store the beat length
on the note class to use it instead. The MidiExport logic is not
worsened at all because previously the beat length wasn't even
considered during export (it was actually improved making the exported
notes extend until the next one instead of cutting shorter).
* Fix the order of included files
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
This fixes at least three issues:
* Help window is not synched with window manager's `X`-button
* Help window is not being closed on track destruction or on closing the plugin window
* Trims help window strings and force-adds a newline, because `QLabel::sizeHint` sometimes computes too small values. Now, together with #6956, all help windows fit their strings. Some help windows are too large by one line, but this seems better than forcing the user to resize them if they are too small by one line.
Introduce a new version of the LADSPA control dialog which uses "bar controllers" and arranges them in a grid layout. Long parameter names are elided long if needed. The new dialog is implemented in the class `LadspaMatrixControlDialog`.
Note: it is still possible to reactivate the old dialog as it has not been removed yet. You can do so in `plugins/LadspaEffect/LadspaControls.h` by replacing the implementation of `createView()` with the following:
```
gui::EffectControlDialog* createView() override
{
return new gui::LadspaControlDialog( this );
}
```
Introduce the new base class `FloatModelEditorBase`. It serves as the base widget for widgets that manipulate a float model and provides some base functionalities like context menus, edit dialogs, mouse handling, etc. Currently `BarModelEditor` and `Knob` inherit from `FloatModelEditorBase`. Therefore lots of code was moved from `Knob` to `FloatModelEditorBase`.
`BarModelEditor` supports style sheets. See the changes in style.css for the available options and their usage.
Extend `LedCheckBox` so that it adds support to render the text with the default font in the default size. The class now supports two modes:
* Legacy mode
* Non-legacy mode
Legacy mode is the default and renders the LedCheckBox as before. The font is set to 7 pixels and all the text is rendered with a shadow.
Non-legacy mode uses the current font to render the text. The text is rendered without a shadow and the pixmap is centered vertically to the left side of the text. Non-legacy mode is currently only used in the context of the matrix LADSPA dialog. Toggle options are rendered using it as well as the "Link Channels" button.
Add `TempoSyncBarModelEditor` which adds a tempo sync option to a `BarModelEditor`. Please note that the code was mostly copied and adjusted from the `TempoSyncKnob` class. It was not attempted yet to unify some of the code because with the current design it seems to be a road to "inheritance hell". A better solution might be to refactor the code so that it becomes more composable.
What follows are the individual commit messages of the 64 commits that have been squashed into a single merge commit.
* First version of a new dynamic LADSPA control dialog
The new dialog shows the LADSPA controls in a matrix layout. Each row
corresponds to a LADSPA parameter. Each parameter can have several
channels which can be linked. Each channel has its own row of controls.
The class LadspaMatrixControlView was added by copying and modifying
LadspaControlView to get rid of the link buttons which are associated
with some controls and some labels.
* Remove trailing whitespaces
* Merge fix
* Use the new connect syntax
* Remove empty destructors
* Use override keyword
* Reformat a bit
* Use nullptr
* Use range-based loops
* Add BarModelEditor and improve layouts
Add the new class `BarModelEditor` which is intended to become a new way
to adjust values of float models.
Simplify the layout in `LadspaMatrixControlDialog` by removing some
nested layouts. Remove the "Parameters" column.
Adjust `LadspaMatrixControlView` to implement the following changes:
* Show the name of the control next to toggle buttons (`LedCheckBox`).
* Use the new `BarModelEditor` for integer and float types.
* SHow the name of the control next to time based parameters that use
`TempoSyncKnob`.
The names are shown so that the "Parameters" column can be removed.
Technical details
------------------
The class `LadspaMatrixControlDialog` now creates a widget that contains
the matrix layout with the controls. This widget is then added to a
scroll area. The layout is populated in the new method
`arrangeControls`.
Add some helper methods to `LadspaMatrixControlDialog` which retrieve
the `LadspaControls` instance and the number of channels.
Add the implementation of `BarModelEditor` to `src/gui/CMakeLists.txt`.
TODOs
------
Extract common code out of the `Knob` class so that it can be reused by
`BarModelEditor`.
* Use factory to create LADSPA control widgets
Replace the class `LadspaMatrixControlView` with the factory class
`LadspaWidgetFactory`. The former was a widget that wrapped the widget
representation of a LADSPA control in yet another widget with a layout.
The factory simply returns the configured widget so that it can be
incorporated directly in layouts or other widgets.
Adjust `LadspaMatrixControlDialog` so that it uses the
`LadspaWidgetFactory` instead of the `LadspaMatrixControlView`.
* Initial version of FloatModelEditorBase
Create an initial version of `FloatModelEditorBase`. It is intended to
become the base widget for all widgets that manipulate a float model and
provides some base functionalities like context menus, edit dialogs,
mouse handling, etc.
The initial version is a copy of `Knob`. The enum and its values have
been suffixed with "Temp" as they will be removed later anyway. Same
applies for the function `convertPixmapToGrayScaleTemp`.
* Remove Knob related code from FloatModelEditorBase
First removal of Knob related code from FloatModelEditorBase.
* Remove setHtmlLabel
* Remove enum for knob types
* Remove label related code
Remove setLabel and the members m_label and m_isHtmlLabel.
* Remove several Qt properties
* Remove angle related members and methods
* Remove unused members and includes
* Clean up includes
* Make BarModelEditor inherit from FloatModelEditorBase
Make `BarModelEditor` inherit from `FloatModelEditorBase` so that it
inherits all shared functionality. Currently the class mostly implements
size related methods and overrides the paint method.
* Move LadspaWidgetFactory to LadspaEffect
Move the class `LadspaWidgetFactory` to the project LadspaEffect to make
it hopefully compile with mingw32 and mingw64.
Interestingly the code compiled and worked under Linux and MacOS.
* Code adjustments after scripted checks
Add an include guard and an additional `#pragme once`. Add comments to
closing namespace scopes.
* Export BarModelEditor
Export BarModelEditor so that for example the LadspaEffect project/
plugin can use it.
* Improve rendering of bar model editor
Increase the margin from 2 to 3 so that we have a more prominent border
around the filled area.
Fix a problem in the rendering code which led to situations where the
bar was drawn to the left of the start position for small values.
Return a more exact minimum size hint.
* Elide long parameter names
Elide long parameter names if needed.
* Enable horizontal direction of manipulation
Extend `FloatModelEditorBase` so that it also allows manipulation of the
values when the mouse is moved in horizontal directions. The default is
to use the vertical direction.
Make use of this new feature in `BarModelEditor` which now reacts to
horizontal movements when changing values.
* Represent enum parameters using the bar widget
The implementation of the current LADSPA dialog in master uses knobs to
represent enum parameters. Therefore it should also work with the new
bar widget.
This gets rid of many labels with the parameter name followed by
"(unsupported)".
* Remove TODO in LadspaWidgetFactory
* Render text of LedCheckBox with default font
Extend LedCheckBox so that it adds support to render the text with the
default font in the default size. The class now supports two modes:
* Legacy mode
* Non-legacy mode
Legacy mode is the default and renders the LedCheckBox as before. The
font is set to 7 pixels and all the text is rendered with a shadow.
Non-legacy mode uses the current font to render the text. The text is
rendered without a shadow and the pixmap is centered vertically to the
left side of the text.
The non-legacy mode is currently only used in the context of the matrix
LADSPA dialog. Toggle options are rendered using it as well as the "Link
Channels" button.
* Use "yellow" LEDs for bool parameters
Use "yellow" LEDs (which are actually blue) for dynamically added bool
parameters so that the dialog is consistent with regards to the LED
colors. The "Link Channels" button also uses a "yellow" LED.
* Fix Qt5 builds
Fix the Qt5 builds which do not know horizontalAdvance as a member of
FontMetrics.
Also refactor LedCheckBox::onTextUpdated to make it more compact.
* Style sheets for BarModelEditor
Add style sheets options for BarModelEditor. See the changes in
style.css for the available options and their usage.
The members that can be manipulated by the style sheet options are
initialized accoriding to the palette so that the BarModelEditor should
also render something useful if no style is set.
Adjust the paintEvent method to use the style sheet brushes and colors.
* Layout optimizations
Set the vertical scroll bar to always show so that the controls do not
move around if the scroll bar is hidden or shown.
Set the margin of the grid layout to 0 so that the whole dialog becomes
tighter.
* Get rid of initial scroll bars
Make sure that the widget is shown without a scrollbar whenever possible
using the following rules.
If the widget fits on the workspace we use the height of the widget as
the minimum size of the scroll area. This will ensure that the scrollbar
is not shown initially (and never will be).
If the widget is larger than the workspace then we want it to mostly
cover the workspace. In that case the minimum height is set to 90 % of
the workspace.
* Switch to a green theme
Switch to a green theme to better match the default theme.
* Adjust classic theme
Adjust the classic theme so that it renders the bars in a legible way.
* Fixes for CodeFactor
Remove virtual keyword from methods that are marked as override.
Remove whitespaces that make CodeFactor unhappy. One of these fixes
includes moving the implementation of
LadspaMatrixControlDialog::isResizable into the cpp file.
* CodeFactor is still unhappy
Remove a blank line after the constructor.
* Center align time based controls
Align time based controls, i.e. knobs, in the center.
The implementation defeats the purpose of the widget factory a bit but
it makes the design look nicer.
* Fix build
Fix the build by adjusting the enums. I added the changes while writing
the commit message for the merge commit but they did not make it.
* Attempt at CodeFactor warning
Try to make the last CodeFactor warning disappear.
* Add bar controller with tempo sync option
Add `TempoSyncBarModelEditor` which adds a tempo sync option to a `BarModelEditor`. Please note that the code was mostly copied and adjusted from the `TempoSyncKnob` class. It was not attempted yet to unify some of the code because with the current design it seems to be a road to "inheritance hell". A better solution might be to refactor the code so that it is more composable.
Another option might be to move the tempo sync functionality into a class like `FloatModelEditorBase`. Although this would not be a 100% right place either because `TempoSyncKnobModel` inherits from `FloatModel`. In that case we'd have specialized code in a generic base class.
Adjust `LadspaWidgetFactory` so that it now returns an instance of a `TempoSyncBarModelEditor` instead of a `TempoSyncKnob`.
Remove the extra layout code from `LadspaMatrixControlDialog.cpp` as most things are bar editors now.
Adjust `TempoSyncKnobModel` so we do not have to make `TempoSyncBarModelEditor` a friend of it.
* Another attempt to please CodeFactor
Have another attempt to fix CodeFactor's complaints about `LadspaMatrixControlDialog.h`.
* Coding conventions, blanks and blank lines
Remove lots of unnecessary white space. Remove blank lines. Remove leading underscores from parameters.
Remove line breaks in `TempoSyncBarModelEditor.cpp` to make the code more readable. Remove repeated method calls by introducing local variables.
* Break down complex method
Break down the complex method `TempoSyncBarModelEditor::updateDescAndIcon` by delegating to the new methods `updateTextDescription` and `updateIcon`.
* Another attempt to please CodeFactor
Another attempt to fix `LadspaMatrixControlDialog.h` to please CodeFactor.
* Work on TODOs
The TODO "Assumes that all processors are equal..." has been turned into a comment when we start iterating over the channels. If the channels are not of the same structure this would likely also have been a problem in the old implementation.
The TODO "Use a factory..." has been removed as this is already done.
The include of `FloatModelEditorBase.h` in LadspaWidgetFactory has been removed.
* Modifier keys for mouse wheel adjustments
Integrate the changes of commit 7000afb2ea into `FloatModelEditorBase`.
This commit added modifier keys for mouse wheel adjustments to the `Knob` class. The port to `FloatModelEditorBase` results in the bar control now also supporting different scales of adjustments that can be switched with the Shift, Ctrl and Alt keys.
* Show current value on mouse over
Integrate the changes of commit fcdf4c0568 into `FloatModelEditorBase`. This commit lets users show the current value of a float model when the mouse is moved over the control.
* Make Knob inherit from FloatModelEditorBase
Make `Knob` inherit from `FloatModelEditorBase`. This is mostly a continuation for the changes introduced with commit c63d86f.
The idea is that `FloatModelEditorBase` contains the underlying functionality and logic to deal with float models. `Knob` and other classes then only override the presentation aspects. This way `Knob` and `BarModelEditor` can share the same functionality but can differ in how they present the data.
Technical details
------------------
Remove all methods that are already defined in `FloatModelEditorBase` from `Knob`. These are all methods that are defined in the same way in `FloatModelEditorBase`. The method `paintEvent` is not removed because it is overridden by `Knob` as it has its own presentation.
Remove forward declaration of `QPixmap` from `FloatModelEditorBase` as it was not used. Remove unused function `convertPixmapToGrayScaleTemp` from `FloatModelEditorBase`.
* Cleanup includes in Knob class
* Code style changes in FloatModelEditorBase
`FloatModelEditorBase` is a new class/file. Therefore we can do some extensive code cleanup on the code that was initially copied from `Knob`.
Adjust whitespace for methods and some if-statements. Remove underscores from parameter names. Use only two blank lines between method definitions.
* Cleanup include for FloatModelEditorBase
* Show effect name as title of dialog
Add the effect name as the title in the content of the window. This improves the structure of the dialog as it is now clearer from the content itself to which effect the controls belong to.
This duplicates the information from the window title. However, the window title is rather small and the larger font in the content makes it easier to find an effect in a set of opened dialogs.
* Revert "Show effect name as title of dialog"
This reverts commit 8ce0d366d0.
* Fix problem with LedCheckBox in grid layout
The LedCheckBox does not play nice when being used in a grid layout as it disables the resizing behavior of every column it appears in.
The solution is to wrap it into the layout of a parent widget that knows how to behave.
* Reduce minimum width of BarModelEditor
Reduce the minimum width of `BarModelEditor` from 200 to 50.
---------
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
This PR makes changes in the submodule `zynaddsubfx`. It affects its
submodule `instruments`:
* updates the URL to use github (since SF is less reliable)
* changes the protocl from SSH to HTTPS (see
https://stackoverflow.com/a/50299434)
* does not change the submodule's commit ID
You must now run
```
git submodule sync --recursive
```
once to reflect this change.
* Fix warnings "QPainterPath::lineTo Invalid coordinates" on console when loading the effect or changing
some paramenters, by not "drawing" the EQ curve when there is no EQ band active.
* Fix warnings on console "QPainterPath::lineTo Invalid coordinates" when EQ is processing a sound, because
in this function log10f generates a pole error when freq is 0, returning and invalid x value pixel
* Update plugins/Eq/EqCurve.cpp
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Fix issue with knob range
* Randomness for BandedWG
* Implement Tubular Bells ADSR
* LFO - update values on change while playing
* coding style
* Vibrato Gain - update
* fixed cmakelists conditions
* Fixed the order messup.
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
---------
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>