-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for multi-channel plugins #7459
Open
messmerd
wants to merge
68
commits into
LMMS:master
Choose a base branch
from
messmerd:pin-connector
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 55 commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
93884a2
Add PluginPortConfig class
messmerd f1f1010
Avoid misleading types and weird casts
messmerd c78c17f
Use PluginPortConfig for mono VSTs
messmerd 4da60af
Refactor; Fix automation clip tooltip
messmerd 798e088
Begin pin connector implementation (WIP)
messmerd af4d6b3
Loading/saving (WIP)
messmerd aafe41c
More efficient loading
messmerd 360eca6
Use new routing methods (WIP)
messmerd 7b7f674
Progress (WIP)
messmerd 1568d3a
Merge branch 'master' into pin-connector
messmerd 5f31c04
Fix up post-merge (WIP)
messmerd 853d80c
Fix crash
messmerd 7935718
Begin implementing PluginPinConnectorView
messmerd b3ad72a
Progress (WIP)
messmerd b55bdec
Fix pin icon while dragging
messmerd bda93bc
More progress
messmerd 15f395e
Draw plugin channel text
messmerd 8d2acad
Fix Linux build
messmerd a00cdba
Some refactoring
messmerd c98353f
Fix build
messmerd 774e3b6
Introduce MatrixView class
messmerd e768a58
Use layouts
messmerd 2ee2c08
Make PluginPinConnector::Matrix a struct; Add tooltips
messmerd 8445f2c
Set model display names
messmerd ecc6318
Fix a display bug
messmerd a317e16
Remove some unused code
messmerd 2571547
Fix crash when reloading project with pin connector open
messmerd ada15d3
Fix miscalculation in mousePressEvent
messmerd a308725
Better pin connector button text; Better naming and comments
messmerd 09eb59f
Use pointing hand cursor when hovering over cells
messmerd f6910c6
Make routing methods const
messmerd ba3ffc6
Improve routing normalization
messmerd af5c16b
Use bitwise OR
messmerd 32557d4
Move some pin connector methods into Matrix
messmerd 1716186
Use `const float*` for process's in buffer
messmerd 23fd48b
Rename `m_trackChannelsUsed` to `m_trackChannelsUpperBound`
messmerd 089ffb4
Merge branch 'master' into pin-connector
messmerd 62efd0e
Various changes
messmerd b7883f1
Use `MAXIMUM_BUFFER_SIZE`
messmerd bd404df
Revert strongly typed sample types
messmerd dcf1fc9
Minor optimization in `mixInputs` lambda
messmerd f522c17
Merge branch 'master' into pin-connector
messmerd 6e1d921
Pin connector refactor (#2)
messmerd d69c449
VST effect wet/dry mixing
messmerd afc24cc
Add pin connector button to EffectView
messmerd 414e7c9
Remove old pin connector button from VstEffectControls
messmerd a56520f
Update pin connector button's tooltip when channel count changes
messmerd a43e121
Fix default connections for instruments with sidechain inputs
messmerd 9136b7d
Draw arrows in and out of plugin channels; Simplifications
messmerd d4b9b43
Add pluginBuffersChange signal; improve error handling
messmerd 5bd1ec3
Merge branch 'master' into pin-connector
messmerd 2a271fd
Fix VST silent output
messmerd b81546a
Fix isMidiBased
messmerd 36c99d9
Rename classes
messmerd 3661bbd
Address review comments
messmerd 262e540
Fix crash when loading VST instrument as a VST effect
messmerd b34df28
Use "summing" behavior rather than "averaging"
messmerd eadeabf
Plugin audio ports (#3)
messmerd b96b2f9
Merge branch 'master' into pin-connector
messmerd 15b15cf
Add pin connector button for all instruments
messmerd 0107d60
Include memory header
messmerd 50dc34d
Merge branch 'master' into pin-connector
messmerd 11aa3fa
Use std::span
messmerd b2b8b3b
Fix saving and loading
messmerd c132756
Use `@tparam` instead of `@param`
messmerd 28aca19
Pass audio port type as template template parameter
messmerd f3a8b3f
Remove `CoreAudioData` and `CoreAudioDataMut`
messmerd b4736cc
Merge branch 'master' into pin-connector
messmerd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/* | ||
* AudioData.h - Audio data types | ||
* | ||
* Copyright (c) 2024 Dalton Messmer <messmer.dalton/at/gmail.com> | ||
* | ||
* This file is part of LMMS - https://lmms.io | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 2 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public | ||
* License along with this program (see COPYING); if not, write to the | ||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
* Boston, MA 02110-1301 USA. | ||
* | ||
*/ | ||
|
||
#ifndef LMMS_AUDIO_DATA_H | ||
#define LMMS_AUDIO_DATA_H | ||
|
||
#include <cassert> | ||
#include <type_traits> | ||
|
||
#include "lmms_basics.h" | ||
|
||
namespace lmms | ||
{ | ||
|
||
//! Conventions for passing audio data | ||
enum class AudioDataLayout | ||
{ | ||
/** | ||
* Given: | ||
* - N == Frame count | ||
* - C == Number of channels | ||
* - i == Sample index, where 0 <= i < N | ||
* - `samples` has the type sample_t* | ||
* - `samples` size == N * C | ||
*/ | ||
|
||
/** | ||
* Layout where the samples for each channel are interleaved. | ||
* i.e. "LRLRLRLR" | ||
* | ||
* Samples for individual channels can be accessed like this: | ||
* - Channel #0 samples: samples[C*i] | ||
* - Channel #1 samples: samples[C*i + 1] | ||
* - Channel #2 samples: samples[C*i + 2] | ||
* - Channel #3 samples: samples[C*i + 3] | ||
* - ... | ||
*/ | ||
Interleaved, | ||
|
||
/** | ||
* Layout where all samples for a particular channel are grouped together. | ||
* i.e. "LLLLRRRR" | ||
* | ||
* Samples for individual channels can be accessed like this: | ||
* - Channel #0 samples: samples[i] | ||
* - Channel #1 samples: samples[1*N + i] | ||
* - Channel #2 samples: samples[2*N + i] | ||
* - Channel #3 samples: samples[3*N + i] | ||
* - ... | ||
*/ | ||
Split | ||
}; | ||
|
||
|
||
/** | ||
* A simple type alias for floating point audio data types which documents the data layout. | ||
* | ||
* For example, `const InterleavedSampleType<sample_t>*` can be used as a replacement for `const sample_t*` | ||
* parameters in order to document that the data layout of the audio is interleaved. | ||
* | ||
* NOTE: Can add support for integer sample types later | ||
*/ | ||
template<AudioDataLayout layout, typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> | ||
using SampleType = T; | ||
|
||
template<typename T> | ||
using SplitSampleType = SampleType<AudioDataLayout::Split, T>; | ||
|
||
template<typename T> | ||
using InterleavedSampleType = SampleType<AudioDataLayout::Interleaved, T>; | ||
|
||
|
||
//! Use when the number of channels is not known at compile time | ||
inline constexpr int DynamicChannelCount = -1; | ||
|
||
|
||
/** | ||
* Non-owning view for multi-channel "split" (non-interleaved) audio data | ||
* | ||
* TODO C++23: Use std::mdspan | ||
*/ | ||
template<typename SampleT, int channelCount = DynamicChannelCount, typename = SplitSampleType<SampleT>> | ||
class SplitAudioData | ||
{ | ||
public: | ||
SplitAudioData() = default; | ||
SplitAudioData(const SplitAudioData&) = default; | ||
|
||
/** | ||
* `data` is a 2D array of channels to buffers: | ||
* data[channels][frames] | ||
* Each buffer contains `frames` frames. | ||
*/ | ||
SplitAudioData(SplitSampleType<SampleT>* const* data, pi_ch_t channels, f_cnt_t frames) | ||
: m_data{data} | ||
, m_channels{channels} | ||
, m_frames{frames} | ||
{ | ||
assert(channelCount == DynamicChannelCount || channels == channelCount); | ||
} | ||
|
||
//! Contruct const from mutable | ||
template<typename T = SampleT, std::enable_if_t<std::is_const_v<T>, bool> = true> | ||
SplitAudioData(const SplitAudioData<std::remove_const_t<T>, channelCount>& other) | ||
: m_data{other.data()} | ||
, m_channels{other.channels()} | ||
, m_frames{other.frames()} | ||
{ | ||
} | ||
|
||
/** | ||
* Returns pointer to the buffer of a given channel. | ||
* The size of the buffer is `frames()`. | ||
*/ | ||
auto buffer(pi_ch_t channel) const -> SplitSampleType<SampleT>* | ||
{ | ||
assert(channel < m_channels); | ||
return m_data[channel]; | ||
} | ||
|
||
template<pi_ch_t channel> | ||
auto buffer() const -> SplitSampleType<SampleT>* | ||
{ | ||
static_assert(channel != DynamicChannelCount); | ||
static_assert(channel < channelCount); | ||
return m_data[channel]; | ||
} | ||
|
||
constexpr auto channels() const -> pi_ch_t | ||
{ | ||
if constexpr (channelCount == DynamicChannelCount) | ||
{ | ||
return m_channels; | ||
} | ||
else | ||
{ | ||
return static_cast<pi_ch_t>(channelCount); | ||
} | ||
} | ||
|
||
auto frames() const -> f_cnt_t { return m_frames; } | ||
|
||
/** | ||
* WARNING: This method assumes that internally there is a single | ||
* contiguous buffer for all channels whose size is channels() * frames(). | ||
* Whether this is true depends on the implementation of the source buffer. | ||
*/ | ||
auto sourceBuffer() const -> SplitSampleType<SampleT>* | ||
{ | ||
assert(m_data != nullptr); | ||
messmerd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return m_data[0]; | ||
} | ||
|
||
auto data() const -> SplitSampleType<SampleT>* const* { return m_data; } | ||
|
||
private: | ||
SplitSampleType<SampleT>* const* m_data = nullptr; | ||
pi_ch_t m_channels = 0; | ||
f_cnt_t m_frames = 0; | ||
}; | ||
|
||
|
||
//! Converts between sample types | ||
template<typename Out, typename In> | ||
inline auto convertSample(const In sample) -> Out | ||
{ | ||
if constexpr (std::is_floating_point_v<In> && std::is_floating_point_v<Out>) | ||
{ | ||
return static_cast<Out>(sample); | ||
} | ||
else | ||
{ | ||
static_assert(always_false_v<In, Out>, "only implemented for floating point samples"); | ||
} | ||
} | ||
|
||
|
||
} // namespace lmms | ||
|
||
#endif // LMMS_AUDIO_DATA_H |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR seems to have many useless includes. While many of them might be caused in the past, at least for those files where you touch the includes (or for all files that you touch?), they should be cleaned in this PR.
Checking for includes can be done as follows (I once need to set up a wiki page for this, or even integrate it):
flags="include-what-you-use;-Xiwyu;--mapping_file=/usr/share/include-what-you-use/qt5_11.imp;-Xiwyu;--keep=*/xmmintrin.h;-Xiwyu;--keep=*/lmmsconfig.h;-Xiwyu;--keep=*/weak_libjack.h;-Xiwyu;--keep=*/sys/*;-Xiwyu;--keep=*/debug.h;-Xiwyu;--keep=*/SDL/*;-Xiwyu;--keep=*/alsa/*;-Xiwyu;--keep=*/FL/x.h;-Xiwyu;--keep=*/MidiApple.h;-Xiwyu;--keep=*/MidiWinMM.h;-Xiwyu;--keep=*/AudioSoundIo.h"
(assuming you use Qt5, you are on Linux and the mapping file is correct)cmake -DCMAKE_C_INCLUDE_WHAT_YOU_USE="$flags" -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="$flags" ..
make >make.txt 2>&1
(and wait a whole while, this can take half an hour)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One note about this: I plan to do a complete
#include
-cleanup on master. You can still do it hear, but you can also merge without this check to master and I will fix it there, anyways.