24 return std::make_shared<RealtimeEffectManager>(
project);
79 mRates.insert({&group, rate});
83 scope.mInstances.push_back(state.
AddGroup(group, chans, rate));
94 mLatency = std::chrono::microseconds(0);
124 float *
const *buffers,
float *
const *scratch,
float *
const dummy,
125 unsigned nBuffers,
size_t numSamples)
134 auto start = std::chrono::steady_clock::now();
138 static_cast<float **
>(alloca(nBuffers *
sizeof(
float *)));
140 static_cast<float **
>(alloca(nBuffers *
sizeof(
float *)));
144 for (
unsigned int i = 0; i < nBuffers; i++) {
145 ibuf[i] = buffers[i];
146 obuf[i] = scratch[i];
153 size_t discardable = 0;
158 state.
Process(group, nBuffers, ibuf, obuf, dummy, numSamples);
159 for (
auto i = 0; i < nBuffers; ++i)
170 for (
unsigned int i = 0; i < nBuffers; i++)
171 memcpy(buffers[i], ibuf[i], numSamples *
sizeof(
float));
174 auto end = std::chrono::steady_clock::now();
175 mLatency = std::chrono::duration_cast<std::chrono::microseconds>(
end - start);
197 : mpManager{ pManager }
209 : mpManager{ other.mpManager }
211 other.mpManager =
nullptr;
217 if (
this != &other) {
219 mpManager = other.mpManager;
220 other.mpManager =
nullptr;
231 for (
auto group : mpManager->mGroups)
237std::shared_ptr<RealtimeEffectState>
242 assert(!pGroup || pGroup->
IsLeader());
246 auto &state = *pNewState;
249 auto pInstance = state.Initialize(pScope->
mSampleRate);
251 for (
const auto group :
mGroups) {
254 if (pGroup && pGroup != group)
256 auto rate =
mRates[group];
259 if (pInstance2 != pInstance)
279 assert(!pGroup || pGroup->
IsLeader());
286 if (!states.AddState(pState))
290 pGroup ? pGroup :
nullptr
299 assert(!pGroup || pGroup->
IsLeader());
301 auto pOldState = states.GetStateAt(index);
309 if (!states.ReplaceState(index, pNewState))
312 pOldState->Finalize();
322 const std::shared_ptr<RealtimeEffectState> pState)
327 states.RemoveState(pState);
332 pGroup ? pGroup :
nullptr
338 const std::shared_ptr<RealtimeEffectState> &pState)
const
341 return states.FindState(pState);
346auto RealtimeEffectManager::GetLatency() const ->
Latency
static AudioUnitEffectsModule::Factory::SubstituteInUnique< AudioUnitEffect > scope
Abstract class ChannelGroup with two discrete iterable dimensions, channels and intervals; subclasses...
static const AttachedProjectObjects::RegisteredFactory manager
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
virtual bool IsLeader() const =0
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
CallbackReturn Publish(const RealtimeEffectManagerMessage &message)
Send a message to connected callbacks.
static RealtimeEffectList & Get(AudacityProject &project)
AudacityProject & mProject
void VisitGroup(ChannelGroup &group, const StateVisitor &func)
Visit the per-project states first, then states for leader if not null.
void VisitAll(const StateVisitor &func)
Visit the per-project states first, then all groups from AddGroup.
RealtimeEffectManager(AudacityProject &project)
std::shared_ptr< RealtimeEffectState > MakeNewState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
void SetSuspended(bool value)
To be called only from main thread.
static RealtimeEffectManager & Get(AudacityProject &project)
void Initialize(RealtimeEffects::InitializationScope &scope, double sampleRate)
Main thread begins to define a set of groups for playback.
void ProcessStart(bool suspended)
std::unordered_map< const ChannelGroup *, double > mRates
bool IsActive() const noexcept
To be called only from main thread.
void Finalize() noexcept
Main thread cleans up after playback.
size_t Process(bool suspended, const ChannelGroup &group, float *const *buffers, float *const *scratch, float *dummy, unsigned nBuffers, size_t numSamples)
void RemoveState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
Main thread removes a global or per-group effect.
std::shared_ptr< RealtimeEffectState > ReplaceState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, size_t index, const PluginID &id)
Main thread replaces a global or per-group effect.
void AddGroup(RealtimeEffects::InitializationScope &scope, const ChannelGroup &group, unsigned chans, float rate)
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.
std::shared_ptr< RealtimeEffectState > AddState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
Main thread appends a global or per-group effect.
void ProcessEnd(bool suspended) noexcept
std::chrono::microseconds Latency
std::vector< const ChannelGroup * > mGroups
all are non-null
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.
std::shared_ptr< EffectInstance > AddGroup(const ChannelGroup &group, unsigned chans, float sampleRate)
Main thread sets up this state before adding it to lists.
bool ProcessEnd()
Worker thread finishes a batch of samples.
bool Finalize() noexcept
Main thread cleans up playback.
bool ProcessStart(bool running)
Worker thread begins a batch of samples.
std::shared_ptr< EffectInstance > Initialize(double rate)
Main thread sets up for playback.
Brackets processing setup and cleanup in the main thread.
std::vector< std::shared_ptr< EffectInstance > > mInstances
unsigned mNumPlaybackChannels
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
constexpr auto sampleRate
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
RealtimeEffectList & FindStates(AudacityProject &project, ChannelGroup *pGroup)
AllListsLock(RealtimeEffectManager *pManager=nullptr)
RealtimeEffectManager * mpManager
AllListsLock & operator=(AllListsLock &&other)
static std::shared_ptr< RealtimeEffectState > make_shared(Args &&...args)