1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-23 15:50:05 +02:00

Less scrub lag: avoid redundant disk traffic in Mixer...

Also improves performance in bug 860, but not as much as the special case
patch for that bug in Bugzilla
This commit is contained in:
Paul-Licameli 2016-05-15 10:06:51 -05:00 committed by Paul Licameli
parent 52910f4f07
commit 6eaff838f2
2 changed files with 28 additions and 28 deletions

View File

@ -22,7 +22,6 @@
#include "Audacity.h" #include "Audacity.h"
#include "Mix.h" #include "Mix.h"
#include <math.h> #include <math.h>
@ -251,13 +250,13 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
const auto numInputTracks = inputTracks.size(); const auto numInputTracks = inputTracks.size();
mHighQuality = highQuality; mHighQuality = highQuality;
mNumInputTracks = numInputTracks; mNumInputTracks = numInputTracks;
mInputTrack = new const WaveTrack*[mNumInputTracks]; mInputTrack = new WaveTrackCache[mNumInputTracks];
// mSamplePos holds for each track the next sample position not // mSamplePos holds for each track the next sample position not
// yet processed. // yet processed.
mSamplePos = new sampleCount[mNumInputTracks]; mSamplePos = new sampleCount[mNumInputTracks];
for(i=0; i<mNumInputTracks; i++) { for(i=0; i<mNumInputTracks; i++) {
mInputTrack[i] = inputTracks[i]; mInputTrack[i].SetTrack(inputTracks[i]);
mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime); mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime);
} }
mTimeTrack = warpOptions.timeTrack; mTimeTrack = warpOptions.timeTrack;
@ -313,7 +312,7 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
mSampleQueue = new float *[mNumInputTracks]; mSampleQueue = new float *[mNumInputTracks];
mResample = new Resample*[mNumInputTracks]; mResample = new Resample*[mNumInputTracks];
for(i=0; i<mNumInputTracks; i++) { for(i=0; i<mNumInputTracks; i++) {
double factor = (mRate / mInputTrack[i]->GetRate()); double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
double minFactor, maxFactor; double minFactor, maxFactor;
if (mTimeTrack) { if (mTimeTrack) {
// variable rate resampling // variable rate resampling
@ -408,11 +407,12 @@ void MixBuffers(int numChannels, int *channelFlags, float *gains,
} }
} }
sampleCount Mixer::MixVariableRates(int *channelFlags, const WaveTrack *track, sampleCount Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
sampleCount *pos, float *queue, sampleCount *pos, float *queue,
int *queueStart, int *queueLen, int *queueStart, int *queueLen,
Resample * pResample) Resample * pResample)
{ {
const WaveTrack *const track = cache.GetTrack();
const double trackRate = track->GetRate(); const double trackRate = track->GetRate();
const double initialWarp = mRate / mSpeed / trackRate; const double initialWarp = mRate / mSpeed / trackRate;
const double tstep = 1.0 / trackRate; const double tstep = 1.0 / trackRate;
@ -455,10 +455,8 @@ sampleCount Mixer::MixVariableRates(int *channelFlags, const WaveTrack *track,
// Nothing to do if past end of play interval // Nothing to do if past end of play interval
if (getLen > 0) { if (getLen > 0) {
if (backwards) { if (backwards) {
track->Get((samplePtr)&queue[*queueLen], auto results = cache.Get(floatSample, *pos - (getLen - 1), getLen);
floatSample, memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
*pos - (getLen - 1),
getLen);
track->GetEnvelopeValues(mEnvValues, track->GetEnvelopeValues(mEnvValues,
getLen, getLen,
@ -468,10 +466,8 @@ sampleCount Mixer::MixVariableRates(int *channelFlags, const WaveTrack *track,
*pos -= getLen; *pos -= getLen;
} }
else { else {
track->Get((samplePtr)&queue[*queueLen], auto results = cache.Get(floatSample, *pos, getLen);
floatSample, memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
*pos,
getLen);
track->GetEnvelopeValues(mEnvValues, track->GetEnvelopeValues(mEnvValues,
getLen, getLen,
@ -558,9 +554,10 @@ sampleCount Mixer::MixVariableRates(int *channelFlags, const WaveTrack *track,
return out; return out;
} }
sampleCount Mixer::MixSameRate(int *channelFlags, const WaveTrack *track, sampleCount Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
sampleCount *pos) sampleCount *pos)
{ {
const WaveTrack *const track = cache.GetTrack();
int slen = mMaxOut; int slen = mMaxOut;
int c; int c;
const double t = *pos / track->GetRate(); const double t = *pos / track->GetRate();
@ -588,7 +585,8 @@ sampleCount Mixer::MixSameRate(int *channelFlags, const WaveTrack *track,
slen = mMaxOut; slen = mMaxOut;
if (backwards) { if (backwards) {
track->Get((samplePtr)mFloatBuffer, floatSample, *pos - (slen - 1), slen); auto results = cache.Get(floatSample, *pos - (slen - 1), slen);
memcpy(mFloatBuffer, results, sizeof(float) * slen);
track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate, 1.0 / mRate); track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate, 1.0 / mRate);
for(int i=0; i<slen; i++) for(int i=0; i<slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here? mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
@ -597,7 +595,8 @@ sampleCount Mixer::MixSameRate(int *channelFlags, const WaveTrack *track,
*pos -= slen; *pos -= slen;
} }
else { else {
track->Get((samplePtr)mFloatBuffer, floatSample, *pos, slen); auto results = cache.Get(floatSample, *pos, slen);
memcpy(mFloatBuffer, results, sizeof(float) * slen);
track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate); track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate);
for(int i=0; i<slen; i++) for(int i=0; i<slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here? mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
@ -632,7 +631,7 @@ sampleCount Mixer::Process(sampleCount maxToProcess)
Clear(); Clear();
for(i=0; i<mNumInputTracks; i++) { for(i=0; i<mNumInputTracks; i++) {
const WaveTrack *track = mInputTrack[i]; const WaveTrack *const track = mInputTrack[i].GetTrack();
for(j=0; j<mNumChannels; j++) for(j=0; j<mNumChannels; j++)
channelFlags[j] = 0; channelFlags[j] = 0;
@ -661,12 +660,12 @@ sampleCount Mixer::Process(sampleCount maxToProcess)
} }
if (mbVariableRates || track->GetRate() != mRate) if (mbVariableRates || track->GetRate() != mRate)
maxOut = std::max(maxOut, maxOut = std::max(maxOut,
MixVariableRates(channelFlags, track, MixVariableRates(channelFlags, mInputTrack[i],
&mSamplePos[i], mSampleQueue[i], &mSamplePos[i], mSampleQueue[i],
&mQueueStart[i], &mQueueLen[i], mResample[i])); &mQueueStart[i], &mQueueLen[i], mResample[i]));
else else
maxOut = std::max(maxOut, maxOut = std::max(maxOut,
MixSameRate(channelFlags, track, &mSamplePos[i])); MixSameRate(channelFlags, mInputTrack[i], &mSamplePos[i]));
double t = (double)mSamplePos[i] / (double)track->GetRate(); double t = (double)mSamplePos[i] / (double)track->GetRate();
if (mT0 > mT1) if (mT0 > mT1)
@ -728,7 +727,7 @@ void Mixer::Restart()
mTime = mT0; mTime = mT0;
for(i=0; i<mNumInputTracks; i++) for(i=0; i<mNumInputTracks; i++)
mSamplePos[i] = mInputTrack[i]->TimeToLongSamples(mT0); mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mT0);
for(i=0; i<mNumInputTracks; i++) { for(i=0; i<mNumInputTracks; i++) {
mQueueStart[i] = 0; mQueueStart[i] = 0;
@ -748,7 +747,7 @@ void Mixer::Reposition(double t)
mTime = std::max(mT0, (std::min(mT1, mTime))); mTime = std::max(mT0, (std::min(mT1, mTime)));
for(i=0; i<mNumInputTracks; i++) { for(i=0; i<mNumInputTracks; i++) {
mSamplePos[i] = mInputTrack[i]->TimeToLongSamples(mTime); mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mTime);
mQueueStart[i] = 0; mQueueStart[i] = 0;
mQueueLen[i] = 0; mQueueLen[i] = 0;
} }

View File

@ -14,16 +14,16 @@
#include "MemoryX.h" #include "MemoryX.h"
#include <wx/string.h> #include <wx/string.h>
#include "SampleFormat.h" #include "SampleFormat.h"
#include "Resample.h"
class Resample;
class DirManager; class DirManager;
class TimeTrack; class TimeTrack;
class TrackFactory; class TrackFactory;
class TrackList; class TrackList;
class WaveTrack; class WaveTrack;
class WaveTrackConstArray; class WaveTrackConstArray;
class WaveTrackCache;
/** @brief Mixes together all input tracks, applying any envelopes, amplitude /** @brief Mixes together all input tracks, applying any envelopes, amplitude
* gain, panning, and real-time effects in the process. * gain, panning, and real-time effects in the process.
@ -141,10 +141,10 @@ class AUDACITY_DLL_API Mixer {
private: private:
void Clear(); void Clear();
sampleCount MixSameRate(int *channelFlags, const WaveTrack *src, sampleCount MixSameRate(int *channelFlags, WaveTrackCache &cache,
sampleCount *pos); sampleCount *pos);
sampleCount MixVariableRates(int *channelFlags, const WaveTrack *track, sampleCount MixVariableRates(int *channelFlags, WaveTrackCache &cache,
sampleCount *pos, float *queue, sampleCount *pos, float *queue,
int *queueStart, int *queueLen, int *queueStart, int *queueLen,
Resample * pResample); Resample * pResample);
@ -152,7 +152,8 @@ class AUDACITY_DLL_API Mixer {
private: private:
// Input // Input
int mNumInputTracks; int mNumInputTracks;
const WaveTrack **mInputTrack; WaveTrackCache *mInputTrack;
bool mbVariableRates; bool mbVariableRates;
const TimeTrack *mTimeTrack; const TimeTrack *mTimeTrack;
sampleCount *mSamplePos; sampleCount *mSamplePos;