Audacity 3.2.0
Classes | Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
RealtimeEffectManager Class Referencefinal

#include <RealtimeEffectManager.h>

Inheritance diagram for RealtimeEffectManager:
[legend]
Collaboration diagram for RealtimeEffectManager:
[legend]

Classes

struct  AllListsLock
 

Public Types

using Latency = std::chrono::microseconds
 
- Public Types inherited from Observer::Publisher< RealtimeEffectManagerMessage >
using message_type = RealtimeEffectManagerMessage
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const RealtimeEffectManagerMessage &) >
 Type of functions that can be connected to the Publisher. More...
 

Public Member Functions

 RealtimeEffectManager (AudacityProject &project)
 
 ~RealtimeEffectManager ()
 
bool IsActive () const noexcept
 To be called only from main thread. More...
 
std::shared_ptr< RealtimeEffectStateAddState (RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
 Main thread appends a global or per-group effect. More...
 
std::shared_ptr< RealtimeEffectStateReplaceState (RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, size_t index, const PluginID &id)
 Main thread replaces a global or per-group effect. More...
 
void RemoveState (RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
 Main thread removes a global or per-group effect. More...
 
std::optional< size_t > FindState (ChannelGroup *pGroup, const std::shared_ptr< RealtimeEffectState > &pState) const
 Report the position of a state in the global or a per-group list. More...
 
bool GetSuspended () const
 
void SetSuspended (bool value)
 To be called only from main thread. More...
 
- Public Member Functions inherited from ClientData::Base
virtual ~Base ()
 
- Public Member Functions inherited from Observer::Publisher< RealtimeEffectManagerMessage >
 Publisher (ExceptionPolicy *pPolicy=nullptr, Alloc a={})
 Constructor supporting type-erased custom allocation/deletion. More...
 
 Publisher (Publisher &&)=default
 
Publisheroperator= (Publisher &&)=default
 
Subscription Subscribe (Callback callback)
 Connect a callback to the Publisher; later-connected are called earlier. More...
 
Subscription Subscribe (Object &obj, Return(Object::*callback)(Args...))
 Overload of Subscribe takes an object and pointer-to-member-function. More...
 

Static Public Member Functions

static RealtimeEffectManagerGet (AudacityProject &project)
 
static const RealtimeEffectManagerGet (const AudacityProject &project)
 

Private Member Functions

std::shared_ptr< RealtimeEffectStateMakeNewState (RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
 
void Initialize (RealtimeEffects::InitializationScope &scope, double sampleRate)
 Main thread begins to define a set of groups for playback. More...
 
void AddGroup (RealtimeEffects::InitializationScope &scope, const ChannelGroup &group, unsigned chans, float rate)
 
void Finalize () noexcept
 Main thread cleans up after playback. More...
 
void ProcessStart (bool suspended)
 
size_t Process (bool suspended, const ChannelGroup &group, float *const *buffers, float *const *scratch, float *dummy, unsigned nBuffers, size_t numSamples)
 
void ProcessEnd (bool suspended) noexcept
 
 RealtimeEffectManager (const RealtimeEffectManager &)=delete
 
RealtimeEffectManageroperator= (const RealtimeEffectManager &)=delete
 
template<typename StateVisitor >
void VisitGroup (ChannelGroup &group, const StateVisitor &func)
 Visit the per-project states first, then states for leader if not null. More...
 
template<typename StateVisitor >
void VisitGroup (const ChannelGroup &group, const StateVisitor &func)
 
template<typename StateVisitor >
void VisitAll (const StateVisitor &func)
 Visit the per-project states first, then all groups from AddGroup. More...
 

Private Attributes

AudacityProjectmProject
 
Latency mLatency { 0 }
 
std::atomic< bool > mSuspended { true }
 
bool mActive { false }
 
std::vector< const ChannelGroup * > mGroups
 all are non-null More...
 
std::unordered_map< const ChannelGroup *, double > mRates
 

Additional Inherited Members

- Static Public Attributes inherited from Observer::Publisher< RealtimeEffectManagerMessage >
static constexpr bool notifies_all
 
- Protected Member Functions inherited from Observer::Publisher< RealtimeEffectManagerMessage >
CallbackReturn Publish (const RealtimeEffectManagerMessage &message)
 Send a message to connected callbacks. More...
 

Detailed Description

Definition at line 48 of file RealtimeEffectManager.h.

Member Typedef Documentation

◆ Latency

using RealtimeEffectManager::Latency = std::chrono::microseconds

Definition at line 53 of file RealtimeEffectManager.h.

Constructor & Destructor Documentation

◆ RealtimeEffectManager() [1/2]

RealtimeEffectManager::RealtimeEffectManager ( AudacityProject project)

Definition at line 39 of file RealtimeEffectManager.cpp.

41{
42}
const auto project

◆ ~RealtimeEffectManager()

RealtimeEffectManager::~RealtimeEffectManager ( )

Definition at line 44 of file RealtimeEffectManager.cpp.

45{
46}

◆ RealtimeEffectManager() [2/2]

RealtimeEffectManager::RealtimeEffectManager ( const RealtimeEffectManager )
privatedelete

Member Function Documentation

◆ AddGroup()

void RealtimeEffectManager::AddGroup ( RealtimeEffects::InitializationScope scope,
const ChannelGroup group,
unsigned  chans,
float  rate 
)
private

Main thread adds one group (passing the first of one or more channels), still before playback

Precondition
group.IsLeader()

Definition at line 73 of file RealtimeEffectManager.cpp.

76{
77 assert(group.IsLeader());
78 mGroups.push_back(&group);
79 mRates.insert({&group, rate});
80
81 VisitGroup(group,
82 [&](RealtimeEffectState & state, bool) {
83 scope.mInstances.push_back(state.AddGroup(group, chans, rate));
84 }
85 );
86}
virtual bool IsLeader() const =0
void VisitGroup(ChannelGroup &group, const StateVisitor &func)
Visit the per-project states first, then states for leader if not null.
std::unordered_map< const ChannelGroup *, double > mRates
std::vector< const ChannelGroup * > mGroups
all are non-null
std::shared_ptr< EffectInstance > AddGroup(const ChannelGroup &group, unsigned chans, float sampleRate)
Main thread sets up this state before adding it to lists.
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope

References RealtimeEffectState::AddGroup(), ChannelGroup::IsLeader(), mGroups, mRates, anonymous_namespace{wxCommandTargets.cpp}::scope, and VisitGroup().

Referenced by RealtimeEffects::InitializationScope::AddGroup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddState()

std::shared_ptr< RealtimeEffectState > RealtimeEffectManager::AddState ( RealtimeEffects::InitializationScope pScope,
ChannelGroup pGroup,
const PluginID id 
)

Main thread appends a global or per-group effect.

Parameters
pScopeif realtime is active but scope is absent, there is no effect
pGroupif null, then state is added to the global list
ididentifies the effect
Returns
if null, the given id was not found
Precondition
!pGroup || pGroup->IsLeader()
Postcondition
result: !result || result->GetEffect() != nullptr

Definition at line 275 of file RealtimeEffectManager.cpp.

278{
279 assert(!pGroup || pGroup->IsLeader());
280 auto &states = FindStates(mProject, pGroup);
281 auto pState = MakeNewState(pScope, pGroup, id);
282 if (!pState)
283 return nullptr;
284
285 // Only now add the completed state to the list, under a lock guard
286 if (!states.AddState(pState))
287 return nullptr;
288 Publish({
290 pGroup ? pGroup : nullptr
291 });
292 return pState;
293}
CallbackReturn Publish(const RealtimeEffectManagerMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
std::shared_ptr< RealtimeEffectState > MakeNewState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
RealtimeEffectList & FindStates(AudacityProject &project, ChannelGroup *pGroup)

References RealtimeEffectManagerMessage::EffectAdded, anonymous_namespace{RealtimeEffectManager.cpp}::FindStates(), ChannelGroup::IsLeader(), MakeNewState(), mProject, and Observer::Publisher< RealtimeEffectManagerMessage >::Publish().

Referenced by AudioIO::AddState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Finalize()

void RealtimeEffectManager::Finalize ( )
privatenoexcept

Main thread cleans up after playback.

Definition at line 88 of file RealtimeEffectManager.cpp.

89{
90 // Reenter suspended state
91 SetSuspended(true);
92
93 // Assume it is now safe to clean up
94 mLatency = std::chrono::microseconds(0);
95
96 VisitAll([](RealtimeEffectState &state, bool){ state.Finalize(); });
97
98 // Reset processor parameters
99 mGroups.clear();
100 mRates.clear();
101
102 // No longer active
103 mActive = false;
104}
void VisitAll(const StateVisitor &func)
Visit the per-project states first, then all groups from AddGroup.
void SetSuspended(bool value)
To be called only from main thread.
bool Finalize() noexcept
Main thread cleans up playback.

References RealtimeEffectState::Finalize(), mActive, mGroups, mLatency, mRates, SetSuspended(), and VisitAll().

Referenced by RealtimeEffects::InitializationScope::~InitializationScope().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindState()

std::optional< size_t > RealtimeEffectManager::FindState ( ChannelGroup pGroup,
const std::shared_ptr< RealtimeEffectState > &  pState 
) const

Report the position of a state in the global or a per-group list.

Definition at line 336 of file RealtimeEffectManager.cpp.

339{
340 auto &states = FindStates(mProject, pGroup);
341 return states.FindState(pState);
342}

References anonymous_namespace{RealtimeEffectManager.cpp}::FindStates(), and mProject.

Here is the call graph for this function:

◆ Get() [1/2]

RealtimeEffectManager & RealtimeEffectManager::Get ( AudacityProject project)
static

◆ Get() [2/2]

const RealtimeEffectManager & RealtimeEffectManager::Get ( const AudacityProject project)
static

Definition at line 34 of file RealtimeEffectManager.cpp.

35{
36 return Get(const_cast<AudacityProject &>(project));
37}
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static RealtimeEffectManager & Get(AudacityProject &project)

References Get(), and project.

Here is the call graph for this function:

◆ GetSuspended()

bool RealtimeEffectManager::GetSuspended ( ) const
inline

Definition at line 113 of file RealtimeEffectManager.h.

114 { return mSuspended.load(std::memory_order_relaxed); }
std::atomic< bool > mSuspended

◆ Initialize()

void RealtimeEffectManager::Initialize ( RealtimeEffects::InitializationScope scope,
double  sampleRate 
)
private

Main thread begins to define a set of groups for playback.

Definition at line 53 of file RealtimeEffectManager.cpp.

55{
56 // (Re)Set processor parameters
57 mRates.clear();
58 mGroups.clear();
59
60 // RealtimeAdd/RemoveEffect() needs to know when we're active so it can
61 // initialize newly added effects
62 mActive = true;
63
64 // Tell each state to get ready for action
66 scope.mInstances.push_back(state.Initialize(sampleRate));
67 });
68
69 // Leave suspended state
70 SetSuspended(false);
71}
std::shared_ptr< EffectInstance > Initialize(double rate)
Main thread sets up for playback.

References RealtimeEffectState::Initialize(), mActive, mGroups, mRates, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, anonymous_namespace{wxCommandTargets.cpp}::scope, SetSuspended(), and VisitAll().

Referenced by RealtimeEffects::InitializationScope::InitializationScope().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsActive()

bool RealtimeEffectManager::IsActive ( ) const
noexcept

To be called only from main thread.

Definition at line 48 of file RealtimeEffectManager.cpp.

49{
50 return mActive;
51}

References mActive.

Referenced by anonymous_namespace{PluginMenus.cpp}::IsRealtimeNotActiveFlag().

Here is the caller graph for this function:

◆ MakeNewState()

std::shared_ptr< RealtimeEffectState > RealtimeEffectManager::MakeNewState ( RealtimeEffects::InitializationScope pScope,
ChannelGroup pGroup,
const PluginID id 
)
private
Precondition
!pGroup || pGroup->IsLeader()

Definition at line 238 of file RealtimeEffectManager.cpp.

241{
242 assert(!pGroup || pGroup->IsLeader());
243 if (!pScope && mActive)
244 return nullptr;
245 auto pNewState = RealtimeEffectState::make_shared(id);
246 auto &state = *pNewState;
247 if (pScope && mActive) {
248 // Adding a state while playback is in-flight
249 auto pInstance = state.Initialize(pScope->mSampleRate);
250 pScope->mInstances.push_back(pInstance);
251 for (const auto group : mGroups) {
252 // Add all groups to a per-project state, but add only the same
253 // group to a state in the per-group list
254 if (pGroup && pGroup != group)
255 continue;
256 auto rate = mRates[group];
257 auto pInstance2 =
258 state.AddGroup(*group, pScope->mNumPlaybackChannels, rate);
259 if (pInstance2 != pInstance)
260 pScope->mInstances.push_back(pInstance2);
261 }
262 }
263 return pNewState;
264}
std::vector< std::shared_ptr< EffectInstance > > mInstances
static std::shared_ptr< RealtimeEffectState > make_shared(Args &&...args)
Definition: MemoryX.h:523

References ChannelGroup::IsLeader(), mActive, SharedNonInterfering< RealtimeEffectState >::make_shared(), mGroups, RealtimeEffects::InitializationScope::mInstances, RealtimeEffects::InitializationScope::mNumPlaybackChannels, mRates, and RealtimeEffects::InitializationScope::mSampleRate.

Referenced by AddState(), and ReplaceState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

RealtimeEffectManager & RealtimeEffectManager::operator= ( const RealtimeEffectManager )
privatedelete

◆ Process()

size_t RealtimeEffectManager::Process ( bool  suspended,
const ChannelGroup group,
float *const *  buffers,
float *const *  scratch,
float *  dummy,
unsigned  nBuffers,
size_t  numSamples 
)
private

Definition at line 122 of file RealtimeEffectManager.cpp.

126{
127 // Can be suspended because of the audio stream being paused or because
128 // effects have been suspended, so allow the samples to pass as-is.
129 if (suspended)
130 return 0;
131
132 // Remember when we started so we can calculate the amount of latency we
133 // are introducing
134 auto start = std::chrono::steady_clock::now();
135
136 // Allocate the in and out buffer arrays
137 const auto ibuf =
138 static_cast<float **>(alloca(nBuffers * sizeof(float *)));
139 const auto obuf =
140 static_cast<float **>(alloca(nBuffers * sizeof(float *)));
141
142 // And populate the input with the buffers we've been given while allocating
143 // NEW output buffers
144 for (unsigned int i = 0; i < nBuffers; i++) {
145 ibuf[i] = buffers[i];
146 obuf[i] = scratch[i];
147 }
148
149 // Now call each effect in the chain while swapping buffer pointers to feed
150 // the output of one effect as the input to the next effect
151 // Tracks how many processors were called
152 size_t called = 0;
153 size_t discardable = 0;
154 VisitGroup(group,
155 [&](RealtimeEffectState &state, bool)
156 {
157 discardable +=
158 state.Process(group, nBuffers, ibuf, obuf, dummy, numSamples);
159 for (auto i = 0; i < nBuffers; ++i)
160 std::swap(ibuf[i], obuf[i]);
161 called++;
162 }
163 );
164
165 // Once we're done, we might wind up with the last effect storing its results
166 // in the temporary buffers. If that's the case, we need to copy it over to
167 // the caller's buffers. This happens when the number of effects processed
168 // is odd.
169 if (called & 1)
170 for (unsigned int i = 0; i < nBuffers; i++)
171 memcpy(buffers[i], ibuf[i], numSamples * sizeof(float));
172
173 // Remember the latency
174 auto end = std::chrono::steady_clock::now();
175 mLatency = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
176
177 //
178 // This is wrong...needs to handle tails
179 //
180 return discardable;
181}
size_t Process(const ChannelGroup &group, unsigned chans, const float *const *inbuf, float *const *outbuf, float *dummybuf, size_t numSamples)
Worker thread processes part of a batch of samples.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:645

References PackedArray::end(), mLatency, RealtimeEffectState::Process(), anonymous_namespace{NoteTrack.cpp}::swap(), and VisitGroup().

Referenced by RealtimeEffects::ProcessingScope::Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessEnd()

void RealtimeEffectManager::ProcessEnd ( bool  suspended)
privatenoexcept

Definition at line 186 of file RealtimeEffectManager.cpp.

187{
188 // Can be suspended because of the audio stream being paused or because
189 // effects have been suspended.
190 VisitAll([suspended](RealtimeEffectState &state, bool){
191 state.ProcessEnd();
192 });
193}
bool ProcessEnd()
Worker thread finishes a batch of samples.

References RealtimeEffectState::ProcessEnd().

Referenced by RealtimeEffects::ProcessingScope::~ProcessingScope().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessStart()

void RealtimeEffectManager::ProcessStart ( bool  suspended)
private

Definition at line 109 of file RealtimeEffectManager.cpp.

110{
111 // Can be suspended because of the audio stream being paused or because
112 // effects have been suspended.
113 VisitAll([suspended](RealtimeEffectState &state, bool listIsActive){
114 state.ProcessStart(!suspended && listIsActive);
115 });
116}
bool ProcessStart(bool running)
Worker thread begins a batch of samples.

References RealtimeEffectState::ProcessStart(), and VisitAll().

Referenced by RealtimeEffects::ProcessingScope::ProcessingScope().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RemoveState()

void RealtimeEffectManager::RemoveState ( RealtimeEffects::InitializationScope pScope,
ChannelGroup pGroup,
std::shared_ptr< RealtimeEffectState pState 
)

Main thread removes a global or per-group effect.

Parameters
pScopeif realtime is active but scope is absent, there is no effect
pGroupif null, then state is added to the global list
statethe state to be removed

No effect if realtime is active but scope is not supplied

Definition at line 319 of file RealtimeEffectManager.cpp.

323{
324 auto &states = FindStates(mProject, pGroup);
325
326 // Remove the state from processing (under the lock guard) before finalizing
327 states.RemoveState(pState);
328 if (mActive)
329 pState->Finalize();
330 Publish({
332 pGroup ? pGroup : nullptr
333 });
334}

References RealtimeEffectManagerMessage::EffectRemoved, anonymous_namespace{RealtimeEffectManager.cpp}::FindStates(), mActive, mProject, and Observer::Publisher< RealtimeEffectManagerMessage >::Publish().

Referenced by AudioIO::RemoveState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReplaceState()

std::shared_ptr< RealtimeEffectState > RealtimeEffectManager::ReplaceState ( RealtimeEffects::InitializationScope pScope,
ChannelGroup pGroup,
size_t  index,
const PluginID id 
)

Main thread replaces a global or per-group effect.

Parameters
pScopeif realtime is active but scope is absent, there is no effect
pGroupif null, then state is added to the global list
indexposition in the list to replace; no effect if out of range
ididentifies the effect
Returns
if null, the given id was not found and the old state remains
Postcondition
result: !result || result->GetEffect() != nullptr

Definition at line 295 of file RealtimeEffectManager.cpp.

298{
299 assert(!pGroup || pGroup->IsLeader());
300 auto &states = FindStates(mProject, pGroup);
301 auto pOldState = states.GetStateAt(index);
302 if (!pOldState)
303 return nullptr;
304 auto pNewState = MakeNewState(pScope, pGroup, id);
305 if (!pNewState)
306 return nullptr;
307
308 // Only now swap the completed state into the list, under a lock guard
309 if (!states.ReplaceState(index, pNewState))
310 return nullptr;
311 if (mActive)
312 pOldState->Finalize();
313 Publish({
315 });
316 return pNewState;
317}

References RealtimeEffectManagerMessage::EffectReplaced, anonymous_namespace{RealtimeEffectManager.cpp}::FindStates(), ChannelGroup::IsLeader(), mActive, MakeNewState(), mProject, and Observer::Publisher< RealtimeEffectManagerMessage >::Publish().

Referenced by AudioIO::ReplaceState().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetSuspended()

void RealtimeEffectManager::SetSuspended ( bool  value)
inline

To be called only from main thread.

Each time a processing scope starts in the audio thread, suspension state is tested, and plug-in instances may need to do things in response to the transitions. Playback of samples may continue but with effects switched off in suspended state.

Definition at line 123 of file RealtimeEffectManager.h.

124 { mSuspended.store(value, std::memory_order_relaxed); }

Referenced by Finalize(), and Initialize().

Here is the caller graph for this function:

◆ VisitAll()

template<typename StateVisitor >
void RealtimeEffectManager::VisitAll ( const StateVisitor &  func)
inlineprivate

Visit the per-project states first, then all groups from AddGroup.

Groups are visited in unspecified order

Definition at line 201 of file RealtimeEffectManager.h.

202 {
203 // Call the function for each effect on the master list
205
206 // And all group lists
207 for (auto group : mGroups)
208 RealtimeEffectList::Get(*group).Visit(func);
209 }
void Visit(const StateVisitor &func)
Apply the function to all states sequentially.
static RealtimeEffectList & Get(AudacityProject &project)

References RealtimeEffectList::Get(), and RealtimeEffectList::Visit().

Referenced by Finalize(), Initialize(), and ProcessStart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ VisitGroup() [1/2]

template<typename StateVisitor >
void RealtimeEffectManager::VisitGroup ( ChannelGroup group,
const StateVisitor &  func 
)
inlineprivate

Visit the per-project states first, then states for leader if not null.

Definition at line 178 of file RealtimeEffectManager.h.

179 {
180 // Call the function for each effect on the master list
182
183 // Call the function for each effect on the group list
184 RealtimeEffectList::Get(group).Visit(func);
185 }

References RealtimeEffectList::Get(), and RealtimeEffectList::Visit().

Referenced by AddGroup(), and Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ VisitGroup() [2/2]

template<typename StateVisitor >
void RealtimeEffectManager::VisitGroup ( const ChannelGroup group,
const StateVisitor &  func 
)
inlineprivate

Definition at line 188 of file RealtimeEffectManager.h.

190 {
191 // Call the function for each effect on the master list
193
194 // Call the function for each effect on the group list
195 RealtimeEffectList::Get(group).Visit(func);
196 }

References RealtimeEffectList::Get(), and RealtimeEffectList::Visit().

Here is the call graph for this function:

Member Data Documentation

◆ mActive

bool RealtimeEffectManager::mActive { false }
private

◆ mGroups

std::vector<const ChannelGroup *> RealtimeEffectManager::mGroups
private

◆ mLatency

Latency RealtimeEffectManager::mLatency { 0 }
private

Definition at line 212 of file RealtimeEffectManager.h.

Referenced by Finalize(), and Process().

◆ mProject

AudacityProject& RealtimeEffectManager::mProject
private

◆ mRates

std::unordered_map<const ChannelGroup *, double> RealtimeEffectManager::mRates
private

Definition at line 222 of file RealtimeEffectManager.h.

Referenced by AddGroup(), Finalize(), Initialize(), and MakeNewState().

◆ mSuspended

std::atomic<bool> RealtimeEffectManager::mSuspended { true }
private

Definition at line 214 of file RealtimeEffectManager.h.


The documentation for this class was generated from the following files: