Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
RealtimeEffectState Class Reference

#include <RealtimeEffectState.h>

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

Classes

struct  Access
 Main thread's interface to inter-thread communication of changes of settings. More...
 
class  AccessState
 Mediator of two-way inter-thread communication of changes of settings. More...
 
struct  EffectFactory
 
struct  SettingsAndCounter
 

Public Member Functions

 RealtimeEffectState (const PluginID &id)
 
 RealtimeEffectState (const RealtimeEffectState &other)=delete
 
RealtimeEffectStateoperator= (const RealtimeEffectState &other)=delete
 
 ~RealtimeEffectState ()
 
void SetID (const PluginID &id)
 May be called with nonempty id at most once in the lifetime of a state. More...
 
const PluginIDGetID () const noexcept
 
const EffectInstanceFactoryGetEffect ()
 Initializes the effect on demand. More...
 
const EffectInstanceFactoryGetEffect () const
 const accessor will not initialize the effect on demand More...
 
std::shared_ptr< EffectInstanceGetInstance ()
 Expose a pointer to the state's instance (making one as needed). More...
 
std::shared_ptr< EffectInstanceInitialize (double rate)
 Main thread sets up for playback. More...
 
std::shared_ptr< EffectInstanceAddTrack (Track &track, unsigned chans, float sampleRate)
 Main thread sets up this state before adding it to lists. More...
 
bool ProcessStart (bool running)
 Worker thread begins a batch of samples. More...
 
size_t Process (Track &track, unsigned chans, const float *const *inbuf, float *const *outbuf, size_t numSamples)
 Worker thread processes part of a batch of samples. More...
 
bool ProcessEnd ()
 Worker thread finishes a batch of samples. More...
 
const EffectSettingsGetSettings () const
 
bool IsEnabled () const noexcept
 Test only in the main thread. More...
 
bool IsActive () const noexcept
 Test only in the worker thread, or else when there is no processing. More...
 
void SetActive (bool active)
 Set only in the main thread. More...
 
bool Finalize () noexcept
 Main thread cleans up playback. More...
 
bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs) override
 
void HandleXMLEndTag (const std::string_view &tag) override
 
XMLTagHandlerHandleXMLChild (const std::string_view &tag) override
 
void WriteXML (XMLWriter &xmlFile)
 
std::shared_ptr< EffectSettingsAccessGetAccess ()
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual bool HandleXMLTag (const std::string_view &tag, const AttributesList &attrs)=0
 
virtual void HandleXMLEndTag (const std::string_view &WXUNUSED(tag))
 
virtual void HandleXMLContent (const std::string_view &WXUNUSED(content))
 
virtual XMLTagHandlerHandleXMLChild (const std::string_view &tag)=0
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 
- Public Member Functions inherited from ClientData::Site< RealtimeEffectState >
 ~Site ()
 
 Site ()
 
 Site (const Site &other)
 
 Site (Site &&other)
 
Siteoperator= (const Site &other)
 
Siteoperator= (Site &&other)
 
size_t size () const
 How many attachment pointers are in the Site. More...
 
Subclass & Get (const RegisteredFactory &key)
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
auto Get (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass & >
 Get reference to an attachment, creating on demand if not present, down-cast it to Subclass. More...
 
Subclass * Find (const RegisteredFactory &key)
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
auto Find (const RegisteredFactory &key) const -> std::enable_if_t< std::is_const< Subclass >::value, Subclass * >
 Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand. More...
 
void Assign (const RegisteredFactory &key, ReplacementPointer &&replacement)
 Reassign Site's pointer to ClientData. More...
 
- Public Member Functions inherited from Observer::Publisher< RealtimeEffectStateChange >
 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 const std::string & XMLTag ()
 
- Static Public Member Functions inherited from SharedNonInterfering< RealtimeEffectState >
static std::shared_ptr< RealtimeEffectStatemake_shared (Args &&...args)
 
- Static Public Member Functions inherited from ClientData::Site< RealtimeEffectState >
static size_t slots ()
 How many static factories have been registered with this specialization of Site. More...
 

Private Member Functions

std::shared_ptr< EffectInstanceEnsureInstance (double rate)
 
AccessStateGetAccessState () const
 
AccessStateTestAccessState () const
 

Private Attributes

PluginID mID
 
std::weak_ptr< EffectInstancemwInstance
 Stateful instance made by the plug-in. More...
 
const EffectInstanceFactorymPlugin {}
 Stateless effect object. More...
 
NonInterfering< SettingsAndCountermMainSettings
 Updated immediately by Access::Set in the main thread. More...
 
Members that are changed also in the worker thread
NonInterfering< SettingsAndCountermWorkerSettings
 
std::optional< EffectInstance::SampleCountmLatency
 How many samples must be discarded. More...
 
bool mLastActive {}
 Assigned in the worker thread at the start of each processing scope. More...
 
Members that do not change during processing
std::unordered_map< Track *, std::pair< size_t, double > > mGroups
 
AtomicUniquePointer< AccessStatempAccessState { nullptr }
 
wxString mParameters
 
size_t mCurrentProcessor { 0 }
 
bool mInitialized { false }
 

Additional Inherited Members

- Public Types inherited from ClientData::Site< RealtimeEffectState >
using DataType = Base
 
using DataPointer = UniquePtr< Base >
 
using DataFactory = std::function< DataPointer(RealtimeEffectState &) >
 Type of function from which RegisteredFactory is constructed; it builds attachments. More...
 
- Public Types inherited from Observer::Publisher< RealtimeEffectStateChange >
using message_type = RealtimeEffectStateChange
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const RealtimeEffectStateChange &) >
 Type of functions that can be connected to the Publisher. More...
 
- Static Public Attributes inherited from Observer::Publisher< RealtimeEffectStateChange >
static constexpr bool notifies_all
 
- Protected Member Functions inherited from ClientData::Site< RealtimeEffectState >
void ForEach (const Function &function)
 Invoke function on each ClientData object that has been created in this. More...
 
void ForEach (const Function &function) const
 Invoke function on each ClientData object that has been created in this. More...
 
BaseFindIf (const Function &function)
 Return pointer to first attachment in this that is not null and satisfies a predicate, or nullptr. More...
 
const BaseFindIf (const Function &function) const
 Return pointer to first attachment in this that is not null and satisfies a predicate, or nullptr. More...
 
void BuildAll ()
 For each RegisteredFactory, if the corresponding attachment is absent in this, build and store it. More...
 
- Protected Member Functions inherited from Observer::Publisher< RealtimeEffectStateChange >
CallbackReturn Publish (const RealtimeEffectStateChange &message)
 Send a message to connected callbacks. More...
 

Detailed Description

Definition at line 32 of file RealtimeEffectState.h.

Constructor & Destructor Documentation

◆ RealtimeEffectState() [1/2]

RealtimeEffectState::RealtimeEffectState ( const PluginID id)
explicit

Definition at line 235 of file RealtimeEffectState.cpp.

236{
237 SetID(id);
238 BuildAll();
239}
void BuildAll()
For each RegisteredFactory, if the corresponding attachment is absent in this, build and store it.
Definition: ClientData.h:441
void SetID(const PluginID &id)
May be called with nonempty id at most once in the lifetime of a state.

References ClientData::Site< RealtimeEffectState >::BuildAll(), and SetID().

Here is the call graph for this function:

◆ RealtimeEffectState() [2/2]

RealtimeEffectState::RealtimeEffectState ( const RealtimeEffectState other)
delete

◆ ~RealtimeEffectState()

RealtimeEffectState::~RealtimeEffectState ( )

Definition at line 241 of file RealtimeEffectState.cpp.

242{
243
244}

Member Function Documentation

◆ AddTrack()

std::shared_ptr< EffectInstance > RealtimeEffectState::AddTrack ( Track track,
unsigned  chans,
float  sampleRate 
)

Main thread sets up this state before adding it to lists.

Set up processors to be visited repeatedly in Process.

The iteration over channels in AddTrack and Process must be the same

Definition at line 358 of file RealtimeEffectState.cpp.

