20std::pair<float, float>
22 double t0,
double t1,
bool mayThrow)
24 std::pair<float, float> results {
26 std::numeric_limits<float>::max(),
27 std::numeric_limits<float>::lowest(),
29 bool clipFound =
false;
40 for (
const auto &clip: channel.
Intervals())
42 if (t1 >= clip->GetPlayStartTime() && t0 <= clip->GetPlayEndTime())
45 auto clipResults = clip->GetMinMax(t0, t1, mayThrow);
46 if (clipResults.first < results.first)
47 results.first = clipResults.first;
48 if (clipResults.second > results.second)
49 results.second = clipResults.second;
55 results = { 0.f, 0.f };
62 double t0,
double t1,
bool mayThrow)
76 for (
const auto &clip: channel.
Intervals())
81 if (t1 >= clip->GetPlayStartTime() && t0 <= clip->GetPlayEndTime())
83 const auto clipStart = std::max(t0, clip->GetPlayStartTime());
84 const auto clipEnd =
std::min(t1, clip->GetPlayEndTime());
86 float cliprms = clip->GetRMS(t0, t1, mayThrow);
88 sumsq += cliprms * cliprms * (clipEnd - clipStart);
89 duration += (clipEnd - clipStart);
92 return duration > 0 ?
sqrt(sumsq / duration) : 0.0;
103 t = clip->SamplesToTime(clip->TimeToSamples(t - clip->GetPlayStartTime())) +
104 clip->GetPlayStartTime();
108std::pair<size_t, size_t>
110 double t,
float* buffer,
size_t numSideSamples,
116 t, buffer + numSideSamples, numSideSamples + 1, mayThrow,
118 return { numSideSamples - numSamplesReadLeft,
119 numSideSamples + numSamplesReadRight };
124template <
typename FloatType>
126 std::is_const_v<std::remove_pointer_t<FloatType>>,
constSamplePtr,
136template <
typename BufferType>
138 const Clip& clip,
double startOrEndTime ,
140 size_t totalToRead,
size_t alreadyRead,
bool forward)
142 assert(totalToRead >= alreadyRead);
143 const auto remainingToRead = totalToRead - alreadyRead;
148 const auto startTime =
151 if (startSamp >= sampsInClip)
156 buffer + alreadyRead),
164 const auto startSamp =
165 std::max(endSamp - remainingToRead,
sampleCount { 0 });
168 const auto len = (endSamp - startSamp).as_size_t();
169 if (len == 0 || startSamp >= sampsInClip)
171 const auto bufferEnd = buffer + remainingToRead;
179 double t,
float* buffer,
size_t numSamples,
bool mayThrow,
184 auto numSamplesRead = 0u;
190 *clip, t, buffer, numSamples, numSamplesRead,
forward);
191 if (!clip->GetSamples(
192 args.offsetBuffer,
floatSample, args.start, args.len,
195 numSamplesRead += args.len;
196 if (numSamplesRead >= numSamples)
200 return numSamplesRead;
204 double t,
float& value,
bool mayThrow)
213 double t,
float& value,
bool mayThrow)
222 double t,
const float* buffer,
size_t numSideSamples,
226 t, buffer, numSideSamples, effectiveFormat,
229 t, buffer + numSideSamples, numSideSamples + 1, effectiveFormat,
234 double t,
const float* buffer,
size_t numSamples,
239 auto numSamplesWritten = 0u;
245 *clip, t, buffer, numSamples, numSamplesWritten,
forward);
249 args.offsetBuffer,
floatSample, args.start, args.len,
251 numSamplesWritten += args.len;
252 if (numSamplesWritten >= numSamples)
266 double t0,
double t1,
267 const std::function<
float(
double sampleTime)>& producer,
273 if (sortedClips.empty())
275 t0 = std::max(t0, (*sortedClips.begin())->GetPlayStartTime());
276 t1 =
std::min(t1, (*sortedClips.rbegin())->GetPlayEndTime());
280 const auto clipStartTime = clip->GetPlayStartTime();
281 const auto clipEndTime = clip->GetPlayEndTime();
282 const auto sampsPerSec = clip->GetRate() / clip->GetStretchRatio();
283 const auto roundedT0 =
284 std::round((t0 - clipStartTime) * sampsPerSec) / sampsPerSec +
286 const auto roundedT1 =
287 std::round((t1 - clipStartTime) * sampsPerSec) / sampsPerSec +
289 if (clipStartTime > roundedT1)
291 const auto tt0 = std::max(clipStartTime, roundedT0);
292 const auto tt1 =
std::min(clipEndTime, roundedT1);
293 const size_t numSamples = (tt1 - tt0) * sampsPerSec + .5;
294 std::vector<float>
values(numSamples);
295 for (
auto i = 0u; i < numSamples; ++i)
296 values[i] = producer(tt0 + clip->SamplesToTime(i));
297 const size_t iChannel = clip->GetChannelIndex();
309template<
typename ClipPo
inter>
315 const auto p = lower_bound(clips.begin(), clips.end(), clip,
317 return CompareClipsByPlayStartTime(*pClip, clip); });
319 if (p == clips.end() || !*p ||
323 return p == clips.end() - 1 ? nullptr : *(p + 1);
325 return p == clips.begin() ? nullptr : *(p - 1);
328template<
typename ClipPo
inter>
332 const auto neighbour =
GetNextClip(clips, clip, direction);
336 return std::abs(clip.GetPlayEndTime() - neighbour->GetPlayStartTime()) <
341 return std::abs(clip.GetPlayStartTime() - neighbour->GetPlayEndTime()) <
384 return &clip->GetEnvelope();
409 return { pointers.begin(), pointers.end() };
416 auto p = std::find_if(
417 clips.rbegin(), clips.rend(), [&](
const auto& clip) {
418 return clip->WithinPlayRegion(time);
420 return p != clips.rend() ? *p :
nullptr;
434 for (
const auto &interval : channel.
Intervals())
435 if (interval->WithinPlayRegion(t))
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Piecewise linear or piecewise exponential function from double to double.
IteratorRange< IntervalIterator< WaveClipChannel > > Intervals()
sampleCount GetVisibleSampleCount() const override
size_t GetChannelIndex() const
int GetRate() const override
double GetPlayStartTime() const override
double GetStretchRatio() const override
double GetPlayDuration() const
Positions or offsets within audio files need a wide type.
bool CompareClipPointersByPlayStartTime(const ClipConstPointer x, const ClipConstPointer y)
WAVE_TRACK_API void SetFloatsCenteredAroundTime(WaveChannel &channel, double t, const float *buffer, size_t numSideSamples, sampleFormat effectiveFormat)
Similar to GetFloatsCenteredAroundTime, but for writing. Sets as many samples as it can according to ...
std::vector< ClipPointer > ClipPointers
WAVE_TRACK_API std::pair< float, float > GetMinMax(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
bool IsSortedByPlayStartTime(const ClipPointers &clips)
WAVE_TRACK_API ClipPointer GetIntervalAtTime(WaveChannel &channel, double t)
std::shared_ptr< const Clip > ClipConstPointer
std::vector< ClipConstPointer > ClipConstPointers
WAVE_TRACK_API bool CompareClipsByPlayStartTime(const Clip &x, const Clip &y)
WAVE_TRACK_API void SetFloatsWithinTimeRange(WaveChannel &channel, double t0, double t1, const std::function< float(double sampleTime)> &producer, sampleFormat effectiveFormat)
Provides a means of setting clip values as a function of time. Included are closest sample to t0 up t...
WAVE_TRACK_API float GetRMS(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
std::shared_ptr< Clip > ClipPointer
WAVE_TRACK_API std::pair< size_t, size_t > GetFloatsCenteredAroundTime(const WaveChannel &channel, double t, float *buffer, size_t numSideSamples, bool mayThrow)
Gets as many samples as it can, but no more than 2 * numSideSamples + 1, centered around t....
WAVE_TRACK_API void SetFloatsFromTime(WaveChannel &channel, double t, const float *buffer, size_t numSamples, sampleFormat effectiveFormat, PlaybackDirection direction)
Similar to GetFloatsFromTime, but for writing. Sets as many samples as it can according to the same r...
WAVE_TRACK_API size_t GetFloatsFromTime(const WaveChannel &channel, double t, float *buffer, size_t numSamples, bool mayThrow, PlaybackDirection direction)
Helper for GetFloatsCenteredAroundTime. If direction == PlaybackDirection::Backward,...
WAVE_TRACK_API ClipPointer GetClipAtTime(WaveChannel &channel, double time)
WAVE_TRACK_API ClipConstPointer GetAdjacentClip(const ClipConstPointers &clips, const Clip &clip, PlaybackDirection searchDirection)
Similar to GetNextClip, but returns nullptr if the neighbour clip is not adjacent.
WAVE_TRACK_API bool GetFloatAtTime(const WaveChannel &channel, double t, float &value, bool mayThrow)
WAVE_TRACK_API Envelope * GetEnvelopeAtTime(WaveChannel &channel, double time)
WAVE_TRACK_API void SetFloatAtTime(WaveChannel &channel, double t, float value, sampleFormat effectiveFormat)
Sets sample nearest to t to value. Silently fails if GetClipAtTime(t) == nullptr.
WAVE_TRACK_API ClipPointers SortedClipArray(WaveChannel &channel)
Get clips sorted by play start time.
WAVE_TRACK_API ClipConstPointer GetNextClip(const ClipConstPointers &clips, const Clip &clip, PlaybackDirection searchDirection)
Returns clips next to clip in the given direction, or nullptr if there is none.
WAVE_TRACK_API void SetFloatsFromTime(WaveClip &clip, double t, size_t iChannel, const float *buffer, size_t numSamples, sampleFormat effectiveFormat)
Considers buffer as audio starting at TimeToSamples(t) (relative to clip play start time) and with eq...
WAVE_TRACK_API bool GetFloatAtTime(const WaveClip &clip, double t, size_t iChannel, float &value, bool mayThrow)
auto DoGetAdjacentClip(const std::vector< ClipPointer > &clips, const Clip &clip, PlaybackDirection direction) -> ClipPointer
SampleAccessArgs< BufferType > GetSampleAccessArgs(const Clip &clip, double startOrEndTime, BufferType buffer, size_t totalToRead, size_t alreadyRead, bool forward)
std::conditional_t< std::is_const_v< std::remove_pointer_t< FloatType > >, constSamplePtr, samplePtr > BufferCharType
void RoundToNearestClipSample(const WaveChannel &channel, double &t)
auto DoGetNextClip(const std::vector< ClipPointer > &clips, const Clip &clip, PlaybackDirection direction) -> ClipPointer
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
__finl float_x4 __vecc sqrt(const float_x4 &a)
const BufferCharType< BufferType > offsetBuffer