mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-08 22:23:59 +01:00
Bug1501: Fix bad_alloc crash for some effects with extreme inputs
This commit is contained in:
@@ -87,7 +87,16 @@ bool EffectEcho::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames
|
|||||||
|
|
||||||
histPos = 0;
|
histPos = 0;
|
||||||
histLen = (sampleCount) (mSampleRate * delay);
|
histLen = (sampleCount) (mSampleRate * delay);
|
||||||
history = new float[histLen];
|
|
||||||
|
// Guard against extreme delay values input by the user
|
||||||
|
try {
|
||||||
|
history = new float[histLen];
|
||||||
|
}
|
||||||
|
catch ( const std::bad_alloc& ) {
|
||||||
|
wxMessageBox(_("Requested value exceeds memory capacity."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
memset(history, 0, sizeof(float) * histLen);
|
memset(history, 0, sizeof(float) * histLen);
|
||||||
|
|
||||||
return history != NULL;
|
return history != NULL;
|
||||||
|
|||||||
@@ -223,26 +223,47 @@ void EffectPaulstretch::OnText(wxCommandEvent & WXUNUSED(evt))
|
|||||||
EnableApply(mUIParent->TransferDataFromWindow());
|
EnableApply(mUIParent->TransferDataFromWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
int EffectPaulstretch::GetBufferSize(double rate)
|
size_t EffectPaulstretch::GetBufferSize(double rate)
|
||||||
{
|
{
|
||||||
// Audacity's fft requires a power of 2
|
// Audacity's fft requires a power of 2
|
||||||
float tmp = rate * mTime_resolution / 2.0;
|
float tmp = rate * mTime_resolution / 2.0;
|
||||||
tmp = log(tmp) / log(2.0);
|
tmp = log(tmp) / log(2.0);
|
||||||
tmp = pow(2.0, floor(tmp + 0.5));
|
tmp = pow(2.0, floor(tmp + 0.5));
|
||||||
|
|
||||||
return std::max<int>((int)tmp, 128);
|
auto stmp = size_t(tmp);
|
||||||
|
if (stmp != tmp)
|
||||||
|
// overflow
|
||||||
|
return 0;
|
||||||
|
if (stmp >= 2 * stmp)
|
||||||
|
// overflow
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return std::max<size_t>(stmp, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int count)
|
bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int count)
|
||||||
{
|
{
|
||||||
int stretch_buf_size = GetBufferSize(track->GetRate());
|
auto badAllocMessage = _("Requested value exceeds memory capacity.");
|
||||||
|
|
||||||
|
const auto stretch_buf_size = GetBufferSize(track->GetRate());
|
||||||
|
if (stretch_buf_size == 0) {
|
||||||
|
::wxMessageBox( badAllocMessage );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double amount = this->mAmount;
|
double amount = this->mAmount;
|
||||||
|
|
||||||
auto start = track->TimeToLongSamples(t0);
|
auto start = track->TimeToLongSamples(t0);
|
||||||
auto end = track->TimeToLongSamples(t1);
|
auto end = track->TimeToLongSamples(t1);
|
||||||
auto len = end - start;
|
auto len = end - start;
|
||||||
|
|
||||||
int minDuration = stretch_buf_size * 2 + 1;
|
const auto minDuration = stretch_buf_size * 2 + 1;
|
||||||
|
if (minDuration < stretch_buf_size) {
|
||||||
|
// overflow!
|
||||||
|
::wxMessageBox( badAllocMessage );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (len < minDuration){ //error because the selection is too short
|
if (len < minDuration){ //error because the selection is too short
|
||||||
|
|
||||||
float maxTimeRes = log(len) / log(2.0);
|
float maxTimeRes = log(len) / log(2.0);
|
||||||
@@ -290,69 +311,78 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun
|
|||||||
|
|
||||||
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate());
|
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate());
|
||||||
|
|
||||||
PaulStretch stretch(amount,stretch_buf_size,track->GetRate());
|
try {
|
||||||
|
// This encloses all the allocations of buffers, including those in
|
||||||
|
// the constructor of the PaulStretch object
|
||||||
|
|
||||||
auto nget = stretch.get_nsamples_for_fill();
|
PaulStretch stretch(amount,stretch_buf_size,track->GetRate());
|
||||||
|
|
||||||
int bufsize=stretch.poolsize;
|
auto nget = stretch.get_nsamples_for_fill();
|
||||||
float *buffer0=new float[bufsize];
|
|
||||||
float *bufferptr0=buffer0;
|
|
||||||
bool first_time=true;
|
|
||||||
|
|
||||||
int fade_len=100;
|
int bufsize=stretch.poolsize;
|
||||||
if (fade_len>(bufsize/2-1)) fade_len=bufsize/2-1;
|
float *buffer0=new float[bufsize];
|
||||||
float *fade_track_smps=new float[fade_len];
|
float *bufferptr0=buffer0;
|
||||||
decltype(len) s=0;
|
bool first_time=true;
|
||||||
bool cancelled=false;
|
|
||||||
|
|
||||||
while (s<len){
|
int fade_len=100;
|
||||||
track->Get((samplePtr)bufferptr0,floatSample,start+s,nget);
|
if (fade_len>(bufsize/2-1)) fade_len=bufsize/2-1;
|
||||||
stretch.process(buffer0,nget);
|
float *fade_track_smps=new float[fade_len];
|
||||||
|
decltype(len) s=0;
|
||||||
|
bool cancelled=false;
|
||||||
|
|
||||||
if (first_time) {
|
while (s<len){
|
||||||
stretch.process(buffer0,0);
|
track->Get((samplePtr)bufferptr0,floatSample,start+s,nget);
|
||||||
};
|
stretch.process(buffer0,nget);
|
||||||
|
|
||||||
s+=nget;
|
if (first_time) {
|
||||||
|
stretch.process(buffer0,0);
|
||||||
if (first_time){//blend the the start of the selection
|
|
||||||
track->Get((samplePtr)fade_track_smps,floatSample,start,fade_len);
|
|
||||||
first_time=false;
|
|
||||||
for (int i=0;i<fade_len;i++){
|
|
||||||
float fi=(float)i/(float)fade_len;
|
|
||||||
stretch.out_buf[i]=stretch.out_buf[i]*fi+(1.0-fi)*fade_track_smps[i];
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
if (s>=len){//blend the end of the selection
|
s+=nget;
|
||||||
track->Get((samplePtr)fade_track_smps,floatSample,end-fade_len,fade_len);
|
|
||||||
for (int i=0;i<fade_len;i++){
|
if (first_time){//blend the the start of the selection
|
||||||
float fi=(float)i/(float)fade_len;
|
track->Get((samplePtr)fade_track_smps,floatSample,start,fade_len);
|
||||||
int i2=bufsize/2-1-i;
|
first_time=false;
|
||||||
stretch.out_buf[i2]=stretch.out_buf[i2]*fi+(1.0-fi)*fade_track_smps[fade_len-1-i];
|
for (int i=0;i<fade_len;i++){
|
||||||
|
float fi=(float)i/(float)fade_len;
|
||||||
|
stretch.out_buf[i]=stretch.out_buf[i]*fi+(1.0-fi)*fade_track_smps[i];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (s>=len){//blend the end of the selection
|
||||||
|
track->Get((samplePtr)fade_track_smps,floatSample,end-fade_len,fade_len);
|
||||||
|
for (int i=0;i<fade_len;i++){
|
||||||
|
float fi=(float)i/(float)fade_len;
|
||||||
|
int i2=bufsize/2-1-i;
|
||||||
|
stretch.out_buf[i2]=stretch.out_buf[i2]*fi+(1.0-fi)*fade_track_smps[fade_len-1-i];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputTrack->Append((samplePtr)stretch.out_buf,floatSample,stretch.out_bufsize);
|
||||||
|
|
||||||
|
nget=stretch.get_nsamples();
|
||||||
|
if (TrackProgress(count, (s / (double) len))) {
|
||||||
|
cancelled=true;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputTrack->Append((samplePtr)stretch.out_buf,floatSample,stretch.out_bufsize);
|
delete [] fade_track_smps;
|
||||||
|
outputTrack->Flush();
|
||||||
|
|
||||||
nget=stretch.get_nsamples();
|
track->Clear(t0,t1);
|
||||||
if (TrackProgress(count, (s / (double) len))) {
|
bool success = track->Paste(t0, outputTrack.get());
|
||||||
cancelled=true;
|
if (!cancelled && success){
|
||||||
break;
|
m_t1 = mT0 + outputTrack->GetEndTime();
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
delete []buffer0;
|
||||||
delete [] fade_track_smps;
|
|
||||||
outputTrack->Flush();
|
return !cancelled;
|
||||||
|
}
|
||||||
track->Clear(t0,t1);
|
catch ( const std::bad_alloc& ) {
|
||||||
bool success = track->Paste(t0, outputTrack.get());
|
::wxMessageBox( badAllocMessage );
|
||||||
if (!cancelled && success){
|
return false;
|
||||||
m_t1 = mT0 + outputTrack->GetEndTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete []buffer0;
|
|
||||||
|
|
||||||
return !cancelled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ private:
|
|||||||
// EffectPaulstretch implementation
|
// EffectPaulstretch implementation
|
||||||
|
|
||||||
void OnText(wxCommandEvent & evt);
|
void OnText(wxCommandEvent & evt);
|
||||||
int GetBufferSize(double rate);
|
size_t GetBufferSize(double rate);
|
||||||
|
|
||||||
bool ProcessOne(WaveTrack *track, double t0, double t1, int count);
|
bool ProcessOne(WaveTrack *track, double t0, double t1, int count);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user