359{
360 auto pInstance = EnsureInstance(sampleRate);
361 if (!pInstance)
362 return {};
363 if (!mPlugin)
364 return {};
365 auto first = mCurrentProcessor;
366 const auto numAudioIn = pInstance->GetAudioInCount();
367 const auto numAudioOut = pInstance->GetAudioOutCount();
368 AllocateChannelsToProcessors(chans, numAudioIn, numAudioOut,
369 [&](unsigned, unsigned){
370 // Add a NEW processor
371 // Pass reference to worker settings, not main -- such as, for connecting
372 // Ladspa ports to the proper addresses.
373 if (pInstance->RealtimeAddProcessor(
374 mWorkerSettings.settings, numAudioIn, sampleRate)
375 ) {
376 mCurrentProcessor++;
377 return true;
378 }
379 else
380 return false;
381 });
382 if (mCurrentProcessor > first) {
383 // Remember the sampleRate of the track, so latency can be computed later
384 mGroups[&track] = { first, sampleRate };
385 return pInstance;
386 }
387 return {};
388}
const EffectInstanceFactory * mPlugin
Stateless effect object.
NonInterfering< SettingsAndCounter > mWorkerSettings
std::shared_ptr< EffectInstance > EnsureInstance(double rate)
std::unordered_map< Track *, std::pair< size_t, double > > mGroups
void AllocateChannelsToProcessors(unsigned chans, const unsigned numAudioIn, const unsigned numAudioOut, const F &f)

References anonymous_namespace{RealtimeEffectState.cpp}::AllocateChannelsToProcessors(), EnsureInstance(), mCurrentProcessor, mGroups, mPlugin, and mWorkerSettings.

Referenced by RealtimeEffectManager::AddTrack().

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

◆ EnsureInstance()

std::shared_ptr< EffectInstance > RealtimeEffectState::EnsureInstance ( double  rate)
private

copying settings in the main thread while worker isn't yet running

If there was already an instance, recycle it; else make one here

Definition at line 279 of file RealtimeEffectState.cpp.

280{
281 if (!mPlugin)
282 return {};
283
284 auto pInstance = mwInstance.lock();
285 if (!mInitialized) {
289
291 if (!pInstance)
292 mwInstance = pInstance = mPlugin->MakeInstance();
293 if (!pInstance)
294 return {};
295
296 // PRL: conserving pre-3.2.0 behavior, but I don't know why this arbitrary
297 // number was important
298 pInstance->SetBlockSize(512);
299
300 if (!pInstance->RealtimeInitialize(mMainSettings.settings, sampleRate))
301 return {};
302 mInitialized = true;
303 return pInstance;
304 }
305 return pInstance;
306}
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
NonInterfering< SettingsAndCounter > mMainSettings
Updated immediately by Access::Set in the main thread.
bool mLastActive
Assigned in the worker thread at the start of each processing scope.
bool IsActive() const noexcept
Test only in the worker thread, or else when there is no processing.
std::weak_ptr< EffectInstance > mwInstance
Stateful instance made by the plug-in.

References IsActive(), EffectInstanceFactory::MakeInstance(), mInitialized, mLastActive, mMainSettings, mPlugin, mwInstance, and mWorkerSettings.

Referenced by AddTrack(), and Initialize().

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

◆ Finalize()

bool RealtimeEffectState::Finalize ( )
noexcept

Main thread cleans up playback.

Definition at line 539 of file RealtimeEffectState.cpp.

540{
541 // This is the main thread cleaning up a state not now used in processing
543
544 mGroups.clear();
546
547 auto pInstance = mwInstance.lock();
548 if (!pInstance)
549 return false;
550
551 auto result = pInstance->RealtimeFinalize(mMainSettings.settings);
552 if(result)
553 //update mLastSettings so that Flush didn't
554 //overwrite what was read from the worker
555 if (auto state = GetAccessState())
556 state->Initialize(mMainSettings);
557 mLatency = {};
558 mInitialized = false;
559 return result;
560}
std::optional< EffectInstance::SampleCount > mLatency
How many samples must be discarded.
AccessState * GetAccessState() const

References GetAccessState(), mCurrentProcessor, mGroups, mInitialized, mLatency, mMainSettings, mwInstance, and mWorkerSettings.

Referenced by RealtimeEffectManager::Finalize().

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

◆ GetAccess()

