mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 22:28:57 +02:00
Remove naked new[] in: mixer
This commit is contained in:
parent
0113e6f44f
commit
ea05fac870
148
src/Mix.cpp
148
src/Mix.cpp
@ -244,18 +244,24 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality, MixerSpec *mixerSpec)
|
||||
{
|
||||
int i;
|
||||
: mNumInputTracks { inputTracks.size() }
|
||||
|
||||
const auto numInputTracks = inputTracks.size();
|
||||
// This is the number of samples grabbed in one go from a track
|
||||
// and placed in a queue, when mixing with resampling.
|
||||
// (Should we use WaveTrack::GetBestBlockSize instead?)
|
||||
, mQueueMaxLen{ 65536 }
|
||||
, mSampleQueue{ mNumInputTracks, mQueueMaxLen }
|
||||
|
||||
, mNumChannels{ static_cast<size_t>(numOutChannels) }
|
||||
, mGains{ mNumChannels }
|
||||
{
|
||||
mHighQuality = highQuality;
|
||||
mNumInputTracks = numInputTracks;
|
||||
mInputTrack = new WaveTrackCache[mNumInputTracks];
|
||||
mInputTrack.reinit(mNumInputTracks);
|
||||
|
||||
// mSamplePos holds for each track the next sample position not
|
||||
// yet processed.
|
||||
mSamplePos = new sampleCount[mNumInputTracks];
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
mSamplePos.reinit(mNumInputTracks);
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mInputTrack[i].SetTrack(inputTracks[i]);
|
||||
mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime);
|
||||
}
|
||||
@ -263,14 +269,12 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
mT0 = startTime;
|
||||
mT1 = stopTime;
|
||||
mTime = startTime;
|
||||
mNumChannels = numOutChannels;
|
||||
mBufferSize = outBufferSize;
|
||||
mInterleaved = outInterleaved;
|
||||
mRate = outRate;
|
||||
mSpeed = 1.0;
|
||||
mFormat = outFormat;
|
||||
mApplyTrackGains = true;
|
||||
mGains = new float[mNumChannels];
|
||||
if( mixerSpec && mixerSpec->GetNumChannels() == mNumChannels &&
|
||||
mixerSpec->GetNumTracks() == mNumInputTracks )
|
||||
mMixerSpec = mixerSpec;
|
||||
@ -286,18 +290,13 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
mInterleavedBufferSize = mBufferSize;
|
||||
}
|
||||
|
||||
mBuffer = new SampleBuffer[mNumBuffers];
|
||||
mTemp = new SampleBuffer[mNumBuffers];
|
||||
mBuffer.reinit(mNumBuffers);
|
||||
mTemp.reinit(mNumBuffers);
|
||||
for (int c = 0; c < mNumBuffers; c++) {
|
||||
mBuffer[c].Allocate(mInterleavedBufferSize, mFormat);
|
||||
mTemp[c].Allocate(mInterleavedBufferSize, floatSample);
|
||||
}
|
||||
mFloatBuffer = new float[mInterleavedBufferSize];
|
||||
|
||||
// This is the number of samples grabbed in one go from a track
|
||||
// and placed in a queue, when mixing with resampling.
|
||||
// (Should we use WaveTrack::GetBestBlockSize instead?)
|
||||
mQueueMaxLen = 65536;
|
||||
mFloatBuffer = Floats{ mInterleavedBufferSize };
|
||||
|
||||
// But cut the queue into blocks of this finer size
|
||||
// for variable rate resampling. Each block is resampled at some
|
||||
@ -305,13 +304,12 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
mProcessLen = 1024;
|
||||
|
||||
// Position in each queue of the start of the next block to resample.
|
||||
mQueueStart = new int[mNumInputTracks];
|
||||
mQueueStart.reinit(mNumInputTracks);
|
||||
|
||||
// For each queue, the number of available samples after the queue start.
|
||||
mQueueLen = new int[mNumInputTracks];
|
||||
mSampleQueue = new float *[mNumInputTracks];
|
||||
mResample = new Resample*[mNumInputTracks];
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
mQueueLen.reinit(mNumInputTracks);
|
||||
mResample.reinit(mNumInputTracks);
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
|
||||
double minFactor, maxFactor;
|
||||
if (mTimeTrack) {
|
||||
@ -332,36 +330,17 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
minFactor = maxFactor = factor;
|
||||
}
|
||||
|
||||
mResample[i] = new Resample(mHighQuality, minFactor, maxFactor);
|
||||
mSampleQueue[i] = new float[mQueueMaxLen];
|
||||
mResample[i] = std::make_unique<Resample>(mHighQuality, minFactor, maxFactor);
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
}
|
||||
|
||||
const auto envLen = std::max(mQueueMaxLen, mInterleavedBufferSize);
|
||||
mEnvValues = new double[envLen];
|
||||
mEnvValues.reinit(envLen);
|
||||
}
|
||||
|
||||
Mixer::~Mixer()
|
||||
{
|
||||
int i;
|
||||
|
||||
delete[] mBuffer;
|
||||
delete[] mTemp;
|
||||
delete[] mInputTrack;
|
||||
delete[] mEnvValues;
|
||||
delete[] mFloatBuffer;
|
||||
delete[] mGains;
|
||||
delete[] mSamplePos;
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
delete mResample[i];
|
||||
delete[] mSampleQueue[i];
|
||||
}
|
||||
delete[] mResample;
|
||||
delete[] mSampleQueue;
|
||||
delete[] mQueueStart;
|
||||
delete[] mQueueLen;
|
||||
}
|
||||
|
||||
void Mixer::ApplyTrackGains(bool apply)
|
||||
@ -461,7 +440,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
else
|
||||
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
|
||||
|
||||
track->GetEnvelopeValues(mEnvValues,
|
||||
track->GetEnvelopeValues(mEnvValues.get(),
|
||||
getLen,
|
||||
(*pos - (getLen- 1)).as_double() / trackRate);
|
||||
*pos -= getLen;
|
||||
@ -473,7 +452,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
else
|
||||
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
|
||||
|
||||
track->GetEnvelopeValues(mEnvValues,
|
||||
track->GetEnvelopeValues(mEnvValues.get(),
|
||||
getLen,
|
||||
(*pos).as_double() / trackRate);
|
||||
|
||||
@ -532,7 +511,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < mNumChannels; c++) {
|
||||
for (size_t c = 0; c < mNumChannels; c++) {
|
||||
if (mApplyTrackGains) {
|
||||
mGains[c] = track->GetChannelGain(c);
|
||||
}
|
||||
@ -543,9 +522,9 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
|
||||
MixBuffers(mNumChannels,
|
||||
channelFlags,
|
||||
mGains,
|
||||
(samplePtr)mFloatBuffer,
|
||||
mTemp,
|
||||
mGains.get(),
|
||||
(samplePtr)mFloatBuffer.get(),
|
||||
mTemp.get(),
|
||||
out,
|
||||
mInterleaved);
|
||||
|
||||
@ -557,7 +536,6 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
|
||||
{
|
||||
const WaveTrack *const track = cache.GetTrack();
|
||||
auto slen = mMaxOut;
|
||||
int c;
|
||||
const double t = ( *pos ).as_double() / track->GetRate();
|
||||
const double trackEndTime = track->GetEndTime();
|
||||
const double trackStartTime = track->GetStartTime();
|
||||
@ -578,37 +556,37 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
|
||||
if (backwards) {
|
||||
auto results = cache.Get(floatSample, *pos - (slen - 1), slen);
|
||||
if (results)
|
||||
memcpy(mFloatBuffer, results, sizeof(float) * slen);
|
||||
memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
|
||||
else
|
||||
memset(mFloatBuffer, 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate);
|
||||
memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues.get(), slen, t - (slen - 1) / mRate);
|
||||
for(decltype(slen) i = 0; i < slen; i++)
|
||||
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
|
||||
ReverseSamples((samplePtr)mFloatBuffer, floatSample, 0, slen);
|
||||
ReverseSamples((samplePtr)mFloatBuffer.get(), floatSample, 0, slen);
|
||||
|
||||
*pos -= slen;
|
||||
}
|
||||
else {
|
||||
auto results = cache.Get(floatSample, *pos, slen);
|
||||
if (results)
|
||||
memcpy(mFloatBuffer, results, sizeof(float) * slen);
|
||||
memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
|
||||
else
|
||||
memset(mFloatBuffer, 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues, slen, t);
|
||||
memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues.get(), slen, t);
|
||||
for(decltype(slen) i = 0; i < slen; i++)
|
||||
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
|
||||
|
||||
*pos += slen;
|
||||
}
|
||||
|
||||
for(c=0; c<mNumChannels; c++)
|
||||
for(size_t c=0; c<mNumChannels; c++)
|
||||
if (mApplyTrackGains)
|
||||
mGains[c] = track->GetChannelGain(c);
|
||||
else
|
||||
mGains[c] = 1.0;
|
||||
|
||||
MixBuffers(mNumChannels, channelFlags, mGains,
|
||||
(samplePtr)mFloatBuffer, mTemp, slen, mInterleaved);
|
||||
MixBuffers(mNumChannels, channelFlags, mGains.get(),
|
||||
(samplePtr)mFloatBuffer.get(), mTemp.get(), slen, mInterleaved);
|
||||
|
||||
return slen;
|
||||
}
|
||||
@ -620,28 +598,27 @@ size_t Mixer::Process(size_t maxToProcess)
|
||||
//if (mT >= mT1)
|
||||
// return 0;
|
||||
|
||||
int i, j;
|
||||
decltype(Process(0)) maxOut = 0;
|
||||
int *channelFlags = new int[mNumChannels];
|
||||
ArrayOf<int> channelFlags{ mNumChannels };
|
||||
|
||||
mMaxOut = maxToProcess;
|
||||
|
||||
Clear();
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
const WaveTrack *const track = mInputTrack[i].GetTrack();
|
||||
for(j=0; j<mNumChannels; j++)
|
||||
for(size_t j=0; j<mNumChannels; j++)
|
||||
channelFlags[j] = 0;
|
||||
|
||||
if( mMixerSpec ) {
|
||||
//ignore left and right when downmixing is not required
|
||||
for( j = 0; j < mNumChannels; j++ )
|
||||
for(size_t j = 0; j < mNumChannels; j++ )
|
||||
channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
switch(track->GetChannel()) {
|
||||
case Track::MonoChannel:
|
||||
default:
|
||||
for(j=0; j<mNumChannels; j++)
|
||||
for(size_t j=0; j<mNumChannels; j++)
|
||||
channelFlags[j] = 1;
|
||||
break;
|
||||
case Track::LeftChannel:
|
||||
@ -657,12 +634,12 @@ size_t Mixer::Process(size_t maxToProcess)
|
||||
}
|
||||
if (mbVariableRates || track->GetRate() != mRate)
|
||||
maxOut = std::max(maxOut,
|
||||
MixVariableRates(channelFlags, mInputTrack[i],
|
||||
&mSamplePos[i], mSampleQueue[i],
|
||||
&mQueueStart[i], &mQueueLen[i], mResample[i]));
|
||||
MixVariableRates(channelFlags.get(), mInputTrack[i],
|
||||
&mSamplePos[i], mSampleQueue[i].get(),
|
||||
&mQueueStart[i], &mQueueLen[i], mResample[i].get()));
|
||||
else
|
||||
maxOut = std::max(maxOut,
|
||||
MixSameRate(channelFlags, mInputTrack[i], &mSamplePos[i]));
|
||||
MixSameRate(channelFlags.get(), mInputTrack[i], &mSamplePos[i]));
|
||||
|
||||
double t = mSamplePos[i].as_double() / (double)track->GetRate();
|
||||
if (mT0 > mT1)
|
||||
@ -673,7 +650,7 @@ size_t Mixer::Process(size_t maxToProcess)
|
||||
mTime = std::min(std::max(t, mTime), mT1);
|
||||
}
|
||||
if(mInterleaved) {
|
||||
for(int c=0; c<mNumChannels; c++) {
|
||||
for(size_t c=0; c<mNumChannels; c++) {
|
||||
CopySamples(mTemp[0].ptr() + (c * SAMPLE_SIZE(floatSample)),
|
||||
floatSample,
|
||||
mBuffer[0].ptr() + (c * SAMPLE_SIZE(mFormat)),
|
||||
@ -685,7 +662,7 @@ size_t Mixer::Process(size_t maxToProcess)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int c=0; c<mNumBuffers; c++) {
|
||||
for(size_t c=0; c<mNumBuffers; c++) {
|
||||
CopySamples(mTemp[c].ptr(),
|
||||
floatSample,
|
||||
mBuffer[c].ptr(),
|
||||
@ -697,8 +674,6 @@ size_t Mixer::Process(size_t maxToProcess)
|
||||
// MB: this doesn't take warping into account, replaced with code based on mSamplePos
|
||||
//mT += (maxOut / mRate);
|
||||
|
||||
delete [] channelFlags;
|
||||
|
||||
return maxOut;
|
||||
}
|
||||
|
||||
@ -719,14 +694,12 @@ double Mixer::MixGetCurrentTime()
|
||||
|
||||
void Mixer::Restart()
|
||||
{
|
||||
int i;
|
||||
|
||||
mTime = mT0;
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++)
|
||||
for(size_t i=0; i<mNumInputTracks; i++)
|
||||
mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mT0);
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
}
|
||||
@ -734,8 +707,6 @@ void Mixer::Restart()
|
||||
|
||||
void Mixer::Reposition(double t)
|
||||
{
|
||||
int i;
|
||||
|
||||
mTime = t;
|
||||
const bool backwards = (mT1 < mT0);
|
||||
if (backwards)
|
||||
@ -743,7 +714,7 @@ void Mixer::Reposition(double t)
|
||||
else
|
||||
mTime = std::max(mT0, (std::min(mT1, mTime)));
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mTime);
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
@ -789,22 +760,11 @@ MixerSpec::MixerSpec( const MixerSpec &mixerSpec )
|
||||
|
||||
void MixerSpec::Alloc()
|
||||
{
|
||||
mMap = new bool*[ mNumTracks ];
|
||||
for( int i = 0; i < mNumTracks; i++ )
|
||||
mMap[ i ] = new bool[ mMaxNumChannels ];
|
||||
mMap.reinit(mNumTracks, mMaxNumChannels);
|
||||
}
|
||||
|
||||
MixerSpec::~MixerSpec()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void MixerSpec::Free()
|
||||
{
|
||||
for( int i = 0; i < mNumTracks; i++ )
|
||||
delete[] mMap[ i ];
|
||||
|
||||
delete[] mMap;
|
||||
}
|
||||
|
||||
bool MixerSpec::SetNumChannels( unsigned newNumChannels )
|
||||
@ -830,8 +790,6 @@ bool MixerSpec::SetNumChannels( unsigned newNumChannels )
|
||||
|
||||
MixerSpec& MixerSpec::operator=( const MixerSpec &mixerSpec )
|
||||
{
|
||||
Free();
|
||||
|
||||
mNumTracks = mixerSpec.mNumTracks;
|
||||
mNumChannels = mixerSpec.mNumChannels;
|
||||
mMaxNumChannels = mixerSpec.mMaxNumChannels;
|
||||
|
30
src/Mix.h
30
src/Mix.h
@ -51,10 +51,9 @@ class AUDACITY_DLL_API MixerSpec
|
||||
unsigned mNumTracks, mNumChannels, mMaxNumChannels;
|
||||
|
||||
void Alloc();
|
||||
void Free();
|
||||
|
||||
public:
|
||||
bool **mMap;
|
||||
public:
|
||||
ArraysOf<bool> mMap;
|
||||
|
||||
MixerSpec( unsigned numTracks, unsigned maxNumChannels );
|
||||
MixerSpec( const MixerSpec &mixerSpec );
|
||||
@ -150,38 +149,37 @@ class AUDACITY_DLL_API Mixer {
|
||||
Resample * pResample);
|
||||
|
||||
private:
|
||||
// Input
|
||||
int mNumInputTracks;
|
||||
WaveTrackCache *mInputTrack;
|
||||
|
||||
// Input
|
||||
size_t mNumInputTracks;
|
||||
ArrayOf<WaveTrackCache> mInputTrack;
|
||||
bool mbVariableRates;
|
||||
const TimeTrack *mTimeTrack;
|
||||
sampleCount *mSamplePos;
|
||||
ArrayOf<sampleCount> mSamplePos;
|
||||
bool mApplyTrackGains;
|
||||
float *mGains;
|
||||
double *mEnvValues;
|
||||
Doubles mEnvValues;
|
||||
double mT0; // Start time
|
||||
double mT1; // Stop time (none if mT0==mT1)
|
||||
double mTime; // Current time (renamed from mT to mTime for consistency with AudioIO - mT represented warped time there)
|
||||
Resample **mResample;
|
||||
float **mSampleQueue;
|
||||
int *mQueueStart;
|
||||
int *mQueueLen;
|
||||
ArrayOf<std::unique_ptr<Resample>> mResample;
|
||||
size_t mQueueMaxLen;
|
||||
FloatBuffers mSampleQueue;
|
||||
ArrayOf<int> mQueueStart;
|
||||
ArrayOf<int> mQueueLen;
|
||||
size_t mProcessLen;
|
||||
MixerSpec *mMixerSpec;
|
||||
|
||||
// Output
|
||||
size_t mMaxOut;
|
||||
unsigned mNumChannels;
|
||||
Floats mGains;
|
||||
unsigned mNumBuffers;
|
||||
size_t mBufferSize;
|
||||
size_t mInterleavedBufferSize;
|
||||
sampleFormat mFormat;
|
||||
bool mInterleaved;
|
||||
SampleBuffer *mBuffer;
|
||||
SampleBuffer *mTemp;
|
||||
float *mFloatBuffer;
|
||||
ArrayOf<SampleBuffer> mBuffer, mTemp;
|
||||
Floats mFloatBuffer;
|
||||
double mRate;
|
||||
double mSpeed;
|
||||
bool mHighQuality;
|
||||
|
@ -622,7 +622,15 @@ class AUDACITY_DLL_API WaveTrack final : public Track {
|
||||
// one block file).
|
||||
class WaveTrackCache {
|
||||
public:
|
||||
explicit WaveTrackCache(const WaveTrack *pTrack = 0)
|
||||
WaveTrackCache()
|
||||
: mPTrack(0)
|
||||
, mBufferSize(0)
|
||||
, mOverlapBuffer()
|
||||
, mNValidBuffers(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit WaveTrackCache(const WaveTrack *pTrack)
|
||||
: mPTrack(0)
|
||||
, mBufferSize(0)
|
||||
, mOverlapBuffer()
|
||||
|
Loading…
x
Reference in New Issue
Block a user