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

Fix memory leak from alloca fix

* Rework `alloca` fix to use new helper class for buffer allocations.
* Add missing `delete[]` for cleanup of the temporary playback buffer.

Signed-off-by: Emily Mabrey <emabrey@tenacityaudio.org>
Reference-to: https://github.com/tenacityteam/tenacity/issues/416
Reference-to: https://github.com/tenacityteam/tenacity/pull/412
Helped-by: Paul Licameli
This commit is contained in:
Emily Mabrey 2021-07-31 01:40:06 -04:00 committed by GitHub
parent cabd66d8e7
commit 3e4a2cf316
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 26 deletions

View File

@ -464,6 +464,7 @@ time warp info and AudioIOListener and whether the playback is looped.
#include "DBConnection.h"
#include "ProjectFileIO.h"
#include "WaveTrack.h"
#include "AudioIOBufferHelper.h"
#include "effects/RealtimeEffectManager.h"
#include "prefs/QualitySettings.h"
@ -3843,14 +3844,7 @@ bool AudioIoCallback::FillOutputBuffers(
}
// ------ MEMORY ALLOCATION ----------------------
// These are small structures.
auto chans = new WaveTrack * [numPlaybackChannels];
auto tempBufs = new float* [numPlaybackChannels];
// And these are larger structures....
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
tempBufs[c] = new float[framesPerBuffer];
}
std::unique_ptr<AudioIOBufferHelper> bufHelper = std::make_unique<AudioIOBufferHelper>(numPlaybackChannels, framesPerBuffer);
// ------ End of MEMORY ALLOCATION ---------------
auto & em = RealtimeEffectManager::Get();
@ -3882,7 +3876,7 @@ bool AudioIoCallback::FillOutputBuffers(
for (unsigned t = 0; t < numPlaybackTracks; t++)
{
WaveTrack *vt = mPlaybackTracks[t].get();
chans[chanCnt] = vt;
bufHelper.get()->chans[chanCnt] = vt;
// TODO: more-than-two-channels
auto nextTrack =
@ -3901,7 +3895,7 @@ bool AudioIoCallback::FillOutputBuffers(
// IF mono THEN clear 'the other' channel.
if ( lastChannel && (numPlaybackChannels>1)) {
// TODO: more-than-two-channels
memset(tempBufs[1], 0, framesPerBuffer * sizeof(float));
memset(bufHelper.get()->tempBufs[1], 0, framesPerBuffer * sizeof(float));
}
drop = TrackShouldBeSilent( *vt );
dropQuickly = drop;
@ -3920,7 +3914,7 @@ bool AudioIoCallback::FillOutputBuffers(
}
else
{
len = mPlaybackBuffers[t]->Get((samplePtr)tempBufs[chanCnt],
len = mPlaybackBuffers[t]->Get((samplePtr)bufHelper.get()->tempBufs[chanCnt],
floatSample,
toGet);
// wxASSERT( len == toGet );
@ -3931,7 +3925,7 @@ bool AudioIoCallback::FillOutputBuffers(
// real-time demand in this thread (see bug 1932). We
// must supply something to the sound card, so pad it with
// zeroes and not random garbage.
memset((void*)&tempBufs[chanCnt][len], 0,
memset((void*)&bufHelper.get()->tempBufs[chanCnt][len], 0,
(framesPerBuffer - len) * sizeof(float));
chanCnt++;
}
@ -3952,7 +3946,7 @@ bool AudioIoCallback::FillOutputBuffers(
len = mMaxFramesOutput;
if( !dropQuickly && selected )
len = em.RealtimeProcess(group, chanCnt, tempBufs, len);
len = em.RealtimeProcess(group, chanCnt, bufHelper.get()->tempBufs, len);
group++;
CallbackCheckCompletion(mCallbackReturn, len);
@ -3971,17 +3965,13 @@ bool AudioIoCallback::FillOutputBuffers(
// For example mono channels output to both left and right output channels.
if (len > 0) for (int c = 0; c < chanCnt; c++)
{
vt = chans[c];
vt = bufHelper.get()->chans[c];
if (vt->GetChannelIgnoringPan() == Track::LeftChannel ||
vt->GetChannelIgnoringPan() == Track::MonoChannel )
AddToOutputChannel( 0, outputMeterFloats, outputFloats,
tempBufs[c], drop, len, vt);
if (vt->GetChannelIgnoringPan() == Track::LeftChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel )
AddToOutputChannel( 0, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
if (vt->GetChannelIgnoringPan() == Track::RightChannel ||
vt->GetChannelIgnoringPan() == Track::MonoChannel )
AddToOutputChannel( 1, outputMeterFloats, outputFloats,
tempBufs[c], drop, len, vt);
if (vt->GetChannelIgnoringPan() == Track::RightChannel || vt->GetChannelIgnoringPan() == Track::MonoChannel )
AddToOutputChannel( 1, outputMeterFloats, outputFloats, bufHelper.get()->tempBufs[c], drop, len, vt);
}
chanCnt = 0;
@ -4002,8 +3992,6 @@ bool AudioIoCallback::FillOutputBuffers(
if (outputMeterFloats != outputFloats)
ClampBuffer( outputMeterFloats, framesPerBuffer*numPlaybackChannels );
delete[] chans;
delete[] tempBufs;
return false;
}

View File

@ -580,8 +580,7 @@ protected:
PlaybackSchedule mPlaybackSchedule;
};
class AUDACITY_DLL_API AudioIO final
: public AudioIoCallback
class AUDACITY_DLL_API AudioIO final : public AudioIoCallback
{
AudioIO();

42
src/AudioIOBufferHelper.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef AUDIOIO_BUFFER_HELPER_H
#define AUDIOIO_BUFFER_HELPER_H
#include "AudioIO.h"
#include "../libraries/lib-utility/MemoryX.h"
class AudioIOBufferHelper
{
private:
unsigned int numPlaybackChannels;
unsigned long framesPerBuffer;
public:
WaveTrack** chans;
float** tempBufs;
AudioIOBufferHelper(const unsigned int numPlaybackChannels, const unsigned long framesPerBuffer) {
this->numPlaybackChannels = numPlaybackChannels;
this->framesPerBuffer = framesPerBuffer;
this->chans = safenew WaveTrack * [numPlaybackChannels];
this->tempBufs = safenew float* [numPlaybackChannels];
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
tempBufs[c] = safenew float[framesPerBuffer];
}
}
~AudioIOBufferHelper() {
for (unsigned int c = 0; c < numPlaybackChannels; c++) {
delete[] tempBufs[c];
}
delete[] tempBufs;
delete[] chans;
}
};
#endif

View File

@ -100,6 +100,7 @@ list( APPEND SOURCES
AudioIO.h
AudioIOBase.cpp
AudioIOBase.h
AudioIOBufferHelper.h
AudioIOListener.h
AutoRecoveryDialog.cpp
AutoRecoveryDialog.h