std::shared_ptr< EffectSettingsAccess > RealtimeEffectState::GetAccess ( )

Expose access so a dialog can be connected to this state To be called by the main thread only

Postcondition
result: result != nullptr

Definition at line 672 of file RealtimeEffectState.cpp.

673{
674 if (!GetEffect())
675 // Effect not found! Return a dummy
676 return std::make_shared<Access>();
677
678 // Only the main thread assigns to the atomic pointer, here and
679 // once only in the lifetime of the state
680 if (!GetAccessState())
681 mpAccessState.emplace(*mPlugin, *this);
682 return std::make_shared<Access>(*this);
683}
const EffectInstanceFactory * GetEffect()
Initializes the effect on demand.
AtomicUniquePointer< AccessState > mpAccessState

References GetAccessState(), GetEffect(), mpAccessState, and mPlugin.

Referenced by SetActive(), and RealtimeEffectStateUI::Show().

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

◆ GetAccessState()

AccessState * RealtimeEffectState::GetAccessState ( ) const
inlineprivate

Definition at line 121 of file RealtimeEffectState.h.

122 {
123 return mpAccessState.load(std::memory_order_relaxed);
124 }

References mpAccessState.

Referenced by Finalize(), and GetAccess().

Here is the caller graph for this function:

◆ GetEffect() [1/2]

const EffectInstanceFactory * RealtimeEffectState::GetEffect ( )

Initializes the effect on demand.

Definition at line 263 of file RealtimeEffectState.cpp.

264{
265 if (!mPlugin) {
267 if (mPlugin) {
268 // Also make EffectSettings, but preserve activation
269 auto wasActive = mMainSettings.settings.extra.GetActive();
270 mMainSettings.counter = 0;
271 mMainSettings.settings = mPlugin->MakeSettings();
272 mMainSettings.settings.extra.SetActive(wasActive);
273 }
274 }
275 return mPlugin;
276}
virtual EffectSettings MakeSettings() const
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.

References GlobalHook< EffectFactory, const EffectInstanceFactory *(const PluginID &) >::Call(), EffectSettingsManager::MakeSettings(), mID, mMainSettings, and mPlugin.

Referenced by GetAccess(), and SetID().

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

◆ GetEffect() [2/2]

const EffectInstanceFactory * RealtimeEffectState::GetEffect ( ) const
inline

const accessor will not initialize the effect on demand

Definition at line 58 of file RealtimeEffectState.h.

58{ return mPlugin; }

References mPlugin.

◆ GetID()

const PluginID & RealtimeEffectState::GetID ( ) const
noexcept

Definition at line 258 of file RealtimeEffectState.cpp.

259{
260 return mID;
261}

References mID.

Referenced by RealtimeEffectStateUI::Show(), and RealtimeEffectStateUI::UpdateTitle().

Here is the caller graph for this function:

◆ GetInstance()

std::shared_ptr< EffectInstance > RealtimeEffectState::GetInstance ( )

Expose a pointer to the state's instance (making one as needed).

Postcondition
true (no promise result is not null)

If there was already an instance, recycle it; else make one here

Definition at line 308 of file RealtimeEffectState.cpp.

309{
311 auto pInstance = mwInstance.lock();
312 if (!pInstance && mPlugin)
313 mwInstance = pInstance = mPlugin->MakeInstance();
314 return pInstance;
315}

References EffectInstanceFactory::MakeInstance(), mPlugin, and mwInstance.

Here is the call graph for this function:

◆ GetSettings()

const EffectSettings & RealtimeEffectState::GetSettings ( ) const
inline

Definition at line 86 of file RealtimeEffectState.h.

86{ return mMainSettings.settings; }

References mMainSettings.

◆ HandleXMLChild()

XMLTagHandler * RealtimeEffectState::HandleXMLChild ( const std::string_view &  tag)
overridevirtual

Implements XMLTagHandler.

Definition at line 628 of file RealtimeEffectState.cpp.

629{
630 // Tag may be for the state, or the list of parameters, or for one parameter.
631 // See the writing method below. All are handled by this
632 return this;
633}

◆ HandleXMLEndTag()

void RealtimeEffectState::HandleXMLEndTag ( const std::string_view &  tag)
override

