Improves the tap tempo algorithm and usage, as well refactoring the code for better maintainability.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This reworks the auto-quit feature by introducing a new AudioBuffer class which keeps track of which channels are currently silent as audio flows through the effects chain.
When track channels going into an effect's input are not marked as quiet, it is assumed a signal is present and the plugin needs to wake up if it is asleep due to auto-quit. After a plugin processes a buffer, the silence status is updated.
When the auto-quit setting is disabled (that is, when effects are always kept running), effects are always assumed to have input noise (a non-quiet signal present at the plugin inputs), which should result in the same behavior as before.
Benefits:
- The auto-quit system now closely follows how it is supposed to function by only waking plugins which have non-zero input rather than waking all plugins at once whenever an instrument plays a note or a sample track plays. This granularity better fits multi-channel plugins and pin connector routing where not all plugin inputs are connected to the same track channels. This means a sleeping plugin whose inputs are connected to channels 3/4 would not need to wake up if a signal is only present on channels 1/2.
- Silencing channels that are already known to be silent is a no-op
- Calculating the absolute peak sample value for a channel already known to be silent is a no-op
- The silence flags also could be useful for other purposes, such as adding visual indicators to represent how audio signals flow in and out of each plugin
- With a little more work, auto-quit could be enabled/disabled for plugins on an individual basis
- With a little more work, auto-quit could be implemented for instrument plugins
- AudioBuffer can be used with SharedMemory
- AudioBuffer could be used in plugins for their buffers
This new system works so long as the silence flags for each channel remain valid at each point along the effect chain. Modifying the buffers without an accompanying update of the silence flags could violate assumptions. Through unit tests, the correct functioning of AudioBuffer itself can be validated, but its usage in AudioBusHandle, Mixer, and a few other places where track channels are handled will need to be done with care.
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Allows detaching a window from LMMS's main window, making things like working on multiple screens easier.
The behavior of detached windows can be customized in the Settings.
Closes#1259
---------
Signed-off-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: SpomJ <mihail_a_m@mail.ru>
Improves performance when moving mixer channels to the left or right using simple Qt layout operations and swapping of values. This commit also addresses a deadlock in Mixer::mixToChannel by ensuring we lock and unlock the same channel regardless of any move operations occurring simultaneously on another thread.
When #7454 was merged, Timelines were refactored to emit a positionJumped signal whenever their internal tick position was changed via Timeline::setTicks. This was meant as an easy way to account for all situations where the user might drag or click or somehow forcefully set the position of a timeline mid-playback.
However, the current way timeline syncing is implemented between the song editor and piano roll (when doing record-play in the piano roll) is by constantly calling setTicks on the piano roll's timeline whenever the song editor's timeline moves. This inadvertantly means that positionJumped is being emitted, even when the timeline is tracking smoothly.
This PR attempts to address this issue by adding an optional parameter to Timeline::setTicks which allows the caller to opt out of emitting positionJumped. Ideally, we would have a better system for syncing timelines together, one which does not rely on forcefully calling setTicks. But for now, this should work.
---------
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
Requested by a user on the forum. Sometimes, it can get tricky when two clips are right next to each other, and you're trying to resize one of them. Either you resize the right one, or the other one starts resizing behind the other, so you end up having to move one over, then resize it, then move it back. And it's just not awesome.
However, this can be mitigated by simply increasing the clip resize grip width. Currently, it is at 4 px, but increasing it to 8 px makes it easier to specifically target which clip you want to resize. It also probably makes it easier to resize clips in general for users who may struggle to aim the mouse perfectly within that 4 pixel gap.
Partially addresses #8188
For some reason, when a knob is set to be a "volume knob", the max volume allowed via double-clicking and typing in a value is 6.0 dB. For knobs such as the amplifier knob in Audio File Processor which go up to 500% (~14 db), this is not enough.
This PR makes it so that the dialog shows the actual max dB value based on the underlying model's max value, instead of being hardcoded to 6.0 dB. This PR does not address the minimum value.
* Clarify VST support to VST2 in README
Updated VST support mention from VST(i) to VST2 in features section for clarity.
* Update README.md
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* mention LV2 support
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Refactors the PortAudio backend to fix issues with DirectSound and MME crackling and not loading properly, as well as to improve code quality and maintainability.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Fixes#8200. Scrolling to change velocity/panning can affect unselected notes if hovering over them in the bottom section of the piano roll. This PR addresses that.
This refactors the export dialog to no longer use the export_project.ui file and moves it into standard C++ Qt code. This also brings minor changes to the dialog, such as horizontal labels instead of vertical ones.
* reimplement getter and setter of FloatModelEditorBase::m_volumeKnob to avoid undo checkpoint creation
* convert FloatModelEditorBase::m_volumeKnob from BoolModel to bool
* clean up
* remove unnecessary inline keywords and fix formatting
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Fixes#8190
When #7454 was merged, I added a check before emitting playbackPositionJumped to only emit when the song was playing, to prevent LFOs from being reset when the user dragged the timeline while the song was paused. However, I used Song::isPlaying(), which only returns true when the song is not exporting. This caused sample clips to not be updated when the playback position jumped back every loop, which means they just kept playing, ignoring the loop. To fix this, I have changed it to use m_playing, which is true for both exporting and normal playing.
Removes `SampleLoader`. File dialog functions were moved into `FileDialog`. Creation functions were moved into `SampleBuffer`.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This PR modifies how the Detuning tool works in the piano roll to let the user modify the automation curve right on the notes. This is actually fairly simple, as automation clips already contain the functions for dragging and removing points like in the Automation Editor. So essentially all that's being done is calculating the relative pos of the mouse to the nearest note, and setting the drag value in the automation clip to that position and key.
You can still access the old automation editor version by shift-click
messmerd asked if the code could be made general for any future note parameter besides detuning, in preparation for CLAP per-note parameter automation. I have refactored the relevant functions to accept an enum type for the kind of note parameter, although currently only detuning is supported.
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Fixes#8182
When #7454 was merged, the frameOffset variable inside Song::PlayPos which kept track of the actual frame position which the song was playing at relative to the last tick, was moved to Timeline. In the process, the type was inadvertently changed from float to f_cnt_t.
This caused the frame offset to be truncated ever time it was updated in Song::processNextBuffer, causing the song playback to slowly drift back ever so slightly, just a handful of frames every bar. This caused any new sample clips spawned to be created slightly late, becoming out of sync with any existing playing samples.
This PR fixes the issue by reverting the frameOffset variable type to be float again, allowing it to track sub-sample offsets over time.
Fixes#8138
Essentially, when playing beat notes in the pattern editor, technically, they have an internal length of 0. However, when the NotePlayHandle is created and recieves that value of 0, it realizes it's supposed to be a beat note, so it asks the instrument track what the default length of note should be. For most instruments, that defaults to whatever the length of the envelope is (no matter whether the envelope is enabled or not. Is that a good system? I don't know.) However, AudioFileProcessor does it custom and returns the length of its sample in frames.
However, the frame count it returned did not take into account that the sample rate of lmms could be different from the sample rate of the sample. This PR fixes that issue by multiplying by the correct sample rate ratio.
Closes#7869
This PR aims to fix linking bugs and it aims to make linking code faster. In the future I would like to replace controller and automation code with linked models, so it is essential for this feature to work as efficiently as possible.
Before this PR:
- AutomatableModels store a list of AutomatableModels that they are linked to.
- setValue() and other functions make recursive calls to themself resulting in the #7869 crash.
- Each AutomatableModel can unlink from other AutomatableModels, unlinking is the inverse operation to linking.
After this PR:
- AutomatableModels store a pointer to an other AutomatableModel making a linked list. The end is connected to the first element resulting in a "ring".
- setValue() and others are now recursion free, the code runs for every linked model, more efficiently than before.
- Each AutomatableModel can NOT unlink form other AutomatableModels, unlinking is NOT the inverse operation to linking. AutomatableModels can unlink themself from the linked list, they can not unlink themself from single models.
---------
Co-authored-by: allejok96 <allejok96@gmail.com>
The TrackContentWidgets in the pattern editor rely on the positionChanged signal to be sent when the pattern index changes so that they know when to update. This signal was removed in #7454, but this PR puts it back.
Previously, this PR simply added a new signal to the Timeline class and had it emitted by the TimeLineWidget class in order to solve #7351.
However, as messmerd pointed out in his review comments, that was quite a hacky solution, and ideally the positionChanged signal would be solely managed by the backend Timeline class, while the frontend TimeLineWidget class would connect to those signals, instead of the other way around.
This PR is no longer a simple bugfix, but instead a refactoring of the Timeline/TimeLineWidget signal/slots.
Changes
- The positionChanged signal and updatePosition slot were removed from TimeLineWidget and moved to Timeline.
- Removed PlayPos, and instead store the timeline position in a TimePos along with a separate frame offset counter variable. The functions to set the ticks/timepos in Timeline emit the positionChanged signal. (Also, may emit positionJumped signal if the ticks were forcefully set--see below)
- The pos() method and PlayPos m_pos were removed from TimeLineWidget;
- The constructor for TimeLineWidget no longer requires a PlayPos reference.
- Since each TimeLineWidget stores a reference to its Timeline, a new method was added, timeline(), for other classes to access it.
- Removed array of PlayPos'es in Song. Now each Timeline holds their respective TimePos.
- Song's methods for getPlayPos were changed to return the TimePos of the respective Timeline. The non-const versions of the methods were removed because Timeline does not expose its TimePos to write.
- All of the places where Timelines are used were updated, along with their calls to access/modify the PlayPos. For example, occurrences of m_timeline->pos() were replaced with m_timeline->timeline()->pos(), and calls to m_timeline->pos().setTicks(ticks) were changed to m_timeline->timeline()->setTicks(ticks).
- ALSO: Removed m_elapsedMilliseconds, m_elapsedBars, and m_elapsedTicks from Song. The elapsed milliseconds is now handled individually by each Timeline.
- NEW: The m_jumped variable has been removed from Timeline. Now jumped events emit Timeline::positionJumped automatically whenever the ticks are forcefully set. This means it is no longer necessary to call timeline->setJumped(true) or timeline->setFrameOffset(0) whenever the playhead position is forcefully set. Many places in the codebase were already missing these calls, so this may fix some unknown bugs.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Alex <allejok96@gmail.com>
* Fix Shift+Space corrupting playback state when used on stopped editors
Shift+Space (togglePause) was allowing state corruption by modifying
m_playing and m_paused without checking m_playMode. This created an
impossible state where m_playing=true while m_playMode=None, causing
the regular Space key to stop working.
Added a guard to ensure togglePause() only operates when something is
actually playing (m_playMode != PlayMode::None). This prevents the
corrupted state and maintains proper play/pause/stop behavior.
Fixes#8036
---------
Co-authored-by: regulus79 <117475203+regulus79@users.noreply.github.com>
Fixes#8152
Revert PianoRoll closing when empty (caused issues with detached windows)
Remove TextFloat warning when there are no instruments/multiple clips (showed up when reloading project)
(Keep clip creation for empty projects)
Add an icon and updated message in empty PianoRoll.
Mark PianoRollWindow invalid when there is no clip, making buttons impossible to click
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
Previously, loading a new sample in an AFP instance with reverse enabled would desync the button from the model, such that the button would indicate the sample was reversed despite the new sample not actually being reversed.
This commit fixes this behavior so that samples loaded into an AFP instance with reverse enabled are actually reversed.
This fixes a regression in commit f44aa3e that caused OGG exports to not flush any remaining data properly when finalizing the export, leading to truncated outputs with a different duration.
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Clang was incorrectly displayed as 'GCC Clang' because __GNUC__ is
defined by Clang for compatibility. Reordered preprocessor checks in
versioninfo.h to test for __clang__ before __GNUC__.
Fixes#8120
This bug was noticed when testing out #7559, but the PR had been open for over a year, so it was decided to merge it and fix it in this one.
Basically, when adding or removing a track, the TrackContainer sends out signals such as trackAdded or trackRemoved which PatternClipView uses to know when to update.
However, it does not send out a signal when a track has been moved.
This is because for some reason, it's done by the GUI TrackContainerView instead of the core TrackContainer.
This PR changes that by moving the core code to the core where it probably belongs, adding an appropriate trackMoved signal to TrackContainer, and connecting that to PatternClipView to update properly.
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
This PR changes the way PatternClips are drawn in include a simple "beat preivew," where each note in any non-empty instrument tracks within the pattern are drawn as short little rectangles on the ClipView. SampleClips and AutomationClips within patterns are not currently supported.
The height of the note boxes changes depending on how many tracks there are in the pattern, and how many of them actually have notes (empty tracks are only drawn half as tall).
There is also some padding at the top and bottom along with a little bit of spacing between each note, both vertically and horizontally. This can be edited in the css, along with the note color.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: Fawn <rubiefawn@gmail.com>
Previously, the autoscroll state of the song editor and piano roll (continuous, stepped, none) was not saved. This can be an issue for users who want to permanently set their autoscroll settings, without having to change them every time they start up LMMS.
This PR adds an option in the settings window to change the default autoscroll state.
Correct the button initialization order so mixer channels show the proper mute and solo states when they first appear. This applies to channels loaded from a project and channels created during the session, ensuring the UI reflects the actual underlying state properly.
* 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.
Fixes an issue where quantizing notes in a midi clip with auto-resize disabled would cause the length to be reset, in cases where there is only a single note in the clip. This was due to how quantization removes and re-adds each note, so for a moment, the clip would be empty, thus treated as a beat clip. Beat clips were mistakenly always automatically resized no matter whether auto-resize was enabled or not. This PR fixes that by only auto-resizing beat clips when they have auto-resize enabled.
Co-authored-by: Fawn <rubiefawn@gmail.com>
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
* SVG-ify arrow buttons
These buttons are used in the instrument window, Vestige, and VST
effects. Separate versions of the arrow icons are used for the classic
theme.
* Fix some unrelated SVG formatting and metadata
* Revert accidental change to classic border radius
* Add some XML stuff back to appease Github
LMMS renders these SVGs just fine, but apparently the removal of the
XML declaration completely breaks Github's ability to render the image,
so I am adding these back for the sake of those who want to actually
look at the diff on the website lmao
* Attempt to fix Github SVG previews again (`xmlns`)
* Fix crossover eq band mute button icon size
You may ask, "what does this have to do with the arrow buttons?" and you
would be right to assume this is unrelated. However, I'm already
touching the relevant lines of the stylesheet so I may as well sneak it
in there.
* Add missing metadata to fader_knob.svg
And fix mixed indentation in headphones.svg
* Add missing `xmlns` to fader_knob.svg
GRADIENTS!!!!!!!!!!!!
* Fix classic theme arrow buttons
The originals were right angle chevrons
* Remove unused getters
The culprit was the little text warning under the instrument tuning view informing the user that MIDI-based instruments do not support the microtuner. The entire instrument window was expanding horizontally to accommodate this. This commit solves this by setting the width of the other tabs to be no wider than the instrument they belong to.
- Display a message when a user attempts to open the piano roll in a project with no MIDI clips instead of opening a non-functional piano roll.
- Create a MIDI clip in the first instrument track when the piano roll is opened in an empty project.
* Rebase against master
Co-authored-by: michaelgregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Fix Qt6 DMG on Apple (#7240)
- Fix linking issues with Qt Framework files
- Fix qmake detection
* Fixes after rebase
* Fix embed.cpp compilation
Fix implicit conversion from int when using QString.arg(...)
* Fix Qt6 signature change for nativeEventFilter (#7254)
* Adds win32EventFilter a wrapper for nativeEventFilter on Windows
* win32EventFilter is currently used to intercept top-level Window events (currently, to avoid VSTs setting transparency of the parent application)
* fix broken signal slot connections (#7274)
QComboBox activated() replaced with textActivated() since Qt 5.14
* Enabled VSTs on Qt 6 (#7273)
* enabled VST support for Qt 6 builds
* Note : Embedding on QT6 will be buggy on linux as a result of using qt embedding, which unfortunately is a qt bug which hasn't been resolved.
* Changed bar lines to follow snap size (#7034)
* Added lines in between bars
* Changed bar lines to follow snap size
* Changed default zoom and quantization value
* Added constants for line widths
* Added QSS configuration for new grid line colors
* Tied line widths to QSS properties
* Changed default quantization to 1/4
* Removed clear() from destructor model
* Removed destructor in ComboBoxModel.h
* Changed member set/get functions to pass by value
* Updated signal connection with newer syntax
* Fix compilation
* Fix MSVC builds
* fix nullptr deref in AudioFileProcessor (qt6 branch) (#7532)
* ensured mouse event != nullptr before deref
* separation of concerns: AFP WaveView updateCursor
extract check to pointerCloseToStartEndOrLoop()
* marked some function parameters as const
* Remove Core5Compat usage
* Fix bad merge
* Fixes after rebase
* Simplify QTX_WRAP_CPP call
* Remove comments that are obvious to a developer
* Whitespace
* Try using Qt 6 for MSVC CI
I chose Qt 6.5 because it's the last Qt LTS release with declared
support for Visual Studio 2019. Once we upgrade to Visual Studio 2022,
we could upgrade Qt as well.
* Fix MSVC build
Also fixes two memory leaks in MidiWinMM
* Fix GuiApplication on MSVC
* Fix interpolateInRgb
* Try building with patched Calf
* Fix submodule
* Fix OpulenZ build
* Try to fix zyn
* Fix comment
* Ty to fix zyn (again)
* Ty to fix RemotePluginBase
* Revert "Ty to fix RemotePluginBase"
This reverts commit 92dac44ffb11e19d1d5a21d9155369f017bd59e9.
* Update plugins/ZynAddSubFx/CMakeLists.txt
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix vertical & horizontal scroll wheel in SongEditor
* AppImage: Fix finding of Qt6 libs
* Fix implicit QString --> QFileInfo conversion
* Point submodule to lmms
* Fix multiple deprecation warnings
* Fix for Clang compiler
* Build with latest Qt LTS version now that we use MSVC 2022
* Update jurplel/install-qt-action to v4.3.0
* Bump minimum Qt6 version for MSVC
* Fix incorrect Qt version checks
Some comparisons were using ">" rather than ">="
* `QSize()` != `QSize(0, 0)`
* Fix more deprecation warnings
* Fix style
* Simplify Spectrum Analyzer mouse events
The Qt bug that used to be present appears to have been fixed, so the
workaround can be removed
* Minor changes
* Fix deprecated QCheckBox signal
* Fix setContent helper functions
* Remove QMultiMap usage from ControlLayout
* Remove SIGNAL and SLOT macros
* Revert TrackView.cpp changes
* Remove Q_DISABLE_MOVE usage since it does not seem to be available in Qt6
---------
Co-authored-by: michaelgregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
Co-authored-by: BoredGuy1 <66702733+BoredGuy1@users.noreply.github.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Lisa Magdalena Riedler <git@riedler.wien>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
PathUtil: Serialization and Formatting
* Serialize all operations to use / instead of platform specific paths.
* Formatting changes for consistency.
* Reorder functions, add serialization enforcement to the other two functions.
Given these changes, the knife tool now uses `Qt::SplitHCursor`, but `Qt::IBeamCursor` is also a a viable option. I am noting this should substantial concern arise over the appearance of `Qt::SplitHCursor` due to cursor themes, such as the default one applied to applications running under WSL.
Instead of including the files directly in plugins/MidiImport/portsmf,
that path is now a git submodule (https://github.com/portsmf/portsmf).
Several other changes have been made to clean up MidiImport as well.
This cleans up typos in source comments and some user-facing strings.
Found via `codespell -q 3 -S "./plugins,./src/3rdparty,./data/locale,*.in,*.xpf" -L continous,currenty,globaly,inports,localy,nd,ot,sie,te,trough`
Set minimum deployment target for macOS builds
- Calculates MACOSX_DEPLOYMENT_TARGET based on qmake's minos value
- Echo's Lowest SDK supported for information purposes
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
Disable ASLR when building RemoteVstPlugin executables on Windows in order to fix crashes when using certain VSTs
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This PR simplifies #7762 by removing the editor-specific code from MainWindow and m_lastPlayMode from Song, and instead uses a static variable in Editor which keeps track of the last played editor.
This PR also removes the spacebar shortcut from MixerChannelView for changing the volume, as multiple users have noticed that it clashes with their intuition after getting used to the spacebar working everywhere else.
- Fixes: when right clicking on a piano key close to the lower edge of the screen, "Mark semitone" will mark the wrong key because it uses the upper edge of the context menu as reference.
- Fixes: getKey() is off by 2 pixels
- Introduces: yCoordOfKey() which is the reverse of getKey()
- Removes: section of code that can never be reached
---------
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
## Fix problems with lifetime of `QByteArray`
Fix a problem with the lifetime of a `QByteArray` in
`attemptToReconnectOutput` and `attemptToReconnectInput`.
The method `constData` was called on a temporary which gets destroyed
before `targetName` and `sourceName` are used, thus leading to undefined
behavior.
## Fix index checks
Fix index checks in `attemptToReconnectOutput` and
`attemptToReconnectInput`.
The previous code would have allowed an index to be `size` of the
underlying vector which would access out-of-bounds memory.
## Braces for one-liner if statements
Add braces for one-liner if statements.
Fix a segmentation fault that occurs if the JACK libraries are not
installed. In that case `jack_client_open` which is called through
`lib_weakjack` will return a `nullptr` for the client. Subsequent calls
to `jack_client_open` do not check for `nullptr` in the library so we
have to do this ourselves to prevent the segmentation fault. The check
is added to `AudioJack::setupWidget::getAudioPortNames`.
Extract the printing of the JACK status into the function
`printJackStatus` as its functionality is needed several times.
Print a warning and the status in `AudioJack::setupWidget::setupWidget`.
## Code review changes
Use `std::printf` and `std::fprintf`and print to `stderr` whenever fitting.
---------
Co-authored-by: Andrew Wiltshire <62200778+AW1534@users.noreply.github.com>
- Add `SampleType` concept
- Make `channels()` static when possible
- Add `dataSizeBytes()` and `dataView()` to `InterleavedBufferView`
- Support conversions between `std::span<SampleFrame>` and `InterleavedBufferView<float, 2>`
- Support iteration over frames of `InterleavedBufferView`
- Add `subspan` method
- Add `AudioBufferView` concept
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Major changes:
- Remove Gate knob from effects, effectively hard coding its value to zero
- Replace effect RMS calculations with a more efficient way of detecting silent buffers
- Only perform silent buffer detection when `ProcessStatus::ContinueIfNotQuiet` is returned from a plugin AND auto-quit is enabled
Minor changes:
- Remove gate from presets
- Remove gate from .mmp projects
- Move `Effect::processorCount()` to `LadspaEffect`
- Rename `Effect::checkGate` to `Effect::handleAutoQuit`
- Adjust silence threshold for better compatibility with old RMS calculations
- Remove some unnecessary methods from `Effect`
- Reset quiet buffer count in `stopRunning`
- Use positive name for auto-quit boolean
- Simplify `m_autoQuitEnabled` initialization
Follow-Up of 7db3fa94a1 .
This was done by setting `CMAKE_C_INCLUDE_WHAT_YOU_USE` and
`CMAKE_CXX_INCLUDE_WHAT_YOU_USE` to (broken down into multiple lines here,
note, all below `FL/x.h` is not required for C):
```
include-what-you-use;
-Xiwyu;--mapping_file=/usr/share/include-what-you-use/qt5_11.imp;
-Xiwyu;--keep=*/xmmintrin.h;
-Xiwyu;--keep=*/lmmsconfig.h;
-Xiwyu;--keep=*/weak_libjack.h;
-Xiwyu;--keep=*/sys/*;
-Xiwyu;--keep=*/debug.h;
-Xiwyu;--keep=*/SDL/*;
-Xiwyu;--keep=*/alsa/*;
-Xiwyu;--keep=*/FL/x.h;
-Xiwyu;--keep=*/MidiApple.h;
-Xiwyu;--keep=*/MidiWinMM.h;
-Xiwyu;--keep=*/AudioSoundIo.h;
-Xiwyu;--keep=*/OpulenZ/adplug/*;
-Xiwyu;--keep=QPainterPath;
-Xiwyu;--keep=QtTest
```
FAQ:
* Q: Does this speed-up a completely fresh compile?
* A: No, I measured it.
* Q: Does it speed up anything else?
* A: Yes. If you change one header, it can reduce the number of CPP files
that your compiler needs to recompile, or your IDE has to re-scan.
* Q: What other reasons are for this PR?
* A: It's idiomatic to only include headers if you need them. Also, it will
reduce output for those who want to use IWYU for new PRs.
Background:
This is just a remainder PR of what I planned. My original idea was to setup
a CI which warns you of useless includes (but not of all issues that IWYU
complains about). However, I could not see that this was favored on Discord.
A full IWYU CI also has the problem that it (possibly??) needs to compile
with `make -j 1`, which would make CI really slow.
However, for that plan, I had to fix the whole code base to be IWYU
compliant - which it now is.
# GUI
## Present inputs/outputs in hierarchical menu
Present the available inputs and outputs in a hierarchical sorted menu
which shows clients with their ports.
The heavy lifting of creating the menu for the tool button is done in the
new method `buildMenu`.
It takes the input/output names in Jack's "Client name:Port name" format.
If an input/output name can be successfully split into the client name
and port name then a sub menu with the client name is created (if it was
not already created before) and the port name is added as an entry.
If the name cannot be split into exactly two components then it is simply
added to the top level menu as is.
Ports of the LMMS client are filtered out to prevent loops.
The menu starts with the client's sub menus in alphabetical order. Then
the top level entries are added in alphabetical order as well.
The callbacks for the `QAction` instances are implemented with lambdas
because MOC does not support nested classes like the setup widget is. For
now the used lambda only sets the text of the `QToolButton` as these are
used for persisting the configuration anyway.
## Disconnected state
Add the option to keep inputs/outputs disconnected.
The disconnected state is represented by the string "-" which is also
what is saved into the configuration in this case. For now the
representation in the GUI and of the save state is the same as it has the
advantage that no translation is necessary and thus not mapping between
display text and save state is necessary.
## Show technical output/input names
Show the technical output and input port names used by LMMS in the setup
dialog. Note: these are the names that are shown in tools like `qjackctl`
or `qpwgraph`.
This was proposed in a review. Personally I like the non-technical names
better but let's see what's accepted.
## Let the tool buttons use available space
Let the tool buttons stretch so that they look uniform and use all the
available space.
# Driver
## Reconnect inputs and outputs
Attempt to reconnect the inputs and outputs from the configuration during
startup of the Jack driver. Nothing will be done for inputs and outputs
that are not available at startup. Example: the users might have saved
some inputs when a device was available. The device is then disconnected
and LMMS restarted. The stored inputs cannot be used anymore. To give the
users the least surprise nothing is done.
`AudioJack::attemptToConnect` does the actual reconnection and also
prints some information for now.
`attemptToReconnectOutput` and `attemptToReconnectInput` delegate to
`attemptToConnect` with the right parameters.
# Technical details
## Generalized number of inputs/outputs
Generalize the number of inputs and outputs by using for loops. This
affects the number of widgets that are created and the amount of
configuration that is stored.
This change is a result of a code review discussion. In my opinion it
adds unnecessary complexity to something that should later be implemented
completely different anyway. It is for example now necessary to compute
the key names that are used during the saving of the configuration based
on the channel number. The commit exists so that its changes can be
discussed further. It might be reverted in one of the next commits.
## Collecting input and output names
Add `AudioJack::setupWidget::getAudioPortNames` which takes the type of
port and then collects all port names which match. Make
`getAudioOutputNames` and `getAudioInputNames` delegate to that method
with the appropriate type. This also hides the different terminologies a
bit.
## Separate Jack client in the GUI
The separate Jack client is necessary because the setup dialog does not
have any access to the actual driver. So a new client is created when the
dialog is opened and deleted when it is closed, i.e. when the dialog is
deleted itself.
## Repeated strings
Repeatedly used hard-coded strings are defined as static constant
variables in the anonymous namespace. This should prevent subtle mistakes
when working with the configuration values of the Jack driver.
## Saving the settings
`AudioJack::setupWidget::saveSettings` saves the selections that have
been made from the widgets right into the configuration.
- Build RemoteVstPlugin in C++20 mode
- Avoids using std::wstring due to strange issues with it when built
with wineg++. See https://bugs.winehq.org/show_bug.cgi?id=58465
- Fix some memory leaks + minor cleanup of RemoteVstPlugin code
- Rename `F_OPEN_UTF8` to `fopenUtf8`
- Use C++20 in our `determine_version_from_source` CMake function
- Update ZynAddSubFX submodule
* Remove Knob::setHtmlLabel
Remove the unused method `Knob::setHtmlLabel` and its associated members.
This removes some unnecessary complexity from the code.
* Public label methods
Make `Knob::setLabel` public. Add `Knob::getLabel` for completeness.
* Delegate in KnobControl::setText
Make `KnobControl::setText` delegate to the `Knob` instance now that `Knob::setLabel` is public again.
Users can now choose if they only want to export the selected notes when
exporting a MIDI clip as an `xpt` or `xptz` file in the piano roll. The
export file dialog now shows a checkbox with the label "Export only
selected notes".
## Technical details
Add the new public method `exportToXML` to `MidiClip`. Compared to
`saveSettings` it has an additional parameter `onlySelectedNotes` which
controls which notes are exported. The default is to export all notes.
The method `saveSettings` now simply delegates to `exportToXML` using the
default.
`PianoRollWindow::exportMidiClip` now adds a check box to the export
dialog which lets users select if they only want to export the selected
notes or all notes. The default is to export all notes. The method now
uses the new method `exportToXML` for the export and passes the state of
the check box into the method.
Fix the import of `xpt` and `xptz` files by adding upgrade code to
`DataFile::type`. The new code maps the old textual representation
"pattern" to the enum `Type::MidiClip`.
Without the extra upgrade code the text "pattern" is mapped to
`Type::Unknown`. This then leads to problems at the end of
`DataFile::loadData` where the enum representation is mapped back to the
textual representation again to retrieve the root element from the
upgraded XML.
So without the upgrade it's:
* Map "pattern" to `Type::Unknown`
* Upgrade XML from "pattern" to "midiclip"
* `Type::Unknown` does not map to "midiclip" and fetching the root
element fails.
With the upgrade it's:
* Map "pattern" to `Type::MidiClip`
* Upgrade XML from "pattern" to "midiclip"
* `Type::MidiClip` is mapped to "midiclip" and fetching the root element
succeeds.
When you record an automation clip with a logarithmic knob (for example, a freq knob in the equalizer) the recorded values in the automation editor are correct.....
....But, for whatever reason, lmms tries to scale the recorded values back to linear when playing the automation, which causes the recorded frequency to be much lower.
This pr does not fix the underlying issue, but instead just scales the recorded values so that everything works.
When clearing notes from a long melody clip in pattern editor, it looks like the clip becomes short, but it actually remains the same length (despite empty), and that affects the length of the whole pattern. This PR fixes this issue.
Makes it so that editor zoom, automation tension, along with quantization, note length, and all other combo boxes are not added to the undo history.
---------
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Changes things so that only sample clips with auto-resize enabled will automatically resize to the sample length when dragging-dropping a sample from the sidebar onto a sample clip. Non-auto-resize clips will keep their original length, but still update so that their start time offset is 0.
Fixes TextFloat flickering which occurs when scrolling on knobs, faders, and note volume in the piano roll.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Adds two non-owning views for audio buffers: `InterleavedBufferView` and `PlanarBufferView`.
The channel count can be specified at either compile-time or runtime. Specifying at compile-time provides both performance and space optimizations. The way this works is the same as `std::span` except this uses the new `DynamicChannelCount` constant rather than `std::dynamic_extent`.
This PR makes it so that when you double-click on a sample clip and select a new sample, it will automatically update the length of the clip, as long as the clip has auto-resize enabled.
Fix a crash that occurs when running under Wayland and when loading a VST
plugin with the option "Keep plugin windows on top when not embedded"
enabled.
Enable the `AudioJack` to take recorded input and push it to the `AudioEngine`. This adds functionality for `AudioJack` which already exists for `AudioSdl` and `AudioPortAudio`. Note that sample track recording in the LMMS core is not completed before #7786 .
This PR also removes the reading and saving of the channel number configuration in several places as it will default to `DEFAULT_CHANNELS` all the time anyway.
Co-authored-by: Johannes Lorenz <j.git@lorenz-ho.me>
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Adjust the `Knob` class so that it defaults to taking the font size of
the knob's font into account when rendering its label. This allows to
use labels of different sizes for different knobs. Previously all knob
labels throughout the whole application were rendered with the same fixed
font size. Hence it was not possible to adjust the label size for a
single knob because this would have affected all other knobs as well.
The new implementation also allows the knobs to pick up CSS rules.
To be able to control the knob behavior two new constructors have been
added to the `Knob` class. Both constructors are concerned with creating
knobs with labels and therefore they directly take the label text as a
parameter. This removes numerous explicit calls to `setLabel` in the
code.
There is only one constructor that allows to switch between the new
behavior of taking the widget's font size into account and the old legacy
behavior of always rendering with the same fixed font size of
`SMALL_FONT_SIZE`. The parameter was modelled as an enum to make it
easier to find the remaining knob instances that use the legacy behavior.
This makes it easier to find them in case they should be removed as well.
In that case the string `LegacyFixedFontSize` can be searched.
The other new constructor allows to directly set the knob's (and
therefore the label's) font size to a pixel value.
Corresponding constructors have been added to `TempoSyncKnob`. The
constructors of `KnobControl` and `CustomTextKnob` have been adjusted to
take advantage of the new constructors. An usused constructor was removed
in `CustomTextKnob`.
The method `Knob::setLabel` has been made protected because labels should
now be set through the new constructors.
A new property called `m_fixedFontSizeLabelRendering` was added to the
`Knob` class. It controls how the labels are rendered. Fixed font size
legacy rendering can be activated by calling the protected method
`setFixedFontSizeLabelRendering`. The current setting can be queried via
`fixedFontSizeLabelRendering`.
## Changes in the plugins
Some plugins have been switched to using layouts to organize their
widgets so that they can accommodate for knobs with label sizes set by
the application font.
The fixed font size (legacy) rendering mode is still used in the
following places:
* EnvelopeAndLfoView
* InstrumentSoundShapingView
* InstrumentFunctionViews
* EffectView
* InstrumentTrackView
* SampleTrackView
* Delay plugin
* Carla plugin
# individual commit messages
What follows are the individual commit messages of the commits that have been squashed into one commit. They might help in case of more detailed investigations of how things came to be.
* Knob with correct label rendering
Enable the knob to render the label correctly at arbitrary sizes if it's configured to do so. Otherwise it will render like before. The used mode is determined when a label is set for the knob because as long as the label is not set a knob does not have one anyway.
The painting code now always renders the label with the font that's set for the widget.
The are now two methods to set the label text. The new method `setLabelLegacy` renders the label as before albeit in a slightly adjusted implementation. It now sets the widget font to a fixed pixel size font and then calculates the new widget size as before, i.e. not really taking the size of the font into account. This might lead to overlaps if the font of the knob is large.
The method `setLabel` now has an additional (temporary) parameter called `legacyMode`. It is by default set to `true` so that all knobs still render like they did before. This is implemented by delegating to `setLabelLegacy` if it's set to `true`. Otherwise the method calculates the new size of the widget by taking the pixmap and the label with the current font into account.
Please note that as of now you must set the knob font before calling any of the methods that sets the label. This is because the new size is only calculated via these code paths. However, this is already much better than only being able to use one hard-coded label size for all knobs.
* Switch from `setLabel` to `setLabelLegacy`
Switch all callers of `setLabel` to `setLabelLegacy` so that it becomes
obvious in which places the old knob implementation is used.
* Remove parameter `legacyMode` from `setLabel`
Remove the parameter `legacyMode` from `setLabel`. Add the member
`m_legacyMode` as it is needed in `Knob::changeEvent` so that we do not
switch the behavior when the knob is enabled/disabled.
* Extract methods
Extract `setLegacyMode` and `updateFixedSize`. Also add the getter `legacyMode`.
* Introduce legacy knob builders
Introduce legacy knob builders and apply them to the plugins. There are three new methods which encapsulate how to create a corresponding legacy knob:
* `Knob::buildLegacyKnob`
* `CustomTextKnob::buildLegacyKnob`
* `TempoSyncKnob::buildLegacyKnob`
These methods set the knob they build to legacy mode and also set a label in legacy mode. The idea is to concentrate the relevant legacy code in these methods. They will later also be useful to quickly find all the places in the application where legacy knobs are used.
The three methods are applied to the plugins directory. Most plugins use the build methods to build their knobs which also enables the removal of the explicit calls to `setLabelLegacy` from their code.
For some plugins their implementations were adjusted so that they can deal with showing the labels in the applicaiton font, i.e. in the font size of the widget their are contained in. Most of the times this involved removing the fixed size and putting the elements in a layout (while also removing move calls). The following LMMS plugins use the application font now and are thus better readable:
* Amplifier
* BassBooster
* Dispersion
* Flanger
* Peak Controller
* ReverbSC
* StereoEnhancer Effect
The Vectorscope now shows the "Persist." label in the same size as the label of the check boxes.
Setting an empty label was removed for Lb302.
* Legacy knob builders in GUI
Apply the legacy knob builders in the GUI components. Most components use the legacy knobs until they can be redesigned:
* Effect view ("W/D", "DECAY", "GATE")
* LFO Controller
* Instrument window
Everything related to the instrument window is for now kept to use the legacy knobs and should be adjusted at a later point to be more flexible:
* Envelope and LFO
* Functions
* Sound Shaping
The Instrument and sample track both use the legacy knobs for the "VOL" and "PAN" knobs. This might be adjusted later.
The following components now render the labels of their knobs with the application font size:
* MIDI CC Rack
* The class `LadspaControlView`, which is not in used anymore
Some vertical spacing was added to the MIDI CC Rack for slightly improved separation of the elements. The knobs are center aligned in the layout so that the transition between element under and over "CC 100" is cleaner. Setting the models in an explicit loop was removed and is now done when the knobs are created.
## Technical details
Extend `Knob::buildLegacyKnob` with the option to also set the name of the knob. This is needed for some changes in this PR.
The method `KnobControl::setText` now needs to distinguish between legacy mode and non-legacy mode.
* Remove `Knob::setLabelLegacy`
Remove `Knob::setLabelLegacy`. Instead make sure that the `Knob` updates its size in the following situations:
* The label is set.
* The font changes.
* Legacy mode is set or unset (already implemented).
The handling of font changes has been added to `Knob::changeEvent`. The update in case of a changed label is added to `Knob::setLabel`.
Every client that called `setLabelLegacy` now also sets the legacy font in size `SMALL_FONT_SIZE` as this was previously done in `setLabelLegacy`. The label is set via `setLabel` now. Both actions should result in an up-to-date size.
The method `KnobControl::setText` now only sets the label via `setLabel`, assuming that the wrapped knob was already configured correctly to either be a legacy knob or not.
* Use descent to calculate base line
Use the descent of the font to calculate the distance of the base line from the bottom of the knob widget if we are not in legacy mode. In legacy mode we still assume the descent to have a value of 2, i.e. the base line will always have a distance of 2 from the bottom of the knob widget regardless of the used font.
Also refactor the code a bit to make it more manageable.
* Extract `Knob::drawLabel`
Extract the method `Knob::drawLabel` which draws the label. It is called from `paintEvent`.
* Use non-legacy knobs for instrument and sample track
Use non-legacy knobs for the "VOL" and "PAN" knobs of the instrument and sample track. This gives a bit more separation between the knob and the label but to make this work the font size had to be decreased by one pixel.
* Introduce `buildKnobWithSmallPixelFont`
Introduce the builder method `buildKnobWithSmallPixelFont` in `Knob` and `TempoSyncKnob`. It creates a non-legacy knob with a small pixel sized font, i.e. it still uses the small font but with a corrected size computation and corrected space between the knob and the label. It is mostly used in places with manual layouts where there's enough space to have the bit of extra space between the knob and the label.
The following plugins use these knobs:
* Bitcrush
* Crossover EQ
* Dual Filter
* Dynamics Processor
* Multitap Echo
* Spectrum analyzer
* Mallets
* Waveshaper
* ZynAddSubFx
The "IN" and "OUT" label of the Bitcrush plugin use the default fixed font size now because the plugin uses a pixel based layout. Using the point based application font looked off.
They are also used in the following component:
* Effect view, i.e. the "W/D", "DECAY", "GATE" knobs of an effect
* LFO Controller
* Non-legacy knobs for VSTs
Use non-legacy knobs with small pixel fonts for the parameter lists of VST instruments and effects.
This is accomplished by renaming `CustomTextKnob::buildLegacyKnob` to `buildKnobWithSmallPixelFont` and removing the call to `setLegacyMode`.
* Fix styled knobs
Fix the handling of styled knobs which are created in non-legacy mode. Styled knobs do not use pixmaps and have no labels. Their size is set from the outside and they are painted within these limits. Hence we should not compute a new size from a pixmap and/or label in `Knob::updateFixedSize`.
This fixes the following plugins:
* FreeBoy
* Kicker
* Monstro
* Nescaline
* Opulenz
* Organic
* Sf2 Player
* sfxr
* SID
* SlicerT
* Triple
* Watsyn
* Xpressive
The functionality broke with commit defa8c0180e.
An alternative would have been to check for a styled knob in the contructor or `initUI` method and to set the legacy flag for these.
The best solution would likely be to create an own class for styled knobs and to pull that functionality out of `Knob` because they somewhat clash in their handling.
* Code review changes
Parameter whitespaces in the builder methods of `Knob`.
Use `adjustedToPixelSize` in `InstrumentTrackView` and `SampleTrackView`.
* Code review changes
Make the code that computes the new fixed size in legacy more readable
even if it is just legacy code that's was not touched. Add some code
documentation.
Other cosmetic changes:
* Whitespace adjustments
* Remove unused parameter in `paintEvent`
* Rename `knob_num` to `knobNum`
* Add documentation for legacy mode
Add some documentation which explains what the effects of legacy mode
are.
* Code review
Remove unnecessary dereference.
Also remove unncessary code repetition by introducing
`currentParamModel`.
* Decrease the label size of some knobs
Decrease the size of the following knob labels to 8 pixels:
* "VOL" and "PAN" in the instrument and sample track views
* "W/D", "DECAY" and "GATE" in the effect view
Technically this is accomplished by introducing
`Knob::buildKnobWithFixedPixelFont` and
`TempoSyncKnob::buildKnobWithFixedPixelFont`.
Both versions of `buildKnobWithSmallPixelFont` now also delegate to
the new methods.
* Adjustments to CrossoverEQControlDialog
Commit the adjustments that were done to `CrossoverEQControlDialog` which I had forgotten to add after fixing the merge.
* Fix formatting of CrossoverEQControlDialog
Fix the formatting of `CrossoverEQControlDialog` which got messed up after copying the code from the current version on GitHub.
* Code review changes
Use `std::max` instead of `qMax`. Remove some unnecessary whitespace.
* Protected legacy mode methods
Make `legacyMode` and `setLegacyMode` protected to ensure that legacy knobs can only be built using the factory method `buildLegacyKnob`. In the long term legacy mode should be removed.
* Code review: remove indexed access
The original request in the code review was to use `size_t` instead of
`uint32_t` in the for-loop. However it is possible to completely remove
the indexed access and to turn it into a simple iterated for-loop.
Also remove code repetition in the calculation of the maximum knob width
of the group. Use std::max instead of manual management.
* Fix u_int16_t to uint16_t
This should hopefully fix the WIndows builds.
* Fix AudioFileProcessor knobs
Fix a problem with the `AudioFileProcessorWaveView::knob` which is caused
by the fact the this knob uses the pixmap based knob type `Bright26`
without a label. Most other knobs that inherit from `Knob` set their knob
type to `Styled` which means that no pixmap is used to render the knob.
In the specific case the knob instance is created and the contructor
runs. In the constructor the AFP knob is set to a fixed size of (37,47).
However, at a later point the method `Knob::changeEvent` is triggered by
Qt due to a font change. This in turn calls `Knob::updateFixedSize` which
then recomputes the fixed size and effectively changes the width of the
knob to the width of the pixmap which is 27. Because the knob previously
was rendered centered with a width of 37 this means that the knob is now
effectively shifted by five pixels to the left.
This commit counters this effect by moving the affected AFP knobs five
pixels to the right. A visual difference between the fixed version and
the current master showed no differences. So this should fix the problem.
Because setting the knob to a fixed size of (37,47) does not have any
lasting effect anyway the code is removed from the constructor of the AFP
knob.
* Use legacy knobs in EffectView
* Legacy knobs for instrument & sample
Use legacy knobs for the instrument and sample track view ("VOL", "PAN").
* Add documentation to Knob builder methods
Add some documentation to the `Knob` builder methods. Mark `buildLegacyKnob` as deprecated and note that it should not be used in new code.
* Ensure legancy rendering for legacy knobs
Ensure that legacy knobs are always rendered at a size of 12 pixels,
i.e. `SMALL_FONT_SIZE`.
The previous implementation used the font metrics of the knob's current
font to compute the new fixed size and to render the label. It assumed
that the knob was created using `Knob::buildLegacyKnob` and that
therefore the font is set to 12 pixels. However, this meant that legacy
knobs can still be affected by style sheet settings. The following CSS
rule for example resulted in legacy knobs with a larger font size:
```
* { font-size: 18px; }
```
The fix is to use a font with a size of `SMALL_FONT_SIZE` when
calculating the fixed size of the `Knob` widget and when rendering it if
we are in legacy mode. This ensures that a legacy knob is unaffected by
CSS rules.
The non-legacy knob still uses the widget's font size and therefore it is
affected by CSS rules. However, this is a feature and not a bug because
when for example using a rule like the one above the knob does exactly
what it's asked to do.
* Remove unused constructor
Remove an unused constructor from CustomTextKnob
* Remove Knob::buildKnobWithSmallPixelFont
Remove the builder method `Knob::buildKnobWithSmallPixelFont` and replace
it with an equivalent new contstructor which takes the same arguments as
the build method.
* Remove Knob::buildKnobWithFixedPixelFont
Remove `Knob::buildKnobWithFixedPixelFont` as it is not used anymore.
Previously it was delegated to by the now removed method
`Knob::buildKnobWithSmallPixelFont`.
* Constructor for knobs with pixel size labels
Remove `TempoSyncKnob::TempoSyncKnob` and add an equivalent constructor.
Make `buildKnobWithSmallPixelFont` use the new constructor.
* Remove TempoSyncKnob::buildKnobWithSmallPixelFont
Remove `TempoSyncKnob::buildKnobWithSmallPixelFont` and make clients use
the new constructor.
* Remove CustomTextKnob::buildKnobWithSmallPixelFont
Remove `CustomTextKnob::buildKnobWithSmallPixelFont` and extend the
constructor so that it also takes a label. Previously all constructions
went through the build method and now all constructions use the extended
constructor.
* Knob constructors whichKnob constructors which take labels
Add constructors for `Knob` and `TempoSyncKnob` which also take the label
text. Make setLabel protected as most knobs should know their labels at
construction time.
This prevents "chatty" code like the following example:
```
Knob* knob = new Knob(KnobType::Bright26, this);
knob->setLabel("My label");
```
This now becomes a simple a one-liner:
```
Knob* knob = new Knob(KnobType::Bright26, "My label", this);
```
The constructor of `KnobControl` also had to be extended with the label
text because it cannot access the setLabel of the Knob that it manages.
However, it can pass the text during construction. Its implementation of
the virtual method `Control::setText` becomes empty due to this. The
`KnobControl` is currently only used in `Lv2ViewProc::Lv2ViewProc`. Here
the `KnobControl` is created by passing the port name into the
constructor. However, the virtual method `setText` is still called in
line 91 for all other implementations.
Add documentation for the constructors.
* Remove Knob::buildLegacyKnob
Remove `Knob::buildLegacyKnob` by extending the very similar constructor
with an enum that indicates whether the constructed `Knob` should be in
legacy mode or not. The default is to build a non-legacy `Knob`.
Wherever `Knob::buildLegacyKnob` was called the constructor is now called
with `Knob::Mode::Legacy` as the parameter. In some places where the
onject name is set `Knob::Mode::NonLegacy` has to be added explicitly.
* Remove TempoSyncKnob::buildLegacyKnob
Remove `TempoSyncKnob::buildLegacyKnob` by extending the very similar
constructor with an enum that indicates whether the constructed
`TempoSyncKnob` should be in legacy mode or not. The default is to
build a non-legacy `TempoSyncKnob`.
Wherever `TempoSyncKnob::buildLegacyKnob` was called the constructor is
now called with `Knob::Mode::Legacy` as the parameter.
* Vertical spacing for Peak Controller
Add a vertical spacing of 10 pixel between the knobs of the Peak Controller.
* Peak Controller: use default margins
Remove the specific call to `setContentsMargins` from the Peak Controller so that the main layout uses Qt's default margins.
Also remove the spacing again.
* Rename the enum `Knob::Mode`
Rename the enum `Knob::Mode` and its values so that they better describe
what they influence.
`Knob::Mode` is renamed to `Knob::LabelRendering` to indicate that its
value affects the label rendering.
The value `NonLegacy` is now called `WidgetFont` to indicate that the
knob uses the font settings of the widget when rendering the label.
The value `Legacy` is now called `LegacyFixedFontSize` to indicate that
it's a legacy behavior which uses a fixed font size that does not adhere
to the font size that's set for the widget's font.
Adjust all callers accordingly.
* Add TempoSyncKnob documentation
Document the constructor of `TempoSyncKnob` that can be used to set the
label rendering to lecacy mode.
* Name adjustments and parameter removal
Rename `m_legacyMode` to `m_fixedFontSizeLabelRendering`.
Rename the method `legacyMode` to `fixedFontSizeLabelRendering`.
Rename `setLegacyMode` to `setFixedFontSizeLabelRendering`. Also remove
the boolean parameter from the method as it was only called with `true`
anyway.
Reworks how note detuning copying works so as not to perform a clip duplication and allocation by default in the constructors
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Upgrade to Windows 2022 build runner and Visual Studio 2022 for MSVC builds.
Continue installing Qt 5.15.2 with the Visual Studio 2019 option since it doesn't provide a VS 2022 option.
A follow up to #7477, which ensures clips have auto-resizing enabled by default. This is needed because auto-resizing was the default behavior, but the code tried to use this newly added attribute with a default of 0 (i.e., auto resizing is not enabled).
Fixes a crash that occurs when attempting to play within the Pattern Editor with no Pattern Track created.
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
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.
Allow for splitting and resizing all types of clips (automation, MIDI, sample, pattern, etc) using the knife tool in the Song Editor.
---------
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Added the ability to favorite items. This gets added to its own tab named "My Favorites".
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
This PR refactors how the spacebar is handled by the editors and the MainWindow to allow it to play/stop (Shift+Space for play/pause) the last played editor, no matter if it is in focus or not.
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
Adds the ability to reverse the selected midi notes in the PianoRoll.
The tool is located under the wrench icon in the PianoRoll and can also be triggered with Shift-R.
---------
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Previously, clicking on a track or dragging in a sample would always create a clip on the closest/previous bar, no matter what the Song Editor's snap size was. This fixes that issue by using the Song Editor's quantization when placing new clips, so for example if the snap size is 1/4 bar, the clip will be added at the closest/previous 1/4 bar mark.
* Add /.cache/ to .gitignore
Normally clangd's .cache exists in /build/, which is already in the .gitignore, but if cmake is run in the repository root instead of /build/ the cache is in turn generated in the repository root.
* Also add compile_commands.json to .gitignore
Newly created MIDI tracks were not automatically assigned to the desired MIDI device when the option to do so was specified in settings. This commit fixes that.
- Remove pointless *.exe option
- Add an "All VST files" option on Linux when there is both LinuxVST and Wine VST support
- Remove *.dll option from Linux builds without Wine VST support (i.e. LinuxVST-only builds)
* Renamed lmms_basics.h to LmmsTypes.h and scoped it down for that purpose.
* Shifted the LMMS_STRINGIFY macro to it's own header.
* Removed the debug.h header file and use cmake to handle the macro logic.
* Remove some unused headers and include directives
Adds a complex strum tool to the Piano Roll, allowing the user to take a selection of chords, and drag around the notes to shape the strum exactly how they want it.
---------
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
Fixes a regression from 07baf9e27a, in
which a channel that was created through a tracks "Assign track to new
mixer channel" context menu would display an incorrect name until it was
renamed by a user.
Created and replaced missing/mismatched assets, fixed mixer send arrows causing mixer height to be wrong, tweaked CSS stylesheet to fix active mixer channel being black
* Fix crash when switching opened projects #7793
When the DAW is already running with an open project and you attempt to
open another project via File > Open, a segfault used to occur.
The crash seems to have been caused by model()->value(), which was
called in Fader::getModelValueAsDbString(). The model() function
looked like it should return a pointer to an AutomatableModel.
I suspect that when a model was dropped in favor of loading models for
a new project, the AutomatableModel pointer became a null pointer.
Add a check to the AutomatableModel pointer so getModelValueAsDbString
returns early (before accessing member functions) if the pointer is
null. This fixes the crash.
Allow embed.cpp to load SVG assets at screen DPI by leveraging QPixmap::setDevicePixelRatio
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
Co-authored-by: Fawn <rubiefawn@gmail.com>
In #7708, the track operations widget was given a centered vertical alignment in order to fix an aesthetic layout issue. This is being reverted, since it is possible to resize tracks, and all the other track interface elements are top-aligned.
The y-axis quantization for graph values was being calculated
incorrectly. This would have gone unnoticed since the only step sizes
currently used are 0 (continuous) or 1. Any other values produce
"sloped" quantization. This fix prevents this error from affecting
any future uses of graphModel.
* Add mute and solo buttons to instrument windows
* Change mute and solo buttons to optimized CC0 SVG assets
* Icons provided by @StakeoutPunch, button backgrounds provided by
@RebeccaDeField
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Co-authored-by: Rebecca Noel Ati <contactme@rebeccadefield.com>
Co-authored-by: Stakeout Punch <StakeoutPunch@users.noreply.github.com>
* Accessors for volume, cutoff, resonance
Add private accessors for the volume, cutoff and resonance parameters (envelope and LFO).
This makes the code less technical and more readable as it for example removes lots of static casts. The casts are now done in a special helper method that returns the parameters for a given target.
* Remove EnvelopeAndLfoParameters array
Remove the `EnvelopeAndLfoParameters` array and use explicit instances for volume, cutoff, resonance. This simplifies construction and initialization of the instances.
Besides the array this also removes the `Target` enum and the `NumTargets` value.
To simplify storage and retrieval of the parameters three private methods have been added which provide the node names of the volume, cutoff and resonance parameters.
Adjust `InstrumentSoundShapingView` to the removed `NumTargets` property.
* Use references instead of pointers
Use references to the volume, cutoff and resonance parameters instead of pointers.
* Remove friend relationship
Remove the friend relationship between `InstrumentSoundShaping` and its related view by providing the models via getters.
* Get rid of targetNames
Get rid of `InstrumentSoundShaping::targetNames` by using translations and strings directly. Move the remaining stuff into `InstrumentSoundShapingView` until it is removed there as well.
* Explicit EnvelopeAndLfoViews
Remove the array of EnvelopeAndLfoViews and use dedicated instances instead.
This also enables the final removal of the remaining `targetNames`.
* Move the code of some getters
Move the code of some getters into the header file.
* Several code review changes
Apply some code review proposals.
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Refactors `AudioFileOgg`, a class used to export to OGG files. There were problems reported of the exported OGG file failing to be played back on some systems. To fix this issue as well as to improve code quality, the class was refactored. In addition, VBR (variable bit rate) is always used, with the quality of the export being determined by a ratio of the selected bit rate and the maximum bit rate allowed. This change naturally occurred when refactoring, though the libvorbisenc documentation recommend VBR for improved audio quality.
Adds the ability to cut multiple notes at once in the Piano Roll. Users can select the Knife tool and create a cut line by holding the mouse and dragging it across the notes that should be cut. This also allows cutting the notes at an angle. When releasing the mouse, the Shift key can be pressed to remove the shorter end of the notes that were cut. If any notes are selected, only they will be considered for the cut, even if the cut line covers more notes.
The scroll bars shown in the main window were removed in favor of a new navigation feature that utilizes dragging the mouse instead. Users can now hold the mouse down on an empty part of the workspace and drag the mouse around to navigate where necessary.
Introduces a new class FileRevealer to manage file selection across different platforms (Windows, macOS, Linux, and other *nix operating systems with xdg). Includes methods to open and select files or directories using the default file manager on the respective platform.
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Use dbFS scale for the faders
Make the faders use a linear dbFS scale. They now also change position on first click and can then be dragged.
The `Fader` class now has a new property called `m_faderMinDb`. It's the minimum value before the amplification drops down fully to 0. It is needed because we cannot represent a scale from -inf to maxDB.
Rename `knobPosY` to `calculateKnobPosYFromModel` and move the implementation into the cpp file. The method now first converts the model's current amplification value to dbFS and then computes a ratio based on that values and the minimum and maximum dbFS values.
Add the method `setVolumeByLocalPixelValue` which takes a local y coordinate of the widget and sets the amplification of the model based on a dbFS scale.
Adjust `mousePressEvent` and `mouseMoveEvent` so that they mostly take the local y coordinate of the event and use that to adjust the model via `setVolumeByLocalPixelValue`.
Remove `m_moveStartPoint` and `m_startValue` and they are not needed anymore.
* Apply curve to faders
Apply a curve, i.e. the cube function and its inverse, to the fader
positions to that we have more space to work with in the "interesting"
areas around 0 dB and less space in the area where we tend to "-inf dB".
Set the minimum dB value of the fader to -120 dB to increase the potential
headroom.
* Support for dB models
Add support for models that are in dB.
There's a new member `m_modelIsLinear` which can be set via the
constructor. The default value in the constructor is `true`.
Add the method `modelIsLinear` which can be used to query the parameter.
It is used in `calculateKnobPosYFromModel` and
`setVolumeByLocalPixelValue`. Both methods got extended to deal with
models in dB. They were also refactored to extract code that is common
for both cases.
Ensure that the constructor of `Fader` is called with `false` for
`CrossoverEQControlDialog` and `EqFader` because these use models that
are in dB.
* Show current dB value of fader in tool tip
Show the current value of the fader in its tool tip. Please note that
this value is always shown in dB because the goal should be to get rid
of the linear values for the faders.
Some of the code is extracted into the new method
`Fader::getModelValueAsDbString` which is shared by
`Fader::modelValueChanged` (also new) and `Fader::updateTextFloat`.
Please note that `getModelValueAsDbString` will use "dB" instead of
"dBFS" as the unit and that it will format "-inf dB" instead of "-∞ dB".
These changes will also be visible in the text float that is used to
show the new values as the fader is being dragged.
* Let users enter values in dB
Let users enter values in dB in the dialog that opens with a double
click.
The minimum value that can be entered is the minimum value that the
fader allows to set, i.e. -120 dB. The maximum value is the maximum
value of the model converted to dB. As of now this is ~6 dB. The
current value is converted to dB. If it corresponds to "-inf dB", i.e.
if the amplification is 0 then the minimum value is used.
* Remove option "Display volume as dBFS"
Remove the option "Display volume as dBFS" from the settings dialog and
the check box option "Volume as dBFS" from the "View" menu. Volumes are
now always treated as dB, i.e. all evaluations of the property
"displaydbfs" have been removed which results in assuming that this
option is always true.
The upgrade code in `ConfigManager::upgrade_1_1_91` was left as is.
However, a note was added which informs the reader that the value of
"displaydbfs" is not evaluated anymore.
* Extend Fader::wheelEvent
Extend `Fader::wheelEvent` for the case where the model is not a dB
model (`modelIsLinear() == true`), e.g. for the mixer faders. In that
case it works as follows. Each step increments or decrements by 1 dB if
no modifier is pressed. With "Shift" pressed the increment value is 3 dB.
With "STRG" ("CTRL") pressed the increment value is reduced to 0.1 dB. If
the value goes below the minimum positive dB value that is allowed by the
fader then the fader is set to "-inf dB", i.e. zero amplification. If the
fader is set to "-inf dB" and the users want to increase the value then
it is first set to the minimum positive value that is allowed by the
fader.
If the model is a dB model then the same behavior as before is used.
Although it should be considered to adjust this case as well. These
models are used by the faders of the Crossover Equalizer, Equalizer,
Compressor and Delay and they are not very usable with the mouse wheel.
* Adjust the wheel behavior for faders with dB models
Make the faders of the Crossover Equalizer, Equalizer, Compressor and
Delay behave like the mixer faders, i.e. step in sizes of 3 dB, 1dB and
0.1 dB depending on whether a modifier key is pressed or not.
Extract some common code to do so and add some `const` keywords.
* Less "jumpy" knobs
Implement a more stable knob behavior.
Remove the jumping behavior if the users directly click on a volume
knob. By storing the offset from the knob center and taking it into
account during the changes it now also feels like the users are
dragging the knob.
Changes to the amplification are now only applied when the mouse is
moved. This makes the double click behavior much more stable, i.e. if
users click on the knob when it is at 0 dB the dialog will also show
0 dB and not something like 0.3 dB because the first click is already
registered as a change of volume.
If the users click next to the knob the amplification will still be
changed immediately to that value.
## Technical details
To make the knobs more stable a variable called `m_knobCenterOffset` was
introduced. It stores the offset of the click from the knob center so
that this value can be taken into account for in the method
`setVolumeByLocalPixelValue`.
* Make MSVC happy
Add an indication that a float value is assigned to a float variable.
* Introduce constexpr for scaling exponent
Introduce the `constexpr c_dBScalingExponent` which describes the
scaling exponent that's used to scale the dB scale in both directions.
This will simplify potential adjustments by keeping the values
consistent everywhere.
* Draw fader ticks
Draw fader ticks in case the model is a linear one. This means that for
now they should only be painted for the mixer faders but not for the
faders of the Compressor, Delay, etc.
Extract the computation of the scaled ratio between the maximum model dB
value and the minimum supported fader dB value into the new private
method `computeScaledRatio`. This is necessary because it is needed to
paint the fader knob at the correct position (using the knob bottom as
the reference) and to paint the fader ticks at the correct position
(using the knob center).
Introduce the private method `paintFaderTicks` which paints the fader
ticks.
Note: to paint some non-evenly spaced fader ticks replace the `for`
expression in `paintFaderTicks` with something like the following:
```
for (auto & i : {6.f, 0.f, -6.f, -12.f, -24.f, -36.f, -48.f, -60.f, -72.f, -84.f, -96.f, -108.f, -120.f})
```
* Fader adjustments via keyboard
Allow the adjustment of the faders via the keyboard. Using the up or
plus key will increment the fader value whereas the down or minus key
will decrement it. The same key modifiers as for the wheel event apply:
* No modifier: adjust by 1 dB
* Shift: adjust by 3 dB
* Control: adjust by 0.1 dB
Due to the very similar behavior of the mouse wheel and key press
handling some common functionality was factored out:
* Determinination of the (absolute) adjustment delta value by
insprecting the modifier keys of an event. Factored into
`determineAdjustmentDelta`.
* Adjustment of the model by a given dB delta value. Factored into
`adjustModelByDBDelta`.
* Move the fader of the selected channel
Move the fader of the selected channel instead of the fader that has
focus when the up/plus or down/minus keys are pressed. Doing so also
feels more natural because users can already change the selected
channel via the left and right keys and now they can immediately adjust
the volume of the currently selected channel while doing so.
Key events are now handled in `MixerView::keyPressEvent` instead of
`Fader::keyPressEvent` and the latter is removed. `MixerChannelView`
now has a method called `fader` which provides the associated fader.
This is needed so that the event handler of `MixerView` can act upon
the currently selected fader.
## Changes in Fader
The `Fader` class provides two new public methods.
The `adjust` method takes the modifier key(s) and the adjustment
direction and then decides internally how the modifier keys are mapped
to increment values. This is done to keep the mapping between modifier
keys and increment values consistent across different clients, e.g. the
key event of the `MixerView` and the wheel event of the `Fader` itself.
The direction is provided by the client because the means to determine
the direction can differ between clients and cases, e.g. a wheel event
determines the direction differently than a key event does.
The method `adjustByDecibelDelta` simply adjusts the fader by the given
delta amount. It currently is not really used in a public way but it
still makes sense to provide this functionality in case a parent class
or client wants to manipulate the faders by its very own logic.
Because the `Fader` class does not react itself to key press events
anymore the call to `setFocusPolicy` is removed again.
* Enter fader value when space key pressed
Let the users enter the fader value via dialog when the space key is
pressed.
Extract the dialog logic into the new method `adjustByDialog` and call
it from `MixerView::keyPressEvent`.
Make `Fader::mouseDoubleClickEvent` delegate to `adjustByDialog` and
also fix the behavior by accepting the event.
* More prominent fader ticks around 0 dB
Make the fader ticks around 0 dB more prominent but drawing them
slightly wider and with a more opaque color.
* Work around a Qt bug
Work around a Qt bug in conjunction with the scroll wheel and the Alt
key. Simply return 0 for the fader delta as soon as Alt is pressed.
* Fix wheel events without any modifier
Fix the handling of wheel events without any modifier key being pressed.
Commit ff435d551b accidentally tested against Alt using a logical OR
instead of an AND.
* Code review changes
First set of code review changes:
* Use Doxygen style documentation comments
* Remove comment about `displaydbfs` from upgrade routine
* White-space changes for touched lines.
* Make minimum dB value a constexpr
Make the minimum dB value a constexpr in the implementation file because
currently it's an implementation detail that should not be of any
interest to any other client.
So `m_faderMinDb` becomes `c_faderMinDb`.
* More flexible painting of fader ticks
Paint the fader ticks in a more systematic and flexible way. This also
removes some "magic numbers", e.g. by using `c_faderMinDb` instead of
`-120.f` as the lower limit.
The upper limit, i.e. the "starting point" is now also computed using
the maximum value of the model so that the fader will still paint
correctly if it ever changes.
* Make the zero indicator bolder
Make the zero indicator tick of the fader bolder.
* Make rendering of fader ticks a preference
Make rendering of fader ticks a preference which is off by default.
Introduce the new option "Show fader ticks" to the setup dialog and save
it to the UI attribute `showfaderticks`.
The configuration value is currently evaluated in `Fader::paintEvent`.
If this leads to performance problems it might be better to introduce a
boolean member to the `Fader` class which caches that value.
* Move constexprs to anonymous namespace
* unmute related FX channels
When soled one FX channel, unmute send and receive channels, to allow complex FX channel routing (BUS, SENDs, etc.)
* Comment change
* SEND channels
Activate also SEND channels recursively
* Remove unnecessary whitespace
* Encapsulate mixer channel index
Make the mixer channel index `m_channelIndex` private and add getters and
setters. Also add a method to determine if the channel is the master
channel.
Move `m_channelIndex` to the end of the initialization list of the
`MixerChannel` constructor because it is now the last member in the
header.
Adjust all clients to make use of the new methods.
* Replace const int& getIndex() with int index() const
* Format changes
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
* use c++20 concepts and numbers for lmms_constants.h
* replace lmms::numbers::sqrt2 with std::numbers::sqrt2
* replace lmms::numbers::e with std::numbers::e
Also replace the only use of lmms::numbers::inv_e with a local constexpr instead
* remove lmms::numbers::pi_half and lmms::numbers::pi_sqr
They were only used in one or two places each
* replace lmms::numbers::pi with std::numbers::pi
* add #include <numbers> to every file touched so far
This is probably not needed for some of these files. I'll remove those later
* Remove lmms::numbers
Rest in peace lmms::numbers::tau, my beloved
* Add missing #include <numbers>
* replace stray use of F_EPSILON with approximatelyEqual()
* make many constants inline constexpr
A lot of the remaining constants in lmms_constants.h are specific to
SaProcessor. If they are only used there, shouldn't they be in SaProcessor.h?
* ok then, it's allowed to be signed
* remove #include "lmms_constants.h" for files that don't need it
- And also move F_EPSILON into lmms_math.h
- And also add an overload for fast_rand() to specify a higher and lower bound
- And a bunch of other nonsense
* ok then, it's allowed to be inferred
* ok then, it can accept an integral
* fix typo
* appease msvc
* appease msvc again
* Replace linearInterpolate with std::lerp()
As well as time travel to undo several foolish decisions and squash tiny
commits together
* Fix msvc constexpr warnings
* Fix msvc float to double truncation warning
* Apply two suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Apply suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* fix silly mistake
* Remove SlicerT's dependence on lmms_math.h
* Allow more type inference on fastRand() and fastPow10f()
* Apply suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Clean up fastRand() a little bit more
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Try to fix MSVC linker error related to lilv
* Remove temporary workaround
* Temporary debugging messages
* oops
* Temporary debugging
* Try to find FluidSynth using Config mode first
* Try again to fix lilv
* Fix FluidSynth installed with vcpkg on Windows
* Fix lilv from vcpkg
* Remove debug flag
* Fix for when lilv is not found (*-NOTFOUND evaluates to false)
* Use lowercase package name for lv2
* Try using only pkg_check_modules for lv2
* Use Lilv::lilv
* Add pkg-config guard back in
* Fix package name
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
* Fix Lilv_INCLUDE_DIRS
* Rename vcpkg cache key
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
macOS: Replace Command + Drag shortcut key with Option + Drag
Add new header `KeyboardShortcuts.h` for platform-specific keyboard mappings
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
* use c++ std::* math functions
This updates usages of sin, cos, tan, pow, exp, log, log10, sqrt, fmod, fabs, and fabsf,
excluding any usages that look like they might be part of a submodule or 3rd-party code.
There's probably some std math functions not listed here that haven't been updated yet.
* fix std::sqrt typo
lmao one always sneaks by
* Apply code review suggestions
- std::pow(2, x) -> std::exp2(x)
- std::pow(10, x) -> lmms::fastPow10f(x)
- std::pow(x, 2) -> x * x, std::pow(x, 3) -> x * x * x, etc.
- Resolve TODOs, fix typos, and so forth
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Fix double -> float truncation, DrumSynth fix
I mistakenly introduced a bug in my recent PR regarding template
constants, in which a -1 that was supposed to appear outside of an abs()
instead was moved inside it, screwing up the generated waveform. I fixed
that and also simplified the function by factoring out the phase domain
wrapping using the new `ediv()` function from this PR. It should behave
how it's supposed to now... assuming all my parentheses are in the right
place lol
* Annotate magic numbers with TODOs for C++20
* On second thought, why wait?
What else is lmms::numbers for?
* begone inline
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* begone other inline
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Re-inline function in lmms_math.h
For functions, constexpr implies inline so this just re-adds inline to
the one that isn't constexpr yet
* Formatting fixes, readability improvements
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix previously missed pow() calls, cleanup
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Just delete ediv() entirely lmao
No ediv(), no std::fmod(), no std::remainder(), just std::floor().
It should all work for negative phase inputs as well. If I end up
needing ediv() in the future, I can add it then.
* Simplify DrumSynth triangle waveform
This reuses more work and is also a lot more easy to visualize.
It's probably a meaningless micro-optimization, but it might be worth changing it back to a switch-case and just calculating ph_tau and saw01 at the beginning of the function in all code paths, even if it goes unused for the first two cases. Guess I'll see if anybody has strong opinions about it.
* Move multiplication inside abs()
* Clean up a few more pow(x, 2) -> x * x
* Remove numbers::inv_pi, numbers::inv_tau
* delete spooky leading 0
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
---------
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This PR attempts a number of improvements to the sample rendering (in the song editor, automation editor, AudioFileProcessor, SlicerT, etc) in LMMS:
Thumbnails: Samples are aggregated into a set of thumbnails of multiple resolutions. The smallest larger thumbnail is then chosen for rendering during sample drawing. Each set of thumbnails is stored with its sample file metadata in an unordered_map, so that duplicate samples will use the same set of thumbnails.
Partial rendering: additionally, this PR only renders the portions of the sample clips visible to the viewer to save rendering time.
* Experimental sample thumbnail
* Rename some classes and type aliases. Make some type declarations explicit
* Use a combination of audioFile name and shared_ptrs to track samples; refactor some loops
* That weird line at the end of the sample is now gone
* Small changes to the code; Add comments
* Add missing word to comment; Fix typo
* Track `SharedSampleThumbnailList`s instead
* Major refactor; implement thumbnailing for SlicerT, AFP and Automation editor
* Code clean up, renames and documenting
* Add the namespace lmms comments
* More code updates and documentation
* Fix error in comment
* Comment out `qDebug`s
* Fix formatting
* Use alternative initialization of `SampleThumbnailVisualizeParameters`
* Remove commented code
* Fix style and simplify code
* Use auto
* Draw lines using floating point
* Merge the classes into one nested class
+ Replace while loop with std::find_if
* Fix comparison of different signedness
* Include memory header
* Fix a logic error when selecting samples; Rename a const
* Fix more issues with signedness
* Fix sample drawing error in `visualizeOriginal`
* Only render regions in view of the sample
* Allow partial repaints of sample clips
* Remove unused variable
* Limit most of the painting to the visible region
* Revert back to using rect() in some places
* Partial rendering for AutomationEditor
* Don't redraw painted regions; allowHighResolution; remove `visualizeOriginal`; Remove s_sampleThumbnailCacheMap
* Add s_sampleThumbnailCacheMap back for testing convenience
* Minor change to the way `thumbnailSizeDivisor` is calculated
* Extend update region by an amount
* forgot about this
* Adapt to master; Redesign VisualizeParameters; Don't rely entirely on needsUpdate()
* Don't try to preserve painted regions
* Allow for a bit more thumbnails; Fix incorrect rendering when vertically scrolling
* Fix missing include statement
* Remove the unused variable
* Code optimization; Remove RMS member from Bit; Rename viewRect to drawRect
* More code optimizations
* Fix formatting
* Use begin instead of cbegin
* Improve generation of thumbnails
* Improve expressiveness of the draw code
* Add support for reversing
* Fix drawing code
* Fix draw code (part 2)
* Apply more fixes and simplifications
* Undo some out of scope changes
* Remove SampleWaveform
* Improve documentation
* Use size_t for some counters
* Change width parameter to be size_t
* Remove temporary aggregated peak variable
* Bump up AggregationPerZoomStep to 10
* Zoom out only requested range of thumbnail instead of clipping it separately
* Rename targetSampleWidth to targetThumbnailWidth
* Handle reversing for AFP; Iterate in reverse instead of reversing the entire thumbnail
* Change names to be more accurate
* Improve implementation of sample thumbnail cache map
* Move AggregationPerZoomStep back down to 2, do not cap smallest thumbnail width to display width
To improve performance with especially long
samples (~20 minutes)
* Simplify sample thumbnail cache handling in constructor
* Call drawLines instead of drawLine in a loop
QPainter::drawLine calls drawLines with a line count of 1. Therefore, calling drawLine in a loop means we are simply calling drawLines a lot more times than necessary.
* Bump up AggregationPerZoomStep to 10 again
Thought using 2 would help performance (when rendering). Maybe it does, but it's still quite slow when rendering a bunch of thumbnails at once.
* Fix off-by-one error when constructing Thumbnail from buffer
* Fix crash when viewport is not in bounds
* Apply performance improvements
Performance in the zoomOut function was bad because of the dynamic memory allocation. Huge chunks of memory were being allocated quite often, casuing a ton of cache misses and all around slower performance. To fix this, all the necessary downsampling is now done within the for loop and handled one pixel after another, instead of all at once.
To further avoid allocations in the draw call, the change to use drawLines has been reverted.
We now pass VisualizeParameters by value (it is only 64 bytes, which will fit quite nicely in a cache line, which is more benefical than reaching for that data by reference to some other part of the code).
After applying these changes, we are now practically only bounded by the painting done by Qt (according to profiling done by Valgrind). Proper use of OpenGL could resolve this issue, which should finally make the performance quite optimal in variety of situations.
* Apply minor changes
Update copyright and unused functions. Move in newly created thumbnail into the cache instead of copying it.
* Use C++20's designated initializers
* Create param right before visualizing
* Fix regressions with reversing
* Fix incorrect rendering in AFP and SlicerT
* Move MaxSampleThumbnailCacheSize and AggregationPerZoomStep into implementation file
* Remove static keyword
* Remove getter and setter for peak data
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
* add templates for common geometric constants
* oops missed one
* LD_2PI -> LD_PI
i re-added the wrong constant ffs
* CamelCase names and also verify compilation without -DLMMS_MINIMAL
* C++20 stuff
Updated to account for `<numbers>` and C++20:
- Marked all `lmms_constants.h` constants with an exact equivalent in `<numbers>` as deprecated
- Removed all `lmms_constants.h` constants where no variant is currently in use
- Using `inline constexpr`
- Using `std::floating_point` concept instead of `typename`
* add lmms::numbers namespace
* Remove panning_constants.h
Moves the four constants in panning_constants.h into panning.h, then
removes panning.h.
* Use std::exp(n) instead of powf(numbers::e, n)
* Use C++ std math functions
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Use overloaded std math functions
An attempt to fix compiler warnings on some platforms
* Remove uses of __USE_XOPEN
And also update two functions I missed from the previous commit
* Missed a few
* Fix ANOTHER std math function use
Of course there's another one
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix rendering for Vectorscope
The rendering of the Vectorscope is broken on Wayland if the size of the
Vectorscope is increased. This is caused by using a `QImage` to render
the scope traces which is then scaled up.
Introduce a new way to paint the vector scope (goniometer) which simply
paints lines or points that progressively get dimmer and which does not
make use of a QImage anymore.
It supports the following features:
* Log mode
* Zooming
* Rendering the drawing performance
* Selecting a different color for the traces
It does not support:
* HQ Mode: The new implementation provides a performance that's
equivalent to Non-HQ mode and look similar or better than the HQ mode.
* Blurring of old data
* Persistence: Might be implemented by using a factor for the dimming
Rendering of the samples/trances uses the composition mode "Plus" so
that overlapping elements will appear like adding brightness. Painting
the grid and lines is done using the normal composition mode "Source
Over" so that it simply replaces existing pixels.
Painting of the lines/points and the grids and lines is done in a
"signal space", i.e. a transform where elements in the interval of
[-1, 1] feel "natural". The text is painted in "widget space".
* Remove old implementation
Remove HQ mode and persistence. Also remove the legacy option again.
This removes the models, loading, saving and the GUI controls.
Remove all unnecessary members from `VectorView`, adjust the
constructor. Move the implementation of `paintLinesMode` into
`paintEvent`. Remove methods `paintLegacyMode` and `paintLinesMode`.
* Move colors into VectorView
Move the colors out of `VecControls` into `VectorView` as they are
related to presentation.
* Remove friend relationship to VectorView
Remove a friend relationship to `VectorView` from `VecControls` by
introducing const getters for the models.
* Remove VectorView::m_visible
Remove the unnecessary member `m_visible` from `VectorView`. It was not
initialized and only written to but never read.
* Make Vectorscope themeable
Make the Vectorscope themeable by introducing Qt properties for the
relevant colors.
The default theme gets the values from the code whereas the classic
theme gets a trace with amber color.
* Rename m_colorFG
Rename `m_colorFG` to `m_colorTrace`. Adjust the Qt property
accordingly.
Remove local variable `traceColor` from paint method and use member
`m_colorTrace` directly.
* Remove m_colorOutline
Remove unused member `m_colorOutline`.
* Fix horizontal lines on silence
Fix the horizontal lines that are rendered on silence. They seem to be
produced when rendering lines that start and end at the same point.
Therefore we only draw a point if the current and last point are the
same.
* Add some margin to the VectorView
Add some margin to the rendering of the `VectorView` so that the circle
does not touch the bounary of the widget.
* Clean up the layout of the Vectorscope
Clean up the layout of the Vectorscope. The checkboxes are not put on
top of the vector view anymore but are organized in a horizontal layout
beneath it. This gives a much tidier look.
* Maximize button for resizable instruments
Show the maximize button for resizable instruments.
Most other changes have the character of refactorings and code
reorganizations.
Remove the negation in the if condition for resizable instruments to
make the code better readable.
Only manipulate the system menu if the instrument is not resizable.
Add a TODO to the special code that sets a size.
* Fix rendering of maximized sub windows
In `SubWindow::paintEvent` don't paint anything if the sub window is
maximized . Otherwise some gradients are visible behind the maximized
child content.
In `SubWindow::adjustTitleBar` hide the title label and the buttons if the
sub window is maximized. Always show the title and close button if not
maximized. This is needed to reset the state correctly after
maximization.
* Add SubWindow::addTitleButton
Add the helper method `SubWindow::addTitleButton` to reduce code
repetition in the constructor.
* Only disable the minimize button
Disable the minimize button by taking the current flags and removing
the minimize button hint from them instead of giving a list which might
become incomplete in the future. So only do what we want to do.
* Remove dependency on MdiArea
Remove a dependency on the `MdiArea` when checking if the sub window is
the active one. Query its own window state to find out if it is active.
* Clear Qt::MSWindowsFixedSizeDialogHint
Clear the `Qt::MSWindowsFixedSizeDialogHint` flag for resizable
instruments (symmetric to the `else` case).
* Update the sub window title bar of exchanged instruments
Update the title bar of an instrument's sub window if the model changes, e.g. if an instrument is exchanged via drag & drop.
The main fix is to call the new method `updateSubWindowState` in `InstrumentTrackWindow::modelChanged`. It contains mostly the code that was previously executed in the constructor of `InstrumentTrackWindow`. The constructor now simply calls this method after it has put the constructed instance into a sub window.
With the current implementation the sub window needs to be explicitly triggered to update its title bar once the flags have been adjusted in `updateSubWindowState`. This is done with the new public method `SubWindow::updateTitleBar`. Please note that such an explicit update is not needed if the instrument windows are managed by a `QMdiSubWindow` instead of a `SubWindow`. This means that the implementation of `SubWindow` is still missing something that `QMdiSubWindow` does. However, debugging also showed that setting the window flags of the sub window does not seem to lead to an event that could be caught in `SubWindow::changeEvent`. This was found out by simply dumping the event types of all events that arrive in that method and exchanging an instrument.
The method `updateSubWindowState` uses the added method `findSubWindowInParents` to find the sub window it is contained in. The latter method should be considered to be moved into a templated helper class because it might be useful in other contexts as well.
## Technical details
If you want to experiment with using QMdiSubWindows then simply add the following method to `MainWindow` (right next to `addWindowedWidget`):
```
QMdiSubWindow* MainWindow::addQMdiSubWindow(QWidget *w, Qt::WindowFlags windowFlags)
{
// wrap the widget in our own *custom* window that patches some errors in QMdiSubWindow
auto win = new QMdiSubWindow(m_workspace->viewport(), windowFlags);
win->setAttribute(Qt::WA_DeleteOnClose);
win->setWidget(w);
m_workspace->addSubWindow(win);
return win;
}
```
Then call that method instead of `addWindowedWidget` in the constructor of `InstrumentTrackWindow`:
```
QMdiSubWindow* subWin = getGUI()->mainWindow()->addQMdiSubWindow( this );
```
You can then comment out the cast and the call of `updateTitleBar` in `updateSubWindowState` and everything will still work.
* Update the system menu
Show or hide the "Size" and "Maximize" entries in the system menu
depending on whether the instrument view is resizable or not.
* Show non-resizable instruments as normal
Show the sub windows of non-resizable instruments as normal if the sub
window is maximized because it was previously used with a resizable
instrument.
* Fix typo
* Rename updateSubWindowState
Rename `updateSubWindowState` to `updateSubWindow`.
* Compile in C++20 mode
* Fix implicit lambda captures of `this` by `[=]`
Those implicit captures were deprecated in C++20
* Silence MSVC atomic std::shared_ptr warning
Unfortunately std::atomic<std::shared_ptr> (P0718R2) is not supported by
GCC until GCC 12 and still is not supported by Clang or Apple Clang, so
it looks like we will continue using std::atomic_load for the time being
* Use C++20 in RemoteVstPlugin
* Simplification
* Add comment
* Fix bitwise operations between different enumeration types
* Revert "Fix bitwise operations between different enumeration types"
This reverts commit d45792cd72.
* Use a helper function to combine keys and modifiers
* Remove AnalyzeTemporaryDtors from .clang-tidy
AnalyzeTemporaryDtors was deprecated in clang-tidy 16 and fully removed
in clang-tidy 18
* Use C++20 in .clang-format
* Use bitwise OR
Prevents issues if any enum flags in `args` have bits in common
* replace std::pow with better performing equivalents
* revert one instance where I swapped to fastPow10f
* Negative slope instead of multiplying -1
Co-authored-by: saker <sakertooth@gmail.com>
---------
Co-authored-by: saker <sakertooth@gmail.com>
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.
* Remove QTextCodec
QTextCodec was removed from Qt6 and is only available through the
Qt5Compat module.
QTextCodec was only used by the HydrogenImport plugin when importing old
Hydrogen files that were saved using TinyXML before it supported UTF-8.
HydrogenImport would use QTextCodec to try to get the current encoding
from the locale, and then use that as a best guess for interpreting the
XML data in the unspecified encoding it was saved in. None of this was
ever reliable, since the encoding of the computer that saved the
Hydrogen file might not be the same as the computer running LMMS and
importing that file.
There is no good solution here, so I decided to simply assume the old
Hydrogen files are UTF-8 encoded. The worst that can happen is someone's
ancient Hydrogen files containing non-ASCII text of some random encoding
becomes mojibake'd after importing into LMMS, which is something that
already could have happened.
* Clean up a little
Remove the member `PluginView::m_isResizable` and it's associated method `setResizable`. Turn `isResizable` into a virtual method.
The reasoning is that whether or not an effect can be resized depends on its implementation. Therefore does not make sense to have a method like `setResizable`. If the underlying implementation does not support resizing then it would not make sense to call `setResizable(true)`. So `isResizable` now describes the underlying ability of a plugin to resize. It's then up to the clients of that method to decide how to treat the result of `isResizable`, i.e. if they want to make use of the ability to resize or not.
Put the elements of the `TrackOperationsWidget` into layouts. These are:
* The grip that can be used to move tracks
* The gear icon that opens the operations menu
* The mute button
* The solo button
The grip that can be used to move tracks around is extracted into its own class called `TrackGrip`. This has several advantages:
* It can be put into a layout.
* It can render itself at arbitrary sizes by simply repeating its pattern pixmap.
* It can be used in a much more object-oriented way because it emits signals when it is grabbed and released.
* It is responsible for locally updating its cursor state.
The default cursor of the grip now is an open hand which indicates to the users that it can be grabbed. While being grabbed the cursor now is a closed hand.
## Technical details
The class `TrackOperationsWidget` now holds an instance of `TrackGrip` and provides a getter to retrieve it. This getter is used by `TrackView` to connect to the two new signals `grabbed` and `released`. The method `TrackOperationsWidget::paintEvent` now only paints the background as it does not need to paint the grip anymore.
The `TrackView` now handles the grabbing and release of the grip in `TrackView::onTrackGripGrabbed` and `TrackView::onTrackGripReleased`. Because the events and cursor states are now handled by `TrackGrip` this code could be removed from `TrackView::mousePressEvent`.
There was a comment in `TrackView` which indicated that the `TrackOperationsWidget` had to be updated when the track is moved and released because it would hide some elements during the move. The comment and the corresponding code was removed because the operations widget does not hide its elements during moves (this was already the state before the changes made by this commit).
Adjust the style sheets of the classic and default themes with regards to the `QPushButton` that's used to show the gear menu in the `TrackOperationsWidget`. The `>` has been removed because the `QPushButton` is not a direct decendent of the `TrackOperationsWidget` anymore.
### Wrapping of `PixmapButton` in `QWidget`
The PixmapButtons that are used in `TrackOperationsWidget` current have to be wrapped into a `QWidget`. This is necessary due to some strange effect where the PixmapButtons are resized to a size that's larger than their minimum/fixed size when the method `show` is called in `TrackContainerView::realignTracks`. Specifically, with the default theme the buttons are resized from their minimum size of (16, 14) to (26, 26). This then makes them behave not as expected in layouts.
The resizing is not done for QWidgets. Therefore we wrap the PixmapButton in a QWidget which is set to a fixed size that will be able to show the active and inactive pixmap. We can then use the QWidget in layouts without any disturbances.
The resizing only seems to affect the track view hierarchy and is triggered by Qt's internal mechanisms. For example the buttons in the mixer view do not seem to be affected.
If you want to debug this simply override "PixmapButton::resizeEvent" and trigger a break point in there, e.g. whenever the new size is not (16, 14).
### More layout-friendly PixmapButton
Make the `PixmapButton` more friendly for layouts by implementing `minimumSizeHint`. It returns a size that accommodate to show the active and the inactive pixmap.
Also make `sizeHint` return the minimum size hint. The previous implementation would have made layouts jump when the pixmap is toggled with pixmaps of different sizes.
## Fix rendering of maximized sub windows
### Adjustments in paintEvent
In `SubWindow::paintEvent` don't paint anything if the sub window is
maximized . Otherwise some gradients are visible behind the maximized
child content.
### Adjustments in adjustTitleBar
In `SubWindow::adjustTitleBar` hide the title label and the buttons if the
sub window is maximized. Always show the title and close button if not
maximized. This is needed to reset the state correctly after
maximization.
Remove some calls to `isMaximized` where we already know that the sub
window is not maximized, i.e. where these calls would always return
`false`.
One adjustment would have resulted in a call to `setHidden(false)`. This
was changed to `setVisible(true)` to get rid of the double negation.
The other `false` would have gotten in an or statement and thus could be
removed completely.
### Add method addTitleButton
Add the helper method `SubWindow::addTitleButton` to reduce code
repetition in the constructor.
### Other changes
Remove a dependency on the `MdiArea` when checking if the sub window is
the active one. Query its own window state to find out if it is active.
When calling `setWindowFlags` in the constructor only adjust the existing
flags with the changes that we actually want to do. It was ensured that
all other flags that have been set before still apply with this change.
Align the rename line edit for tracks.
Make sure that the rename line edit of the `TrackLabelButton` has the
same font size as the widget itself. Because the font size is defined
via style sheets the font size of the line edit has to be set when the
actual renaming starts and not in the constructor. The reason is that
style sheets are set after the constructor has run.
Rename the local variable `txt` to the more speaking name `trackName`.
Ensure that the line edit is moved to the correct place for different
icon sizes by taking the icon size into account. To make this work this
also has to be done in the `rename` method.
## Other changes
Streamline the default style sheet of `TrackLabelButton` by removing
repeated properties that are inherited from the "main" style sheet, i.e.
that are already part of `lmms--gui--TrackLabelButton`.
Interestingly, the `background-color` property had to be repeated for
`lmms--gui--TrackLabelButton:hover`.
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Fix the problem with empty windows as described in issue #7412.
The `refocus` method in `MainWindow` is made public so that it can be called from `Editor::closeEvent`. It has also been refactored for better readability.
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Add proportional scrolling to the song editor, piano roll and automation editor. Proportional scrolling means that if for example a certain measure is on the right side of the song editor then it will take a certain number of mouse wheel moves to get it to the left side of the editor. It is the same number of wheel moves regardless of the zoom level.
* fix out-of-bounds crash in AudioFileProcessor
by correctly setting m_from and m_to without them interfering with each other
* fixed flattened wave caused by inaccurate math
see PR for before/after
* simply stop drawing AFP waveform when there's no more data
this fixes the single point at the end of waveforms that sometimes shows up
* fixed seemingly insignificant type confusion (?)
execution seemed fine but my debugger started freaking out,
and if gdb is telling me I got a negative-sized vector,
I'd rather fix this issue than speculate "it's probably fine"
* fixed data offset for AFP waveform vis
the data itself isn't reversed, so we have to account for that
* Add fast fma functions
* Use fast fma functions
* Add fast pow function
* Use fast pow function
* Fix build
* Remove fastFma
* Avoid UB in fastPow
On GCC with -O1 or -O2 optimizations, this new implementation generates
identical assembly to the old union-based implementation
* changed font sizes to better values
* rename gui_templates.h to FontHelper.h
* replace hardcoded values with constants
* make knob labels use small font
* code review from michael
* more consolidation
* Fix text problem in Vectorscope
Fix a problem with cutoff text in Vectorscope. During the constructor
call of `LedCheckBox` the method `LedCheckBox::onTextUpdated` is
triggered which sets a fixed size that fits the pixmap and the text.
After instantiating the two instances in `VecControlsDialog` the
constructor then set a minimum size which overrode the fixed size that
was previously set. This then led to text that was cutoff.
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
* 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>
This problem seem to arise due to casting _n->framesLeft() and _n->offset() from an unsigned type (size_t) to a signed type (int). The fix is to use size_t as the type for std::max across the board.
* Fix: unnecessary space in Update EqControlsDialog.cpp
Fix: unnecessary space in Update EqControlsDialog.cpp
Greetings,
Gootector
* Style fix from Ross
---------
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* simplified fraction and absfraction functions
* removed unused fastSqrt() and fastPow()
functions
* unused absMin() and absMax()
* move roundAt to math header
* Code review from saker
Co-authored-by: saker <sakertooth@gmail.com>
* use std::trunc()
* fixup after fixing merge conflicts
* remove unused fastFma and fastFmal functions.
* remove lmms_basics include, not needed
* use signedPowf from lmms_math in NES
* removed fastRand function, unused
* remove unused sinc function
* cleanup signedPowf
* code review
* further simplify random number math
* removed static from lmms_math file
---------
Co-authored-by: saker <sakertooth@gmail.com>
Ensure that no MIDI information (connected inputs, outputs, etc.) is
stored in presets. This main fix can be found in
`InstrumentTrack::saveTrackSpecificSettings` where the state of the
MIDI ports are now only saved if we are not in preset mode.
The remaining changes are concered with a refactoring of the code
that's related to saving and loading presets.
The refactoring mainly revolves around the removal of the member
`m_simpleSerializingMode` and the method `setSimpleSerializing` in
`Track`.
This is accomplished by introducing two new methods `saveTrack` and
`loadTrack`. These methods have a similar interface to `saveSettings`
and `loadSettings` but they additionally contain a boolean which
indicates if a preset is saved/loaded or a whole track. Both new
methods contain the previous code of `saveSettings` and `loadSettings`.
The latter two now only delegate to the new methods assuming that the
full track is to be stored/loaded if called via the overridden methods
`saveSettings` and `loadSettings`.
The methods `savePreset` and `loadPreset` are added as well. They call
`saveTrack` and `loadTrack` with the preset boolean set to `true`.
These methods are now used by all places in the code where presets are
saved or loaded which makes the code more readable. Clients also do not
need to know any implementation details of `Track`, e.g. like having to
call `setSimpleSerializing`.
Adjust `saveTrackSpecificSettings` so that it also passes information
of whether a preset or a whole track is stored. This leads to changes
in the interfaces of `AutomationTrack`, `InstrumentTrack`,
`PatternTrack` and `SampleTrack`. Only the implementation of
`InstrumentTrack` uses the new information though.
Remove the fallback code in `CMakeLists.txt`. Keep the message that's shown when SDL is wanted but not found. Remove the specific `LMMS_HAVE_SDL2` define.
Just print "OK" if SDL is found.
Remove several ifdefs which check for SDL2 or SDL1. Remove all code related to SDL1.
* Enable configuration of input device for SDL
Up to now the SDL audio driver attempted to use the default recording
device. This might not be what users want or expect, especially since the
actually used device is not visible anywhere. So if recording does not
work for the users they have no way to find out what's wrong.
Extend the settings screen of the SDL driver with a combo box that allows
to select the input device to be used. Store the selected device name in
a new attribute called "inputdevice" in the "audiosdl" section of the
configuration file.
Use the information from the configuration when attempting to inialize
the input device. Fall back to the default device if that does not work.
(cherry picked from commit 33139b9f4c)
* Provide a setting for system default input
Provide the setting "[System Default]" which instructs the SDL driver to
use the default device of the system as the input device. In the
configuration file this option is represented as an empty string. This
should play well with the current existing configuration of the users.
(cherry picked from commit 29c43c2bb6)
* Configuration of output device for SDL
Let users configure the output device that's used by the SDL driver.
Code-wise the implementation is very similar to the input device
configuration.
Use a `QComboBox` instead of a `QLineEdit` for `m_device` and rename it
to `m_playbackDeviceComboBox`.
Rename `s_defaultInputDevice` to `s_systemDefaultDevice` because it is
used in the context of playback and input devices.
(cherry picked from commit 1ab45e4994)
* Ensure label visibility
Make sure that labels are always shown by setting the row wrap policy of
the form layout to wrap long rows.
(cherry picked from commit a123d0e3cb)
* Rename "Device"
Rename "Device" to "Playback device" to make clear what the setting
refers to.
(cherry picked from commit 1f0cda4983)
* Remove repeated strings
Introduce const expressions to get rid of repeated strings with a risk
of typos.
(cherry picked from commit f9ea9705b8)
* Apply some more changes
Apply some more changes that have been made to `AudioSdl` in the
recording branch.
* Conditional ternary operator
Also use a conditional ternary operator for the input device setup.
* Methods for population of combo boxes
Move the population of the input and playback device combo boxes into
the methods `populatePlaybackDeviceComboBox` and
`populateInputDeviceComboBox`.
* Sort devices in combo box
Sort the devices names alphabetically in the input and playback combo
boxes. The default devices is always shown as the first entry.
* Code review fixes
Use `AudioDeviceSetupWidget` instead of `QObject` to translate "[System
Default]".
Fix copy/paste error in comment.
* Simplify some constexpr statements
* Fix#5851: Implement `EffectRackView::sizeHint()`
This fixes `EffectRackView` to have a permanent size hint instead of
resizing the widget once in `InstrumentTrackWindow`. The size hint tells
the `InstrumentTrackWindow` to not increase with a growing number of
effects in the `EffectRackView`.
* remove typeInfo struct from lmms_basics.h
* Code review
Co-authored-by: saker <sakertooth@gmail.com>
* converted epsilon to a constant
* renamed to approximatelyEqual and moved to top
---------
Co-authored-by: saker <sakertooth@gmail.com>
Introduce a method which checks if a file that's loaded has the LADSPA
controls saved in an old format that was written with a version before
commit e99efd541a.
The method is run at the end so that problems in all file versions are
detected. If a real upgrade was to be implemented it would have to run
between `DataFile::upgrade_0_4_0_rc2` and `DataFile::upgrade_1_0_99`.
See #5738 for more details.
If a problematic file is encountered a warning dialog that provides the number of affected LADSPA plugins is shown.
* Initial Commit
* Refactor code and add new icons
* Fix logical error
* Add smooth scrolling to Song Editor
* Remove unused variable
* Fix scrolling speed and scrollbar width
* Remove QDebug and re-add a newline I deleted in an unrelated file
* Forgot to add files to commit
* Remove unused variable
* Fix Styling
* Fix Styling Again
* Fix Styling Again
* Fix Styling Again
* Add icons for classic theme
* Accidentally committed varying scroll speed with zoom -- removing
* Change abs to std::abs
Co-authored-by: saker <sakertooth@gmail.com>
* Change qMax to std::max and use static_cast
Co-authored-by: saker <sakertooth@gmail.com>
* Simplify stepped auto scrolling
Co-authored-by: saker <sakertooth@gmail.com>
* Remove unnecessary parentheses
* Remove return statement causing the play head line to stop
* Add specific tooltips to auto scrolling button states
* Remove `== true` from SongEditor.cpp
Co-authored-by: saker <sakertooth@gmail.com>
* Make tooltips translatable
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Fix zooming position calculation
* Rename bars to ticks
* Fix rubberband rect size
---------
Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
Defines `fpp_t` and `f_cnt_t` to be of `size_t` within `lmms_basics.h`. Most of the codebase used `fpp_t` to represent the size of an array of sample frames, which is incorrect, given that `fpp_t` was only 16 bits when sizes greater than 32767 are very possible. `f_cnt_t` was defined as `size_t` as well for consistency.
---------
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
About the PR:
* We use "blocked" as an abstract term, when there may be different reasons
* If there is a concrete reason, we use a more concrete word like "unstable"
or "not useful"
* Double negations like "don't block" or "block unstable" are avoided
Besides this, this PR
* Lets `Lv2Manager` hide the full `std::set` of plugin URIs
* Fixes occurences of "BuffersizeLessThan32" - it is less or equal
* Moves `enableBlockedPlugins` from Engine to `ConfigManager`
Fix a buzzing sound in Monstro's 2nd oscillator. It was introduced with
commit c2f2b7e0d7.
The problem was caused by checking if `len_r` is not equal to 0 instead of
checking `pd_r`.
* Adds "Show Hidden Content Dialogue"
* Update FileBrowser.cpp
* Automatically rearrange layout to fit check boxes
* check if files are hidden in a cross platform manner
* put the hidden files checkbox below the user and factory check boxes at all times
* removed layout rearrangement code
* moved checkbox code to FileBrowser
* Removed unused include
* Cleanup in FileBrowser
Move the method `addContentCheckBox` to the other private methods.
Remove the method parameters because it can use the members.
Remove the conditional when adding the "Hidden content" checkbox because
it was always true.
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
* 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>
When launching the wine VST process various wrappers may be involved,
when they exit the VST process becomes orphaned. This breaks the
PollParentThread mechanism which is responsible for cleaning up
processes in case of a crash. Because of this 64bit VST process exits
prematurely, in other words 64bit VST is currently broken in a typical
wine configuration.
A solution suggested by Lukas W is to set the PR_SET_CHILD_SUBREAPER
flag which makes the kernel reparent such process to lmms and
PollParentThread then works as intended.
Co-authored-by: Lukas W <lukaswhl@gmail.com>
Fixes an issue where sorted arpeggios over multiple notes used a largely
unusable algorithm. piano-octave-arp instead of octave-arp-piano.
Fixes#6499Fixes#4491
## Add support for "factorysample:" prefix
Add support to upgrade files with `src` tags that are prefixed with "factorysample:".
## Fix "bassloopes" typo
Fix projects that still reference files with the typo "bassloopes" in their name.
The upgrade is implemented in its own method because it is unrelated to the BPM renaming even if it is technically very similar in its solution.
Introduce the helper method `mapSrcAttributeInElementsWithResources` which replaces the `src` attribute in elements with resources (samples and AFP) if it can be found in a map.
Add peak indicators to the mixer strips. They show the maximum peak value
that was observed and can be reset by clicking on them.
## Implementation details
The implementation works via a signal/slot mechanism. The `Fader` class
has a new signal `peakChanged` which reports peak values as
amplifications. A new class `PeakIndicator` is added which has a slot
`updatePeak` which is connected to the new signal in `Fader`.
The `PeakIndicator` inherits from `QLabel` and mainly deals with updating
the label text from the current peak value.
Add a `PeakIndicator` instance to `MixerChannelView`. Add a `reset`
method to `MixerChannelView` so that the mixer channel can be reset on
the loading of new projects, etc. The current implementation resets the
peak indicator back to -inf dbFS. The `reset` method is called in
`MixerView::clear`.
Remove the clamping in `Fader::setPeak` so that all peaks are reported.
Emit the new signal if the peak changes.
Adjust the rendering of BarModelEditor to make it respect logarithmic
and linear models. The code now uses `inverseScaledValue` instead of
`value` just like the `Knob` class does when calculating the angle.
## Make mixer channels resizable
Make the mixer channels resizable within the mixer view.
Remove the setting of the size policy from `MixerChannelView`. Add the
`Fader` widget with a stretch factor so that it is resized within the
layout of the mixer channel/strip. Remove the stretch that was added to
the layout because the fader now stretches.
In `MixerView` remove the top alignments when widgets are added to the
layout so that they can resize. Set the channel layout to align to the
left so that it behaves correctly when it is resized by the scroll area
it is contained in. Make the widget resizable in the scroll area so that
it always fills the space. Set the minimum height of the scroll area to
the minimum size of the widget plus the scrollbar height so that the
channel strips are never overlapped by the scrollbar.
Set the size policy of the "new channel" button so that it grows
vertically with the mixer view. Set a fixed size so that it is as wide as
a mixer strip.
## Enable maximization for mixer view
Enable the maximize button for the mixer view now that it is fully
resizable.
Don't make LMMS calculate the song length for every added TCO when a new project is created or a project is loaded. Instead do it only once afterwards. This is accomplished by preventing any calculations in `Song::updateLength` if a song is currently loaded. `Song::updateLength` is then called immediately after the loading flag has been set to `false` in both cases.
---------
Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
The CPU feature requirements for any currently supported 32-bit version of Windows (8.1 and 10) are PAE, NX and SSE2. That should mean a green light for bumping the CPU we build for to the minimum one with SSE2.
* Revert "Fix glitch with automation points (#7269)"
This reverts commit d60fd0d022.
* Fix glitch in Automation Editor. This reverts the earlier fix and tries to solve the issue by instead rounding off the values of the top/bottom levels before comparison with the automation point value.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Update MinGW CI to Ubuntu 20.04
* Use ghcr.io/lmms/linux.mingw:20.04
* Fix deprecation in ClipView.cpp
* Fix ccache and simplify git configuration
* Apply patch by @DomClark for MinGW's SDL2 target
* Update excludelist-win
* some css tweaks for accessibility
* suggestions from review
* classic theme focus
* fix bug where button color disappears on focus
* More scrollbar color changes on hover.
* Commented the hover effect for now.
* Remove handle "hover" effect.
* scrollbar
* revert button active state
Fix the missing initialization of some variables in `TrackContentWidget`.
This led to some performances issues when the widget was painted because
a for loop was executed for which the variable started at a very large
negative number and was then incremented.
* Added lines in between bars
* Changed bar lines to follow snap size
* Changed default zoom and quantization value
* Added constants for line widths
* Added QSS configuration for new grid line colors
* Tied line widths to QSS properties
* Changed default quantization to 1/4
* Removed clear() from destructor model
* Removed destructor in ComboBoxModel.h
* Changed member set/get functions to pass by value
* Updated signal connection with newer syntax
- Switch to Ubuntu 20.04 Docker image ghcr.io/lmms/linux.gcc:20.04
- Linux packages have migrated from Docker Hub to https://github.com/orgs/lmms/packages
- Built using the Dockerfiles from Update Linux images lmms-ci-docker#15
- Updated the veal submodule to the latest commit on the default ladspa branch
- Fixed an error when catching a polymorphic type with GCC 9. See: LMMS/veal@0ae9287
- Added GCC flag -Wno-format-truncation for ZynAddSubFx build.
- Adds GCC flag -Wno-format-overflow for calf/veal build.
Closes#6993
Oversampling can have many different effects to the audio signal such as latency, phase issues, clipping, smearing, etc, so this should really be an option on a per-plugin basis, not globally across all of LMMS (which, in some places, shouldn't really need to oversample at all but were oversampled anyways).
Add the virtual method `Effect::onEnabledChanged` which can be overridden by effects so that they can react to state changes with regards to being enabled or bypassed. The call of this methods is connected to state changes of the enabled model in the constructor of `Effect`.
Implement the method in `DualFilterEffect` by resetting the history of the two filters. This is done to prevent pops that have been reported in #4612.
The original code was doing division in `int`, which causes lost of accuracy and results in the waveform randomly shifting when zooming in and out.
This should fix it by casting variables to `float` before dividing, as well as keeping the values in `float` type.
The pull request also changes some type declaration to explicit to increase readability
Fix the upgrade routine that was introduced with pull request #6747 which added the BPM value to some file names.
This also simplifies the implementation by using a map.
Note: this also removes the code about the prefix `factorysample:`. If it is used in some files these entries will also have to be added to the map.
Check if a non-empty buffer was loaded and only set the sample clip if that's the case.
## Other changes
Move setting the song to modified towards the core in the context of `SampleClip`. Previously the `SampleClipView` did this but it's none of it's business.
Introduce `SampleClip::changeLengthToSampleLength` which changes the length of the clip to the length of the sample. This was also previously done by the view which is again the wrong place to do the necessary calculations. An unnecessary `static_cast` was removed while carrying over the code.
Add the method `SampleClip::hasSampleFileLoaded` which checks if the loaded sample corresponds to a given file name.
Fix code formatting.
The previous implementation of Lb302`s decay used a fixed decay factor that was multiplied with the signal until the minimum threshold of 1/65536 was crossed. This fixed factor resulted in different lengths in time for different sample rates.
This is fixed by computing the decay factor by taking the sample rate into account as well. The new static method `computeDecayFactor` computes the factor that is needed to make a signal decay from 1 to a given attenuation over a given time.
The parameters used in the call to that method in `Lb302Synth::process` have been fine-tuned such that, at a sample rate of 44.1 kHz, they result in a factor very close to the previous hard-coded factor of 0.99897516.
When applying its release stage Kicker did not take the frames before the release into account but instead always applied the release to the full buffer. This potentially lead to a jump in the attenuation values instead of a clean linear decay.
See #7225 for more details.
## Instrument flags as a property of an instrument
The instruments flags (single streamed, MIDI based, not bendable) are properties of an instrument that do not change over time. Therefore the flags are made a property of the instrument which is initialized at construction time.
Adjust the constructors of all instruments which overrode the `flags` method to pass their flags into the `Instrument` constructor.
## Add helper methods for flags
Add helper methods for the flags. This makes the code more concise and readable and clients do not need to know the technical details on how to evaluate a flag.
## Remove the flags methods
Remove the flags methods to make it an implementation detail on how the flags are managed.
Many, many years ago (93a456c), high quality mode was merely disabled after it was noted that it can be problematic rather than being completely removed. Remove it from the codebase so we can get rid of some code and clean things up a bit.
Make instruments report their release time in milliseconds so that it becomes independent of the sample rate and sounds the same at any sample rate.
Technically this is done by removing the virtual keyword from `desiredReleaseFrames` so that it cannot be overridden anymore. The method now only serves to compute the number of frames from the given release time in milliseconds.
A new virtual method `desiredReleaseTimeMs` is added which instruments can override. The default returns 0 ms just like the default implementation previously returned 0 frames.
The method `computeReleaseTimeMsByFrameCount` is added for instruments that still use a hard coded release in frames. As of now this is only `SidInstrument`.
Add the helper method `getSampleRate` to `Instrument`.
Adjust several instruments to report their release times in milliseconds. The times are computed by taking the release in frames and assuming a sample rate of 44.1 kHz. In most cases the times are rounded to a "nice" next value, e.g.:
* 64 frames -> 1.5 ms (66 frames)
* 128 frames -> 3.0 ms (132 frames)
* 512 frames -> 12. ms (529 frames)
* 1000 frames -> 23 ms (1014 samples)
In parentheses the number of frames are shown which result from the rounded number of milliseconds when converted back assuming a sample rate of 44.1 kHz. The difference should not be noticeable in existing projects.
Remove the overrides for instruments that return the same value as the base class `Instrument` anyway. These are:
* GigPlayer
* Lb302
* Sf2Player
For `MonstroInstrument` the implementation is adjusted to behave in a very similar way. First the maximum of the envelope release times is computed. These are already available in milliseconds. Then the maximum of that value and 1.5 ms is taken and returned as the result.
Move icon determination into TrackLabelButton again
Fully undo the changes made in commit 88e0e94dcd because the intermediate revert made in commit 04ecf73395 seems to have led to a performance problem due to the icon being set over and over again in `TrackLabelButton::paintEvent`.
The original intention of the changes made in pull request #7114 was to remove the painting code that dynamically determines the icon over and over again. Ideally the icon that is used by an instrument should be somewhat of a "static" property that should be known very early on when an instrument view is created. There should not be any need to dynamically resolve the icon over and over, especially not in a button class very far down in the widget hierarchy. However, due to technical reasons this is not the case in the current code. See pull request #7132 for more details.
- Explain why you believe the proposed enhancement to be a good idea, and (if applicable) how it helps overcome a limitation of LMMS you are currently facing.
- Explain why you believe the proposed enhancement to be a good idea, and (if applicable) how it helps
overcome a limitation of LMMS you are currently facing.
set(STATUS_VST_64"${STATUS_VST_64}\n\tWARNING: You are using wine ${WINE_VERSION} which cannot disable ASLR, please consider upgrading to wine 10.14 or higher. ASLR may cause crashes with older VSTs.")
[Artist & User Wiki/Documentation](https://lmms.io/documentation)<br>
[Sound Demos](https://lmms.io/showcase/)<br>
[LMMS Sharing Platform](https://lmms.io/lsp/) Share your songs!
LMMS is an open-source cross-platform digital audio workstation designed for music production. It includes an advanced Piano Roll, Beat Sequencer, Song Editor, and Mixer for composing, arranging, and mixing music. It comes with 15+ synthesizer plugins by default, along with VST2 and SoundFont2 support.
Features
---------
* Song-Editor for composing songs
* Song-Editor for arranging melodies, samples, patterns, and automation
* Pattern-Editor for creating beats and patterns
* An easy-to-use Piano-Roll for editing patterns and melodies
* A Mixer with unlimited mixer channels and arbitrary number of effects
* Many powerful instrument and effect-plugins out of the box
* Full user-defined track-based automation and computer-controlled automation sources
* Compatible with many standards such as SoundFont2, VST(i), LADSPA, GUS Patches, and full MIDI support
* Compatible with many standards such as SoundFont2, VST2 (instruments and effects), LADSPA, LV2, GUS Patches, and full MIDI support
* MIDI file importing and exporting
Building
---------
See [Compiling LMMS](https://github.com/LMMS/lmms/wiki/Compiling) on our
wiki for information on how to build LMMS.
See [Compiling LMMS](https://github.com/LMMS/lmms/wiki/Compiling)
Join LMMS-development
----------------------
If you are interested in LMMS, its programming, artwork, testing, writing demo
songs, (and improving this README...) or something like that, you're welcome
to participate in the development of LMMS!
If you are interested in LMMS, its programming, artwork, testing, writing demo songs, (and improving this README...) or something like that, you're welcome to participate in the development of LMMS!
Information about what you can do and how can be found in the
[wiki](https://github.com/LMMS/lmms/wiki).
Information about what you can do and how can be found in the [wiki](https://github.com/LMMS/lmms/wiki).
Before coding a new big feature, please _always_
[file an issue](https://github.com/LMMS/lmms/issues/new) for your idea and
suggestions about your feature and about the intended implementation on GitHub,
or ask in one of the tech channels on Discord and wait for replies! Maybe there are different ideas, improvements, or hints, or
maybe your feature is not welcome/needed at the moment.
Before coding a new big feature, please _always_ [file an issue](https://github.com/LMMS/lmms/issues/new) for your idea and suggestions about your feature and about the intended implementation on GitHub, or ask in one of the tech channels on Discord and wait for replies! Maybe there are different ideas, improvements, or hints, or maybe your feature is not welcome/needed at the moment.
MESSAGE(STATUS"Bash completion script for ${SCRIPT_NAME} will be installed to ${BASHCOMP_PKG_PATH} or fallback to ${BASHCOMP_USER_PATH} if unwritable.")
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.