Commit Graph

7977 Commits

Author SHA1 Message Date
Michael Gregorius
8e8f68552f Disentangle and clean the classes of the Audio File Processor (#7069)
## Extract views
Extract the classes `AudioFileProcessorWaveView` and `AudioFileProcessorView` into their own files.

Reformat the new classes by removing unnecessary whitespace and underscores. Add spaces to if-statements.

Cleanup the includes.

## Remove friend relationship
Remove the friend relationship between `AudioFileProcessor` and `AudioFileProcessorView`.

Introduce getters for entities that the view is interested in.
2024-01-21 12:25:00 +01:00
Michael Gregorius
1e6a902dd3 Fix most of the track cloning for MIDI ports (#7066)
Fixes most of the problem that the MIDI port information is not cloned when a track is cloned.

The bug was caused because cloning is implemented via serialization and deserialization of the Track. The previous code only serialized the MIDI port if `Engine::getSong()->isSavingProject()` is true. However, when we are cloning the statement will be `false` because we are not saving the song. Therefore the MIDI port's state was not saved and the clone was initialized with the default values.

The fix is to serialize the MIDI port in the following cases:
* We are not in song saving mode, i.e. we are in the state that this issue is about, e.g. cloning.
* We save a song and the MIDI connections are not discarded.

Using boolean algebra these conditions can be simplified as seen in the changed statement.
2024-01-17 16:53:32 +01:00
szeli1
3343496c00 Compressor plugin hideable controls (#7008) 2024-01-15 17:20:59 -05:00
saker
6c4d458599 Migrate to CTest (#7062) 2024-01-15 17:19:33 -05:00
Michael Gregorius
629ba0362b Fix mixer channel updates on solo/mute (#7055)
* Fix mixer channel updates on solo/mute

Fix the update of the mixer channels whenever a channel is soloed or muted.

The solution is rather "brutal" as it updates all mixer channel views when one of the models changes.

Introduce private helper method `MixerView::updateAllMixerChannels`. It calls the `update` method on each `MixerChannelView` so that they can get repainted.

Call `updateAllMixerChannels` at the end of the existing method `toggledSolo`.

Introduce a new method `MixerView::toggledMute` which is called whenever the mute model of a channel changes. It also updates all mixer channels.

Fixes #7054.

* Improve mixer channel update for mute events

Improve the mixer channel update for mute events by not delegating to `MixerView` like for the solo case. Instead the `MixerChannelView` now has its own `toggledMute` slot which simply updates the widget on changes to the mute model.

Also fix `MixerChannelView::setChannelIndex` by disconnecting from the signals of the previous mixer channel and connecting to the signals for the new one.

Remove `toggledMute` from `MixerView`.

The solo implementation is kept as is because it also triggers changes to the core model. So the chain seems to be:
* Solo button clicked in mixer channel view
* Button changes solo model
* Solo model signals to mixer view which was connected via the mixer channel view
* Mixer view performs changes in the other core models
* All mixer channels are updated.

Are better chain would first update the core models and then update the GUI from the changes:
* Solo button clicked in mixer channel view
* Button changes solo model
* Solo model signals to core mixer, i.e. not a view!
* Mixer view performs changes in the other core models
* Changed models emit signal to GUI elements

* Revert "Improve mixer channel update for mute events"

This reverts commit ede65963ea.

* Add comment

After the revert done with commit the code is more consistent again but not in a good way. Hence a comment is added which indicates that an inprovement is needed.

* Abstract mixer retrieval

Abstract the retrieval of the mixer behind the new method `getMixer`. This is done in preparation for some dependency injection so that the `MixerView` does not have to ask the `Engine` for the mixer but gets it injected, a.k.a. the "Hollywood principle": "Don't call us, we'll call you."

It's called `getMixer` and not just mixer because it allows for locale variables to be called `mixer` without confusing it with the method.

* Let MixerView connect directly to models

Let the `MixerView` connect directly to the solo and mute models it is connected with.

Remove the connections that are made in `MixerChannelView` which acted as a proxy which only complicated things.

Add `connectToSoloAndMute` which connects the `MixerView` to the solo and mute models of a given channel. Call it whenever a new channel is created.

Add `disconnectFromSoloAndMute` which disconnects the `MixerView` from the solo and mute models of a given channel. Call it when a channel is deleted.

* Code cleanup

Cleanup code related to the creation of the master channel view.

* Inject the Mixer into the MixerView

Inject the `Mixer` into the `MixerView` via the constructor. This makes it more explicit that the `Mixer` is the model of the view. It also implements the "Dependency Inversion Principle" in that the `MIxerView` does not have to ask the `Engine` for the `Mixer` anymore.

The current changes should be safe in that the `Mixer` instance is static and does not change.

* Fix connections on song load

Disconnect and reconnect in `MixerView::refreshDisplay` which is called when a song is loaded.
2024-01-15 02:37:11 -05:00
saker
5fdf611357 Fix memory leaks within tests (#7001)
Caused by not calling `Engine::destroy`, as well as creating tracks/clips on the heap and not freeing the memory at the end of the test.

Instead of creating tracks/clips on the heap, they are now made on the stack, similar to how the surrounding tests create its objects.
2024-01-15 02:34:46 -05:00
Michael Gregorius
abe2c92bed Resizable mixer window (#7037)
Make the mixer window resizable and allow the effects rack to grow. This enables the users a better overview of the effects used.
2024-01-14 11:17:13 -05:00
saker
b53f2b4f54 Fix AFP playback indicator not shown when dragging and dropping samples (#7064)
The issue occurred because `AudioFileProcessorWaveView::updateSampleRange` was not being called in `AudioFileProcessorWaveView::dropEvent`.
2024-01-13 22:12:24 -05:00
zynskeywolf
af90aff84c Some minor UI fixes (#7044)
* fix ladspa browser description (unwanted line breaks), add missing labels to instruments' controls

* some more ui fixes

* translation context + style fixup
2024-01-13 21:08:41 -05:00
saker
b67c53ad29 Fix sliding of waveform when drawing sample in reverse (#7063) 2024-01-13 21:05:18 -05:00
Michael Gregorius
85399c12c2 Abstraction in MixerChannelView (#7057)
Reduce code repetition in `MixerChannelView` by introducing methods that:
* Retrieve the `MixerChannel` that's associated with the view
* Check if the associated channel is the master channel

This abstracts some functionality and also reduces direct usage of the variable `m_channelIndex`.
2024-01-13 22:03:03 +01:00
Michael Gregorius
d945ac1cbe Fix scaling of PixmapButton in layouts (#7053) 2024-01-08 09:44:58 -05:00
Rossmaxx
18d34431b3 Run without terminal for non-debug Windows builds (#7022)
* set win32 flag

* added mingw too to win32 flag + dom's suggestions

* revert unnecessary changes i made.

* simplify msys linker flag condition

* removed extra whitespace

* whitespace change 2
2024-01-08 10:20:55 +09:00
Michael Gregorius
1eff322c2a Fix crash on subsequent song loads (#7051)
Fix a crash that occurs when songs are loaded after each other. The crash only occurs if the "participating" songs have at least one other channel besides the master channel.

The crash occurred because the `MixerChannelViews` were not really deleted in `MixerView::refreshDisplay`. As a consequence the parent child relationship was still given between the `MixerView` and the `MixerChannelView`. When a song was loaded the event queue was evaluated which in turn resulted in the method `Fader::knobPosY` being called on a `Fader` which did not have a model anymore.

Fixes #7046.
2024-01-07 10:06:34 +01:00
Lost Robot
56e7f7de50 Add setSampleRate to BasicFilters and update LOMM allpass sample rate (#7048) 2024-01-04 15:31:22 -08:00
Michael Gregorius
c2f2b7e0d7 Handle divisions by 0 in Lb302 and Monstro (#7021)
* 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
2024-01-03 17:01:28 +01:00
Lost Robot
8eba258bda Accept Editor close event (#7035) 2023-12-31 19:53:52 -08:00
saker
4049cc29d3 Fix Fader pixmaps (#7041) 2023-12-31 21:52:56 -05:00
saker
f79695e4f8 Fix regressions from #6610 (#7040)
Fixes crashes when using decodeSampleOggVorbis, as well as missing supported audio formats
2023-12-31 18:05:46 -05:00
Michael Gregorius
1868fa170a Fix equalizer peak updates (#7038)
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.
2023-12-31 15:52:24 +01:00
Michael Gregorius
36cb0ed7ca Extend TabWidget's style sheet options
# Extend TabWidget's style sheet options

Extend the `TabWidget` class so that the text color of the selected tab
can be set in the style sheet. Adjust the paint method to make use of
the new property.

Adjust the default style sheet as follows:
* Background color of the selected tab is the green of the knobs
* Text color of the selected tab is full on white

Adjust the classic style sheet in such a way that nothing changes, i.e.
the text colors of the selected tab and the other ones are the same.

# Code review style changes

Completely adjust the code style of TabWidget:
* Pointer/reference close to type
* Remove underscores from parameter names
* Remove spaces from parentheses
* Add space after if and for statements

# Remove repeated iterator dereferences

Remove repeated iterator dereferences by introducing variables with speaking names.

Fixes #6730.
2023-12-31 11:55:59 +01:00
Michael Gregorius
bf4e57da19 Fix minimum size of LADSPA dialogs (#6982) (#7019)
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.
2023-12-31 11:49:15 +01:00
saker
6b21dc7896 Use Qt layouts for mixer channels (#6591)
Use Qt layouts for the mixer channels. These changes will enable several other improvements, like for example making the mixer and faders resizable, adding peak indicators, etc.

This is a squash commit which consists of the following individual commits:

* Remove extra transparency in send/receive arrows
The extra transparency was conflicting with the positioning of
the arrows in the layout

* Begin reimplementing MixerChannelView

MixerChannelView is now a combination of the
MixerLine with the previous MixerChannelView

* Adjust SendButtonIndicator to use MixerChannelView

* Remove MixerLine
- Move MixerChannelView into src/gui

* Remove MixerView::MixerChannelView

* Remove header of MixerLine

* Change MixerView.h to use MixerChannelView
Change MixerView.h to use MixerChannelView rather than MixerLine
Also do some cleanup, such as removing an unused forward declaration
of QButtonGroup

* Create EffectRackView
+ Set height of sizeHint() using MIXER_CHANNEL_HEIGHT (287)

* Remove include of MixerLine
- Include MixerChannelView

* Phase 1: Adjust MixerView to use new MixerChannelView

* Move children wigets into header file

* Phase 2: Adjust MixerView to use new MixerChannelView

* Phase 3: Adjust MixerView to use new MixerChannelView

* Phase 4: Adjust MixerView to use new MixerChannelView

* Phase 5: Adjust MixerView to use new MixerChannelView

* Phase 5: Adjust MixerView to use new MixerChannelView

* Remove places where MixerChannelView is being deleted

Before, MixerChannelView was not inherited by QWidget,
meaning it could not have a parent and had to be deleted
when necessary. Since the MixerView owns the
new MixerChannelView, this is no longer necessary.

* Replace MixerLine with MixerChannelView
- Include MixerChannelView in MixerView

* Replace setCurrentMixerLine calls with setCurrentMixerChannel around codebase

* Add event handlers in MixerChannelView

* Implement MixerChannelView::eventFilter

* Update theme styles to use MixerChannelView

* Add QColor properties from style
- Set the Qt::WA_StyledBackground attribute on

* Add effect rack to rack layout when adding channel

* Set size for MixerChannelView
- Change nullptr to this for certain widgets
   - Some custom widgets may expect there to be a parent
- Add spacing in channel layout
- Increase size of mixer channel

* Retain size when widgets are hidden

* Implement paintEvent
- Rename states in SendReceiveState

* Implement send/receive arrow toggling
- Make maxTextHeight constexpr in elideName
- Remove background changing on mouse press
(is now handled in paintEvent)

* Implement renaming mixer channels

* Implement color functions

* Implement channel moving/removing functions

* Do some cleanup
Not sure if that connection with the mute model was needed, but removing
it did not seem to introduce any issues.

* Include cassert

* Replace references to MixerLine with MixerChannelView

* Reduce height
+ Make m_renameLineEdit transparent
+ Retain size when LCD is hidden
+ Remove stretch after renameLineEdit in layout

* Remove trailing whitespace

* Make m_renameLineEdit read only
+ Transpose m_renameLineEditView rectangle (with 5px offset)

* Set spacing in channel layout back to 0

* Remove sizeHint override and constant size

* Use sizeHint for mixerChannelSize
+ Leave auto fill background to false in MixerChannelView
+ Only set width for EffectRackView

* Set margins to 4 on all sides in MixerChannelView

* Move solo and mute closer to each other

Move the solo and mute buttons closer to each other in the mixer channels.

Technically this is accomplished by putting them into their own layout with minimal margins and spacing.

* Fixes for CodeFactor

* Code review changes

Mostly whitespace and formatting changes: remove tabs, remove spaces in parameter lists, remove underscores from parameter names.

Some lines have been shortened by introducing intermediate variables, e.g. in `MixerChannelView`.

`MixerView` has many changes but only related to whitespace. Spaces have been introduced for if and for statements. Whitespace at round braces has been removed everywhere in the implementation file even if a line was not touched by the intial changes.

Remove duplicate forward declaration of `MixerChannelView`.

* Adjust parameter order in MixerChannelView's constructor

Make the parent `QWidget` the first parameter as it is a Qt convention. The default parameter had to be removed due to this.

* Move styling of rename line edit into style sheets

Move the style of the `QGraphicsView` for the rename line edit from the code into the style sheets of the default and classic theme.

* More code review changes

Fix spaces between types and references/pointers, e.g. use `const QBrush& c` instead of `const QBrush & c`.
Remove underscores from parameter names.
Remove spaces near parentheses.
Replace tabs with spaces.
Introduce intermediate variable to resolve "hanging" + operator.
Replace the connection for the periodic fader updates with one that uses function pointers instead of `SIGNAL` and `SLOT`.

---------

Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
2023-12-30 17:55:28 +01:00
saker
4e63f60652 Add missing copyright in SampleDecoder.cpp (#7030) 2023-12-25 13:14:19 -05:00
Spekular
4eba656bd3 New loop marker shortcuts, attempt 2 (#6382)
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
2023-12-25 16:26:35 +00:00
saker
ce722dd6b6 Refactor `SampleBuffer` (#6610)
* 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>
2023-12-25 07:07:11 -05:00
Lost Robot
3aefe7b3d3 Fix LOMM crossovers (#7026) 2023-12-22 13:58:02 -08:00
Dominic Clark
f3d3a1421e Split TimeLineWidget into core and GUI parts (#7004) 2023-12-16 14:19:36 +00:00
Michael Gregorius
8136b7002c Fix floating point exception in Spectrum Analyzer (#7018)
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.
2023-12-10 11:42:02 +01:00
szeli1
67ce167775 Fix AudioFileProcessor reverse bug (#6958) 2023-11-25 17:24:05 -05:00
DanielKauss
c2811aebef Ghost notes for the automation editor (#6940)
Show ghost notes or sample track as a visual aid in the Automation Editor.

---------

Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
2023-11-25 12:16:56 +01:00
saker
3a928d80b2 Enforce lazy loading for FileBrowser (#6996) 2023-11-23 20:31:49 -05:00
Lost Robot
ced1f18eca Rewrite Amplifier plugin code (#6989)
* rewrite amplifier plugin style

* pomelo

* oroblanco

* grapefruit

* calamlamondin
2023-11-23 16:30:40 -05:00
Dominic Clark
dc8c49a539 Use std::optional for colour interfaces and storage (#6991) 2023-11-19 14:52:37 +00:00
saker
aa050ae0b7 Fix memory leaks (#6879)
* 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
2023-11-19 00:44:15 -05:00
saker
fad0011508 Analyze and improve search in the file browser (again) (#6985)
Improves performance when searching in the file browser (confirmed with profiling using KCacheGrind), adds a search indicator at the bottom to let the user know a search is in progress, blacklists unnecessary system directories (speeding up both the search speed and potentially load times as well by reducing the number of filesystem entries to consider), and fixes an issue that causes not all of the search results to appear.
2023-11-18 20:47:15 -05:00
IanCaio
17c919879f Implement Note Types (#5902)
* 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>
2023-11-18 17:14:27 -05:00
Lost Robot
0255704138 Disable Compressor background autofill (#6986) 2023-11-18 16:06:26 -05:00
saker
7268827624 Revamp synchronization with the audio engine (#6881)
The revamp consists of one lock. When the audio thread needs to render audio or another thread wants to run a change, acquiring the lock grants mutual exclusion to do one of the two. The intention is that this will provide stronger guarantees that changes do not run concurrently with the audio thread, as well as having the synchronization mechanism itself be free of data races (verified with TSan).
2023-11-18 15:28:01 -05:00
Hyunjin Song
1e2167d005 Fix Sf2 player freezing on project unloading with shared SoundFonts (#6950)
* Require FluidSynth >= 1.1.7

* Use `fluid_sfont_t` directly without sharing

* Adjust formatting a bit
2023-11-18 07:27:09 -05:00
Mirko Di
a64bbc7633 Add BPM tags to built-in beat loops (#5439) (#6747)
* Added floating-point vorbis BPM tags to files in lmms/data/samples/beats
* Added rounded BPM to filenames, surrounded by square brackets and separated from the rest of the filename by an underscore
2023-11-17 16:46:28 +01:00
Bernhard
609c008a71 Keep master bus color on FX Mixer when switching project
Fixes #6398
2023-11-13 12:37:28 +01:00
Johannes Lorenz
ecc5ff8ca7 Fixes #6753: Lv2 help window issues (#6957)
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.
2023-11-12 02:25:26 +01:00
Johannes Lorenz
652b1fa57a SubWindow: Increase to respect child's sizeHint (#6956)
Before this commit, on creation, `SubWindow` gets resized to exactly the
children's `sizeHint`. This makes the child too small, since the
`SubWindow` already contains a title bar and borders.

With this commit, the `SubWindow` is calculated such that after
rendering, the child window gets exactly the `size` that its `sizeHint`
has previously suggested.

Most of LMMS widgets are not resizable, but the Lv2 help window is a
good example to test this out. The help windows now in most cases
contain enough space to fit the help text. In some cases, it still does
not fit, though debug prints show that the `size` matches the
`sizeHint`.
2023-11-12 02:21:51 +01:00
Johannes Lorenz
5c37aa2e2e Fixes #6786: Lv2Proc: Fix losing automation on export (#6944)
This PR is a about reloading an `Lv2Proc`, e.g. in case of a sample rate
change.

Prior to this PR, #6419 handled this by first saving the models into
XML, then destroying and re-initializing the whole `Lv2Proc` and finally
reloading the saved XML. However, #6786 shows that the automation is not
properly restored in such a case.

This PR thus attempts to not destroy the automatable models, just
everything else. This is done by moving `Lv2Proc::createPorts` into the
CTOR before calling `Lv2Proc::initPlugin`, which makes `initPlugin()`
and `shutdownPlugin()` proper inverses of each other (note that in jalv,
the ports are also created before the features are). The new class
`Lv2ProcSuspender` adds an RAII interface for reloading the `Lv2Proc`.

Note that another, possibly more clean approach would be to separate the
features and the plugin from the models ("controls"), to then only
destroy the features and the plugin. This could be done by having
`Lv2Effect` contain an `Lv2Proc` and `Lv2FxControls` contain an
`Lv2ProcControls`. Then the effect classes are the usual way round, and
you still maintain the separation between processor and controls in the
core LV2 code. (Similarly for the instrument, except we don't have a
processor/control split for instruments, so an instance of each class
would be contained within the same instrument instance.) - Thanks for
this proposal to @DomClark .
2023-11-12 02:20:53 +01:00
Johannes Lorenz
379acb970b Lv2Proc: Fix shutdown routine (#6944) 2023-11-12 02:20:53 +01:00
DanielKauss
c779521730 Add slicer plugin (#6857)
* extremly basic slicer, note playback and gui works

* very simple peak detection working

* basic phase vocoder implementation, no effects yet

* phase vocoder slight rewrite

* pitch shifting works more or less

* basic timeshift working

* PV timeshift working (no pitch shift)

* basic functions work (UI, editing, playback)

* slice editor Ui working

* fundamental  functionality done

* Everything basic works fully

* cleanup and code guidelines

* more file cleanup

* Tried fixing multi slice playback (still broken)

* remove includes, add license

* code factoring issues

* more code factoring

* fixed multinote playback and bpm check

* UI performance improvments + code style

* initial UI changes + more code style

* threadsafe(maybe) + UI finished

* preparing for dinamic timeshifting

* dynamic timeshifting start

* realtime time scaling (no stereo)

* stereo added, very slow

* playback performance improvments

* Roxas new UI start

* fixed cmake

* Waveform UI finished

* Roxas UI knobs + layout

* Spectral flux onset detection

* build + PV fixes

* clang-format formatting

* slice snap + better defaults

* windows build fixes

* windows build fixes part 2

* Fixed slice bug + Waveform code cleanup

* UI button text + reorder + file cleanup

* Added knob colors

* comments + code cleanup

* var names fit convention

* PV better windowing

* waveform zoom

* Minor style fixes.

* Initial artistic rebalancing of the plugin artwork.

* PV phase ghosting fix

* Use base note as keyboard slice start

* Good draft of Artwork, renamed bg to artwork

* Removed soft glow.

* Fixed load crashes + findSlices cleanup

* Added sync button

* added pitch shifting, sometimes crashes

* pitch fixes

* MacOs build fixes

* use linear interpolation

* copyright + div by 0 fixes

* Fixed rare crash + name changes + license

* review: memcpy, no array, LMMS header, name change

* static constexpr added

* static vars to public + LMMS guards

* remove references in classes

* remove constexpr and parent pointer in waveform

* std::array for fft

* fixed wrong name in style

* remove c style casts

* use src_process

* use note vector for return

* Moved PhaseVocoder into core

* removed PV from plugin

* remove pointers in waveform

* clang-format again

* Use std:: + review suggestions

Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
Co-authored-by: saker <sakertooth@gmail.com>

* More review changes

* new signal slot + more review

* Fixed pitch shifting

* Fixed buffer overflow in PV

* Fixed mouse bug + better empty screen

* Small editor refactor + improvments

* Editor playback visual + small fixes

* Roxas UI improvments

* initial timeshift removing

* Remove timeshift + slice refactor

* Removed unused files

* Fix export bug

* Fix zoom bug

* Review changes SakerTooth#2

* Remove most comments

* Performance + click to load

* update PlaybackState + zerocross snapping

* Fix windows build issue

* Review + version

* Fixed fade out bug

* Use cosine interpolation

* Apply suggestions from code review

Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>

* More review changes

* Renamed files

* Full sample only at base note

* Fix memory leak

Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>

* Style fixes

---------

Co-authored-by: Katherine Pratt <consolegrl@gmail.com>
Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com>
Co-authored-by: saker <sakertooth@gmail.com>
2023-11-11 18:09:38 -05:00
saker
8b2769bb69 Fix regression involving missed filters in #6962 (#6978) 2023-11-10 18:45:25 -05:00
saker
5596abb66a Improve search performance in FileBrowser (#6962)
Improves the search performance of the file browser by delegating the search to a worker thread. The main thread then builds the tree and displays it to the user.
2023-11-10 14:26:31 -05:00
Lost Robot
89c98a77a5 LOMM (upward/downward multiband compressor) (#6925) 2023-11-10 07:10:44 -08:00