Definition at line 617 of file RealtimeEffectState.cpp.

618{
619 if (tag == XMLTag()) {
620 if (mPlugin && !mParameters.empty()) {
622 mPlugin->LoadSettings(parms, mMainSettings.settings);
623 }
624 mParameters.clear();
625 }
626}
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
virtual bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const =0
Restore settings from keys and values.
static const std::string & XMLTag()

References EffectSettingsManager::LoadSettings(), mMainSettings, mParameters, mPlugin, and XMLTag().

Here is the call graph for this function:

◆ HandleXMLTag()

bool RealtimeEffectState::HandleXMLTag ( const std::string_view &  tag,
const AttributesList attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 576 of file RealtimeEffectState.cpp.

578{
579 if (tag == XMLTag()) {
580 mParameters.clear();
581 mPlugin = nullptr;
582 mID.clear();
583 for (auto &[attr, value] : attrs) {
584 if (attr == idAttribute) {
585 SetID(value.ToWString());
586 if (!mPlugin) {
587 // TODO - complain!!!!
588 }
589 }
590 else if (attr == versionAttribute) {
591 }
592 else if (attr == activeAttribute)
593 // Updating the EffectSettingsExtra although we haven't yet built
594 // the settings
595 mMainSettings.settings.extra.SetActive(value.Get<bool>());
596 }
597 return true;
598 }
599 else if (tag == parametersAttribute)
600 return true;
601 else if (tag == parameterAttribute) {
602 wxString n;
603 wxString v;
604 for (auto &[attr, value] : attrs) {
605 if (attr == nameAttribute)
606 n = value.ToWString();
607 else if (attr == valueAttribute)
608 v = value.ToWString();
609 }
610 mParameters += wxString::Format(wxT("\"%s=%s\" "), n, v);
611 return true;
612 }
613 else
614 return false;
615}
wxT("CloseDown"))
static const auto parametersAttribute
static const auto versionAttribute
static const auto parameterAttribute
static const auto nameAttribute
static const auto idAttribute
static const auto valueAttribute
static constexpr auto activeAttribute

References activeAttribute, idAttribute, mID, mMainSettings, mParameters, mPlugin, nameAttribute, parameterAttribute, parametersAttribute, SetID(), valueAttribute, versionAttribute, wxT(), and XMLTag().

Here is the call graph for this function:

◆ Initialize()

std::shared_ptr< EffectInstance > RealtimeEffectState::Initialize ( double  rate)

Main thread sets up for playback.

Definition at line 318 of file RealtimeEffectState.cpp.

319{
320 if (!mPlugin)
321 return {};
322
324 mGroups.clear();
325 mLatency = {};
326 return EnsureInstance(sampleRate);
327}

References EnsureInstance(), mCurrentProcessor, mGroups, mLatency, and mPlugin.

Referenced by RealtimeEffectManager::Initialize().

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

◆ IsActive()

bool RealtimeEffectState::IsActive ( ) const
noexcept

Test only in the worker thread, or else when there is no processing.

Definition at line 521 of file RealtimeEffectState.cpp.

522{
523 return mWorkerSettings.settings.extra.GetActive();
524}

References mWorkerSettings.

Referenced by EnsureInstance(), ProcessEnd(), and ProcessStart().

Here is the caller graph for this function:

◆ IsEnabled()

bool RealtimeEffectState::IsEnabled ( ) const
noexcept

Test only in the main thread.

Definition at line 516 of file RealtimeEffectState.cpp.

517{
518 return mMainSettings.settings.extra.GetActive();
519}

References mMainSettings.

◆ operator=()

RealtimeEffectState & RealtimeEffectState::operator= ( const RealtimeEffectState other)
delete

◆ Process()

size_t RealtimeEffectState::Process ( Track track,
unsigned  chans,
const float *const *  inbuf,
float *const *  outbuf,
size_t  numSamples 
)

Worker thread processes part of a batch of samples.

Visit the effect processors that were added in AddTrack.

Returns
how many leading samples are discardable for latency

The iteration over channels in AddTrack and Process must be the same

Parameters
inbufchans input buffers
outbufchans output buffers

Definition at line 424 of file RealtimeEffectState.cpp.

