26 return std::make_shared<RealtimeEffectManager>(project);
77 Track &track,
unsigned chans,
float rate)
79 auto leader = *track.
GetOwner()->FindLeader(&track);
83 mChans.insert({leader, chans});
84 mRates.insert({leader, rate});
88 scope.mInstances.push_back(state.
AddTrack(*leader, chans, rate));
99 mLatency = std::chrono::microseconds(0);
151 float *
const *buffers,
float *
const *scratch,
159 auto chans =
mChans[&track];
163 auto start = std::chrono::steady_clock::now();
167 static_cast<float **
>(alloca(chans *
sizeof(
float *)));
169 static_cast<float **
>(alloca(chans *
sizeof(
float *)));
173 for (
unsigned int i = 0; i < chans; i++)
175 ibuf[i] = buffers[i];
176 obuf[i] = scratch[i];
186 if (!(listIsActive && state.
IsActive()))
189 state.
Process(track, chans, ibuf, obuf, scratch[chans], numSamples);
190 for (
auto i = 0; i < chans; ++i)
201 for (
unsigned int i = 0; i < chans; i++)
202 memcpy(buffers[i], ibuf[i], numSamples *
sizeof(
float));
205 auto end = std::chrono::steady_clock::now();
206 mLatency = std::chrono::duration_cast<std::chrono::microseconds>(
end - start);
228 : mpManager{ pManager }
240 : mpManager{ other.mpManager }
242 other.mpManager =
nullptr;
248 if (
this != &other) {
250 mpManager = other.mpManager;
251 other.mpManager =
nullptr;
262 for (
auto leader : mpManager->mGroupLeaders)
277 std::optional<RealtimeEffects::SuspensionScope> myScope;
280 myScope.emplace(*pScope,
mProject.weak_from_this());
286 auto &state = *pState;
291 auto pInstance = state.Initialize(pScope->
mSampleRate);
297 if (pLeader && pLeader != leader)
300 auto chans =
mChans[leader];
301 auto rate =
mRates[leader];
303 auto pInstance2 = state.AddTrack(*leader, chans, rate);
304 if (pInstance2 != pInstance)
310 bool added = states.
AddState(pState);
316 pLeader ? pLeader->shared_from_this() :
nullptr
324 Track *pTrack,
const std::shared_ptr<RealtimeEffectState> &pState)
331 std::optional<RealtimeEffects::SuspensionScope> myScope;
334 myScope.emplace(*pScope,
mProject.weak_from_this());
347 pLeader ? pLeader->shared_from_this() :
nullptr
353auto RealtimeEffectManager::GetLatency() const ->
Latency
static TransactionScope::Factory::Scope scope
static const AttachedProjectObjects::RegisteredFactory manager
for(int ii=0, nn=names.size();ii< nn;++ii)
declares abstract base class Track, TrackList, and iterators over TrackList
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
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)
bool AddState(std::shared_ptr< RealtimeEffectState > pState)
void RemoveState(const std::shared_ptr< RealtimeEffectState > &pState)
AudacityProject & mProject
std::atomic< bool > mActive
std::shared_ptr< RealtimeEffectState > AddState(RealtimeEffects::InitializationScope *pScope, Track *pTrack, const PluginID &id)
Main thread appends a global or per-track effect.
std::unordered_map< Track *, double > mRates
std::vector< Track * > mGroupLeaders
all are non-null
void VisitAll(const StateVisitor &func)
Visit the per-project states first, then all tracks from AddTrack.
RealtimeEffectManager(AudacityProject &project)
bool GetSuspended() const
void SetSuspended(bool value)
static RealtimeEffectManager & Get(AudacityProject &project)
void Initialize(RealtimeEffects::InitializationScope &scope, double sampleRate)
Main thread begins to define a set of tracks for playback.
void ProcessStart(bool suspended)
bool IsActive() const noexcept
void Finalize() noexcept
Main thread cleans up after playback.
std::unordered_map< Track *, unsigned > mChans
void ProcessEnd(bool suspended) noexcept
void AddTrack(RealtimeEffects::InitializationScope &scope, Track &track, unsigned chans, float rate)
std::chrono::microseconds Latency
void RemoveState(RealtimeEffects::InitializationScope *pScope, Track *pTrack, const std::shared_ptr< RealtimeEffectState > &pState)
Main thread removes a global or per-track effect.
size_t Process(bool suspended, Track &track, float *const *buffers, float *const *scratch, size_t numSamples)
void VisitGroup(Track &leader, const StateVisitor &func)
Visit the per-project states first, then states for leader if not null.
bool Finalize() noexcept
Main thread cleans up playback.
bool ProcessStart(bool running)
Worker thread begins a batch of samples.
std::shared_ptr< EffectInstance > AddTrack(Track &track, unsigned chans, float sampleRate)
Main thread sets up this state before adding it to lists.
bool IsActive() const noexcept
Test only in the worker thread, or else when there is no processing.
std::shared_ptr< EffectInstance > Initialize(double rate)
Main thread sets up for playback.
bool ProcessEnd(bool running)
Worker thread finishes a batch of samples.
size_t Process(Track &track, unsigned chans, const float *const *inbuf, float *const *outbuf, float *dummybuf, size_t numSamples)
Worker thread processes part of a batch of samples.
Brackets processing setup and cleanup in the main thread.
std::vector< std::shared_ptr< EffectInstance > > mInstances
Abstract base class for an object holding data associated with points on a time axis.
std::shared_ptr< TrackList > GetOwner() const
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
AllListsLock(RealtimeEffectManager *pManager=nullptr)
RealtimeEffectManager * mpManager
AllListsLock & operator=(AllListsLock &&other)
static std::shared_ptr< RealtimeEffectState > make_shared(Args &&...args)