24template<
typename T,
typename F> std::vector<T>
27 std::vector<T> result( dim1 );
28 for (
auto &row : result)
33template<
typename T> std::vector<std::vector<T>>
36 return initVector<std::vector<T>>(dim1,
37 [dim2](
auto &row){ row.resize(dim2); });
44 mResample[j] = std::make_unique<Resample>(
70 unsigned iChannel,
const size_t maxOut,
float &floatBuffer)
76 const auto queueLen = &
mQueueLen[iChannel];
77 const auto pResample =
mResample[iChannel].get();
79 const auto pFloat = &floatBuffer;
80 const auto track = cache.GetTrack().get();
81 const double trackRate = track->GetRate();
83 const double initialWarp =
mRate / mSpeed / trackRate;
84 const double tstep = 1.0 / trackRate;
101 double endTime = track->GetEndTime();
102 double startTime = track->GetStartTime();
103 const bool backwards = (mT1 < mT0);
104 const double tEnd = backwards
105 ? std::max(startTime, mT1)
107 const auto endPos = track->TimeToLongSamples(tEnd);
109 double t = ((*pos).as_long_long() +
110 (backwards ? *queueLen : - *queueLen)) / trackRate;
112 while (out < maxOut) {
115 memmove(queue, &queue[*queueStart], (*queueLen) * sampleSize);
120 backwards ? *pos - endPos : endPos - *pos
127 cache.GetFloats(*pos - (getLen - 1), getLen,
mMayThrow);
129 memcpy(&queue[*queueLen], results,
sizeof(
float) * getLen);
131 memset(&queue[*queueLen], 0,
sizeof(
float) * getLen);
134 getLen, (*pos - (getLen - 1)).as_double() / trackRate);
138 auto results = cache.GetFloats(*pos, getLen,
mMayThrow);
140 memcpy(&queue[*queueLen], results,
sizeof(
float) * getLen);
142 memset(&queue[*queueLen], 0,
sizeof(
float) * getLen);
145 getLen, (*pos).as_double() / trackRate);
150 for (
decltype(getLen)
i = 0;
i < getLen;
i++) {
165 thisProcessLen = *queueLen;
168 double factor = initialWarp;
178 t - (
double)thisProcessLen / trackRate + tstep, t + tstep);
181 t, t + (
double)thisProcessLen / trackRate);
184 auto results = pResample->Process(factor,
198 const auto input_used = results.first;
199 *queueStart += input_used;
200 *queueLen -= input_used;
201 out += results.second;
202 t += (input_used / trackRate) * (backwards ? -1 : 1);
209 assert(out <= maxOut);
222 const auto pFloat = &floatBuffer;
223 const auto track = cache.GetTrack().get();
224 const double t = ( *pos ).as_double() / track->GetRate();
225 const double trackEndTime = track->GetEndTime();
226 const double trackStartTime = track->GetStartTime();
228 const bool backwards = (mT1 < mT0);
229 const double tEnd = backwards
230 ? std::max(trackStartTime, mT1)
234 if ((backwards ? t <= tEnd : t >= tEnd))
242 sampleCount{ (backwards ? t - tEnd : tEnd - t) * track->GetRate() + 0.5 }
246 auto results = cache.GetFloats(*pos - (slen - 1), slen,
mMayThrow);
248 memcpy(pFloat, results,
sizeof(
float) * slen);
250 memset(pFloat, 0,
sizeof(
float) * slen);
251 track->GetEnvelopeValues(
mEnvValues.data(), slen, t - (slen - 1) /
mRate);
252 for (
size_t i = 0;
i < slen;
i++)
259 auto results = cache.GetFloats(*pos, slen,
mMayThrow);
261 memcpy(pFloat, results,
sizeof(
float) * slen);
263 memset(pFloat, 0,
sizeof(
float) * slen);
264 track->GetEnvelopeValues(
mEnvValues.data(), slen, t);
265 for (
size_t i = 0;
i < slen;
i++)
271 assert(slen <= maxOut);
276 size_t produced,
size_t max,
float &floatBuffer)
278 assert(produced <= max);
279 const auto pFloat = &floatBuffer;
280 std::fill(pFloat + produced, pFloat + max, 0);
285 bool mayThrow, std::shared_ptr<TimesAndSpeed> pTimesAndSpeed,
287) : mpLeader{ leader.SharedPointer<const
SampleTrack>() }
288 , mnChannels{
TrackList::NChannels(leader) }
290 , mEnvelope{ options.envelope }
291 , mMayThrow{ mayThrow }
292 , mTimesAndSpeed{ move(pTimesAndSpeed) }
293 , mInputTrack( mnChannels )
294 , mSamplePos( mnChannels )
295 , mSampleQueue{
initVector<float>(mnChannels, sQueueMaxLen) }
296 , mQueueStart( mnChannels, 0 )
297 , mQueueLen( mnChannels, 0 )
298 , mResampleParameters{ highQuality, leader, rate, options }
299 , mResample( mnChannels )
300 , mEnvValues(
std::max(sQueueMaxLen, bufferSize) )
320 auto iter = range.begin();
321 std::advance(iter, iChannel);
327 return mpMap ?
mpMap[iChannel].get() :
nullptr;
340#define stackAllocate(T, count) static_cast<T*>(alloca(count * sizeof(T)))
350 const bool backwards = (mT1 < mT0);
353 const auto limit = std::min<size_t>(
mnChannels, maxChannels);
356 for (
size_t j = 0; j < limit; ++j) {
358 auto &result = mixed[j];
364 maxTrack = std::max(maxTrack, result);
365 auto newT =
mSamplePos[j].as_double() / track->GetRate();
369 mTime = std::max(mTime, newT);
372 for (
size_t j = 0; j < limit; ++j) {
374 const auto result = mixed[j];
375 ZeroFill(result, maxTrack, *pFloat);
379 assert(maxTrack <= bound);
383 assert(bound == 0 ||
Remaining() == 0 || maxTrack > 0);
#define stackAllocate(T, count)
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Accumulates (non-interleaved) data during effect processing.
float & GetWritePosition(unsigned iChannel)
Get writable position for one channel.
size_t BufferSize() const
unsigned Channels() const
Piecewise linear or piecewise exponential function from double to double.
double AverageOfInverse(double t0, double t1) const
std::vector< double > mEnvValues
Gain envelopes are applied to input before other transformations.
const ResampleParameters mResampleParameters
size_t MixVariableRates(unsigned iChannel, size_t maxOut, float &floatBuffer)
const BoundedEnvelope *const mEnvelope
Resampling, as needed, after gain envelope.
const std::shared_ptr< TimesAndSpeed > mTimesAndSpeed
std::vector< std::vector< float > > mSampleQueue
First intermediate buffer when resampling is needed.
sampleCount Remaining() const override
Result includes any amount Acquired and not yet Released.
MixerSource(const SampleTrack &leader, size_t bufferSize, double rate, const MixerOptions::Warp &options, bool highQuality, bool mayThrow, std::shared_ptr< TimesAndSpeed > pTimesAndSpeed, const ArrayOf< bool > *pMap)
const SampleTrack * GetChannel(unsigned iChannel) const
static constexpr size_t sQueueMaxLen
bool AcceptsBlockSize(size_t blockSize) const override
std::vector< sampleCount > mSamplePos
Fetch position for source.
std::vector< SampleTrackCache > mInputTrack
SampleTrackCaches are the source of data.
bool AcceptsBuffers(const Buffers &buffers) const override
static constexpr size_t sProcessLen
bool Terminates() const override
const ArrayOf< bool > *const mpMap
bool Release() override
Caller is done examining last Acquire()d positions.
std::vector< std::unique_ptr< Resample > > mResample
std::vector< int > mQueueLen
For each queue, the number of available samples after the queue start.
std::vector< int > mQueueStart
Position in each queue of the start of the next block to resample.
void Reposition(double time, bool skipping)
unsigned mMaxChannels
Remember how many channels were passed to Acquire()
void ZeroFill(size_t produced, size_t max, float &floatBuffer)
const bool * MixerSpec(unsigned iChannel) const
std::optional< size_t > Acquire(Buffers &data, size_t bound) override
Occupy vacant space in Buffers with some data.
size_t MixSameRate(unsigned iChannel, size_t maxOut, float &floatBuffer)
const std::shared_ptr< const SampleTrack > mpLeader
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Positions or offsets within audio files need a wide type.
std::vector< std::vector< T > > initVector(size_t dim1, size_t dim2)
double ComputeWarpFactor(const Envelope &env, double t0, double t1)
Compute the integral warp factor between two non-warped time points.
std::vector< double > mMaxFactor
std::vector< double > mMinFactor
Immutable structure is an argument to Mixer's constructor.