426{
427 auto pInstance = mwInstance.lock();
428 if (!mPlugin || !pInstance || !mLastActive) {
429 // Process trivially
430 for (size_t ii = 0; ii < chans; ++ii)
431 memcpy(outbuf[ii], inbuf[ii], numSamples * sizeof(float));
432 return 0;
433 }
434 const auto numAudioIn = pInstance->GetAudioInCount();
435 const auto numAudioOut = pInstance->GetAudioOutCount();
436 const auto clientIn = stackAllocate(const float *, numAudioIn);
437 const auto clientOut = stackAllocate(float *, numAudioOut);
438 size_t len = 0;
439 const auto &pair = mGroups[&track];
440 auto processor = pair.first;
441 // Outer loop over processors
442 AllocateChannelsToProcessors(chans, numAudioIn, numAudioOut,
443 [&](unsigned indx, unsigned ondx){
444 // Point at the correct input buffers
445 unsigned copied = std::min(chans - indx, numAudioIn);
446 std::copy(inbuf + indx, inbuf + indx + copied, clientIn);
447 // If there are too few input channels for what the processor requires,
448 // re-use input channels from the beginning
449 while (auto need = numAudioIn - copied) {
450 auto moreCopied = std::min(chans, need);
451 std::copy(inbuf, inbuf + moreCopied, clientIn + copied);
452 copied += moreCopied;
453 }
454
455 // Point at the correct output buffers
456 copied = std::min(chans - ondx, numAudioOut);
457 std::copy(outbuf + ondx, outbuf + ondx + copied, clientOut);
458 if (copied < numAudioOut) {
459 // Make determinate pointers
460 std::fill(clientOut + copied, clientOut + numAudioOut, nullptr);
461 }
462
463 // Inner loop over blocks
464 const auto blockSize = pInstance->GetBlockSize();
465 for (size_t block = 0; block < numSamples; block += blockSize) {
466 auto cnt = std::min(numSamples - block, blockSize);
467 // Assuming we are in a processing scope, use the worker settings
468 auto processed = pInstance->RealtimeProcess(processor,
469 mWorkerSettings.settings, clientIn, clientOut, cnt);
470 if (!mLatency)
471 // Find latency once only per initialization scope,
472 // after processing one block
473 mLatency.emplace(
474 pInstance->GetLatency(mWorkerSettings.settings, pair.second));
475 for (size_t i = 0 ; i < numAudioIn; i++)
476 if (clientIn[i])
477 clientIn[i] += cnt;
478 for (size_t i = 0 ; i < numAudioOut; i++)
479 if (clientOut[i])
480 clientOut[i] += cnt;
481 if (ondx == 0) {
482 // For the first processor only
483 len += processed;
484 auto discard = limitSampleBufferSize(len, *mLatency);
485 len -= discard;
486 *mLatency -= discard;
487 }
488 }
489 ++processor;
490 return true;
491 });
492 // Report the number discardable during the processing scope
493 // We are assuming len as calculated above is the same in case of multiple
494 // processors
495 return numSamples - len;
496}
int min(int a, int b)
#define stackAllocate(T, count)
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22

References anonymous_namespace{RealtimeEffectState.cpp}::AllocateChannelsToProcessors(), limitSampleBufferSize(), mGroups, min(), mLastActive, mLatency, mPlugin, mwInstance, mWorkerSettings, and stackAllocate.

Referenced by RealtimeEffectManager::Process().

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

◆ ProcessEnd()

bool RealtimeEffectState::ProcessEnd ( )

Worker thread finishes a batch of samples.

Definition at line 498 of file RealtimeEffectState.cpp.

499{
500 auto pInstance = mwInstance.lock();
501 bool result = pInstance && IsActive() && mLastActive &&
502 // Assuming we are in a processing scope, use the worker settings
503 pInstance->RealtimeProcessEnd(mWorkerSettings.settings);
504
505 if (auto pAccessState = TestAccessState())
506 // Always done, regardless of activity
507 // Some dialogs require communication back from the processor so that
508 // they can update their appearance in idle time, and some plug-in
509 // libraries (like lv2) require the host program to mediate the
510 // communication
511 pAccessState->WorkerWrite();
512
513 return result;
514}
AccessState * TestAccessState() const

