Audacity 3.2.0
AudioGraphTask.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file AudioGraphTask.cpp
6
7 Dominic Mazzoni
8 Vaughan Johnson
9 Martyn Shaw
10
11 Paul Licameli split from PerTrackEffect.cpp
12
13**********************************************************************/
14#include "AudioGraphTask.h"
15#include "AudioGraphBuffers.h"
16#include "AudioGraphSink.h"
17#include "AudioGraphSource.h"
18#include "SampleCount.h"
19#include <cassert>
20
21AudioGraph::Task::Task(Source &source, Buffers &buffers, Sink &sink)
22 : mSource{ source }, mBuffers{ buffers }, mSink{ sink }
23{
24 assert(source.AcceptsBlockSize(buffers.BlockSize()));
25 assert(source.AcceptsBuffers(buffers));
26 assert(sink.AcceptsBuffers(buffers));
27}
28
30{
31 // Satisfy invariant initially
32 mBuffers.Rewind();
33 Status status{};
34 do {
35 assert(mBuffers.Remaining() >= mBuffers.BlockSize());
36 status = RunOnce();
37 } while (status == Status::More);
38 return status == Status::Done;
39}
40
42{
43 const auto blockSize = mBuffers.BlockSize();
44 assert(mBuffers.Remaining() >= blockSize); // pre
45
46#ifndef NDEBUG
47 // Variable used only for a loop termination sanity check
48 std::optional<sampleCount> oldRemaining;
49 if (mRanOnce)
50 oldRemaining.emplace(mSource.Remaining());
51 // else Remaining() may not be meaningful
52#endif
53
54 if (auto oCurBlockSize = mSource.Acquire(mBuffers, blockSize)) {
55 const auto curBlockSize = *oCurBlockSize;
56#ifndef NDEBUG
57 mRanOnce = true;
58 const auto remaining = mSource.Remaining();
59 // Assert a post of Acquire which is part of proof of termination
60 assert(!mSource.Terminates() || !oldRemaining ||
61 *oldRemaining == remaining);
62 oldRemaining.emplace(remaining);
63 // Assert another post that guarantees progress (even if not terminating)
64 assert(blockSize == 0 || remaining == 0 || curBlockSize > 0);
65#endif
66 if (curBlockSize == 0)
67 // post (same as pre) obviously preserved
68 return Status::Done;
69
70 // post of source.Acquire() satisfies pre of sink.Release()
71 assert(curBlockSize <= blockSize);
72 if (!mSink.Release(mBuffers, curBlockSize))
73 return Status::Fail;
74
75 // This may break the post
76 mBuffers.Advance(curBlockSize);
77
78 // posts of source.Acquire() and source.Release()
79 // give termination guarantee
80 assert(mSource.Remaining() == 0 || curBlockSize > 0);
81 if (!mSource.Release())
82 return Status::Fail;
83#ifndef NDEBUG
84 // Assert a post of Release
85 assert(!mSource.Terminates() ||
86 mSource.Remaining() == remaining - curBlockSize);
87#endif
88
89 // Reestablish the post
90 if (!mSink.Acquire(mBuffers))
91 return Status::Fail;
92 assert(mBuffers.Remaining() >= blockSize);
93
94 return Status::More;
95 }
96 else
97 return Status::Fail;
98}
Accumulates (non-interleaved) data during effect processing.
size_t BlockSize() const
Downstream receiver of sample streams, taking Buffers as external context.
virtual bool AcceptsBuffers(const Buffers &buffers) const =0
Upstream producer of sample streams, taking Buffers as external context.
virtual bool AcceptsBlockSize(size_t blockSize) const =0
virtual bool AcceptsBuffers(const Buffers &buffers) const =0
Task(Source &source, Buffers &buffers, Sink &sink)
bool RunLoop()
Do the complete copy.
Status RunOnce()
Do an increment of the copy.