22 Push({ clips.begin(), clips.end() });
32 auto &[intervals, ii] = mStack.back();
41 if (mpTrack && !mStack.empty()) {
42 auto &[intervals, ii] = mStack.back();
43 if (++ii == intervals.size())
46 Push(intervals[ii]->GetCutLines());
58 while (!clips.empty()) {
59 auto nextClips = clips[0]->GetCutLines();
60 mStack.push_back({ move(clips), 0 });
61 clips = move(nextClips);
79 float *pointers0[2]{ buffers0[0].get(),
80 width > 1 ? buffers0[1].get() :
nullptr };
83 float *pointers1[2]{ buffers1[0].get(),
84 width > 1 ? buffers1[1].get() :
nullptr };
85 constexpr auto reverseBuffers =
86 [](
float *
const (&pointers)[2],
size_t size){
87 for (
const auto pointer : pointers)
92 auto originalLen = originalEnd - originalStart;
97 auto second = first + (len - block);
99 track.
GetFloats(0, width, pointers0, first, block);
100 reverseBuffers(pointers0, block);
101 track.
GetFloats(0, width, pointers1, second, block);
102 reverseBuffers(pointers1, block);
115 2 * (first - originalStart).as_double() / originalLen.as_double()
132 auto end = start + len;
135 const auto invariant = [&]{
136 return std::is_sorted(clipArray.begin(), clipArray.end(),
137 [](
const auto &pA,
const auto &pB){
138 return pA->GetPlayStartTime() < pB->GetPlayEndTime();
147 for (
size_t ii = 0; ii < clipArray.size(); ++ii) {
148 const auto &clip = *clipArray[ii];
149 auto clipStart = clip.GetPlayStartSample();
150 auto clipEnd = clip.GetPlayEndSample();
151 const auto splitAt = [&](
double splitTime){
152 auto [
_, second] = track.
SplitAt(splitTime);
154 clipArray.insert(clipArray.begin() + ii + 1, second);
156 if (clipStart < start && clipEnd > start && clipEnd <=
end) {
161 else if (clipStart >= start && clipStart < end && clipEnd >
end) {
166 else if (clipStart < start && clipEnd >
end) {
180 bool checkedFirstClip =
false;
184 auto currentEnd =
end;
194 for (
const auto &clip : clipArray) {
196 auto clipStart = clip->GetPlayStartSample();
197 auto clipEnd = clip->GetPlayEndSample();
199 if (clipStart >= start && clipEnd <=
end) {
205 if (!checkedFirstClip && clipStart > start) {
206 checkedFirstClip =
true;
208 if (clipArray[i - 1]->GetPlayEndSample() <= start)
209 currentEnd -= (clipStart - start);
212 currentEnd -= (clipStart - start);
215 auto revStart = std::max(clipStart, start);
217 auto revLen = revEnd - revStart;
218 if (revEnd >= revStart) {
227 auto clipOffsetStart = currentEnd - (clipEnd - clipStart);
229 if (i + 1 < clipArray.size()) {
231 auto nextClipStart = clipArray[i + 1]->GetPlayStartSample();
232 currentEnd = currentEnd -
233 (clipEnd - clipStart) - (nextClipStart - clipEnd);
237 revClips.push_back(clip);
240 revClips.back()->SetPlayStartTime(
244 else if (clipStart >=
end) {
247 otherClips.push_back(clip);
257 for (
auto it = revClips.rbegin(), revEnd = revClips.rend();
264 for (
auto &clip : otherClips)
273 for (
const auto &pInterval : track.
Intervals())
274 result += pInterval->GetSequenceSamplesCount();
281 for (
const auto &pInterval : track.
Intervals())
282 result += pInterval->CountBlocks();
288 for (
const auto &pClip : track.Intervals())
294 bool removed =
false;
295 for (
const auto &pClip : track.
Intervals())
296 if (pClip->RemoveCutLine(cutLinePosition)) {
306 double cutLinePosition,
double* cutlineStart,
312 double start = 0,
end = 0;
314 const auto pEnd = clips.end();
315 const auto pClip = std::find_if(clips.begin(), pEnd,
316 [&](
const auto &clip) {
317 return clip->FindCutLine(cutLinePosition, &start, &end); });
319 auto &&clip = *pClip;
320 if (!editClipCanMove) {
323 for (
const auto &clip2: clips)
324 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime() &&
325 clip->GetPlayEndTime() +
end - start > clip2->GetPlayStartTime())
329 XO(
"There is not enough room available to expand the cut line"),
331 "Error:_Insufficient_space_in_track"
335 clip->ExpandCutLine(cutLinePosition);
340 *cutlineStart = start;
346 for (
const auto &clip2 : clips)
347 if (clip2->GetPlayStartTime() > clip->GetPlayStartTime())
348 clip2->ShiftBy(
end - start);
355 return std::any_of(clips.begin(), clips.end(), [](
const auto &pClip){
356 return pClip->GetTrimLeft() != 0 || pClip->GetTrimRight() != 0;
362 for (
const auto &pClip : track.
Intervals()) {
363 if (pClip->GetTrimLeft() != 0) {
364 auto t0 = pClip->GetPlayStartTime();
365 pClip->SetTrimLeft(0);
366 pClip->ClearLeft(t0);
368 if (pClip->GetTrimRight() != 0) {
369 auto t1 = pClip->GetPlayEndTime();
370 pClip->SetTrimRight(0);
371 pClip->ClearRight(t1);
383 for (
const auto &pChannel : pClip->Channels()) {
384 auto blocks = pChannel->GetSequenceBlockArray();
385 for (
const auto &block : *blocks) {
386 auto &pBlock = block.sb;
388 if (pIDs && !pIDs->insert(pBlock->GetBlockID()).second)
405 double t0,
double t1)
409 const auto &intervals = track.
Intervals();
410 copy_if(intervals.begin(), intervals.end(), back_inserter(result),
411 [&](
const auto &pClip){
412 return pClip->IntersectsPlayRegion(t0, t1); });
420 const auto nextClip =
@ BadUserAction
Indicates that the user performed an action that is not allowed.
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
bool GetEditClipsCanMove()
bool GetFloats(size_t iChannel, size_t nBuffers, float *const buffers[], sampleCount start, size_t len, bool backwards=false, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
A MessageBoxException that shows a given, unvarying string.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
This allows multiple clips to be a part of one WaveTrack.
void StretchRightTo(double to)
Sets from the right to the absolute time (if in expected range)
A Track that contains audio waveform data.
void InsertInterval(const IntervalHolder &interval, bool newClip, bool allowEmpty=false)
IntervalConstHolder GetNextInterval(const Interval &interval, PlaybackDirection searchDirection) const
bool SetFloats(const float *const *buffers, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Random-access assignment of a range of samples.
std::pair< IntervalHolder, IntervalHolder > SplitAt(double t)
IntervalHolders SortedIntervalArray()
Return all WaveClips sorted by clip play start time.
std::vector< IntervalHolder > IntervalHolders
std::vector< IntervalConstHolder > IntervalConstHolders
size_t NChannels() const override
A constant property.
size_t GetMaxBlockSize() const
size_t GetBestBlockSize(sampleCount t) const
void RemoveInterval(const IntervalHolder &interval)
value_type operator*() const
void Push(IntervalHolders clips)
AllClipsIterator & operator++()
double LongSamplesToTime(sampleCount pos) const
double SnapToSample(double t) const
Positions or offsets within audio files need a wide type.
WAVE_TRACK_API void InspectBlocks(const TrackList &tracks, BlockInspector inspector, SampleBlockIDSet *pIDs=nullptr)
WAVE_TRACK_API size_t CountBlocks(const WaveTrack &track)
WAVE_TRACK_API sampleCount GetSequenceSamplesCount(const WaveTrack &track)
std::function< void(std::shared_ptr< const SampleBlock >)> BlockInspector
WAVE_TRACK_API bool Reverse(WaveTrack &track, sampleCount start, sampleCount len, const ProgressReport &report={})
WAVE_TRACK_API void ExpandCutLine(WaveTrack &track, double cutLinePosition, double *cutlineStart=nullptr, double *cutlineEnd=nullptr)
WAVE_TRACK_API void CloseLock(WaveTrack &track) noexcept
Should be called upon project close. Not balanced by unlocking calls.
std::vector< IntervalHolder > IntervalHolders
std::unordered_set< SampleBlockID > SampleBlockIDSet
IteratorRange< AllClipsIterator > GetAllClips(WaveTrack &track)
WAVE_TRACK_API bool RemoveCutLine(WaveTrack &track, double cutLinePosition)
Remove cut line, without expanding the audio in it.
std::function< bool(double)> ProgressReport
WAVE_TRACK_API void ExpandClipTillNextOne(const WaveTrack &track, WaveTrack::Interval &interval)
WAVE_TRACK_API bool HasHiddenData(const WaveTrack &track)
Whether any clips have hidden audio.
WAVE_TRACK_API void DiscardTrimmed(WaveTrack &track)
Remove hidden audio from all clips.
std::function< void(const std::shared_ptr< SampleBlock > &)> BlockVisitor
WAVE_TRACK_API void VisitBlocks(TrackList &tracks, BlockVisitor visitor, SampleBlockIDSet *pIDs=nullptr)
WAVE_TRACK_API WaveTrack::IntervalConstHolders GetClipsIntersecting(const WaveTrack &track, double t0, double t1)
BuiltinEffectsModule::Registration< Reverse > reverse
bool ReverseOneClip(WaveTrack &track, sampleCount start, sampleCount len, sampleCount originalStart, sampleCount originalEnd, const WaveTrackUtilities::ProgressReport &report)
const char * end(const char *str) noexcept
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
IntervalHolder value_type