References IsActive(), mLastActive, mwInstance, mWorkerSettings, and TestAccessState().

Referenced by RealtimeEffectManager::ProcessEnd().

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

◆ ProcessStart()

bool RealtimeEffectState::ProcessStart ( bool  running)

Worker thread begins a batch of samples.

Parameters
runningmeans no pause or deactivation of containing list

Definition at line 390 of file RealtimeEffectState.cpp.

391{
392 // Get state changes from the main thread
393 // Note that it is only here that the answer of IsActive() may be changed,
394 // and it is important that for each state the answer is unchanging in one
395 // processing scope.
396 if (auto pAccessState = TestAccessState())
397 pAccessState->WorkerRead();
398
399 // Detect transitions of activity state
400 auto pInstance = mwInstance.lock();
401 bool active = IsActive() && running;
402 if (active != mLastActive) {
403 if (pInstance) {
404 bool success = active
405 ? pInstance->RealtimeResume()
406 : pInstance->RealtimeSuspend();
407 if (!success)
408 return false;
409 }
410 mLastActive = active;
411 }
412
413 if (!pInstance || !active)
414 return false;
415
416 // Assuming we are in a processing scope, use the worker settings
417 return pInstance->RealtimeProcessStart(mWorkerSettings.settings);
418}

References IsActive(), mLastActive, mwInstance, mWorkerSettings, and TestAccessState().

Referenced by RealtimeEffectManager::ProcessStart().

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

◆ SetActive()

void RealtimeEffectState::SetActive ( bool  active)

Set only in the main thread.

Definition at line 526 of file RealtimeEffectState.cpp.

