tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TimeRange.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11#pragma once
12
13#include "tracktion_Time.h"
14
15namespace tracktion { inline namespace core
16{
17
18template<typename PositionType>
19struct RangeType;
20
21//==============================================================================
22//==============================================================================
28
37
38
39//==============================================================================
41[[ nodiscard ]] juce::Range<int64_t> toSamples (TimeRange, double sampleRate);
42
44[[ nodiscard ]] TimeRange timeRangeFromSamples (juce::Range<int64_t> sampleRange, double sampleRate);
45
47template<typename SourceRangeType>
48[[ nodiscard ]] TimeRange timeRangeFromSeconds (SourceRangeType);
49
50//==============================================================================
51//==============================================================================
62template<typename PositionType>
64{
65 using Position = PositionType;
66 using Duration = typename Position::DurationType;
68 //==============================================================================
70 RangeType() = default;
71
73 RangeType (const RangeType&) = default;
74
76 RangeType& operator= (const RangeType&) = default;
77
79 RangeType (Position start, Position end);
80
83
85 static RangeType endingAt (Position end, Duration);
86
89
92
93 //==============================================================================
95 constexpr Position getStart() const;
96
98 constexpr Position getEnd() const;
99
101 constexpr Duration getLength() const;
102
104 constexpr Position getCentre() const;
105
108
109 //==============================================================================
111 bool isEmpty() const;
112
114 bool overlaps (const RangeType&) const;
115
117 bool contains (const RangeType&) const;
118
120 bool intersects (const RangeType&) const;
121
123 bool contains (Position) const;
124
126 bool containsInclusive (Position) const;
127
128 //==============================================================================
130 [[ nodiscard ]] RangeType getUnionWith (RangeType) const;
131
133 [[ nodiscard ]] RangeType getIntersectionWith (RangeType) const;
134
136 [[ nodiscard ]] RangeType rescaled (Position anchorTime, double factor) const;
137
141 [[ nodiscard ]] RangeType constrainRange (RangeType) const;
142
144 [[ nodiscard ]] RangeType expanded (Duration) const;
145
147 [[ nodiscard ]] RangeType reduced (Duration) const;
148
150 [[ nodiscard ]] RangeType movedToStartAt (Position) const;
151
153 [[ nodiscard ]] RangeType movedToEndAt (Position) const;
154
156 [[ nodiscard ]] RangeType withStart (Position) const;
157
159 [[ nodiscard ]] RangeType withEnd (Position) const;
160
162 [[ nodiscard ]] RangeType withLength (Duration) const;
163
164private:
165 Position start, end;
166
167 void checkInvariants() const;
168};
169
170//==============================================================================
172template<typename PositionType>
173[[ nodiscard ]] bool operator== (const RangeType<PositionType>&, const RangeType<PositionType>&);
174
176template<typename PositionType>
177[[ nodiscard ]] bool operator!= (const RangeType<PositionType>&, const RangeType<PositionType>&);
178
180template<typename PositionType>
182
184template<typename PositionType>
186
187//==============================================================================
189template<typename PositionType>
191
192//==============================================================================
193// _ _ _ _
194// __| | ___ | |_ __ _ (_)| | ___
195// / _` | / _ \| __| / _` || || |/ __|
196// | (_| || __/| |_ | (_| || || |\__ \ _ _ _
197// \__,_| \___| \__| \__,_||_||_||___/(_)(_)(_)
198//
199// Code beyond this point is implementation detail...
200//
201//==============================================================================
202template<typename PositionType>
203PositionType fromUnderlyingType (double);
204
205template<> inline TimePosition fromUnderlyingType<TimePosition> (double t) { return TimePosition::fromSeconds (t); }
206template<> inline TimeDuration fromUnderlyingType<TimeDuration> (double t) { return TimeDuration::fromSeconds (t); }
207inline double toUnderlyingType (TimePosition t) { return t.inSeconds(); }
208inline double toUnderlyingType (TimeDuration t) { return t.inSeconds(); }
209
210template<> inline BeatPosition fromUnderlyingType<BeatPosition> (double t) { return BeatPosition::fromBeats (t); }
211template<> inline BeatDuration fromUnderlyingType<BeatDuration> (double t) { return BeatDuration::fromBeats (t); }
212inline double toUnderlyingType (BeatPosition t) { return t.inBeats(); }
213inline double toUnderlyingType (BeatDuration t) { return t.inBeats(); }
214
216{
217 return { TimePosition::fromSamples (r.getStart(), sampleRate),
218 TimePosition::fromSamples (r.getEnd(), sampleRate) };
219}
220
221template<typename SourceRangeType>
222inline TimeRange timeRangeFromSeconds (SourceRangeType r)
223{
224 return { TimePosition::fromSeconds (r.getStart()),
225 TimePosition::fromSeconds (r.getEnd()) };
226}
227
228template<typename PositionType>
230 : start (s), end (e)
231{
232 checkInvariants();
233}
234
235template<typename PositionType>
237 : start (s), end (s + d)
238{
239 checkInvariants();
240}
241
242template<typename PositionType>
247
248template<typename PositionType>
250{
251 return p1 < p2 ? RangeType (p1, p2)
252 : RangeType (p2, p1);
253}
254
255template<typename PositionType>
260
261template<typename PositionType> inline constexpr typename RangeType<PositionType>::Position RangeType<PositionType>::getStart() const { return start; }
262template<typename PositionType> inline constexpr typename RangeType<PositionType>::Position RangeType<PositionType>::getEnd() const { return end; }
263template<typename PositionType> inline constexpr typename RangeType<PositionType>::Duration RangeType<PositionType>::getLength() const { return end - start; }
264template<typename PositionType> inline constexpr typename RangeType<PositionType>::Position RangeType<PositionType>::getCentre() const { return fromUnderlyingType<Position> ((toUnderlyingType (start) + toUnderlyingType (end)) * 0.5); }
265template<typename PositionType> inline typename RangeType<PositionType>::Position RangeType<PositionType>::clipPosition (Position position) const { return juce::jlimit (start, end, position); }
266
267template<typename PositionType> inline bool RangeType<PositionType>::isEmpty() const { return end <= start; }
268template<typename PositionType> inline bool RangeType<PositionType>::overlaps (const RangeType& other) const { return other.start < end && start < other.end; }
269template<typename PositionType> inline bool RangeType<PositionType>::contains (const RangeType& other) const { return other.start >= start && other.end <= end; }
270template<typename PositionType> inline bool RangeType<PositionType>::intersects (const RangeType& other) const { return other.start < end && start < other.end; }
271
272template<typename PositionType> inline bool RangeType<PositionType>::contains (Position time) const { return time >= start && time < end; }
273template<typename PositionType> inline bool RangeType<PositionType>::containsInclusive (Position time) const { return time >= start && time <= end; }
274
275template<typename PositionType>
277{
278 return { std::min (start, o.start),
279 std::max (end, o.end) };
280}
281
282template<typename PositionType>
284{
285 auto newStart = std::max (start, o.start);
286 return { newStart, std::max (newStart, std::min (end, o.end)) };
287}
288
289template<typename PositionType>
291{
292 jassert (factor > 0);
293 return { anchorTime + fromUnderlyingType<Duration> (toUnderlyingType (start - anchorTime) * factor),
294 anchorTime + fromUnderlyingType<Duration> (toUnderlyingType (end - anchorTime) * factor) };
295}
296
297template<typename PositionType>
299{
300 auto otherLen = rangeToConstrain.getLength();
301
302 return getLength() <= otherLen
303 ? *this
304 : rangeToConstrain.movedToStartAt (juce::jlimit (start, end - otherLen,
305 rangeToConstrain.getStart()));
306}
307
308template<typename PositionType>
310{
311 jassert (amount >= Duration());
312 return { start - amount, end + amount };
313}
314
315template<typename PositionType>
317{
318 jassert (amount >= Duration());
319 amount = std::min (amount, fromUnderlyingType<Duration> (toUnderlyingType (getLength()) / 2.0));
320 return { start + amount, end - amount };
321}
322
323template<typename PositionType>
325{
326 return { newStart, end + (newStart - start) };
327}
328
329template<typename PositionType>
331{
332 return { start + (newEnd - end), newEnd };
333}
334
335template<typename PositionType>
337{
338 jassert (newStart <= end);
339 return { newStart, std::max (end, newStart) };
340}
341
342template<typename PositionType>
344{
345 jassert (newEnd >= start);
346 return { std::min (start, newEnd), newEnd };
347}
348
349template<typename PositionType>
351{
352 jassert (newLength >= Duration());
353 return { start, start + std::max (Duration(), newLength) };
354}
355
356
357template<typename PositionType>
359{
360 jassert (end >= start);
361}
362
363inline juce::Range<int64_t> toSamples (TimeRange r, double sampleRate)
364{
365 return { toSamples (r.getStart(), sampleRate),
366 toSamples (r.getEnd(), sampleRate) };
367}
368
369template<typename PositionType>
370inline bool operator== (const RangeType<PositionType>& r1, const RangeType<PositionType>& r2) { return r1.getStart() == r2.getStart() && r1.getEnd() == r2.getEnd(); }
371template<typename PositionType>
372inline bool operator!= (const RangeType<PositionType>& r1, const RangeType<PositionType>& r2) { return ! operator== (r1, r2); }
373
374template<typename PositionType>
376template<typename PositionType>
378
379template<typename PositionType>
384
385template<typename RangeType,
388 bool> = true>
389std::string to_string (RangeType range)
390{
391 return std::to_string (toUnderlyingType (range.getStart())) + ", "
392 + std::to_string (toUnderlyingType (range.getEnd()));
393}
394
395inline std::ostream& operator<< (std::ostream& os, const TimeRange& r) { os << to_string (r); return os; }
396inline std::ostream& operator<< (std::ostream& os, const BeatRange& r) { os << to_string (r); return os; }
397
398}} // namespace tracktion
399
400
401//==============================================================================
402//==============================================================================
403template<>
404struct std::hash<tracktion::TimeRange>
405{
406 std::size_t operator()(const tracktion::TimeRange tr) const noexcept
407 {
408 std::size_t h1 = std::hash<double>{} (tr.getStart().inSeconds());
409 std::size_t h2 = std::hash<double>{} (tr.getEnd().inSeconds());
410
411 return tracktion::hash (h1, h2);
412 }
413};
414
415template<>
416struct std::hash<tracktion::BeatRange>
417{
418 std::size_t operator()(const tracktion::BeatRange tr) const noexcept
419 {
420 std::size_t h1 = std::hash<double>{} (tr.getStart().inBeats());
421 std::size_t h2 = std::hash<double>{} (tr.getEnd().inBeats());
422
423 return tracktion::hash (h1, h2);
424 }
425};
constexpr ValueType getStart() const noexcept
constexpr ValueType getEnd() const noexcept
T is_pointer_v
#define jassert(expression)
T max(T... args)
T min(T... args)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
constexpr auto toUnderlyingType(T t) -> std::enable_if_t< std::is_enum_v< T >, std::underlying_type_t< T > >
TimeRange timeRangeFromSamples(juce::Range< int64_t > sampleRange, double sampleRate)
Creates a TimeRange from a range of samples.
TimeRange timeRangeFromSeconds(SourceRangeType)
Creates a TimeRange from a range of seconds.
constexpr int64_t toSamples(TimePosition, double sampleRate)
Converts a TimePosition to a number of samples.
RangeType< PositionType > withEndExtended(RangeType< PositionType > &, typename RangeType< PositionType >::Duration)
Adds an amount to the end of the range and returns a new range.
T operator()(T... args)
static constexpr BeatDuration fromBeats(T durationInBeats)
Create a BeatPosition from a number of beats.
static constexpr BeatPosition fromBeats(T positionInBeats)
Create a BeatPosition from a number of beats.
Describes a range of two positions with a duration separating them.
RangeType withLength(Duration) const
Returns a range with the same start position as this one but a new duration length.
static RangeType emptyRange(Position)
Returns a range with the specified start position and a length of zero.
RangeType reduced(Duration) const
Reduces the start and end of this range by the given ammount.
typename Position::DurationType Duration
The duration type of the range.
bool intersects(const RangeType &) const
Returns true if the given range intersects this one.
static RangeType between(Position, Position)
Returns the range that lies between two positions (in either order).
constexpr Position getEnd() const
Returns the end of the range.
bool overlaps(const RangeType &) const
Returns true if this range overlaps the provided one.
RangeType getIntersectionWith(RangeType) const
Returns the intersection of this range with the given one.
bool contains(const RangeType &) const
Returns true if this range contains the provided one.
RangeType()=default
Creates an empty range.
RangeType movedToStartAt(Position) const
Returns a range with the same duration as this one but a new start position.
RangeType(const RangeType &)=default
Creates a copy of another range.
constexpr Position getStart() const
Returns the start of the range.
RangeType movedToEndAt(Position) const
Returns a range with the same duration as this one but a new end position.
Position clipPosition(Position) const
Clamps the given position to this range.
RangeType rescaled(Position anchorTime, double factor) const
Returns a range that has been expanded or contracted around the given position.
static RangeType endingAt(Position end, Duration)
Creates a Range from a duration and an end position.
RangeType constrainRange(RangeType) const
Returns a given range, after moving it forwards or backwards to fit it within this range.
RangeType expanded(Duration) const
Expands the start and end of this range by the given ammount.
constexpr Duration getLength() const
Returns the length of the range.
RangeType withStart(Position) const
Returns a range with the same end position as this one but a new start position.
PositionType Position
The position type of the range.
bool isEmpty() const
Returns true if this range has a 0 length duration.
constexpr Position getCentre() const
Returns the centre position of the range.
RangeType withEnd(Position) const
Returns a range with the same start position as this one but a new end position.
RangeType & operator=(const RangeType &)=default
Creates a copy of another range.
RangeType getUnionWith(RangeType) const
Returns the range that contains both of these ranges.
bool containsInclusive(Position) const
Returns true if this range contains the provided position even if it lies at the end position.
Represents a duration in real-life time.
static constexpr TimeDuration fromSeconds(T positionInSeconds)
Create a TimeDuration from a number of seconds.
Represents a position in real-life time.
static constexpr TimePosition fromSeconds(T positionInSeconds)
Create a TimePosition from a number of seconds.
static constexpr TimePosition fromSamples(IntType numSamples, double sampleRate)
Create a TimePosition from a number of samples and a sample rate.
time
T to_string(T... args)