20 #include "../exception.h"
28 void consistencyTest(
const std::vector<FragmentPtr>& fragments) {
30 for (
auto it : fragments) {
31 Beatmup::DebugAssertion::check(it.length > 0,
32 "Non-positive length in fragment %d: %d",
index, it.length);
33 Beatmup::DebugAssertion::check(it.offset >= 0,
34 "Negative offset in fragment %d: %d",
index, it.offset);
35 Beatmup::DebugAssertion::check(it.length + it.offset <= it.fragment->getSampleCount(),
36 "Out-of-range mapping of fragment %d: %d",
index, it.fragment->getSampleCount());
96 ptr->moveTo(ptr->getTime());
109 if (timeLeft >= timeRight || timeLeft >=
getDuration() || timeRight <= 0) {
121 if (
cumTimes[rightFragment] == timeRight)
125 if (rightFragment !=
fragments.size() - 1)
127 if (leftFragment > 0)
142 if (leftFragment == rightFragment) {
143 dt = timeRight - timeLeft;
163 if (fromTime >= toTime)
176 throw Sequence::AccessException(
"A border is out of sequence scope", *
this);
183 int numFragments = toFragment - fromFragment + 1;
184 result->fragments.reserve(numFragments);
186 result->cumTimes.reserve(numFragments + 1);
187 result->cumTimes.push_back(0);
192 result->fragments[0].offset += dt;
195 if (fromFragment == toFragment) {
196 dt = toTime - fromTime;
197 result->fragments[0].length = dt;
198 result->cumTimes.push_back(dt);
201 dtime cumTime = (
result->fragments[0].length -= dt);
202 result->cumTimes.push_back(cumTime);
205 for (
int i = fromFragment + 1; i <= toFragment - 1; ++i) {
209 result->cumTimes.push_back(cumTime);
215 result->fragments.back().length = l;
216 result->cumTimes.push_back(cumTime + l);
229 throw AccessException(
"Bad insert position", *
this);
255 if (fromTime >= toTime)
256 throw AccessException(
"Inconsistent time bounds when removing", *
this);
274 int removeRangeBegin = fromFragment;
277 int removeRangeEnd = toFragment >= 0 ? toFragment :
fragments.size();
280 if (removeRangeBegin <= removeRangeEnd) {
281 if (removeRangeBegin < removeRangeEnd)
285 int index = fromFragment;
290 if (toFragment >= 0) {
300 dt = toTime - fromTime;
301 int index = fromFragment + 1;
308 int index = fromFragment;
325 right =
copy(0, duration);
327 else if (
time >= duration - 1) {
366 sequence.
fragments[fragmentIdx].editData();
367 pointer = sequence.
fragments[fragmentIdx];
369 pointer.offset += dt;
370 pointer.length -= dt;
378 if (0 <= fragmentIdx && fragmentIdx < sequence.
fragments.size()-1) {
380 pointer = sequence.
fragments[fragmentIdx];
381 currentTime = sequence.
cumTimes[fragmentIdx];
Represents a continuous set of data samples.
void moveTo(dtime time)
Sets pointer to a specific time.
FragmentPtr pointer
pointed fragment
void watch()
Enables "watching mode", i.e., if the sequence is modified, the pointer will follow the modifications...
Pointer(Sequence &sequence, dtime time, bool writing)
void step()
Moves the pointer forward an arbitrary number of samples.
bool writing
if true, the pointer is used to modify the data
Fragmented signal in time domain.
std::vector< Pointer * > pointers
pointers currently accessing the sequence
int findFragment(dtime time) const
Log search for a fragment containing given time moment.
void remove(dtime fromTime, dtime toTime)
Erases a part of the sequence between two given time moments.
void shrink(dtime timeLeft, dtime timeRight)
Shrinks the sequence to given time bounds.
const dtime getDuration() const
Returns sequence duration in number of samples.
static const int VOID_RIGHT
returned by getFragment() when the entire sequence is on the left of the given time moment
void splitFragment(int index, dtime delta)
Splits a given fragment in two.
void split(dtime time, Sequence *left, Sequence *right) const
Splits the sequence in two at a specific time.
std::vector< dtime > cumTimes
cumulative sum of fragment lengths, starts from 0, of N+1 entries (N = num. of fragments)
virtual Sequence * createEmpty() const =0
Initializes an empty sequence, used to bootstrap copying operations.
void syncPointers()
Resets pointers once the sequence changes to keep them consistent.
void concatenate(Fragment &fragment, dtime offset, dtime length)
Adds a new fragment at the end of the sequence.
void clear()
Removes the content of the sequence making it empty (of zero duration).
std::vector< FragmentPtr > fragments
the content
static const int VOID_LEFT
returned by getFragment() when the entire sequence is on the right of the given time moment
void insert(const Sequence &sequence, dtime time)
Inserts a Sequence at a given position in time.
Sequence * copy(dtime fromTime, dtime toTime) const
Copies a given piece of the current sequence into new Sequence.
#define BEATMUP_DEBUG_E(...)
#define BEATMUP_ASSERT_DEBUG(C)
Abstract fragmented signals representation.
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
int offset
offset in samples inside the fragment since its beginning
int length
number of samples to use from the fragment
JNIEnv jobject jint jint jint jfloat fragment
jlong jlong jint jint jint jint jint left