| 66 | } |
| 67 | |
| 68 | size_t MixerSource::MixVariableRates( |
| 69 | unsigned nChannels, const size_t maxOut, float *floatBuffers[]) |
| 70 | { |
| 71 | const auto &[mT0, mT1, mSpeed, _] = *mTimesAndSpeed; |
| 72 | const bool backwards = (mT1 < mT0); |
| 73 | |
| 74 | const double sequenceRate = mpSeq->GetRate(); |
| 75 | const double initialWarp = mRate / mSpeed / sequenceRate; |
| 76 | const double tstep = 1.0 / sequenceRate; |
| 77 | const auto sampleSize = SAMPLE_SIZE(floatSample); |
| 78 | // Find the last sample |
| 79 | const auto endPos = [mpSeq = mpSeq, mT1 = mT1, backwards]{ |
| 80 | double endTime = mpSeq->GetEndTime(); |
| 81 | double startTime = mpSeq->GetStartTime(); |
| 82 | const double tEnd = backwards |
| 83 | ? std::max(startTime, mT1) |
| 84 | : std::min(endTime, mT1); |
| 85 | return mpSeq->TimeToLongSamples(tEnd); |
| 86 | }(); |
| 87 | |
| 88 | auto pos = mSamplePos; |
| 89 | auto queueStart = mQueueStart; |
| 90 | auto queueLen = mQueueLen; |
| 91 | |
| 92 | size_t out = 0; |
| 93 | |
| 94 | /* time is floating point. Sample rate is integer. The number of samples |
| 95 | * has to be integer, but the multiplication gives a float result, which we |
| 96 | * round to get an integer result. TODO: is this always right or can it be |
| 97 | * off by one sometimes? Can we not get this information directly from the |
| 98 | * clip (which must know) rather than convert the time? |
| 99 | * |
| 100 | * LLL: Not at this time. While WaveClips provide methods to retrieve the |
| 101 | * start and end sample, they do the same float->sampleCount conversion |
| 102 | * to calculate the position. |
| 103 | */ |
| 104 | |
| 105 | // Find the time corresponding to the start of the queue, for use with time track |
| 106 | double t = ((pos).as_long_long() + |
| 107 | (backwards ? queueLen : - queueLen)) / sequenceRate; |
| 108 | |
| 109 | while (out < maxOut) { |
| 110 | if (queueLen < (int)sProcessLen) { |
| 111 | // Shift pending portion to start of the buffer |
| 112 | for (size_t iChannel = 0; iChannel < nChannels; ++iChannel) { |
| 113 | const auto queue = mSampleQueue[iChannel].data(); |
| 114 | memmove(queue, &queue[queueStart], (queueLen) * sampleSize); |
| 115 | } |
| 116 | queueStart = 0; |
| 117 | |
| 118 | // How far to advance depends on endPos, |
| 119 | // which is independent of channel |
| 120 | auto getLen = limitSampleBufferSize( |
| 121 | sQueueMaxLen - queueLen, |
| 122 | backwards ? pos - endPos : endPos - pos |
| 123 | ); |
| 124 | |
| 125 | // Nothing to do if past end of play interval |
nothing calls this directly
no test coverage detected