527{
528 auto access = GetAccess();
529 access->ModifySettings([&](EffectSettings &settings) {
530 settings.extra.SetActive(active);
531 });
532 access->Flush();
533
534 Publish(active
537}
static Settings & settings()
Definition: TrackInfo.cpp:87
CallbackReturn Publish(const RealtimeEffectStateChange &message)
Send a message to connected callbacks.
Definition: Observer.h:207
std::shared_ptr< EffectSettingsAccess > GetAccess()
Externalized state of a plug-in.

References EffectOff, EffectOn, GetAccess(), Observer::Publisher< RealtimeEffectStateChange >::Publish(), and settings().

Here is the call graph for this function:

◆ SetID()

void RealtimeEffectState::SetID ( const PluginID id)

May be called with nonempty id at most once in the lifetime of a state.

Call with empty id is ignored. Called by the constructor that takes an id

Definition at line 246 of file RealtimeEffectState.cpp.

247{
248 bool empty = id.empty();
249 if (mID.empty() && !empty) {
250 mID = id;
251 GetEffect();
252 }
253 else
254 // Set mID to non-empty at most once
255 assert(empty);
256}
int id

References GetEffect(), id, and mID.

Referenced by HandleXMLTag(), and RealtimeEffectState().

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

◆ TestAccessState()

AccessState * RealtimeEffectState::TestAccessState ( ) const
inlineprivate

Definition at line 125 of file RealtimeEffectState.h.

126 {
127 return mpAccessState.load(std::memory_order_acquire);
128 }

References mpAccessState.

Referenced by ProcessEnd(), and ProcessStart().

Here is the caller graph for this function:

◆ WriteXML()

void RealtimeEffectState::WriteXML ( XMLWriter xmlFile)

Definition at line 635 of file RealtimeEffectState.cpp.

636{
637 if (!mPlugin)
638 return;
639
640 xmlFile.StartTag(XMLTag());
641 const auto active = mMainSettings.settings.extra.GetActive();
642 xmlFile.WriteAttr(activeAttribute, active);
645
646 CommandParameters cmdParms;
647 if (mPlugin->SaveSettings(mMainSettings.settings, cmdParms)) {
649
650 wxString entryName;
651 long entryIndex;
652 bool entryKeepGoing;
653
654 entryKeepGoing = cmdParms.GetFirstEntry(entryName, entryIndex);
655 while (entryKeepGoing) {
656 wxString entryValue = cmdParms.Read(entryName, "");
657
659 xmlFile.WriteAttr(nameAttribute, entryName);
660 xmlFile.WriteAttr(valueAttribute, entryValue);
661 xmlFile.EndTag(parameterAttribute);
662
663 entryKeepGoing = cmdParms.GetNextEntry(entryName, entryIndex);
664 }
665
667 }
668
669 xmlFile.EndTag(XMLTag());
670}
virtual wxString GetVersion() const =0
virtual bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const =0
Store settings as keys and values.
static PluginID GetID(PluginProvider *provider)
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:80
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:37
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:103

References activeAttribute, XMLWriter::EndTag(), PluginManager::GetID(), ComponentInterface::GetVersion(), idAttribute, mMainSettings, mPlugin, nameAttribute, parameterAttribute, parametersAttribute, EffectSettingsManager::SaveSettings(), XMLWriter::StartTag(), valueAttribute, versionAttribute, XMLWriter::WriteAttr(), and XMLTag().

Here is the call graph for this function:

◆ XMLTag()

const std::string & RealtimeEffectState::XMLTag ( )
static

Definition at line 562 of file RealtimeEffectState.cpp.

563{
564 static const std::string result{"effect"};
565 return result;
566}

Referenced by RealtimeEffectList::HandleXMLChild(), HandleXMLEndTag(), HandleXMLTag(), and WriteXML().

Here is the caller graph for this function:

Member Data Documentation

◆ mCurrentProcessor

size_t RealtimeEffectState::mCurrentProcessor { 0 }
private

Definition at line 178 of file RealtimeEffectState.h.

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

◆ mGroups

std::unordered_map<Track *, std::pair<size_t, double> > RealtimeEffectState::mGroups
private

Definition at line 170 of file RealtimeEffectState.h.

Referenced by AddTrack(), Finalize(), Initialize(), and Process().

◆ mID

PluginID RealtimeEffectState::mID
private

Definition at line 130 of file RealtimeEffectState.h.

Referenced by GetEffect(), GetID(), HandleXMLTag(), and SetID().

◆ mInitialized

bool RealtimeEffectState::mInitialized { false }
private

◆ mLastActive

bool RealtimeEffectState::mLastActive {}
private

Assigned in the worker thread at the start of each processing scope.

Definition at line 162 of file RealtimeEffectState.h.

Referenced by EnsureInstance(), Process(), ProcessEnd(), and ProcessStart().

◆ mLatency

std::optional<EffectInstance::SampleCount> RealtimeEffectState::mLatency
private

How many samples must be discarded.

Definition at line 160 of file RealtimeEffectState.h.

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

◆ mMainSettings

NonInterfering<SettingsAndCounter> RealtimeEffectState::mMainSettings
private

◆ mpAccessState

AtomicUniquePointer<AccessState> RealtimeEffectState::mpAccessState { nullptr }
private

Definition at line 175 of file RealtimeEffectState.h.

Referenced by GetAccess(), GetAccessState(), and TestAccessState().

◆ mParameters

wxString RealtimeEffectState::mParameters
private

Definition at line 177 of file RealtimeEffectState.h.

Referenced by HandleXMLEndTag(), and HandleXMLTag().

◆ mPlugin

const EffectInstanceFactory* RealtimeEffectState::mPlugin {}
private

◆ mwInstance

std::weak_ptr<EffectInstance> RealtimeEffectState::mwInstance
private

Stateful instance made by the plug-in.

Definition at line 133 of file RealtimeEffectState.h.

Referenced by EnsureInstance(), Finalize(), GetInstance(), RealtimeEffectState::AccessState::MainRead(), Process(), ProcessEnd(), and ProcessStart().

◆ mWorkerSettings

NonInterfering<SettingsAndCounter> RealtimeEffectState::mWorkerSettings
private

Updated with delay, but atomically, in the worker thread; skipped by the copy constructor so that there isn't a race when pushing an Undo state

Definition at line 158 of file RealtimeEffectState.h.

Referenced by AddTrack(), EnsureInstance(), Finalize(), IsActive(), Process(), ProcessEnd(), ProcessStart(), RealtimeEffectState::AccessState::WorkerRead(), and RealtimeEffectState::AccessState::WorkerWrite().


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