Audacity 3.2.0
LV2Instance.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file LV2Instance.cpp
6
7 Paul Licameli split from LV2Effect.cpp
8
9 Audacity(R) is copyright (c) 1999-2008 Audacity Team.
10 License: GPL v2 or later. See License.txt.
11
12**********************************************************************/
13#if defined(USE_LV2)
14
15#if defined(__GNUC__)
16#pragma GCC diagnostic ignored "-Wparentheses"
17#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
18#elif defined(__clang__)
19#pragma clang diagnostic ignored "-Wparentheses"
20#pragma clang diagnostic ignored "-Wdeprecated-declarations"
21#endif
22
23#include "LV2Instance.h"
24#include "LV2Wrapper.h"
25#include "AudacityException.h"
26
28 const PerTrackEffect &effect, const LV2FeaturesList &features,
29 const LV2Ports &ports
30) : PerTrackEffect::Instance{ effect }
31 , mFeatures{ features }
32 , mPorts{ ports }
33{
35
36 int userBlockSize;
37 LV2Preferences::GetBufferSize(effect, userBlockSize);
38 mUserBlockSize = std::max(1, userBlockSize);
39 lv2_atom_forge_init(&mForge, mFeatures.Base().URIDMapFeature());
40}
41
43
45 double sampleRate)
46{
47 // Come here only when doing non-realtime application of the effect, in which
48 // case, we don't care about capturing the output ports
49 if (mMaster && sampleRate == mFeatures.mSampleRate) {
50 // Already made but be sure to connect control ports to the right place
51 mMaster->ConnectControlPorts(mPorts, GetSettings(settings), nullptr);
52 return;
53 }
54 mMaster = MakeWrapper(settings, sampleRate, nullptr);
56}
57
58std::unique_ptr<LV2Wrapper>
60 double sampleRate, EffectOutputs *pOutputs)
61{
63 GetSettings(settings), sampleRate, pOutputs);
64}
65
66size_t LV2Instance::SetBlockSize(size_t maxBlockSize)
67{
69 std::min({maxBlockSize, mUserBlockSize, mFeatures.mMaxBlockSize}));
70 if (mMaster)
71 mMaster->SendBlockSize();
72 for (auto &pSlave : mSlaves)
73 pSlave->SendBlockSize();
74 return GetBlockSize();
75}
76
78{
79 return mFeatures.mBlockSize;
80}
81
83{
84 return mPorts.mAudioIn;
85}
86
88{
89 return mPorts.mAudioOut;
90}
91
92auto LV2Instance::GetLatency(const EffectSettings &, double) const
94{
95 if (mMaster && mUseLatency && mPorts.mLatencyPort >= 0)
96 return mMaster->GetLatency();
97 return 0;
98}
99
100// Start of destructive processing path
102 double sampleRate, ChannelNames chanMap)
103{
104 MakeMaster(settings, sampleRate);
105 if (!mMaster)
106 return false;
107 for (auto & state : mPortStates.mCVPortStates)
108 state.mBuffer.reinit(GetBlockSize(), state.mpPort->mIsInput);
109 mMaster->Activate();
110 return true;
111}
112
114 const float *const *inbuf, float *const *outbuf, size_t size)
115{
116 using namespace LV2Symbols;
117 if (size > GetBlockSize())
118 return 0;
119 assert(mMaster); // else ProcessInitialize() returned false, I'm not called
120 const auto instance = &mMaster->GetInstance();
121
122 int i = 0;
123 int o = 0;
124 for (auto & port : mPorts.mAudioPorts)
125 lilv_instance_connect_port(instance,
126 port->mIndex,
127 const_cast<float*>(port->mIsInput ? inbuf[i++] : outbuf[o++]));
128
129 for (auto & state : mPortStates.mAtomPortStates)
130 state->SendToInstance(mForge, mPositionFrame, mPositionSpeed);
131
132 lilv_instance_run(instance, size);
133
134 // Main thread consumes responses
135 mMaster->ConsumeResponses();
136
137 for (auto & state : mPortStates.mAtomPortStates)
138 state->ResetForInstanceOutput();
139
140 return size;
141}
142
144{
145 for (auto & state : mPortStates.mCVPortStates)
146 state.mBuffer.reinit(GetBlockSize(), state.mpPort->mIsInput);
147 return true;
148}
149
151{
152return GuardedCall<bool>([&]{
153 mSlaves.clear();
154 for (auto & state : mPortStates.mCVPortStates)
155 state.mBuffer.reset();
156 return true;
157});
158}
159
161 EffectOutputs *pOutputs, unsigned, float sampleRate)
162{
163 // Connect to outputs only if this is the first processor for the track.
164 // (What's right when a mono effect is on a stereo channel? Unclear, but
165 // this definitely causes connection with the first channel.)
166 auto pInstance = LV2Wrapper::Create(mFeatures,
167 mPorts, mPortStates, GetSettings(settings), sampleRate,
168 mSlaves.empty() ? static_cast<LV2EffectOutputs *>(pOutputs) : nullptr);
169 if (!pInstance)
170 return false;
171 pInstance->Activate();
172 mSlaves.push_back(move(pInstance));
173 return true;
174}
175
177{
178 if (mMaster)
179 mMaster->Deactivate();
180 for (auto &pSlave : mSlaves)
181 pSlave->Deactivate();
182
183 mPositionSpeed = 0.0;
184 mPositionFrame = 0;
185 mRolling = false;
186
187 return true;
188}
189
191{
192 if (mMaster)
193 mMaster->Activate();
194 for (auto &pSlave : mSlaves)
195 pSlave->Activate();
196
197 mPositionSpeed = 1.0;
198 mPositionFrame = 0;
199 mRolling = true;
200
201 return true;
202}
203
205{
206 mNumSamples = 0;
207 for (auto & state : mPortStates.mAtomPortStates)
208 state->SendToInstance(mForge, mPositionFrame, mPositionSpeed);
209 return true;
210}
211
213 const float *const *inbuf, float *const *outbuf, size_t numSamples)
214{
215 if (group >= mSlaves.size())
216 return 0;
217 assert(numSamples <= (size_t) GetBlockSize());
218
219 if (group < 0 || group >= (int) mSlaves.size())
220 return 0;
221
222 const auto slave = mSlaves[group].get();
223 const auto instance = &slave->GetInstance();
224
225 int i = 0;
226 int o = 0;
227 for (auto & port : mPorts.mAudioPorts)
228 lilv_instance_connect_port(instance,
229 port->mIndex,
230 const_cast<float*>(port->mIsInput ? inbuf[i++] : outbuf[o++]));
231
232 mNumSamples = std::max(numSamples, mNumSamples);
233
234 if (mRolling)
235 lilv_instance_run(instance, numSamples);
236 else
237 while (--i >= 0)
238 for (decltype(numSamples) s = 0; s < numSamples; s++)
239 outbuf[i][s] = inbuf[i][s];
240
241 // Background thread consumes responses from yet another worker thread
242 slave->ConsumeResponses();
243
244 for (auto & state : mPortStates.mAtomPortStates)
245 state->ResetForInstanceOutput();
246
247 if (group == 0)
248 mPositionFrame += numSamples;
249
250 return numSamples;
251}
252
254{
255return GuardedCall<bool>([&]{
256 // Nothing to do if we did process any samples
257 if (mNumSamples == 0)
258 return true;
259
260 // Why is this not also done on the destructive processing path?
261 // Because it is soon dimissing the modal dialog anyway.
262 for (auto & state : mPortStates.mAtomPortStates)
263 state->ReceiveFromInstance();
264
265 mNumSamples = 0;
266
267 return true;
268});
269}
270#endif
Declare abstract class AudacityException, some often-used subclasses, and GuardedCall.
int min(int a, int b)
ChannelName
LV2EffectSettings & GetSettings(EffectSettings &settings)
Definition: LV2Ports.h:215
static Settings & settings()
Definition: TrackInfo.cpp:87
uint64_t SampleCount
Hold values to send to effect output meters.
LV2_URID_Map * URIDMapFeature() const
bool RealtimeSuspend() override
std::vector< std::unique_ptr< LV2Wrapper > > mSlaves
Each holds lv2 library state for realtime processing of one track.
Definition: LV2Instance.h:84
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
Definition: LV2Instance.cpp:82
LV2InstanceFeaturesList mFeatures
Definition: LV2Instance.h:76
LV2Instance(const PerTrackEffect &effect, const LV2FeaturesList &features, const LV2Ports &ports)
Definition: LV2Instance.cpp:27
std::unique_ptr< LV2Wrapper > mMaster
Holds lv2 library state for destructive processing.
Definition: LV2Instance.h:81
size_t mNumSamples
Definition: LV2Instance.h:94
LV2_Atom_Forge mForge
Definition: LV2Instance.h:86
bool RealtimeInitialize(EffectSettings &settings, double sampleRate) override
float mPositionSpeed
Definition: LV2Instance.h:89
LV2PortStates mPortStates
Definition: LV2Instance.h:78
size_t RealtimeProcess(size_t group, EffectSettings &settings, const float *const *inbuf, float *const *outbuf, size_t numSamples) override
bool RealtimeFinalize(EffectSettings &settings) noexcept override
bool ProcessInitialize(EffectSettings &settings, double sampleRate, ChannelNames chanMap) override
size_t mUserBlockSize
Definition: LV2Instance.h:92
const LV2Ports & mPorts
Definition: LV2Instance.h:77
bool RealtimeResume() override
bool mUseLatency
Definition: LV2Instance.h:96
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
Definition: LV2Instance.cpp:87
size_t SetBlockSize(size_t maxBlockSize) override
Definition: LV2Instance.cpp:66
bool mRolling
Definition: LV2Instance.h:95
bool RealtimeAddProcessor(EffectSettings &settings, EffectOutputs *pOutputs, unsigned numChannels, float sampleRate) override
SampleCount GetLatency(const EffectSettings &settings, double sampleRate) const override
Definition: LV2Instance.cpp:92
std::unique_ptr< LV2Wrapper > MakeWrapper(const EffectSettings &settings, double sampleRate, EffectOutputs *pOutputs)
Definition: LV2Instance.cpp:59
~LV2Instance() override
void MakeMaster(const EffectSettings &settings, double sampleRate)
Definition: LV2Instance.cpp:44
bool RealtimeProcessStart(MessagePackage &package) override
settings are possibly changed, since last call, by an asynchronous dialog
size_t GetBlockSize() const override
Definition: LV2Instance.cpp:77
bool RealtimeProcessEnd(EffectSettings &settings) noexcept override
settings can be updated to let a dialog change appearance at idle
int64_t mPositionFrame
Definition: LV2Instance.h:90
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
LV2CVPortStateArray mCVPortStates
Definition: LV2Ports.h:296
LV2AtomPortStateArray mAtomPortStates
Definition: LV2Ports.h:295
unsigned mAudioOut
Definition: LV2Ports.h:273
unsigned mAudioIn
Definition: LV2Ports.h:272
LV2AudioPortArray mAudioPorts
Definition: LV2Ports.h:271
static std::unique_ptr< LV2Wrapper > Create(LV2InstanceFeaturesList &baseFeatures, const LV2Ports &ports, LV2PortStates &portStates, const LV2EffectSettings &settings, float sampleRate, EffectOutputs *pOutputs)
Factory.
Definition: LV2Wrapper.cpp:32
Base class for many of the effects in Audacity.
bool GetUseLatency(const EffectDefinitionInterface &effect, bool &useLatency)
bool GetBufferSize(const EffectDefinitionInterface &effect, int &bufferSize)
Externalized state of a plug-in.
Carry output control port information back to main thread.
Definition: LV2Ports.h:228
const LV2FeaturesList & Base() const