* Handle divisions by 0 in Lb302
Handle potential division by 0 which in turn lead to floating point exceptions in Lb302. The division can occur in the `process` method if it is called with the member `vco_inc` still initialized to 0. This seems to happen then the Lb302 processes with no notes actually being played.
The offending call is `BandLimitedWave::pdToLen(vco_inc)` which is now prevented when the increment is 0. In the latter case a sample of 0 is produced. This works because in all other cases the Lb302 instance should process a note which in turn sets the increments to something different from 0.
* Fix FPEs in Monstro
Fix some floating point exceptions in `MonstroSynth::renderOutput` that occurred due to calling `BandLimitedWave::pdToLen` with a value of 0. This happened when one of the phase deltas was set to 0, i.e. `pd_l` or `pd_r`. These cases are now checked and produce silence in the corresponding components if the phase delta is set to 0.
* Fix uninitialized variables
Initialize the local variables `len_l` and `len_r` to 0. This fixes compiler warnings a la "error: 'len_r' may be used uninitialized in this function" which are treated as errors on the build server.
* Adjust whitespace of touched code
Fix the peak update of the LMMS equalizer which accidentally used the same sample twice.
Simplify the `gain` method by removing repeated deferences which made the code hard to read.
Use `std::max` to update the peak values to the maximum of the buffer.
Remove the code which computes a minimum height for the LADSPA dialogs. It was intended to make sure that no scrollbar is shown in most cases. However, doing so came at the cost that the computed height was the minimum height as well. Therefore the dialogs took a lot of space on low-res displays and could not be made smaller.
After the removal the behavior is still sane. Small dialogs are shown in full and dialogs which are larger, e.g. "Calf Equalizer 12 Band LADSPA", seem to be sized around half the height of the workspace and show scrollbars.
* Add refactored SampleBuffer
* Add Sample
* Add SampleLoader
* Integrate changes into AudioSampleRecorder
* Integrate changes into Oscillator
* Integrate changes into SampleClip/SamplePlayHandle
* Integrate changes into Graph
* Remove SampleBuffer include from SampleClipView
* Integrate changes into Patman
* Reduce indirection to sample buffer from Sample
* Integrate changes into AudioFileProcessor
* Remove old SampleBuffer
* Include memory header in TripleOscillator
* Include memory header in Oscillator
* Use atomic_load within SampleClip::sample
* Include memory header in EnvelopeAndLfoParameters
* Use std::atomic_load for most calls to Oscillator::userWaveSample
* Revert accidental change on SamplePlayHandle L.111
* Check if audio file is empty before loading
* Add asserts to Sample
* Add cassert include within Sample
* Adjust assert expressions in Sample
* Remove use of shared ownership for Sample
Sample does not need to be wrapped around a std::shared_ptr.
This was to work with the audio thread, but the audio thread
can instead have their own Sample separate from the UI's Sample,
so changes to the UI's Sample would not leave the audio worker thread
using freed data if it had pointed to it.
* Use ArrayVector in Sample
* Enforce std::atomic_load for users of std::shared_ptr<const SampleBuffer>
* Use requestChangesGuard in ClipView::remove
Fixes data race when deleting SampleClip
* Revert only formatting changes
* Update ClipView::remove comment
* Revert "Remove use of shared ownership for Sample"
This reverts commit 1d452331d1.
In some cases, you can infact do away with shared ownership
on Sample if there are no writes being made to either of them,
but to make sure changes are reflected to the object in cases
where writes do happen, they should work with the same one.
* Fix heap-use-after-free in Track::loadSettings
* Remove m_buffer asserts
* Refactor play functionality (again)
The responsibility of resampling the buffer
and moving the frame index is now in Sample::play, allowing the removal
of both playSampleRangeLoop and playSampleRangePingPong.
* Change copyright
* Cast processingSampleRate to float
Fixes division by zero error
* Update include/SampleLoader.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update include/SampleLoader.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Format SampleLoader.h
* Remove SampleBuffer.h include in SampleRecordHandle.h
* Update src/core/Oscillator.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Use typeInfo<float> for float equality comparison
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Use std::min in Sample::visualize
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Move in result to m_data
* Use if block in playSampleRange
* Pass in unique_ptr to SampleClip::setSampleBuffer
* Return const QString& from SampleBuffer::audioFile
* Do not pass in unique_ptr by r-value reference
* Use isEmpty() within SampleClipView::updateSample
* Remove use of atomic_store and atomic_load
* Remove ArrayVector comment
* Use array specialization for unique_ptr when managing DrumSynth data
Also made it so that we don't create result
before checking if we failed to decode the file,
potentially saving us an allocation.
* Don't manually delete Clip if it has a Track
* Clean up generateAntiAliasUserWaveTable function
Also, make it so that we actually call this function
when necessary in TripleOscillator.
* Set user wave, even when value is empty
If the value or file is empty, I think showing a
error popup here is ideal.
* Remove whitespace in EnvelopeAndLfoParameters.cpp L#121
* Fix error in c5f7ccba49
We still have to delete the Clip's, or else we would just be eating
up memory. But we should first make sure that the Track's no longer
see this Clip in their m_clips vector. This has to happen
as it's own operation because we have to wait for the audio thread(s)
first. This would ensure that Track's do not create
PlayHandle's that would refer to a Clip that is currently
being destroyed. After that, then we call deleteLater on the Clip.
* Convert std::shared_ptr<Sample> to Sample
This conversion does not apply to Patman as there seems to be issues
with it causing heap-use-after-free issues, such as with
PatmanInstrument::unloadCurrentPatch
* Fix segfault when closing LMMS
Song should be deleted before AudioEngine.
* Construct buffer through SampleLoader in FileBrowser's previewFileItem function
+ Remove const qualification in SamplePlayHandle(const QString&)
constructor for m_sample
* Move guard out of removeClip and deleteClips
+ Revert commit 1769ed517d since
this would fix it anyway
(we don't try to lock the engine to
delete the global automation track when closing LMMS now)
* Simplify the switch in play function for loopMode
* Add SampleDecoder
* Add LMMS_HAVE_OGGVORBIS comment
* Fix unused variable error
* Include unordered_map
* Simplify SampleDecoder
Instead of using the extension (which could be wrong) for the file,
we simply loop through all the decoders available. First sndfile because
it covers a lot of formats, then the ogg decoder for the few cases where sndfile
would not work for certain audio codecs, and then the DrumSynth decoder.
* Attempt to fix Mac builds
* Attempt to fix Mac builds take 2
* Add vector include to SampleDecoder
* Add TODO comment about shared ownership with clips
Calls to ClipView::remove may occur at any point, which can cause
a problem when the Track is using the clip about to be removed.
A suitable solution would be to use shared ownership between the Track
and ClipView for the clip. Track's can then simply remove the shared
pointer in their m_clips vector, and ClipView can call reset on the
shared pointer on calls to ClipView::remove.
* Adjust TODO comment
Disregard the shared ownership idea. Since we would be modifying
the collection of Clip's in Track when removing the Clip, the Track
could be iterating said collection while this happens,
causing a bug. In this case, we do actually
want a synchronization mechanism.
However, I didn't mention another separate issue in the TODO comment
that should've been addressed: ~Clip should not be responsible for
actually removing the itself from it's Track. With calls to removeClip,
one would expect that to already occur.
* Remove Sample::playbackSize
Inside SampleClip::sampleLength, we should be using Sample::sampleSize
instead.
* Fix issues involving length of Sample's
SampleClip::sampleLength should be passing the Sample's sample rate to
Engine::framesPerTick.
I also changed sampleDuration to return a std::chrono::milliseconds
instead of an int so that the callers know what time interval
is being used.
* Simplify if condition in src/gui/FileBrowser.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Simplify if condition in src/core/SampleBuffer.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update style in include/Oscillator.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Format src/core/SampleDecoder.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Set the sample rate to be that of the AudioEngine by default
I also removed some checks involving the state of the SampleBuffer.
These functions should expect a valid SampleBuffer each time.
This helps to simplify things since we don't have to validate it
in each function.
* Set single-argument constructors in Sample and SampleBuffer to be explicit
* Do not make a copy when reading result from the decoder
* Add constructor to pass in vector of sampleFrame's directly
* Do a pass by value and move in SampleBuffer.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Pass vector by value in SampleBuffer.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Make Sample(std::shared_ptr) constructor explicit
* Properly draw sample waveform when reversed
* Collect sample not found errors when loading project
Also return empty buffers when trying to load
either an empty file or empty Base64 string
* Use std::make_unique<SampleBuffer> in SampleLoader
* Fix loop modes
* Limit sample duration to [start, end] and not the entire buffer
* Use structured binding to access buffer
* Check if GUI exists before displaying error
* Make Base64 constructor pass in the string instead
* Remove use of QByteArray::fromBase64Encoding
* Inline simple functions in SampleBuffer
* Dynamically include supported audio file types
* Remove redundant inline specifier
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Translate file types
* Cache calls to SampleDecoder::supportedAudioTypes
* Fix translations in SampleLoader (again)
Also ensure that all the file types are listed first.
Also simplified the generation of the list a bit.
* Store static local variable for supported audio types instead of in the header
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Clamp frame index depending on loop mode
* Inline member functions of PlaybackState
* Do not collect errors in SampleLoader when loading projects
Also fix conflicts with surrounding codebase
* Default construct shared pointers to SampleBuffer
* Simplify and optimize Sample::visulaize()
* Remove redundant gui:: prefix
* Rearrange Sample::visualize after optimizations by DanielKauss
* Apply amplification when visualizing sample waveforms
* Set default min and max values to 1 and -1
* Treat waveform as mono signal when visualizing
* Ensure visualization works when framesPerPixel < 1
* Simplify Sample::visualize a bit more
* Fix CPU lag in Sample by using atomics (with relaxed ordering)
Changing any of the frame markers originally took a writer
lock on a mutex.
The problem is that Sample::play took a reader lock first before
executing. Because Sample::play has to wait on the writer, this
created a lot of lag and raised the CPU meter. The solution
would to be to use atomics instead.
* Fix errors from merge
* Fix broken LFO controller functionality
The shared_ptr should have been taken by reference.
* Remove TODO
* Update EnvelopeAndLfoView.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update src/gui/clips/SampleClipView.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update plugins/SlicerT/SlicerT.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Update plugins/SlicerT/SlicerT.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Store shortest relative path in SampleBuffer
* Tie up a few loose ends
* Use sample_rate_t when storing sample rate in SampleBuffer
* Add missing named requirement functions and aliases
* Use sampledata attribute when loading from Base64 in AFP
* Remove initializer for m_userWave in the constructor
* Do not use trailing return syntax when return is void
* Move decoder functionality into unnamed namespace
* Remove redundant gui:: prefix
* Use PathUtil::toAbsolute to simplify code in SampleLoader::openAudioFile
* Fix translations in SampleLoader::openAudioFile
Co-authored-by: DomClark <mrdomclark@gmail.com>
* Fix formatting for ternary operator
* Remove redundant inlines
* Resolve UB when decoding from Base64 data in SampleBuffer
* Fix up SampleClip constructors
* Add AudioResampler, a wrapper class around libsamplerate
The wrapper has only been applied to Sample::PlaybackState for now.
AudioResampler should be used by other classes in the future that do
resampling with libsamplerate.
* Move buffer when moving and simplify assignment functions in Sample
* Move Sample::visualize out of Sample and into the GUI namespace
* Initialize supportedAudioTypes in static lambda
* Return shared pointer from SampleLoader
* Create and use static empty SampleBuffer by default
* Fix header guard in SampleWaveform.h
* Remove use of src_clone
CI seems to have an old version of libsamplerate and does not have this method.
* Include memory header in SampleBuffer.h
* Remove mutex and shared_mutex includes in Sample.h
* Attempt to fix string operand error within AudioResampler
* Include string header in AudioResampler.cpp
* Add LMMS_EXPORT for SampleWaveform class declaration
* Add LMMS_EXPORT for AudioResampler class declaration
* Enforce returning std::shared_ptr<const SampleBuffer>
* Restrict the size of the memcpy to the destination size, not the source size
* Do not make resample const
AudioResampler::resample, while seemingly not changing the data of the resampler, still alters its internal state and therefore should not be const.
This is because libsamplerate manages state when
resampling.
* Initialize data.end_of_input
* Add trailing new lines
* Simplify AudioResampler interface
* Fix header guard prefix to LMMS_GUI instead of LMMS
* Remove Sample::resampleSampleRange
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
Co-authored-by: Daniel Kauss <daniel.kauss.serna@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: DomClark <mrdomclark@gmail.com>
Fix a floating point exception in the Spectrum Analyzer which occurs if the amplitude is 0. The amplitude is used in the calculation of a logarithm which is not defined for values smaller or equal to 0.
The fix is to replace a value of 0 with the minimum positive float value. Negative values are not handled because it seems that only values greater or equal to 0 are fed into the method. This assumption is asserted in case this ever changes.
* Replace knobFModel with std::vector
* Create QPixmap's on the stack
* Assign parent for QGraphicsScene
A call to QGraphicsView::setScene does not make
the view take ownership of the scene.
* Do not allocate QList on the heap
* Use static QPixmap's
The QPixmap's need to be created within the constructor, and not outside
where they are defined, since it can't find them otherwise.
I'm not too sure why.
* Clear m_vi2->knobFModel in destructor
* Use local static QPixmap's
* Do not allocate QPixmap with new in AudioFileProcessor
* Do not allocate QPixmap with new in Nes
* Do not allocate QPixmap with new in Organic
* Do not allocate QPixmap with new in SaControlsDialog
* Do not allocate QPixmap with new in Vestige
* Do not allocate QPixmap with new for FileBrowser
* Do not allocate QPixmap with new in MixerLine
* Do not allocate QPixmap with new in SendButtonIndicator
* Do not allocate QPixmap with new in AutomationClipView
* Do not allocate QPixmap with new in MidiClipView
* Do not allocate QPixmap with new in AutomationEditor
* Do not allocate QPixmap with new in PianoRoll
* Do not allocate QPixmap with new in TimeLineWidget
* Do not allocate QPixmap with new in EnvelopeAndLfoView
* Do not allocate QPixmap with new in PianoView
* Do not allocate QPixmap with new in ComboBox
* Do not allocate QPixmap with new in Fader
* Do not allocate QPixmap with new for LcdWidget
* Do not allocate QPixmap with new for LedCheckbox
* Use m_ as prefix for members
* Use uniform initialization
I already started using uniform initialization for the QPixmap changes
for some reason, so I'm finishing that up.
* Uniform initiaization
* And then he realized he was making copies...
* Do not call QPixmap copy constructor
* Do not call QPixmap copy constructor in SaControlsDialog
* Do not make pixmap's static for Lcd's and Led's
* Initialize pixmaps in-class
* Fix few mistakes and formatting
* Initial Commit
Starts implementing Note Types. The two available types are
RegularNote and StepNote. PianoRoll now paints the color with a
different color for StepNotes. Pattern::addStep now sets the type of the
note to StepNote.
Negative size is still used to signal a step note.
* Update Pattern.cpp to account for the Note::Type
Updates the methods noteAtStep(), addStepNote() and checkType()
from Pattern.cpp to account for the note type and not the note length.
* Update PatternView::paintEvent to draw step notes
PatternView::paintEvent now draws the pattern if the pattern
type is BeatPattern and TCOs aren't fixed (Song Editor). Color used is
still the BeatPattern color (grey) and the conditional doesn't look very
nice and can be improved.
Pattern::beatPatternLength was also updated so it accounts for
the note type not note length. Review this method, as it looks a bit
weird (particularly the second conditional).
* Implements StepNotes setting a NPH with 0 frames
Now, instead of TimePos returning 0 for negative lengths, we
create a NotePlayHandle with 0 frames when the note type is StepNote on
InstrumentTrack::play.
* Improves PatternView::paintEvent conditional
Improves a conditional inside PatternView::paintEvent by
reversing the order in which they are executed.
* Adds upgrade method for backwards compatibility
Adds an upgrade method that converts notes with negative length
to StepNotes, so old projects can be loaded properly.
Explicitly set the Note::RegularNote value as 0.
Make the default "type" value "0", so notes without a type are
loaded as RegularNotes.
* Addresses Veratil's review
- Changes "addStepNote" so "checkType" isn't called twice in a
row.
- Changes style on a one line conditional.
* Uses ternary expression on statement
Reduces number of lines by using ternary expression.
* Addresses PR review (sakertooth)
- Changes class setter to inline
- Uses enum class instead of enum
- Uses auto and const where appropriate
* Finished changes from review (sakertooth)
- Used std::max instead of qMax
- Fixed style on lines changed in the PR
* Uses std::find_if to save codelines
As suggested by sakertooth, by using std::find_if we are able to
simplify the checkType method to two lines.
* Addresses review from sakertooth
- Reverts m_detuning in-class initialization
- Removes testing warning
- Removes unnecessary comment
* Addresses DomClark's review
- Rename the Note Types enum to avoid redundancy
- Uses std::all_of instead of std::find_if on MidiClip checkType
- Rewrites addStepNote so it sets the note type before adding it
to the clip, avoiding having to manually change the type of the clip
after adding the note
* Updates MidiExport to use Note Types
- Now MidiExport is updated to use note types instead of relying
on negative length notes.
- For that change it was necessary to find a way of letting
MidiExport know how long step notes should be. The solution found was to
add an attribute to the Instrument XML called "beatlen", which would
hold the number of frames of the instrument's beat. That would be
converted to ticks, so we could calculate how long the MIDI notes would
have to be to play the whole step note. If the attribute was not found,
the default value of 16 ticks would be used as a length of step notes,
as a fallback.
* Fixes ambiguity on enum usage
Due to changes in the name of enum classes, there was an
ambiguity caused in NotePlayHandle.cpp. That was fixed.
* Addresses new code reviews
- Addresses code review from PhysSong and Messmerd
* Fixes note drawing on Song Editor
- Notes were not being draw on the song editor for BeatClips.
This commit fixes this.
* Adds cassert header to TimePos.cpp
- Adds header to use assert() on TimePos.cpp
* Apply suggestions from code review
Fixes style on some lines
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Reverts some changes on MidiExport
- Some changes were reverted on MidiExport and InstrumentTrack.
We were storing the beat length on the XML of Instrument Tracks, but in
reality the beat length is a per note attribute, and some instruments
could run into a segmentation fault when calling beat length without a
NotePlayHandle (i.e.: AFP). Because of that I reverted this change, so
the beat length is not stored on the XML anymore, and instead we have a
magic number on the MidiExport class that holds a default beat length
which is actually an upper limit for the MIDI notes of step notes. In
the future we can improve this by finding a way to store the beat length
on the note class to use it instead. The MidiExport logic is not
worsened at all because previously the beat length wasn't even
considered during export (it was actually improved making the exported
notes extend until the next one instead of cutting shorter).
* Fix the order of included files
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
This fixes at least three issues:
* Help window is not synched with window manager's `X`-button
* Help window is not being closed on track destruction or on closing the plugin window
* Trims help window strings and force-adds a newline, because `QLabel::sizeHint` sometimes computes too small values. Now, together with #6956, all help windows fit their strings. Some help windows are too large by one line, but this seems better than forcing the user to resize them if they are too small by one line.
Introduce a new version of the LADSPA control dialog which uses "bar controllers" and arranges them in a grid layout. Long parameter names are elided long if needed. The new dialog is implemented in the class `LadspaMatrixControlDialog`.
Note: it is still possible to reactivate the old dialog as it has not been removed yet. You can do so in `plugins/LadspaEffect/LadspaControls.h` by replacing the implementation of `createView()` with the following:
```
gui::EffectControlDialog* createView() override
{
return new gui::LadspaControlDialog( this );
}
```
Introduce the new base class `FloatModelEditorBase`. It serves as the base widget for widgets that manipulate a float model and provides some base functionalities like context menus, edit dialogs, mouse handling, etc. Currently `BarModelEditor` and `Knob` inherit from `FloatModelEditorBase`. Therefore lots of code was moved from `Knob` to `FloatModelEditorBase`.
`BarModelEditor` supports style sheets. See the changes in style.css for the available options and their usage.
Extend `LedCheckBox` so that it adds support to render the text with the default font in the default size. The class now supports two modes:
* Legacy mode
* Non-legacy mode
Legacy mode is the default and renders the LedCheckBox as before. The font is set to 7 pixels and all the text is rendered with a shadow.
Non-legacy mode uses the current font to render the text. The text is rendered without a shadow and the pixmap is centered vertically to the left side of the text. Non-legacy mode is currently only used in the context of the matrix LADSPA dialog. Toggle options are rendered using it as well as the "Link Channels" button.
Add `TempoSyncBarModelEditor` which adds a tempo sync option to a `BarModelEditor`. Please note that the code was mostly copied and adjusted from the `TempoSyncKnob` class. It was not attempted yet to unify some of the code because with the current design it seems to be a road to "inheritance hell". A better solution might be to refactor the code so that it becomes more composable.
What follows are the individual commit messages of the 64 commits that have been squashed into a single merge commit.
* First version of a new dynamic LADSPA control dialog
The new dialog shows the LADSPA controls in a matrix layout. Each row
corresponds to a LADSPA parameter. Each parameter can have several
channels which can be linked. Each channel has its own row of controls.
The class LadspaMatrixControlView was added by copying and modifying
LadspaControlView to get rid of the link buttons which are associated
with some controls and some labels.
* Remove trailing whitespaces
* Merge fix
* Use the new connect syntax
* Remove empty destructors
* Use override keyword
* Reformat a bit
* Use nullptr
* Use range-based loops
* Add BarModelEditor and improve layouts
Add the new class `BarModelEditor` which is intended to become a new way
to adjust values of float models.
Simplify the layout in `LadspaMatrixControlDialog` by removing some
nested layouts. Remove the "Parameters" column.
Adjust `LadspaMatrixControlView` to implement the following changes:
* Show the name of the control next to toggle buttons (`LedCheckBox`).
* Use the new `BarModelEditor` for integer and float types.
* SHow the name of the control next to time based parameters that use
`TempoSyncKnob`.
The names are shown so that the "Parameters" column can be removed.
Technical details
------------------
The class `LadspaMatrixControlDialog` now creates a widget that contains
the matrix layout with the controls. This widget is then added to a
scroll area. The layout is populated in the new method
`arrangeControls`.
Add some helper methods to `LadspaMatrixControlDialog` which retrieve
the `LadspaControls` instance and the number of channels.
Add the implementation of `BarModelEditor` to `src/gui/CMakeLists.txt`.
TODOs
------
Extract common code out of the `Knob` class so that it can be reused by
`BarModelEditor`.
* Use factory to create LADSPA control widgets
Replace the class `LadspaMatrixControlView` with the factory class
`LadspaWidgetFactory`. The former was a widget that wrapped the widget
representation of a LADSPA control in yet another widget with a layout.
The factory simply returns the configured widget so that it can be
incorporated directly in layouts or other widgets.
Adjust `LadspaMatrixControlDialog` so that it uses the
`LadspaWidgetFactory` instead of the `LadspaMatrixControlView`.
* Initial version of FloatModelEditorBase
Create an initial version of `FloatModelEditorBase`. It is intended to
become the base widget for all widgets that manipulate a float model and
provides some base functionalities like context menus, edit dialogs,
mouse handling, etc.
The initial version is a copy of `Knob`. The enum and its values have
been suffixed with "Temp" as they will be removed later anyway. Same
applies for the function `convertPixmapToGrayScaleTemp`.
* Remove Knob related code from FloatModelEditorBase
First removal of Knob related code from FloatModelEditorBase.
* Remove setHtmlLabel
* Remove enum for knob types
* Remove label related code
Remove setLabel and the members m_label and m_isHtmlLabel.
* Remove several Qt properties
* Remove angle related members and methods
* Remove unused members and includes
* Clean up includes
* Make BarModelEditor inherit from FloatModelEditorBase
Make `BarModelEditor` inherit from `FloatModelEditorBase` so that it
inherits all shared functionality. Currently the class mostly implements
size related methods and overrides the paint method.
* Move LadspaWidgetFactory to LadspaEffect
Move the class `LadspaWidgetFactory` to the project LadspaEffect to make
it hopefully compile with mingw32 and mingw64.
Interestingly the code compiled and worked under Linux and MacOS.
* Code adjustments after scripted checks
Add an include guard and an additional `#pragme once`. Add comments to
closing namespace scopes.
* Export BarModelEditor
Export BarModelEditor so that for example the LadspaEffect project/
plugin can use it.
* Improve rendering of bar model editor
Increase the margin from 2 to 3 so that we have a more prominent border
around the filled area.
Fix a problem in the rendering code which led to situations where the
bar was drawn to the left of the start position for small values.
Return a more exact minimum size hint.
* Elide long parameter names
Elide long parameter names if needed.
* Enable horizontal direction of manipulation
Extend `FloatModelEditorBase` so that it also allows manipulation of the
values when the mouse is moved in horizontal directions. The default is
to use the vertical direction.
Make use of this new feature in `BarModelEditor` which now reacts to
horizontal movements when changing values.
* Represent enum parameters using the bar widget
The implementation of the current LADSPA dialog in master uses knobs to
represent enum parameters. Therefore it should also work with the new
bar widget.
This gets rid of many labels with the parameter name followed by
"(unsupported)".
* Remove TODO in LadspaWidgetFactory
* Render text of LedCheckBox with default font
Extend LedCheckBox so that it adds support to render the text with the
default font in the default size. The class now supports two modes:
* Legacy mode
* Non-legacy mode
Legacy mode is the default and renders the LedCheckBox as before. The
font is set to 7 pixels and all the text is rendered with a shadow.
Non-legacy mode uses the current font to render the text. The text is
rendered without a shadow and the pixmap is centered vertically to the
left side of the text.
The non-legacy mode is currently only used in the context of the matrix
LADSPA dialog. Toggle options are rendered using it as well as the "Link
Channels" button.
* Use "yellow" LEDs for bool parameters
Use "yellow" LEDs (which are actually blue) for dynamically added bool
parameters so that the dialog is consistent with regards to the LED
colors. The "Link Channels" button also uses a "yellow" LED.
* Fix Qt5 builds
Fix the Qt5 builds which do not know horizontalAdvance as a member of
FontMetrics.
Also refactor LedCheckBox::onTextUpdated to make it more compact.
* Style sheets for BarModelEditor
Add style sheets options for BarModelEditor. See the changes in
style.css for the available options and their usage.
The members that can be manipulated by the style sheet options are
initialized accoriding to the palette so that the BarModelEditor should
also render something useful if no style is set.
Adjust the paintEvent method to use the style sheet brushes and colors.
* Layout optimizations
Set the vertical scroll bar to always show so that the controls do not
move around if the scroll bar is hidden or shown.
Set the margin of the grid layout to 0 so that the whole dialog becomes
tighter.
* Get rid of initial scroll bars
Make sure that the widget is shown without a scrollbar whenever possible
using the following rules.
If the widget fits on the workspace we use the height of the widget as
the minimum size of the scroll area. This will ensure that the scrollbar
is not shown initially (and never will be).
If the widget is larger than the workspace then we want it to mostly
cover the workspace. In that case the minimum height is set to 90 % of
the workspace.
* Switch to a green theme
Switch to a green theme to better match the default theme.
* Adjust classic theme
Adjust the classic theme so that it renders the bars in a legible way.
* Fixes for CodeFactor
Remove virtual keyword from methods that are marked as override.
Remove whitespaces that make CodeFactor unhappy. One of these fixes
includes moving the implementation of
LadspaMatrixControlDialog::isResizable into the cpp file.
* CodeFactor is still unhappy
Remove a blank line after the constructor.
* Center align time based controls
Align time based controls, i.e. knobs, in the center.
The implementation defeats the purpose of the widget factory a bit but
it makes the design look nicer.
* Fix build
Fix the build by adjusting the enums. I added the changes while writing
the commit message for the merge commit but they did not make it.
* Attempt at CodeFactor warning
Try to make the last CodeFactor warning disappear.
* Add bar controller with tempo sync option
Add `TempoSyncBarModelEditor` which adds a tempo sync option to a `BarModelEditor`. Please note that the code was mostly copied and adjusted from the `TempoSyncKnob` class. It was not attempted yet to unify some of the code because with the current design it seems to be a road to "inheritance hell". A better solution might be to refactor the code so that it is more composable.
Another option might be to move the tempo sync functionality into a class like `FloatModelEditorBase`. Although this would not be a 100% right place either because `TempoSyncKnobModel` inherits from `FloatModel`. In that case we'd have specialized code in a generic base class.
Adjust `LadspaWidgetFactory` so that it now returns an instance of a `TempoSyncBarModelEditor` instead of a `TempoSyncKnob`.
Remove the extra layout code from `LadspaMatrixControlDialog.cpp` as most things are bar editors now.
Adjust `TempoSyncKnobModel` so we do not have to make `TempoSyncBarModelEditor` a friend of it.
* Another attempt to please CodeFactor
Have another attempt to fix CodeFactor's complaints about `LadspaMatrixControlDialog.h`.
* Coding conventions, blanks and blank lines
Remove lots of unnecessary white space. Remove blank lines. Remove leading underscores from parameters.
Remove line breaks in `TempoSyncBarModelEditor.cpp` to make the code more readable. Remove repeated method calls by introducing local variables.
* Break down complex method
Break down the complex method `TempoSyncBarModelEditor::updateDescAndIcon` by delegating to the new methods `updateTextDescription` and `updateIcon`.
* Another attempt to please CodeFactor
Another attempt to fix `LadspaMatrixControlDialog.h` to please CodeFactor.
* Work on TODOs
The TODO "Assumes that all processors are equal..." has been turned into a comment when we start iterating over the channels. If the channels are not of the same structure this would likely also have been a problem in the old implementation.
The TODO "Use a factory..." has been removed as this is already done.
The include of `FloatModelEditorBase.h` in LadspaWidgetFactory has been removed.
* Modifier keys for mouse wheel adjustments
Integrate the changes of commit 7000afb2ea into `FloatModelEditorBase`.
This commit added modifier keys for mouse wheel adjustments to the `Knob` class. The port to `FloatModelEditorBase` results in the bar control now also supporting different scales of adjustments that can be switched with the Shift, Ctrl and Alt keys.
* Show current value on mouse over
Integrate the changes of commit fcdf4c0568 into `FloatModelEditorBase`. This commit lets users show the current value of a float model when the mouse is moved over the control.
* Make Knob inherit from FloatModelEditorBase
Make `Knob` inherit from `FloatModelEditorBase`. This is mostly a continuation for the changes introduced with commit c63d86f.
The idea is that `FloatModelEditorBase` contains the underlying functionality and logic to deal with float models. `Knob` and other classes then only override the presentation aspects. This way `Knob` and `BarModelEditor` can share the same functionality but can differ in how they present the data.
Technical details
------------------
Remove all methods that are already defined in `FloatModelEditorBase` from `Knob`. These are all methods that are defined in the same way in `FloatModelEditorBase`. The method `paintEvent` is not removed because it is overridden by `Knob` as it has its own presentation.
Remove forward declaration of `QPixmap` from `FloatModelEditorBase` as it was not used. Remove unused function `convertPixmapToGrayScaleTemp` from `FloatModelEditorBase`.
* Cleanup includes in Knob class
* Code style changes in FloatModelEditorBase
`FloatModelEditorBase` is a new class/file. Therefore we can do some extensive code cleanup on the code that was initially copied from `Knob`.
Adjust whitespace for methods and some if-statements. Remove underscores from parameter names. Use only two blank lines between method definitions.
* Cleanup include for FloatModelEditorBase
* Show effect name as title of dialog
Add the effect name as the title in the content of the window. This improves the structure of the dialog as it is now clearer from the content itself to which effect the controls belong to.
This duplicates the information from the window title. However, the window title is rather small and the larger font in the content makes it easier to find an effect in a set of opened dialogs.
* Revert "Show effect name as title of dialog"
This reverts commit 8ce0d366d0.
* Fix problem with LedCheckBox in grid layout
The LedCheckBox does not play nice when being used in a grid layout as it disables the resizing behavior of every column it appears in.
The solution is to wrap it into the layout of a parent widget that knows how to behave.
* Reduce minimum width of BarModelEditor
Reduce the minimum width of `BarModelEditor` from 200 to 50.
---------
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
This PR makes changes in the submodule `zynaddsubfx`. It affects its
submodule `instruments`:
* updates the URL to use github (since SF is less reliable)
* changes the protocl from SSH to HTTPS (see
https://stackoverflow.com/a/50299434)
* does not change the submodule's commit ID
You must now run
```
git submodule sync --recursive
```
once to reflect this change.
* Fix warnings "QPainterPath::lineTo Invalid coordinates" on console when loading the effect or changing
some paramenters, by not "drawing" the EQ curve when there is no EQ band active.
* Fix warnings on console "QPainterPath::lineTo Invalid coordinates" when EQ is processing a sound, because
in this function log10f generates a pole error when freq is 0, returning and invalid x value pixel
* Update plugins/Eq/EqCurve.cpp
---------
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Fix issue with knob range
* Randomness for BandedWG
* Implement Tubular Bells ADSR
* LFO - update values on change while playing
* coding style
* Vibrato Gain - update
* fixed cmakelists conditions
* Fixed the order messup.
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
---------
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Mallets - Add random knob function
Implement randomness for the instrument. When Random is applied, Hardness and Position of instrument 1 - 9, or Modulator and Crossfade on instrument 10 (Tubular Bells), are nudged on every note to liven up the sound. With the modulated knobs placed at their center values, Random at max will select from the full range of possible values.
Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
Remove identical calls to `InstrumentTrack::processAudioBuffer` which appear in the overridden implementations of `Instrument::play` and `Instrument::playNotes`. Instead the call to `processAudioBuffer` has been moved into `InstrumentPlayHandle::play` and `InstrumentTrack::playNote`. These two methods call the aforementioned methods of `Instrument`. Especially in the case of `InstrumentTrack::playNote` the previous implementation resulted in some unncessary "ping pong" where `InstrumentTrack` called a method on an `Instrument` which then in turn called a method on `InstrumentTrack`. And this was done in almost every instrument.
In `InstrumentTrack::playNote` an additional check was added which only calls `processAudioBuffer` if the buffer is not `nullptr`. The reason is that under certain circumstances `PlayHandle::doProcessing` calls the `play` method by explicitly passing a `nullptr` as the buffer. This behavior was added with commit 7bc97f5d5b. Because it is unknown if this was done for some side effects the code was adjusted so that it behaves identical in this case.
Move the complex implementation for `InstrumentPlayHandle::play` and `InstrumentPlayHandle::isFromTrack` into the cpp file and optimize the includes.
* Add options to enable sanitizers
* Specify them as debugging options
* Apply suggestions made by Dom
* Fix linking issues
There were linking issues, most likely because we were
applying the sanitizer flags to unnecessary targets that
are part of the build. Now, we only focus on adding the
compiler flags to lmmsobjs as a PUBLIC dependency,
and selectively choose what targets we need to apply
the linker flags to as PRIVATE dependencies.
* Add UBSan
* Add status messages
* Remove GNU as supported compiler for MSan
* Revert to using add_<compile|link>_options again
* Fix sanitizer linkage within veal and cmt libraries
I suspect that our sanitizer flags were removed for these two CMake
targets. Instead of setting the properties directly, we call
target_compile_options and target_link_options
instead.
* Remove TODO comment
* Revert "Fix sanitizer linkage within veal and cmt libraries"
This reverts commit b04dce8d8c.
* Use CMAKE_<LANG>_FLAGS_<CONFIG> and apply fixes
* Remove quotes
* Add support for additional flags
* Disable vptr for UBSan
* Print "Debug using" in status for clarity
* Wrap ${supported_compilers} and ${status_flag} in quotes
* Replace semicolons with spaces in additional_flags
* Remove platform check for no-undefined flag
The platform check was added as an attempt
to make this branch compile with the veal
and cmt libraries. However, it seems to work
without it, so the problem must've been something
else occuring in these files.
* Undo change to FP exceptions status message
* Use spaces instead of tabs
* Remove -no-undefined flag for cmt and veal libraries
* Fix LADSPA effects memory leak
* Fix buffer overflow in PianoView
* Avoid using invalid iterators in AutomationClip
* Fix memory leaks in SimpleTextFloat
* Handle potential case where QMap::lowerBound(...) returns end iterator
* Implement suggestions from review
* Add `ArrayVector` class template and tests
* Fix counting of failed test suites
* Support detuning and panning with Sf2 Player
* Restrict panning to supported FluidSynth versions
* Fix data array cast type
* Fix tests for Qt<5.10 and correct mistaken test
* DIsplay warning for FluidSynth < 2
* Remove unnecessary clamp
* Update include guard name
* Add Tap Tempo Feature (#6375)
Resolves#5181
* Update formatting, use namespaces, etc.
* Use Qt Designer .ui file to handle the UI
Thanks to irrenhaus for the idea
Also added a few buttons I will add functionality for
* Play metronome sound when tapped
* Improve stabilization speed by comparing differences in length between intervals
To improve the speed at which the BPM counter stabilizes at a
certain number, we now compare the differences in length between
the last two taps and the most recent two taps and reset the counter
if the threshold is passed.
I made it so that a difference of 500 ms resets the counter.
* Remove duplicate m_ui
An artifact from my battle with Git and merge conflicts..
* Format TapTempoUi header file
* Add lmms namespace in UI file
* Remove taptempo.ui XML file
Not needed
* Add LMMS_EXPORT to SamplePlayHandle
* Use std::chrono::duration<double, std::milli> for intervals
Co-authored-by: irrenhaus3 <irrenhaus3@gmail.com>
* Use alias for steady_clock
Co-authored-by: irrenhaus3 <irrenhaus3@gmail.com>
* Speed up convergence by accounting for recent intervals
This uses a combination of keeping track of a more accurate BPM,
while also using a BPM difference threshold to move towards the true BPM
more quickly.
After three taps, a "recent interval" is calculated, which is similar
to the latest interval, but less fluctuating since it accounts for
three taps instead of one. This allows for comparing between
the BPM on the display with the recent BPM more closely.
We then compare the difference in magnitude of both BPM's
with the threshold. If the threshold is passed, the counter gets reset.
* Remove semicolon from "QOBJECT;" in plugins/TapTempo/TapTempo.h
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Add newline between using alias and constructor
* Cleanup header files
* Add // namespace lmms::gui comment
* Rename header guards in plugins/TapTempo/TapTempo.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Rename header guards in plugins/TapTempo/TapTempo.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Rename header guards in plugins/TapTempo/TapTempoUi.h
Will merge this file with ``TapTempoView`` soon.
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Rename header guards in plugins/TapTempo/TapTempoUi.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update plugins/TapTempo/TapTempo.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Replace virtual with override in plugins/TapTempo/TapTempo.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Merge UI file into TapTempoView
* Pass TapTempo* directly into constructor in plugins/TapTempo/TapTempoView.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Update style in plugins/TapTempo/TapTempoView.h
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Add parameter name for keyPressEvent function in plugins/TapTempo/TapTempoView.h
Also reorder the function declarations to match the order in the source file.
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Remove dynamic_cast to TapTempo* in plugins/TapTempo/TapTempoView.cpp
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Restrict C linkage to only lmms_plugin_main and plugin descriptor
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Simplify algorithm
* Update labels when calling closeEvent
* Add reset button
* Adjust layout
* Format document
* Only allow the tap button to gain focus
* Use icon provided by LMMS
* Add sync button and adjust formatting
* Make the metronome downbeat the first beat
Also simplify code
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Round BPM values when syncing with project tempo
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Change Plugin::Tool to Plugin::Type::Tool
---------
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
* Replace QVector with std::vector in AudioEngine
* Replace QVector with std::vector in AudioEngineWorkerThread
* Replace QVector with std::vector in AudioJack
* Replace QVector with std::vector in AutomatableModel
* Replace QVector with std::vector in AutomationClip
* Replace QVector with std::vector in AutomationEditor
* Replace QVector with std::vector in ConfigManager
* Replace QVector with std::vector in Controller
* Replace QVector with std::vector in ControllerConnection
* Replace QVector with std::vector in EffectChain
* Replace QVector with std::vector in EnvelopeAndLfoParameters
* Replace QVector with std::vector in InstrumentFunctions
* Replace QVector with std::vector in MidiClient
* Replace QVector with std::vector in Mixer
* Replace QVector with std::vector in Note
* Replace QVector with std::vector in PeakController
* Replace QVector with std::vector in PianoRoll
* Replace QVector with std::vector in PluginFactory
* Replace QVector with std::vector in RenderManager
* Replace QVector with std::vector in StepRecorder
* Replace QVector with std::vector in Track
* Replace QVector with std::vector in TrackContainer
* Replace QVector with std::vector in Song
* Adapt QVector to std::vector changes in ControllerConnectionDialog
* Phase 2: Use std::abs in panning.h
Without this, the QVector changes will make the code not compile.
* Phase 2: Replace QVector with std::vector in PeakControllerEffect
* Phase 2: Replace QVector with std::vector in AutomatableModel
* Phase 2: Replace QVector with std::vector in AutomationClip
* Phase 2: Replace QVector with std::vector in ControllerConnection
* Phase 2: Replace QVector with std::vector in EffectChain
* Phase 2: Replace QVector with std::vector in Mixer
* Phase 2: Replace QVector with std::vector in PeakController
* Phase 2: Replace QVector with std::vector in RenderManager
* Phase 2: Replace QVector with std::vector in Song
* Phase 2: Replace QVector with std::vector in StepRecorder
* Phase 2: Replace QVector with std::vector in Track
* Phase 2: Replace QVector with std::vector in TrackContainer
* Phase 2: Adapt QVector changes in EffectRackView
* Phase 2: Adapt QVector changes in AutomationClipView
* Phase 2: Adapt QVector changes in ClipView
* Phase 2: Adapt QVector changes in AutomationEditor
* Phase 2: Adapt QVector changes in PianoRoll
* Phase 2: Adapt QVector changes in TrackContainerView
* Phase 2: Adapt QVector changes in TrackContentWidget
* Phase 2: Adapt QVector changes in InstrumentTrack
* Phase 2: Adapt QVector changes in MidiClip
* Phase 2: Adapt QVector changes in SampleTrack
* Fix segmentation fault in ConfigManager::value
* Fix unintended faulty std::vector insert in AutomationClip::resolveAllIDs
* Resolve trailing whitespace in src/core/StepRecorder.cpp
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Use std::next and std::prev in EffectChain::moveUp/moveDown
* Introduce static "combineAllTracks" function in AutomationClip
* Adjust variable name in Song::automatedValuesAt
* Adjust removal of long step notes in StepRecorder::removeNotesReleasedForTooLong
* Iterate over m_chords by const reference in src/core/InstrumentFunctions.cpp
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Fix StepRecorder::removeNotesReleasedForTooLong again
* Combine the ConfigManager::value overloads using std::optional
* Revise StepRecorder::removeNotesReleasedForTooLong
* Remove redundant std::optional in ConfigManager::value
* Remove trailing whitespace in ConfigManager::value
* Fix: Prevent incorrect use of std::distance when element not found
* Chore: Remove trailing whitespace in edited files
* Only set the id attribute if the controller was found
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Remove extra indents from 84b8fe8a559855ed263b74cc582eab3655250c5f
* Fix compilation issues
* Add LMMS_ prefix for header guard in Track.h
* Undo changes made to MixerView::deleteUnusedChannels
* Simplify code to handle failure of finding tracks
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Split ternary operator into separate if statement
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Undo changes to indentation in MixerRoute
* Do general clean-up
Some of the changes made:
+ Use auto where benefical
+ Fix bug in AutomatableModel::globalAutomationValueAt (for loop should be looping over clips variable, not clipsInRange)
+ Undo out of focus whitespace changes
* Always assign to m_steps regardless if clip is found or not
Even when the clip is not found (i.e., currentClip is -1), m_steps still
gets assigned to.
* Insert at the end of tracks vector in src/core/Mixer.cpp
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Insert at the end of tracks vector in src/core/Mixer.cpp (2)
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Remove redundant template parameter
* Use std::array for zoomLevels
---------
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>