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, bool useOutput)
46{
47 if (mMaster && sampleRate == mFeatures.mSampleRate) {
48 // Already made but be sure to connect control ports to the right place
49 mMaster->ConnectControlPorts(mPorts, GetSettings(settings), useOutput);
50 return;
51 }
52 mMaster = MakeWrapper(settings, sampleRate, useOutput);
54}
55
56std::unique_ptr<LV2Wrapper>
58 double sampleRate, bool useOutput)
59{
61 GetSettings(settings), sampleRate, useOutput);
62}
63
64size_t LV2Instance::SetBlockSize(size_t maxBlockSize)
65{
67 std::min({maxBlockSize, mUserBlockSize, mFeatures.mMaxBlockSize}));
68 if (mMaster)
69 mMaster->SendBlockSize();
70 for (auto &pSlave : mSlaves)
71 pSlave->SendBlockSize();
72 return GetBlockSize();
73}
74
76{
77 return mFeatures.mBlockSize;
78}
79
81{
82 return mPorts.mAudioIn;
83}
84
86{
87 return mPorts.mAudioOut;
88}
89
90auto LV2Instance::GetLatency(const EffectSettings &, double) const
92{
93 if (mMaster && mUseLatency && mPorts.mLatencyPort >= 0)
94 return mMaster->GetLatency();
95 return 0;
96}
97
98// Start of destructive processing path
100 double sampleRate, ChannelNames chanMap)
101{
102 MakeMaster(settings, sampleRate, false);
103 if (!mMaster)
104 return false;
105 for (auto & state : mPortStates.mCVPortStates)
106 state.mBuffer.reinit(GetBlockSize(), state.mpPort->mIsInput);
107 mMaster->Activate();
108 return true;
109}
110
112 const float *const *inbuf, float *const *outbuf, size_t size)
113{
114 using namespace LV2Symbols;
115 if (size > GetBlockSize())
116 return 0;
117 assert(mMaster); // else ProcessInitialize() returned false, I'm not called
118 const auto instance = &mMaster->GetInstance();
119
120 int i = 0;
121 int o = 0;
122 for (auto & port : mPorts.mAudioPorts)
123 lilv_instance_connect_port(instance,
124 port->mIndex,
125 const_cast<float*>(port->mIsInput ? inbuf[i++] : outbuf[o++]));
126
127 for (auto & state : mPortStates.mAtomPortStates)
128 state->SendToInstance(mForge, mPositionFrame, mPositionSpeed);
129
130 lilv_instance_run(instance, size);
131
132 // Main thread consumes responses
133 mMaster->ConsumeResponses();
134
135 for (auto & state : mPortStates.mAtomPortStates)
136 state->ResetForInstanceOutput();
137
138 return size;
139}
140
142{
143 for (auto & state : mPortStates.mCVPortStates)
144 state.mBuffer.reinit(GetBlockSize(), state.mpPort->mIsInput);
145 return true;
146}
147
149{
150return GuardedCall<bool>([&]{
151 mSlaves.clear();
152 for (auto & state : mPortStates.mCVPortStates)
153 state.mBuffer.reset();
154 return true;
155});
156}
157
159 EffectSettings &settings, unsigned, float sampleRate)
160{
161 auto pInstance = LV2Wrapper::Create(mFeatures,
162 mPorts, mPortStates, GetSettings(settings), sampleRate, false);
163 if (!pInstance)
164 return false;
165 pInstance->Activate();
166 mSlaves.push_back(move(pInstance));
167 return true;
168}
169
171{
172 if (mMaster)
173 mMaster->Deactivate();
174 for (auto &pSlave : mSlaves)
175 pSlave->Deactivate();
176
177 mPositionSpeed = 0.0;
178 mPositionFrame = 0;
179 mRolling = false;
180
181 return true;
182}
183
185{
186 if (mMaster)
187 mMaster->Activate();
188 for (auto &pSlave : mSlaves)
189 pSlave->Activate();
190
191 mPositionSpeed = 1.0;
192 mPositionFrame = 0;
193 mRolling = true;
194
195 return true;
196}
197
199{
200 mNumSamples = 0;
201 for (auto & state : mPortStates.mAtomPortStates)
202 state->SendToInstance(mForge, mPositionFrame, mPositionSpeed);
203 return true;
204}
205
207 const float *const *inbuf, float *const *outbuf, size_t numSamples)
208{
209 if (group >= mSlaves.size())
210 return 0;
211 assert(numSamples <= (size_t) GetBlockSize());
212
213 if (group < 0 || group >= (int) mSlaves.size())
214 return 0;
215
216 const auto slave = mSlaves[group].get();
217 const auto instance = &slave->GetInstance();
218
219 int i = 0;
220 int o = 0;
221 for (auto & port : mPorts.mAudioPorts)
222 lilv_instance_connect_port(instance,
223 port->mIndex,
224 const_cast<float*>(port->mIsInput ? inbuf[i++] : outbuf[o++]));
225
226 mNumSamples = std::max(numSamples, mNumSamples);
227
228 if (mRolling)
229 lilv_instance_run(instance, numSamples);
230 else
231 while (--i >= 0)
232 for (decltype(numSamples) s = 0; s < numSamples; s++)
233 outbuf[i][s] = inbuf[i][s];
234
235 // Background thread consumes responses from yet another worker thread
236 slave->ConsumeResponses();
237
238 for (auto & state : mPortStates.mAtomPortStates)
239 state->ResetForInstanceOutput();
240
241 if (group == 0)
242 mPositionFrame += numSamples;
243
244 return numSamples;
245}
246
248{
249return GuardedCall<bool>([&]{
250 // Nothing to do if we did process any samples
251 if (mNumSamples == 0)
252 return true;
253
254 // Why is this not also done on the destructive processing path?
255 // Because it is soon dimissing the modal dialog anyway.
256 for (auto & state : mPortStates.mAtomPortStates)
257 state->ReceiveFromInstance();
258
259 mNumSamples = 0;
260
261 return true;
262});
263}
264#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
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:85
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
Definition: LV2Instance.cpp:80
LV2InstanceFeaturesList mFeatures
Definition: LV2Instance.h:77
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:82
size_t mNumSamples
Definition: LV2Instance.h:95
LV2_Atom_Forge mForge
Definition: LV2Instance.h:87
bool RealtimeInitialize(EffectSettings &settings, double sampleRate) override
std::unique_ptr< LV2Wrapper > MakeWrapper(const EffectSettings &settings, double sampleRate, bool useOutput)
Definition: LV2Instance.cpp:57
float mPositionSpeed
Definition: LV2Instance.h:90
LV2PortStates mPortStates
Definition: LV2Instance.h:79
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
Definition: LV2Instance.cpp:99
size_t mUserBlockSize
Definition: LV2Instance.h:93
const LV2Ports & mPorts
Definition: LV2Instance.h:78
bool RealtimeResume() override
bool mUseLatency
Definition: LV2Instance.h:97
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
Definition: LV2Instance.cpp:85
size_t SetBlockSize(size_t maxBlockSize) override
Definition: LV2Instance.cpp:64
bool mRolling
Definition: LV2Instance.h:96
SampleCount GetLatency(const EffectSettings &settings, double sampleRate) const override
Definition: LV2Instance.cpp:90
void MakeMaster(const EffectSettings &settings, double sampleRate, bool useOutput)
Definition: LV2Instance.cpp:44
~LV2Instance() override
bool RealtimeAddProcessor(EffectSettings &settings, unsigned numChannels, float sampleRate) override
bool RealtimeProcessStart(EffectSettings &settings) override
settings are possibly changed, since last call, by an asynchronous dialog
size_t GetBlockSize() const override
Definition: LV2Instance.cpp:75
bool RealtimeProcessEnd(EffectSettings &settings) noexcept override
settings can be updated to let a dialog change appearance at idle
int64_t mPositionFrame
Definition: LV2Instance.h:91
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:287
LV2AtomPortStateArray mAtomPortStates
Definition: LV2Ports.h:286
unsigned mAudioOut
Definition: LV2Ports.h:264
unsigned mAudioIn
Definition: LV2Ports.h:263
LV2AudioPortArray mAudioPorts
Definition: LV2Ports.h:262
static std::unique_ptr< LV2Wrapper > Create(LV2InstanceFeaturesList &baseFeatures, const LV2Ports &ports, LV2PortStates &portStates, const LV2EffectSettings &settings, float sampleRate, bool useOutput)
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.
const LV2FeaturesList & Base() const