Remove naked new[] in: builtin effects
This commit is contained in:
parent
f858d97352
commit
6ca89c28ff
|
@ -50,8 +50,8 @@ Param( MaximumPause, double, XO("MaximumPause"), 1.0, 0.0, DB
|
|||
* Common constants
|
||||
*/
|
||||
|
||||
enum : size_t { kBufSize = 131072 }; // number of samples to process at once
|
||||
enum : size_t { kRMSWindowSize = 100 }; // samples in circular RMS window buffer
|
||||
static const size_t kBufSize = 131072u; // number of samples to process at once
|
||||
static const size_t kRMSWindowSize = 100u; // samples in circular RMS window buffer
|
||||
|
||||
/*
|
||||
* A auto duck region and an array of auto duck regions
|
||||
|
@ -286,103 +286,99 @@ bool EffectAutoDuck::Process()
|
|||
|
||||
int rmsPos = 0;
|
||||
float rmsSum = 0;
|
||||
float *rmsWindow = new float[kRMSWindowSize];
|
||||
for (size_t i = 0; i < kRMSWindowSize; i++)
|
||||
rmsWindow[i] = 0;
|
||||
|
||||
float *buf = new float[kBufSize];
|
||||
|
||||
bool inDuckRegion = false;
|
||||
|
||||
// initialize the following two variables to prevent compiler warning
|
||||
double duckRegionStart = 0;
|
||||
sampleCount curSamplesPause = 0;
|
||||
|
||||
// to make the progress bar appear more natural, we first look for all
|
||||
// duck regions and apply them all at once afterwards
|
||||
AutoDuckRegionArray regions;
|
||||
auto pos = start;
|
||||
|
||||
while (pos < end)
|
||||
bool inDuckRegion = false;
|
||||
{
|
||||
const auto len = limitSampleBufferSize( kBufSize, end - pos );
|
||||
Floats rmsWindow{ kRMSWindowSize, true };
|
||||
|
||||
mControlTrack->Get((samplePtr)buf, floatSample, pos, len);
|
||||
Floats buf{ kBufSize };
|
||||
|
||||
for (auto i = pos; i < pos + len; i++)
|
||||
// initialize the following two variables to prevent compiler warning
|
||||
double duckRegionStart = 0;
|
||||
sampleCount curSamplesPause = 0;
|
||||
|
||||
auto pos = start;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
rmsSum -= rmsWindow[rmsPos];
|
||||
// i - pos is bounded by len:
|
||||
auto index = ( i - pos ).as_size_t();
|
||||
rmsWindow[rmsPos] = buf[ index ] * buf[ index ];
|
||||
rmsSum += rmsWindow[rmsPos];
|
||||
rmsPos = (rmsPos + 1) % kRMSWindowSize;
|
||||
const auto len = limitSampleBufferSize( kBufSize, end - pos );
|
||||
|
||||
mControlTrack->Get((samplePtr)buf.get(), floatSample, pos, len);
|
||||
|
||||
bool thresholdExceeded = rmsSum > threshold;
|
||||
|
||||
if (thresholdExceeded)
|
||||
for (auto i = pos; i < pos + len; i++)
|
||||
{
|
||||
// everytime the threshold is exceeded, reset our count for
|
||||
// the number of pause samples
|
||||
curSamplesPause = 0;
|
||||
rmsSum -= rmsWindow[rmsPos];
|
||||
// i - pos is bounded by len:
|
||||
auto index = ( i - pos ).as_size_t();
|
||||
rmsWindow[rmsPos] = buf[ index ] * buf[ index ];
|
||||
rmsSum += rmsWindow[rmsPos];
|
||||
rmsPos = (rmsPos + 1) % kRMSWindowSize;
|
||||
|
||||
if (!inDuckRegion)
|
||||
bool thresholdExceeded = rmsSum > threshold;
|
||||
|
||||
if (thresholdExceeded)
|
||||
{
|
||||
// the threshold has been exceeded for the first time, so
|
||||
// let the duck region begin here
|
||||
inDuckRegion = true;
|
||||
duckRegionStart = mControlTrack->LongSamplesToTime(i);
|
||||
// everytime the threshold is exceeded, reset our count for
|
||||
// the number of pause samples
|
||||
curSamplesPause = 0;
|
||||
|
||||
if (!inDuckRegion)
|
||||
{
|
||||
// the threshold has been exceeded for the first time, so
|
||||
// let the duck region begin here
|
||||
inDuckRegion = true;
|
||||
duckRegionStart = mControlTrack->LongSamplesToTime(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!thresholdExceeded && inDuckRegion)
|
||||
{
|
||||
// the threshold has not been exceeded and we are in a duck
|
||||
// region, but only fade in if the maximum pause has been
|
||||
// exceeded
|
||||
curSamplesPause += 1;
|
||||
|
||||
if (curSamplesPause >= minSamplesPause)
|
||||
{
|
||||
// do the actual duck fade and reset all values
|
||||
double duckRegionEnd =
|
||||
mControlTrack->LongSamplesToTime(i - curSamplesPause);
|
||||
|
||||
regions.Add(AutoDuckRegion(
|
||||
duckRegionStart - mOuterFadeDownLen,
|
||||
duckRegionEnd + mOuterFadeUpLen));
|
||||
|
||||
inDuckRegion = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!thresholdExceeded && inDuckRegion)
|
||||
{
|
||||
// the threshold has not been exceeded and we are in a duck
|
||||
// region, but only fade in if the maximum pause has been
|
||||
// exceeded
|
||||
curSamplesPause += 1;
|
||||
pos += len;
|
||||
|
||||
if (curSamplesPause >= minSamplesPause)
|
||||
{
|
||||
// do the actual duck fade and reset all values
|
||||
double duckRegionEnd =
|
||||
mControlTrack->LongSamplesToTime(i - curSamplesPause);
|
||||
|
||||
regions.Add(AutoDuckRegion(
|
||||
duckRegionStart - mOuterFadeDownLen,
|
||||
duckRegionEnd + mOuterFadeUpLen));
|
||||
|
||||
inDuckRegion = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += len;
|
||||
|
||||
if (TotalProgress(
|
||||
if (TotalProgress(
|
||||
(pos - start).as_double() /
|
||||
(end - start).as_double() /
|
||||
(GetNumWaveTracks() + 1)
|
||||
))
|
||||
))
|
||||
{
|
||||
cancel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// apply last duck fade, if any
|
||||
if (inDuckRegion)
|
||||
{
|
||||
cancel = true;
|
||||
break;
|
||||
double duckRegionEnd =
|
||||
mControlTrack->LongSamplesToTime(end - curSamplesPause);
|
||||
regions.Add(AutoDuckRegion(
|
||||
duckRegionStart - mOuterFadeDownLen,
|
||||
duckRegionEnd + mOuterFadeUpLen));
|
||||
}
|
||||
}
|
||||
|
||||
// apply last duck fade, if any
|
||||
if (inDuckRegion)
|
||||
{
|
||||
double duckRegionEnd =
|
||||
mControlTrack->LongSamplesToTime(end - curSamplesPause);
|
||||
regions.Add(AutoDuckRegion(
|
||||
duckRegionStart - mOuterFadeDownLen,
|
||||
duckRegionEnd + mOuterFadeUpLen));
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
delete[] rmsWindow;
|
||||
|
||||
if (!cancel)
|
||||
{
|
||||
CopyInputTracks(); // Set up mOutputTracks.
|
||||
|
@ -518,7 +514,7 @@ bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t,
|
|||
auto start = t->TimeToLongSamples(t0);
|
||||
auto end = t->TimeToLongSamples(t1);
|
||||
|
||||
float *buf = new float[kBufSize];
|
||||
Floats buf{ kBufSize };
|
||||
auto pos = start;
|
||||
|
||||
auto fadeDownSamples = t->TimeToLongSamples(
|
||||
|
@ -538,7 +534,7 @@ bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t,
|
|||
{
|
||||
const auto len = limitSampleBufferSize( kBufSize, end - pos );
|
||||
|
||||
t->Get((samplePtr)buf, floatSample, pos, len);
|
||||
t->Get((samplePtr)buf.get(), floatSample, pos, len);
|
||||
|
||||
for (auto i = pos; i < pos + len; i++)
|
||||
{
|
||||
|
@ -557,7 +553,7 @@ bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t,
|
|||
buf[ ( i - pos ).as_size_t() ] *= DB_TO_LINEAR(gain);
|
||||
}
|
||||
|
||||
t->Set((samplePtr)buf, floatSample, pos, len);
|
||||
t->Set((samplePtr)buf.get(), floatSample, pos, len);
|
||||
|
||||
pos += len;
|
||||
|
||||
|
@ -571,7 +567,6 @@ bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t,
|
|||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
return cancel;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#ifndef __BIQUAD_H__
|
||||
#define __BIQUAD_H__
|
||||
typedef struct {
|
||||
float* pfIn;
|
||||
float* pfOut;
|
||||
float fNumerCoeffs [3]; // B0 B1 B2
|
||||
float fDenomCoeffs [2]; // A1 A2
|
||||
float fPrevIn;
|
||||
float fPrevPrevIn;
|
||||
float fPrevOut;
|
||||
float fPrevPrevOut;
|
||||
float* pfIn {};
|
||||
float* pfOut {};
|
||||
float fNumerCoeffs [3] { 1.0f, 0.0f, 0.0f }; // B0 B1 B2
|
||||
float fDenomCoeffs [2] { 0.0f, 0.0f }; // A1 A2
|
||||
float fPrevIn {};
|
||||
float fPrevPrevIn {};
|
||||
float fPrevOut {};
|
||||
float fPrevPrevOut {};
|
||||
} BiquadStruct;
|
||||
void Biquad_Process (BiquadStruct* pBQ, int iNumSamples);
|
||||
void ComplexDiv (float fNumerR, float fNumerI, float fDenomR, float fDenomI, float* pfQuotientR, float* pfQuotientI);
|
||||
|
|
|
@ -420,22 +420,15 @@ void EffectChangePitch::DeduceFrequencies()
|
|||
auto start = track->TimeToLongSamples(t0);
|
||||
|
||||
auto analyzeSize = windowSize * numWindows;
|
||||
float * buffer;
|
||||
buffer = new float[analyzeSize];
|
||||
Floats buffer{ analyzeSize };
|
||||
|
||||
float * freq;
|
||||
freq = new float[windowSize / 2];
|
||||
Floats freq{ windowSize / 2 };
|
||||
Floats freqa{ windowSize / 2, true };
|
||||
|
||||
float * freqa;
|
||||
freqa = new float[windowSize / 2];
|
||||
|
||||
for(size_t j = 0; j < windowSize / 2; j++)
|
||||
freqa[j] = 0;
|
||||
|
||||
track->Get((samplePtr) buffer, floatSample, start, analyzeSize);
|
||||
track->Get((samplePtr) buffer.get(), floatSample, start, analyzeSize);
|
||||
for(unsigned i = 0; i < numWindows; i++) {
|
||||
ComputeSpectrum(buffer + i * windowSize, windowSize,
|
||||
windowSize, rate, freq, true);
|
||||
ComputeSpectrum(buffer.get() + i * windowSize, windowSize,
|
||||
windowSize, rate, freq.get(), true);
|
||||
for(size_t j = 0; j < windowSize / 2; j++)
|
||||
freqa[j] += freq[j];
|
||||
}
|
||||
|
@ -444,10 +437,6 @@ void EffectChangePitch::DeduceFrequencies()
|
|||
if (freqa[j] > freqa[argmax])
|
||||
argmax = j;
|
||||
|
||||
delete [] freq;
|
||||
delete [] freqa;
|
||||
delete [] buffer;
|
||||
|
||||
auto lag = (windowSize / 2 - 1) - argmax;
|
||||
m_dStartFrequency = rate / lag;
|
||||
}
|
||||
|
|
|
@ -485,11 +485,11 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
|||
// the length of the selection being processed.
|
||||
auto inBufferSize = track->GetMaxBlockSize();
|
||||
|
||||
float * inBuffer = new float[inBufferSize];
|
||||
Floats inBuffer{ inBufferSize };
|
||||
|
||||
// mFactor is at most 100-fold so this shouldn't overflow size_t
|
||||
auto outBufferSize = size_t( mFactor * inBufferSize + 10 );
|
||||
float * outBuffer = new float[outBufferSize];
|
||||
Floats outBuffer{ outBufferSize };
|
||||
|
||||
// Set up the resampling stuff for this track.
|
||||
Resample resample(true, mFactor, mFactor); // constant rate resampling
|
||||
|
@ -506,18 +506,18 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
|||
);
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) inBuffer, floatSample, samplePos, blockSize);
|
||||
track->Get((samplePtr) inBuffer.get(), floatSample, samplePos, blockSize);
|
||||
|
||||
const auto results = resample.Process(mFactor,
|
||||
inBuffer,
|
||||
inBuffer.get(),
|
||||
blockSize,
|
||||
((samplePos + blockSize) >= end),
|
||||
outBuffer,
|
||||
outBuffer.get(),
|
||||
outBufferSize);
|
||||
const auto outgen = results.second;
|
||||
|
||||
if (outgen > 0)
|
||||
outputTrack->Append((samplePtr)outBuffer, floatSample,
|
||||
outputTrack->Append((samplePtr)outBuffer.get(), floatSample,
|
||||
outgen);
|
||||
|
||||
// Increment samplePos
|
||||
|
@ -533,10 +533,6 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
|||
// Flush the output WaveTrack (since it's buffered, too)
|
||||
outputTrack->Flush();
|
||||
|
||||
// Clean up the buffers
|
||||
delete [] inBuffer;
|
||||
delete [] outBuffer;
|
||||
|
||||
// Take the output track and insert it in place of the original
|
||||
// sample data
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
|
|
|
@ -214,13 +214,13 @@ bool EffectClickRemoval::ProcessOne(int count, WaveTrack * track, sampleCount st
|
|||
|
||||
bool bResult = true;
|
||||
decltype(len) s = 0;
|
||||
float *buffer = new float[idealBlockLen];
|
||||
float *datawindow = new float[windowSize];
|
||||
Floats buffer{ idealBlockLen };
|
||||
Floats datawindow{ windowSize };
|
||||
while ((len - s) > windowSize / 2)
|
||||
{
|
||||
auto block = limitSampleBufferSize( idealBlockLen, len - s );
|
||||
|
||||
track->Get((samplePtr) buffer, floatSample, start + s, block);
|
||||
track->Get((samplePtr) buffer.get(), floatSample, start + s, block);
|
||||
|
||||
for (decltype(block) i = 0; i + windowSize / 2 < block; i += windowSize / 2)
|
||||
{
|
||||
|
@ -231,14 +231,14 @@ bool EffectClickRemoval::ProcessOne(int count, WaveTrack * track, sampleCount st
|
|||
for(auto j = wcopy; j < windowSize; j++)
|
||||
datawindow[j] = 0;
|
||||
|
||||
mbDidSomething |= RemoveClicks(windowSize, datawindow);
|
||||
mbDidSomething |= RemoveClicks(windowSize, datawindow.get());
|
||||
|
||||
for(decltype(wcopy) j = 0; j < wcopy; j++)
|
||||
buffer[i+j] = datawindow[j];
|
||||
}
|
||||
|
||||
if (mbDidSomething) // RemoveClicks() actually did something.
|
||||
track->Set((samplePtr) buffer, floatSample, start + s, block);
|
||||
track->Set((samplePtr) buffer.get(), floatSample, start + s, block);
|
||||
|
||||
s += block;
|
||||
|
||||
|
@ -249,13 +249,10 @@ bool EffectClickRemoval::ProcessOne(int count, WaveTrack * track, sampleCount st
|
|||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
delete[] datawindow;
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool EffectClickRemoval::RemoveClicks(int len, float *buffer)
|
||||
bool EffectClickRemoval::RemoveClicks(size_t len, float *buffer)
|
||||
{
|
||||
bool bResult = false; // This effect usually does nothing.
|
||||
int i;
|
||||
|
@ -265,8 +262,8 @@ bool EffectClickRemoval::RemoveClicks(int len, float *buffer)
|
|||
float msw;
|
||||
int ww;
|
||||
int s2 = sep/2;
|
||||
float *ms_seq = new float[len];
|
||||
float *b2 = new float[len];
|
||||
Floats ms_seq{ len };
|
||||
Floats b2{ len };
|
||||
|
||||
for( i=0; i<len; i++)
|
||||
b2[i] = buffer[i]*buffer[i];
|
||||
|
@ -322,8 +319,6 @@ bool EffectClickRemoval::RemoveClicks(int len, float *buffer)
|
|||
}
|
||||
}
|
||||
}
|
||||
delete[] ms_seq;
|
||||
delete[] b2;
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ private:
|
|||
bool ProcessOne(int count, WaveTrack * track,
|
||||
sampleCount start, sampleCount len);
|
||||
|
||||
bool RemoveClicks(int len, float *buffer);
|
||||
bool RemoveClicks(size_t len, float *buffer);
|
||||
|
||||
void OnWidthText(wxCommandEvent & evt);
|
||||
void OnThreshText(wxCommandEvent & evt);
|
||||
|
|
|
@ -84,9 +84,6 @@ EffectCompressor::EffectCompressor()
|
|||
mThreshold = 0.25;
|
||||
mNoiseFloor = 0.01;
|
||||
mCompression = 0.5;
|
||||
mCircle = NULL;
|
||||
mFollow1 = NULL;
|
||||
mFollow2 = NULL;
|
||||
mFollowLen = 0;
|
||||
|
||||
SetLinearEffectFlag(false);
|
||||
|
@ -94,18 +91,6 @@ EffectCompressor::EffectCompressor()
|
|||
|
||||
EffectCompressor::~EffectCompressor()
|
||||
{
|
||||
if (mCircle) {
|
||||
delete[] mCircle;
|
||||
mCircle = NULL;
|
||||
}
|
||||
if(mFollow1!=NULL) {
|
||||
delete[] mFollow1;
|
||||
mFollow1 = NULL;
|
||||
}
|
||||
if(mFollow2!=NULL) {
|
||||
delete[] mFollow2;
|
||||
mFollow2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// IdentInterface implementation
|
||||
|
@ -346,13 +331,8 @@ bool EffectCompressor::NewTrackPass1()
|
|||
|
||||
mLastLevel = mThreshold;
|
||||
|
||||
if (mCircle)
|
||||
delete[] mCircle;
|
||||
mCircleSize = 100;
|
||||
mCircle = new double[mCircleSize];
|
||||
for(int j=0; j<mCircleSize; j++) {
|
||||
mCircle[j] = 0.0;
|
||||
}
|
||||
mCircle.reinit( mCircleSize, true );
|
||||
mCirclePos = 0;
|
||||
mRMSSum = 0.0;
|
||||
|
||||
|
@ -374,18 +354,12 @@ bool EffectCompressor::InitPass1()
|
|||
//Iterate to the next track
|
||||
track = (WaveTrack *) iter.Next();
|
||||
}
|
||||
if(mFollow1!=NULL) {
|
||||
delete[] mFollow1;
|
||||
mFollow1 = NULL;
|
||||
}
|
||||
if(mFollow2!=NULL) {
|
||||
delete[] mFollow2;
|
||||
mFollow2 = NULL;
|
||||
}
|
||||
mFollow1.reset();
|
||||
mFollow2.reset();
|
||||
// Allocate buffers for the envelope
|
||||
if(maxlen > 0) {
|
||||
mFollow1 = new float[maxlen];
|
||||
mFollow2 = new float[maxlen];
|
||||
mFollow1.reinit(maxlen);
|
||||
mFollow2.reinit(maxlen);
|
||||
}
|
||||
mFollowLen = maxlen;
|
||||
|
||||
|
@ -426,7 +400,7 @@ bool EffectCompressor::TwoBufferProcessPass1
|
|||
|
||||
// buffer2 is NULL on the last and only the last call
|
||||
if(buffer2 != NULL) {
|
||||
Follow(buffer2, mFollow2, len2, mFollow1, len1);
|
||||
Follow(buffer2, mFollow2.get(), len2, mFollow1.get(), len1);
|
||||
}
|
||||
|
||||
if(buffer1 != NULL) {
|
||||
|
@ -442,9 +416,7 @@ bool EffectCompressor::TwoBufferProcessPass1
|
|||
#endif
|
||||
|
||||
// Rotate the buffer pointers
|
||||
float *tmpfloat = mFollow1;
|
||||
mFollow1 = mFollow2;
|
||||
mFollow2 = tmpfloat;
|
||||
mFollow1.swap(mFollow2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -465,7 +437,7 @@ void EffectCompressor::FreshenCircle()
|
|||
// Recompute the RMS sum periodically to prevent accumulation of rounding errors
|
||||
// during long waveforms
|
||||
mRMSSum = 0;
|
||||
for(int i=0; i<mCircleSize; i++)
|
||||
for(size_t i=0; i<mCircleSize; i++)
|
||||
mRMSSum += mCircle[i];
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../widgets/wxPanelWrapper.h"
|
||||
|
||||
#include "TwoPassSimpleMono.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
class EffectCompressorPanel;
|
||||
class ShuttleGui;
|
||||
|
@ -79,9 +80,9 @@ private:
|
|||
|
||||
private:
|
||||
double mRMSSum;
|
||||
int mCircleSize;
|
||||
int mCirclePos;
|
||||
double *mCircle;
|
||||
size_t mCircleSize;
|
||||
size_t mCirclePos;
|
||||
Doubles mCircle;
|
||||
|
||||
double mAttackTime;
|
||||
double mThresholdDB;
|
||||
|
@ -100,8 +101,7 @@ private:
|
|||
int mNoiseCounter;
|
||||
double mGain;
|
||||
double mLastLevel;
|
||||
float *mFollow1;
|
||||
float *mFollow2;
|
||||
Floats mFollow1, mFollow2;
|
||||
size_t mFollowLen;
|
||||
|
||||
double mMax; //MJS
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../widgets/valnum.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
// Define keys, defaults, minimums, and maximums for the effect parameters
|
||||
//
|
||||
|
@ -95,22 +96,19 @@ bool EffectEcho::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelNames
|
|||
if (requestedHistLen !=
|
||||
(histLen = static_cast<size_t>(requestedHistLen.as_long_long())))
|
||||
throw std::bad_alloc{};
|
||||
history = new float[histLen];
|
||||
history.reinit(histLen, true);
|
||||
}
|
||||
catch ( const std::bad_alloc& ) {
|
||||
wxMessageBox(_("Requested value exceeds memory capacity."));
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(history, 0, sizeof(float) * histLen);
|
||||
|
||||
return history != NULL;
|
||||
}
|
||||
|
||||
bool EffectEcho::ProcessFinalize()
|
||||
{
|
||||
delete [] history;
|
||||
|
||||
history.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <wx/textctrl.h>
|
||||
|
||||
#include "Effect.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
class ShuttleGui;
|
||||
|
||||
|
@ -58,7 +59,7 @@ private:
|
|||
private:
|
||||
double delay;
|
||||
double decay;
|
||||
float *history;
|
||||
Floats history;
|
||||
size_t histPos;
|
||||
size_t histLen;
|
||||
};
|
||||
|
|
|
@ -213,14 +213,14 @@ BEGIN_EVENT_TABLE(EffectEqualization, wxEvtHandler)
|
|||
END_EVENT_TABLE()
|
||||
|
||||
EffectEqualization::EffectEqualization()
|
||||
: mFFTBuffer{ windowSize }
|
||||
, mFilterFuncR{ windowSize }
|
||||
, mFilterFuncI{ windowSize }
|
||||
{
|
||||
mCurve = NULL;
|
||||
mPanel = NULL;
|
||||
|
||||
hFFT = InitializeFFT(windowSize);
|
||||
mFFTBuffer = new float[windowSize];
|
||||
mFilterFuncR = new float[windowSize];
|
||||
mFilterFuncI = new float[windowSize];
|
||||
|
||||
SetLinearEffectFlag(true);
|
||||
|
||||
|
@ -285,15 +285,6 @@ EffectEqualization::~EffectEqualization()
|
|||
if(hFFT)
|
||||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
if(mFFTBuffer)
|
||||
delete[] mFFTBuffer;
|
||||
mFFTBuffer = NULL;
|
||||
if(mFilterFuncR)
|
||||
delete[] mFilterFuncR;
|
||||
if(mFilterFuncI)
|
||||
delete[] mFilterFuncI;
|
||||
mFilterFuncR = NULL;
|
||||
mFilterFuncI = NULL;
|
||||
}
|
||||
|
||||
// IdentInterface implementation
|
||||
|
@ -386,11 +377,11 @@ bool EffectEqualization::ValidateUI()
|
|||
//(done in a hurry, may not be the neatest -MJS)
|
||||
if (mDirty && !mDrawMode)
|
||||
{
|
||||
int numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
double *when = new double[numPoints];
|
||||
double *value = new double[numPoints];
|
||||
mLogEnvelope->GetPoints(when, value, numPoints);
|
||||
for (int i = 0, j = 0; j < numPoints - 2; i++, j++)
|
||||
size_t numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
mLogEnvelope->GetPoints(when.get(), value.get(), numPoints);
|
||||
for (size_t i = 0, j = 0; j + 2 < numPoints; i++, j++)
|
||||
{
|
||||
if ((value[i] < value[i + 1] + .05) && (value[i] > value[i + 1] - .05) &&
|
||||
(value[i + 1] < value[i + 2] + .05) && (value[i + 1] > value[i + 2] - .05))
|
||||
|
@ -400,8 +391,6 @@ bool EffectEqualization::ValidateUI()
|
|||
j--;
|
||||
}
|
||||
}
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
Select((int) mCurves.GetCount() - 1);
|
||||
}
|
||||
SaveCurves();
|
||||
|
@ -528,12 +517,14 @@ bool EffectEqualization::Init()
|
|||
bool EffectEqualization::Process()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
|
||||
if(mEffectEqualization48x)
|
||||
if(mEffectEqualization48x) {
|
||||
if(mBench) {
|
||||
mBench=false;
|
||||
return mEffectEqualization48x->Benchmark(this);
|
||||
} else
|
||||
}
|
||||
else
|
||||
return mEffectEqualization48x->Process(this);
|
||||
}
|
||||
#endif
|
||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||
bool bGoodResult = true;
|
||||
|
@ -1039,7 +1030,7 @@ bool EffectEqualization::TransferDataFromWindow()
|
|||
mPanel->Refresh(false);
|
||||
}
|
||||
|
||||
int m = 2 * mMSlider->GetValue() + 1; // odd numbers only
|
||||
size_t m = 2 * mMSlider->GetValue() + 1; // odd numbers only
|
||||
if (m != mM) {
|
||||
mM = m;
|
||||
ForceRecalc();
|
||||
|
@ -1069,12 +1060,12 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
|
|||
if (idealBlockLen % L != 0)
|
||||
idealBlockLen += (L - (idealBlockLen % L));
|
||||
|
||||
float *buffer = new float[idealBlockLen];
|
||||
Floats buffer{ idealBlockLen };
|
||||
|
||||
float *window1 = new float[windowSize];
|
||||
float *window2 = new float[windowSize];
|
||||
float *thisWindow = window1;
|
||||
float *lastWindow = window2;
|
||||
Floats window1{ windowSize };
|
||||
Floats window2{ windowSize };
|
||||
float *thisWindow = window1.get();
|
||||
float *lastWindow = window2.get();
|
||||
|
||||
auto originalLen = len;
|
||||
|
||||
|
@ -1090,7 +1081,7 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
|
|||
{
|
||||
auto block = limitSampleBufferSize( idealBlockLen, len );
|
||||
|
||||
t->Get((samplePtr)buffer, floatSample, s, block);
|
||||
t->Get((samplePtr)buffer.get(), floatSample, s, block);
|
||||
|
||||
for(size_t i = 0; i < block; i += L) //go through block in lumps of length L
|
||||
{
|
||||
|
@ -1113,7 +1104,7 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
|
|||
lastWindow = tempP;
|
||||
} //next i, lump of this block
|
||||
|
||||
output->Append((samplePtr)buffer, floatSample, block);
|
||||
output->Append((samplePtr)buffer.get(), floatSample, block);
|
||||
len -= block;
|
||||
s += block;
|
||||
|
||||
|
@ -1142,7 +1133,7 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
|
|||
for(size_t j = 0; j < mM - 1; j++)
|
||||
buffer[j] = lastWindow[wcopy + j];
|
||||
}
|
||||
output->Append((samplePtr)buffer, floatSample, mM - 1);
|
||||
output->Append((samplePtr)buffer.get(), floatSample, mM - 1);
|
||||
output->Flush();
|
||||
|
||||
// now move the appropriate bit of the output back to the track
|
||||
|
@ -1208,10 +1199,6 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
|
|||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
delete[] window1;
|
||||
delete[] window2;
|
||||
|
||||
return bLoopSuccess;
|
||||
}
|
||||
|
||||
|
@ -1277,9 +1264,9 @@ bool EffectEqualization::CalcFilter()
|
|||
}
|
||||
|
||||
//transfer to time domain to do the padding and windowing
|
||||
float *outr = new float[mWindowSize];
|
||||
float *outi = new float[mWindowSize];
|
||||
InverseRealFFT(mWindowSize, mFilterFuncR, NULL, outr); // To time domain
|
||||
Floats outr{ mWindowSize };
|
||||
Floats outi{ mWindowSize };
|
||||
InverseRealFFT(mWindowSize, mFilterFuncR.get(), NULL, outr.get()); // To time domain
|
||||
|
||||
{
|
||||
size_t i = 0;
|
||||
|
@ -1302,7 +1289,7 @@ bool EffectEqualization::CalcFilter()
|
|||
outr[mWindowSize - i] = 0;
|
||||
}
|
||||
}
|
||||
float *tempr = new float[mM];
|
||||
Floats tempr{ mM };
|
||||
{
|
||||
size_t i = 0;
|
||||
for(; i < (mM - 1) / 2; i++)
|
||||
|
@ -1313,21 +1300,17 @@ bool EffectEqualization::CalcFilter()
|
|||
tempr[(mM - 1) / 2 + i] = outr[i];
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < mM; i++)
|
||||
for (size_t i = 0; i < mM; i++)
|
||||
{ //and copy useful values back
|
||||
outr[i] = tempr[i];
|
||||
}
|
||||
for(size_t i = mM; i < mWindowSize; i++)
|
||||
for (size_t i = mM; i < mWindowSize; i++)
|
||||
{ //rest is padding
|
||||
outr[i]=0.;
|
||||
}
|
||||
|
||||
//Back to the frequency domain so we can use it
|
||||
RealFFT(mWindowSize, outr, mFilterFuncR, mFilterFuncI);
|
||||
|
||||
delete[] outr;
|
||||
delete[] outi;
|
||||
delete[] tempr;
|
||||
RealFFT(mWindowSize, outr.get(), mFilterFuncR.get(), mFilterFuncI.get());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1353,8 +1336,8 @@ void EffectEqualization::Filter(size_t len, float *buffer)
|
|||
mFFTBuffer[1] = buffer[1] * mFilterFuncR[len/2];
|
||||
|
||||
// Inverse FFT and normalization
|
||||
InverseRealFFTf(mFFTBuffer, hFFT);
|
||||
ReorderToTime(hFFT, mFFTBuffer, buffer);
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT);
|
||||
ReorderToTime(hFFT, mFFTBuffer.get(), buffer);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1855,10 +1838,10 @@ void EffectEqualization::EnvelopeUpdated()
|
|||
void EffectEqualization::EnvelopeUpdated(Envelope *env, bool lin)
|
||||
{
|
||||
// Allocate and populate point arrays
|
||||
int numPoints = env->GetNumberOfPoints();
|
||||
double *when = new double[ numPoints ];
|
||||
double *value = new double[ numPoints ];
|
||||
env->GetPoints( when, value, numPoints );
|
||||
size_t numPoints = env->GetNumberOfPoints();
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
env->GetPoints( when.get(), value.get(), numPoints );
|
||||
|
||||
// Clear the unnamed curve
|
||||
int curve = mCurves.GetCount()-1;
|
||||
|
@ -1867,8 +1850,7 @@ void EffectEqualization::EnvelopeUpdated(Envelope *env, bool lin)
|
|||
if(lin)
|
||||
{
|
||||
// Copy and convert points
|
||||
int point;
|
||||
for( point = 0; point < numPoints; point++ )
|
||||
for (size_t point = 0; point < numPoints; point++)
|
||||
{
|
||||
double freq = when[ point ] * mHiFreq;
|
||||
double db = value[ point ];
|
||||
|
@ -1884,8 +1866,7 @@ void EffectEqualization::EnvelopeUpdated(Envelope *env, bool lin)
|
|||
double denom = hiLog - loLog;
|
||||
|
||||
// Copy and convert points
|
||||
int point;
|
||||
for( point = 0; point < numPoints; point++ )
|
||||
for (size_t point = 0; point < numPoints; point++)
|
||||
{
|
||||
double freq = pow( 10., ( ( when[ point ] * denom ) + loLog ));
|
||||
double db = value[ point ];
|
||||
|
@ -1899,10 +1880,6 @@ void EffectEqualization::EnvelopeUpdated(Envelope *env, bool lin)
|
|||
|
||||
// set 'unnamed' as the selected curve
|
||||
Select( (int) mCurves.GetCount()-1 );
|
||||
|
||||
// Clean up
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1925,7 +1902,7 @@ void EffectEqualization::Flatten()
|
|||
ForceRecalc();
|
||||
if( !mDrawMode )
|
||||
{
|
||||
for( int i=0; i< mBandsInUse; i++)
|
||||
for( size_t i = 0; i < mBandsInUse; i++)
|
||||
{
|
||||
mSliders[i]->SetValue(0);
|
||||
mSlidersOld[i] = 0;
|
||||
|
@ -2154,13 +2131,13 @@ void EffectEqualization::UpdateCurves()
|
|||
|
||||
void EffectEqualization::UpdateDraw()
|
||||
{
|
||||
int numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
double *when = new double[ numPoints ];
|
||||
double *value = new double[ numPoints ];
|
||||
size_t numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
double deltadB = 0.1;
|
||||
double dx, dy, dx1, dy1, err;
|
||||
|
||||
mLogEnvelope->GetPoints( when, value, numPoints );
|
||||
mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
|
||||
// set 'unnamed' as the selected curve
|
||||
EnvelopeUpdated();
|
||||
|
@ -2170,8 +2147,8 @@ void EffectEqualization::UpdateDraw()
|
|||
{
|
||||
flag = false;
|
||||
int numDeleted = 0;
|
||||
mLogEnvelope->GetPoints( when, value, numPoints );
|
||||
for(int j=0;j<numPoints-2;j++)
|
||||
mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
for (size_t j = 0; j + 2 < numPoints; j++)
|
||||
{
|
||||
dx = when[j+2+numDeleted] - when[j+numDeleted];
|
||||
dy = value[j+2+numDeleted] - value[j+numDeleted];
|
||||
|
@ -2187,8 +2164,6 @@ void EffectEqualization::UpdateDraw()
|
|||
}
|
||||
}
|
||||
}
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
|
||||
if(mLin) // do not use IsLinear() here
|
||||
{
|
||||
|
@ -2230,7 +2205,7 @@ void EffectEqualization::UpdateGraphic()
|
|||
mFreqRuler->ruler.SetRange(mLoFreq, mHiFreq);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mBandsInUse; i++)
|
||||
for (size_t i = 0; i < mBandsInUse; i++)
|
||||
{
|
||||
if( kThirdOct[i] == mLoFreq )
|
||||
mWhenSliders[i] = 0.;
|
||||
|
@ -2243,7 +2218,7 @@ void EffectEqualization::UpdateGraphic()
|
|||
mEQVals[i] = -20.;
|
||||
}
|
||||
ErrMin(); //move sliders to minimise error
|
||||
for (int i = 0; i < mBandsInUse; i++)
|
||||
for (size_t i = 0; i < mBandsInUse; i++)
|
||||
{
|
||||
mSliders[i]->SetValue(lrint(mEQVals[i])); //actually set slider positions
|
||||
mSlidersOld[i] = mSliders[i]->GetValue();
|
||||
|
@ -2281,52 +2256,49 @@ void EffectEqualization::UpdateGraphic()
|
|||
|
||||
void EffectEqualization::EnvLogToLin(void)
|
||||
{
|
||||
int numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
size_t numPoints = mLogEnvelope->GetNumberOfPoints();
|
||||
if( numPoints == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double *when = new double[ numPoints ];
|
||||
double *value = new double[ numPoints ];
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
|
||||
mLinEnvelope->Flatten(0.);
|
||||
mLinEnvelope->SetTrackLen(1.0);
|
||||
mLogEnvelope->GetPoints( when, value, numPoints );
|
||||
mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
mLinEnvelope->Move(0., value[0]);
|
||||
double loLog = log10(20.);
|
||||
double hiLog = log10(mHiFreq);
|
||||
double denom = hiLog - loLog;
|
||||
|
||||
for( int i=0; i < numPoints; i++)
|
||||
for (size_t i = 0; i < numPoints; i++)
|
||||
mLinEnvelope->Insert(pow( 10., ((when[i] * denom) + loLog))/mHiFreq , value[i]);
|
||||
mLinEnvelope->Move(1., value[numPoints-1]);
|
||||
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
}
|
||||
|
||||
void EffectEqualization::EnvLinToLog(void)
|
||||
{
|
||||
int numPoints = mLinEnvelope->GetNumberOfPoints();
|
||||
size_t numPoints = mLinEnvelope->GetNumberOfPoints();
|
||||
if( numPoints == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double *when = new double[ numPoints ];
|
||||
double *value = new double[ numPoints ];
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
|
||||
mLogEnvelope->Flatten(0.);
|
||||
mLogEnvelope->SetTrackLen(1.0);
|
||||
mLinEnvelope->GetPoints( when, value, numPoints );
|
||||
mLinEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
mLogEnvelope->Move(0., value[0]);
|
||||
double loLog = log10(20.);
|
||||
double hiLog = log10(mHiFreq);
|
||||
double denom = hiLog - loLog;
|
||||
bool changed = false;
|
||||
|
||||
for( int i=0; i < numPoints; i++)
|
||||
for (size_t i = 0; i < numPoints; i++)
|
||||
{
|
||||
if( when[i]*mHiFreq >= 20 )
|
||||
{
|
||||
|
@ -2344,9 +2316,6 @@ void EffectEqualization::EnvLinToLog(void)
|
|||
}
|
||||
mLogEnvelope->Move(1., value[numPoints-1]);
|
||||
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
|
||||
if(changed)
|
||||
EnvelopeUpdated(mLogEnvelope.get(), false);
|
||||
}
|
||||
|
@ -2354,13 +2323,12 @@ void EffectEqualization::EnvLinToLog(void)
|
|||
void EffectEqualization::ErrMin(void)
|
||||
{
|
||||
double vals[NUM_PTS];
|
||||
int i;
|
||||
double error = 0.0;
|
||||
double oldError = 0.0;
|
||||
double mEQValsOld = 0.0;
|
||||
double correction = 1.6;
|
||||
bool flag;
|
||||
int j=0;
|
||||
size_t j=0;
|
||||
Envelope testEnvelope;
|
||||
testEnvelope.SetInterpolateDB(false);
|
||||
testEnvelope.SetRange(-120.0, 60.0);
|
||||
|
@ -2368,13 +2336,13 @@ void EffectEqualization::ErrMin(void)
|
|||
testEnvelope.SetTrackLen(1.0);
|
||||
testEnvelope.CopyFrom(mLogEnvelope.get(), 0.0, 1.0);
|
||||
|
||||
for(i=0; i < NUM_PTS; i++)
|
||||
for(size_t i = 0; i < NUM_PTS; i++)
|
||||
vals[i] = testEnvelope.GetValue(mWhens[i]);
|
||||
|
||||
// Do error minimisation
|
||||
error = 0.;
|
||||
GraphicEQ(&testEnvelope);
|
||||
for(i=0; i < NUM_PTS; i++) //calc initial error
|
||||
for(size_t i = 0; i < NUM_PTS; i++) //calc initial error
|
||||
{
|
||||
double err = vals[i] - testEnvelope.GetValue(mWhens[i]);
|
||||
error += err*err;
|
||||
|
@ -2382,7 +2350,7 @@ void EffectEqualization::ErrMin(void)
|
|||
oldError = error;
|
||||
while( j < mBandsInUse*12 ) //loop over the sliders a number of times
|
||||
{
|
||||
i = j%mBandsInUse; //use this slider
|
||||
auto i = j % mBandsInUse; //use this slider
|
||||
if( (j > 0) & (i == 0) ) // if we've come back to the first slider again...
|
||||
{
|
||||
if( correction > 0 )
|
||||
|
@ -2408,7 +2376,7 @@ void EffectEqualization::ErrMin(void)
|
|||
}
|
||||
GraphicEQ(&testEnvelope); //calculate envelope
|
||||
error = 0.;
|
||||
for(int k=0; k < NUM_PTS; k++) //calculate error
|
||||
for(size_t k = 0; k < NUM_PTS; k++) //calculate error
|
||||
{
|
||||
double err = vals[k] - testEnvelope.GetValue(mWhens[k]);
|
||||
error += err*err;
|
||||
|
@ -2448,7 +2416,7 @@ void EffectEqualization::GraphicEQ(Envelope *env)
|
|||
case kBspline: // B-spline
|
||||
{
|
||||
int minF = 0;
|
||||
for(int i=0; i<NUM_PTS; i++)
|
||||
for(size_t i = 0; i < NUM_PTS; i++)
|
||||
{
|
||||
while( (mWhenSliders[minF] <= mWhens[i]) & (minF < mBandsInUse) )
|
||||
minF++;
|
||||
|
@ -2514,7 +2482,7 @@ void EffectEqualization::GraphicEQ(Envelope *env)
|
|||
case kCosine: // Cosine squared
|
||||
{
|
||||
int minF = 0;
|
||||
for(int i=0; i<NUM_PTS; i++)
|
||||
for(size_t i = 0; i < NUM_PTS; i++)
|
||||
{
|
||||
while( (mWhenSliders[minF] <= mWhens[i]) & (minF < mBandsInUse) )
|
||||
minF++;
|
||||
|
@ -2571,14 +2539,16 @@ void EffectEqualization::GraphicEQ(Envelope *env)
|
|||
ForceRecalc();
|
||||
}
|
||||
|
||||
void EffectEqualization::spline(double x[], double y[], int n, double y2[])
|
||||
void EffectEqualization::spline(double x[], double y[], size_t n, double y2[])
|
||||
{
|
||||
int i;
|
||||
double p, sig, *u = new double[n];
|
||||
wxASSERT( n > 0 );
|
||||
|
||||
double p, sig;
|
||||
Doubles u{ n };
|
||||
|
||||
y2[0] = 0.; //
|
||||
u[0] = 0.; //'natural' boundary conditions
|
||||
for(i=1;i<n-1;i++)
|
||||
for (size_t i = 1; i + 1 < n; i++)
|
||||
{
|
||||
sig = ( x[i] - x[i-1] ) / ( x[i+1] - x[i-1] );
|
||||
p = sig * y2[i-1] + 2.;
|
||||
|
@ -2586,24 +2556,25 @@ void EffectEqualization::spline(double x[], double y[], int n, double y2[])
|
|||
u[i] = ( y[i+1] - y[i] ) / ( x[i+1] - x[i] ) - ( y[i] - y[i-1] ) / ( x[i] - x[i-1] );
|
||||
u[i] = (6.*u[i]/( x[i+1] - x[i-1] ) - sig * u[i-1]) / p;
|
||||
}
|
||||
y2[n-1] = 0.;
|
||||
for(i=n-2;i>=0;i--)
|
||||
y2[n - 1] = 0.;
|
||||
for (size_t i = n - 1; i--;)
|
||||
y2[i] = y2[i]*y2[i+1] + u[i];
|
||||
|
||||
delete [] u;
|
||||
}
|
||||
|
||||
double EffectEqualization::splint(double x[], double y[], int n, double y2[], double xr)
|
||||
double EffectEqualization::splint(double x[], double y[], size_t n, double y2[], double xr)
|
||||
{
|
||||
wxASSERT( n > 1 );
|
||||
|
||||
double a, b, h;
|
||||
static double xlast = 0.; // remember last x value requested
|
||||
static int k = 0; // and which interval we were in
|
||||
static size_t k = 0; // and which interval we were in
|
||||
|
||||
if( xr < xlast )
|
||||
k = 0; // gone back to start, (or somewhere to the left)
|
||||
xlast = xr;
|
||||
while( (x[k] <= xr) && (k < n-1) )
|
||||
while( (x[k] <= xr) && (k + 1 < n) )
|
||||
k++;
|
||||
wxASSERT( k > 0 );
|
||||
k--;
|
||||
h = x[k+1] - x[k];
|
||||
a = ( x[k+1] - xr )/h;
|
||||
|
@ -2631,7 +2602,7 @@ void EffectEqualization::OnErase(wxEraseEvent & WXUNUSED(event))
|
|||
void EffectEqualization::OnSlider(wxCommandEvent & event)
|
||||
{
|
||||
wxSlider *s = (wxSlider *)event.GetEventObject();
|
||||
for (int i = 0; i < mBandsInUse; i++)
|
||||
for (size_t i = 0; i < mBandsInUse; i++)
|
||||
{
|
||||
if( s == mSliders[i])
|
||||
{
|
||||
|
@ -2741,7 +2712,7 @@ void EffectEqualization::OnInvert(wxCommandEvent & WXUNUSED(event)) // Inverts a
|
|||
{
|
||||
if(!mDrawMode) // Graphic (Slider) mode. Invert the sliders.
|
||||
{
|
||||
for (int i = 0; i < mBandsInUse; i++)
|
||||
for (size_t i = 0; i < mBandsInUse; i++)
|
||||
{
|
||||
mEQVals[i] = -mEQVals[i];
|
||||
int newPosn = (int)mEQVals[i];
|
||||
|
@ -2760,7 +2731,7 @@ void EffectEqualization::OnInvert(wxCommandEvent & WXUNUSED(event)) // Inverts a
|
|||
else // Draw mode. Invert the points.
|
||||
{
|
||||
bool lin = IsLinear(); // refers to the 'log' or 'lin' of the frequency scale, not the amplitude
|
||||
int numPoints; // number of points in the curve/envelope
|
||||
size_t numPoints; // number of points in the curve/envelope
|
||||
|
||||
// determine if log or lin curve is the current one
|
||||
// and find out how many points are in the curve
|
||||
|
@ -2776,16 +2747,16 @@ void EffectEqualization::OnInvert(wxCommandEvent & WXUNUSED(event)) // Inverts a
|
|||
if( numPoints == 0 )
|
||||
return;
|
||||
|
||||
double *when = new double[ numPoints ];
|
||||
double *value = new double[ numPoints ];
|
||||
Doubles when{ numPoints };
|
||||
Doubles value{ numPoints };
|
||||
|
||||
if(lin)
|
||||
mLinEnvelope->GetPoints( when, value, numPoints );
|
||||
mLinEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
else
|
||||
mLogEnvelope->GetPoints( when, value, numPoints );
|
||||
mLogEnvelope->GetPoints( when.get(), value.get(), numPoints );
|
||||
|
||||
// invert the curve
|
||||
for( int i=0; i < numPoints; i++)
|
||||
for (size_t i = 0; i < numPoints; i++)
|
||||
{
|
||||
if(lin)
|
||||
mLinEnvelope->Move(when[i] , -value[i]);
|
||||
|
@ -2793,9 +2764,6 @@ void EffectEqualization::OnInvert(wxCommandEvent & WXUNUSED(event)) // Inverts a
|
|||
mLogEnvelope->Move(when[i] , -value[i]);
|
||||
}
|
||||
|
||||
delete [] when;
|
||||
delete [] value;
|
||||
|
||||
// copy it back to the other one (just in case)
|
||||
if(lin)
|
||||
EnvLinToLog();
|
||||
|
@ -2882,9 +2850,6 @@ EqualizationPanel::EqualizationPanel(EffectEqualization *effect, wxWindow *paren
|
|||
{
|
||||
mParent = parent;
|
||||
mEffect = effect;
|
||||
|
||||
mOutr = NULL;
|
||||
mOuti = NULL;
|
||||
|
||||
mBitmap = NULL;
|
||||
mWidth = 0;
|
||||
|
@ -2899,11 +2864,6 @@ EqualizationPanel::EqualizationPanel(EffectEqualization *effect, wxWindow *paren
|
|||
|
||||
EqualizationPanel::~EqualizationPanel()
|
||||
{
|
||||
if (mOuti)
|
||||
delete [] mOuti;
|
||||
if (mOutr)
|
||||
delete [] mOutr;
|
||||
|
||||
if(HasCapture())
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
@ -2916,16 +2876,11 @@ void EqualizationPanel::ForceRecalc()
|
|||
|
||||
void EqualizationPanel::Recalc()
|
||||
{
|
||||
if (mOutr)
|
||||
delete [] mOutr;
|
||||
mOutr = new float[mEffect->mWindowSize];
|
||||
|
||||
if (mOuti)
|
||||
delete [] mOuti;
|
||||
mOuti = new float[mEffect->mWindowSize];
|
||||
mOutr = Floats{ mEffect->mWindowSize };
|
||||
mOuti = Floats{ mEffect->mWindowSize };
|
||||
|
||||
mEffect->CalcFilter(); //to calculate the actual response
|
||||
InverseRealFFT(mEffect->mWindowSize, mEffect->mFilterFuncR, mEffect->mFilterFuncI, mOutr);
|
||||
InverseRealFFT(mEffect->mWindowSize, mEffect->mFilterFuncR.get(), mEffect->mFilterFuncI.get(), mOutr.get());
|
||||
}
|
||||
|
||||
void EqualizationPanel::OnSize(wxSizeEvent & WXUNUSED(event))
|
||||
|
@ -2995,37 +2950,38 @@ void EqualizationPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
|
|||
}
|
||||
|
||||
// Med-blue envelope line
|
||||
memDC.SetPen(wxPen(theTheme.Colour( clrGraphLines ), 3, wxSOLID));
|
||||
memDC.SetPen(wxPen(theTheme.Colour(clrGraphLines), 3, wxSOLID));
|
||||
|
||||
// Draw envelope
|
||||
double *values = new double[mEnvRect.width];
|
||||
mEffect->mEnvelope->GetValues(values, mEnvRect.width, 0.0, 1.0/mEnvRect.width);
|
||||
int x, y, xlast = 0, ylast = 0;
|
||||
bool off = false, off1 = false;
|
||||
for(int i=0; i<mEnvRect.width; i++)
|
||||
{
|
||||
x = mEnvRect.x + i;
|
||||
y = lrint(mEnvRect.height*((mEffect->mdBMax-values[i])/(mEffect->mdBMax-mEffect->mdBMin)) + .25 ); //needs more optimising, along with'what you get'?
|
||||
if( y >= mEnvRect.height)
|
||||
Doubles values{ size_t(mEnvRect.width) };
|
||||
mEffect->mEnvelope->GetValues(values.get(), mEnvRect.width, 0.0, 1.0 / mEnvRect.width);
|
||||
bool off = false, off1 = false;
|
||||
for (int i = 0; i < mEnvRect.width; i++)
|
||||
{
|
||||
y = mEnvRect.height - 1;
|
||||
off = true;
|
||||
x = mEnvRect.x + i;
|
||||
y = lrint(mEnvRect.height*((mEffect->mdBMax - values[i]) / (mEffect->mdBMax - mEffect->mdBMin)) + .25); //needs more optimising, along with'what you get'?
|
||||
if (y >= mEnvRect.height)
|
||||
{
|
||||
y = mEnvRect.height - 1;
|
||||
off = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
off = false;
|
||||
off1 = false;
|
||||
}
|
||||
if ((i != 0) & (!off1))
|
||||
{
|
||||
AColor::Line(memDC, xlast, ylast,
|
||||
x, mEnvRect.y + y);
|
||||
}
|
||||
off1 = off;
|
||||
xlast = x;
|
||||
ylast = mEnvRect.y + y;
|
||||
}
|
||||
else
|
||||
{
|
||||
off = false;
|
||||
off1 = false;
|
||||
}
|
||||
if ( (i != 0) & (!off1) )
|
||||
{
|
||||
AColor::Line(memDC, xlast, ylast,
|
||||
x, mEnvRect.y + y);
|
||||
}
|
||||
off1 = off;
|
||||
xlast = x;
|
||||
ylast = mEnvRect.y + y;
|
||||
}
|
||||
delete[] values;
|
||||
|
||||
//Now draw the actual response that you will get.
|
||||
//mFilterFunc has a linear scale, window has a log one so we have to fiddle about
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "../widgets/Grid.h"
|
||||
#include "../widgets/Ruler.h"
|
||||
#include "../RealFFTf.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
#define EQUALIZATION_PLUGIN_SYMBOL XO("Equalization")
|
||||
|
||||
|
@ -125,7 +126,7 @@ private:
|
|||
// EffectEqualization implementation
|
||||
|
||||
// Number of samples in an FFT window
|
||||
enum : size_t {windowSize=16384}; //MJS - work out the optimum for this at run time? Have a dialog box for it?
|
||||
static const size_t windowSize = 16384u; //MJS - work out the optimum for this at run time? Have a dialog box for it?
|
||||
|
||||
// Low frequency of the FFT. 20Hz is the
|
||||
// low range of human hearing
|
||||
|
@ -166,8 +167,8 @@ private:
|
|||
void EnvLinToLog(void);
|
||||
void ErrMin(void);
|
||||
void GraphicEQ(Envelope *env);
|
||||
void spline(double x[], double y[], int n, double y2[]);
|
||||
double splint(double x[], double y[], int n, double y2[], double xr);
|
||||
void spline(double x[], double y[], size_t n, double y2[]);
|
||||
double splint(double x[], double y[], size_t n, double y2[], double xr);
|
||||
|
||||
void OnSize( wxSizeEvent & event );
|
||||
void OnErase( wxEraseEvent & event );
|
||||
|
@ -191,9 +192,7 @@ private:
|
|||
|
||||
private:
|
||||
HFFT hFFT;
|
||||
float *mFFTBuffer;
|
||||
float *mFilterFuncR;
|
||||
float *mFilterFuncI;
|
||||
Floats mFFTBuffer, mFilterFuncR, mFilterFuncI;
|
||||
size_t mM;
|
||||
wxString mCurveName;
|
||||
bool mLin;
|
||||
|
@ -205,7 +204,7 @@ private:
|
|||
|
||||
double mWhens[NUM_PTS];
|
||||
double mWhenSliders[NUMBER_OF_BANDS+1];
|
||||
int mBandsInUse;
|
||||
size_t mBandsInUse;
|
||||
RulerPanel *mdBRuler;
|
||||
RulerPanel *mFreqRuler;
|
||||
|
||||
|
@ -320,8 +319,7 @@ private:
|
|||
// size_t mWindowSize;
|
||||
// float *mFilterFuncR;
|
||||
// float *mFilterFuncI;
|
||||
float *mOutr;
|
||||
float *mOuti;
|
||||
Floats mOutr, mOuti;
|
||||
|
||||
// double mLoFreq;
|
||||
// double mHiFreq;
|
||||
|
|
|
@ -169,7 +169,7 @@ void free_simd(void* mem)
|
|||
|
||||
EffectEqualization48x::EffectEqualization48x():
|
||||
mThreadCount(0),mFilterSize(0),mWindowSize(0),mBlockSize(0),mWorkerDataCount(0),mBlocksPerBuffer(20),
|
||||
mScratchBufferSize(0),mSubBufferSize(0),mBigBuffer(NULL),mBufferInfo(NULL),mEQWorkers(0),mThreaded(false),
|
||||
mScratchBufferSize(0),mSubBufferSize(0),mBigBuffer(NULL),mThreaded(false),
|
||||
mBenching(false),mBufferCount(0)
|
||||
{
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ bool EffectEqualization48x::AllocateBuffersWorkers(int nThreads)
|
|||
mSubBufferSize=mBlockSize*(mBufferCount*(mBlocksPerBuffer-1)); // we are going to do a full block overlap
|
||||
mBigBuffer=(float *)malloc_simd(sizeof(float)*(mSubBufferSize+mFilterSize+mScratchBufferSize)*mWorkerDataCount); // we run over by filtersize
|
||||
// fill the bufferInfo
|
||||
mBufferInfo = new BufferInfo[mWorkerDataCount];
|
||||
mBufferInfo.reinit(mWorkerDataCount);
|
||||
for(int i=0;i<mWorkerDataCount;i++) {
|
||||
mBufferInfo[i].mFftWindowSize=mWindowSize;
|
||||
mBufferInfo[i].mFftFilterSize=mFilterSize;
|
||||
|
@ -226,9 +226,9 @@ bool EffectEqualization48x::AllocateBuffersWorkers(int nThreads)
|
|||
if(mThreadCount) {
|
||||
// start the workers
|
||||
mDataMutex.IsOk();
|
||||
mEQWorkers=new EQWorker[mThreadCount];
|
||||
mEQWorkers.reinit(mThreadCount);
|
||||
for(int i=0;i<mThreadCount;i++) {
|
||||
mEQWorkers[i].SetData( mBufferInfo, mWorkerDataCount, &mDataMutex, this);
|
||||
mEQWorkers[i].SetData( mBufferInfo.get(), mWorkerDataCount, &mDataMutex, this);
|
||||
mEQWorkers[i].Create();
|
||||
mEQWorkers[i].Run();
|
||||
}
|
||||
|
@ -245,13 +245,11 @@ bool EffectEqualization48x::FreeBuffersWorkers()
|
|||
for(int i=0;i<mThreadCount;i++) {
|
||||
mEQWorkers[i].Wait();
|
||||
}
|
||||
delete[] mEQWorkers; // kill the workers ( go directly to jail)
|
||||
mEQWorkers= NULL;
|
||||
mEQWorkers.reset(); // kill the workers ( go directly to jail)
|
||||
mThreadCount=0;
|
||||
mWorkerDataCount=0;
|
||||
}
|
||||
delete [] mBufferInfo;
|
||||
mBufferInfo = NULL;
|
||||
mBufferInfo.reset();
|
||||
free_simd(mBigBuffer);
|
||||
mBigBuffer=NULL;
|
||||
return true;
|
||||
|
@ -415,8 +413,8 @@ bool EffectEqualization48x::DeltaTrack(WaveTrack * t, WaveTrack * t2, sampleCoun
|
|||
|
||||
auto trackBlockSize = t->GetMaxBlockSize();
|
||||
|
||||
float *buffer1 = new float[trackBlockSize];
|
||||
float *buffer2 = new float[trackBlockSize];
|
||||
Floats buffer1{ trackBlockSize };
|
||||
Floats buffer2{ trackBlockSize };
|
||||
|
||||
AudacityProject *p = GetActiveProject();
|
||||
auto output=p->GetTrackFactory()->NewWaveTrack(floatSample, t->GetRate());
|
||||
|
@ -425,16 +423,14 @@ bool EffectEqualization48x::DeltaTrack(WaveTrack * t, WaveTrack * t2, sampleCoun
|
|||
|
||||
while(len > 0) {
|
||||
auto curretLength = limitSampleBufferSize(trackBlockSize, len);
|
||||
t->Get((samplePtr)buffer1, floatSample, currentSample, curretLength);
|
||||
t2->Get((samplePtr)buffer2, floatSample, currentSample, curretLength);
|
||||
t->Get((samplePtr)buffer1.get(), floatSample, currentSample, curretLength);
|
||||
t2->Get((samplePtr)buffer2.get(), floatSample, currentSample, curretLength);
|
||||
for(decltype(curretLength) i=0;i<curretLength;i++)
|
||||
buffer1[i]-=buffer2[i];
|
||||
output->Append((samplePtr)buffer1, floatSample, curretLength);
|
||||
output->Append((samplePtr)buffer1.get(), floatSample, curretLength);
|
||||
currentSample+=curretLength;
|
||||
len-=curretLength;
|
||||
}
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
output->Flush();
|
||||
len=originalLen;
|
||||
ProcessTail(t, output.get(), start, len);
|
||||
|
@ -669,7 +665,7 @@ bool EffectEqualization48x::ProcessOne1x(int count, WaveTrack * t,
|
|||
}
|
||||
currentSample-=mBlockSize+(mFilterSize>>1);
|
||||
|
||||
ProcessBuffer1x(mBufferInfo);
|
||||
ProcessBuffer1x(mBufferInfo.get());
|
||||
bBreakLoop=mEffectEqualization->TrackProgress(count, (double)(bigRun)/bigRuns.as_double());
|
||||
if( bBreakLoop )
|
||||
break;
|
||||
|
@ -850,7 +846,7 @@ bool EffectEqualization48x::ProcessOne4x(int count, WaveTrack * t,
|
|||
}
|
||||
currentSample-=mBlockSize+(mFilterSize>>1);
|
||||
|
||||
ProcessBuffer4x(mBufferInfo);
|
||||
ProcessBuffer4x(mBufferInfo.get());
|
||||
bBreakLoop=mEffectEqualization->TrackProgress(count, (double)(bigRun)/bigRuns.as_double());
|
||||
if( bBreakLoop )
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,8 @@ Intrinsics (SSE/AVX) and Threaded Equalization
|
|||
#include "../Experimental.h"
|
||||
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
|
||||
|
||||
#include "../MemoryX.h"
|
||||
|
||||
#ifdef __AVX_ENABLED
|
||||
#define __MAXBUFFERCOUNT 8
|
||||
#else
|
||||
|
@ -155,9 +157,9 @@ private:
|
|||
size_t mScratchBufferSize;
|
||||
size_t mSubBufferSize;
|
||||
float *mBigBuffer;
|
||||
BufferInfo* mBufferInfo;
|
||||
ArrayOf<BufferInfo> mBufferInfo;
|
||||
wxMutex mDataMutex;
|
||||
EQWorker* mEQWorkers;
|
||||
ArrayOf<EQWorker> mEQWorkers;
|
||||
bool mThreaded;
|
||||
bool mBenching;
|
||||
friend EQWorker;
|
||||
|
|
|
@ -95,7 +95,6 @@ bool EffectFindClipping::Process()
|
|||
{
|
||||
std::shared_ptr<AddedAnalysisTrack> addedTrack;
|
||||
Maybe<ModifiedAnalysisTrack> modifiedTrack;
|
||||
//Track *original = NULL;
|
||||
const wxString name{ _("Clipping") };
|
||||
|
||||
LabelTrack *lt = NULL;
|
||||
|
@ -158,19 +157,19 @@ bool EffectFindClipping::ProcessOne(LabelTrack * lt,
|
|||
return true;
|
||||
}
|
||||
|
||||
float *buffer;
|
||||
Floats buffer;
|
||||
try {
|
||||
if (blockSize < mStart)
|
||||
// overflow
|
||||
throw std::bad_alloc{};
|
||||
buffer = new float[blockSize];
|
||||
buffer.reinit(blockSize);
|
||||
}
|
||||
catch( const std::bad_alloc & ) {
|
||||
wxMessageBox(_("Requested value exceeds memory capacity."));
|
||||
return false;
|
||||
}
|
||||
|
||||
float *ptr = buffer;
|
||||
float *ptr = buffer.get();
|
||||
|
||||
decltype(len) s = 0, startrun = 0, stoprun = 0, samps = 0;
|
||||
decltype(blockSize) block = 0;
|
||||
|
@ -187,8 +186,8 @@ bool EffectFindClipping::ProcessOne(LabelTrack * lt,
|
|||
|
||||
block = limitSampleBufferSize( blockSize, len - s );
|
||||
|
||||
wt->Get((samplePtr)buffer, floatSample, start + s, block);
|
||||
ptr = buffer;
|
||||
wt->Get((samplePtr)buffer.get(), floatSample, start + s, block);
|
||||
ptr = buffer.get();
|
||||
}
|
||||
|
||||
float v = fabs(*ptr++);
|
||||
|
@ -226,8 +225,6 @@ bool EffectFindClipping::ProcessOne(LabelTrack * lt,
|
|||
block--;
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return bGoodResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,14 +100,13 @@ EffectNoiseRemoval::EffectNoiseRemoval()
|
|||
mHasProfile = false;
|
||||
mDoProfile = true;
|
||||
|
||||
mNoiseThreshold = new float[mSpectrumSize];
|
||||
mNoiseThreshold.reinit(mSpectrumSize);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
EffectNoiseRemoval::~EffectNoiseRemoval()
|
||||
{
|
||||
delete [] mNoiseThreshold;
|
||||
}
|
||||
|
||||
// IdentInterface implementation
|
||||
|
@ -247,10 +246,10 @@ bool EffectNoiseRemoval::Process()
|
|||
|
||||
void EffectNoiseRemoval::ApplyFreqSmoothing(float *spec)
|
||||
{
|
||||
float *tmp = new float[mSpectrumSize];
|
||||
int i, j, j0, j1;
|
||||
Floats tmp{ mSpectrumSize };
|
||||
int j, j0, j1;
|
||||
|
||||
for(i = 0; i < mSpectrumSize; i++) {
|
||||
for(int i = 0; i < mSpectrumSize; i++) {
|
||||
j0 = wxMax(0, i - mFreqSmoothingBins);
|
||||
j1 = wxMin(mSpectrumSize-1, i + mFreqSmoothingBins);
|
||||
tmp[i] = 0.0;
|
||||
|
@ -260,16 +259,12 @@ void EffectNoiseRemoval::ApplyFreqSmoothing(float *spec)
|
|||
tmp[i] /= (j1 - j0 + 1);
|
||||
}
|
||||
|
||||
for(i = 0; i < mSpectrumSize; i++)
|
||||
for(size_t i = 0; i < mSpectrumSize; i++)
|
||||
spec[i] = tmp[i];
|
||||
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::Initialize()
|
||||
{
|
||||
int i;
|
||||
|
||||
mSampleRate = mProjectRate;
|
||||
mFreqSmoothingBins = (int)(mFreqSmoothingHz * mWindowSize / mSampleRate);
|
||||
mAttackDecayBlocks = 1 +
|
||||
|
@ -287,68 +282,52 @@ void EffectNoiseRemoval::Initialize()
|
|||
if (mHistoryLen < mMinSignalBlocks)
|
||||
mHistoryLen = mMinSignalBlocks;
|
||||
|
||||
mSpectrums = new float*[mHistoryLen];
|
||||
mGains = new float*[mHistoryLen];
|
||||
mRealFFTs = new float*[mHistoryLen];
|
||||
mImagFFTs = new float*[mHistoryLen];
|
||||
for(i = 0; i < mHistoryLen; i++) {
|
||||
mSpectrums[i] = new float[mSpectrumSize];
|
||||
mGains[i] = new float[mSpectrumSize];
|
||||
mRealFFTs[i] = new float[mSpectrumSize];
|
||||
mImagFFTs[i] = new float[mSpectrumSize];
|
||||
}
|
||||
mSpectrums.reinit(mHistoryLen, mSpectrumSize);
|
||||
mGains.reinit(mHistoryLen, mSpectrumSize);
|
||||
mRealFFTs.reinit(mHistoryLen, mSpectrumSize);
|
||||
mImagFFTs.reinit(mHistoryLen, mSpectrumSize);
|
||||
|
||||
// Initialize the FFT
|
||||
hFFT = InitializeFFT(mWindowSize);
|
||||
|
||||
mFFTBuffer = new float[mWindowSize];
|
||||
mInWaveBuffer = new float[mWindowSize];
|
||||
mWindow = new float[mWindowSize];
|
||||
mOutOverlapBuffer = new float[mWindowSize];
|
||||
mFFTBuffer.reinit(mWindowSize);
|
||||
mInWaveBuffer.reinit(mWindowSize);
|
||||
mWindow.reinit(mWindowSize);
|
||||
mOutOverlapBuffer.reinit(mWindowSize);
|
||||
|
||||
// Create a Hanning window function
|
||||
for(i=0; i<mWindowSize; i++)
|
||||
for(size_t i=0; i<mWindowSize; i++)
|
||||
mWindow[i] = 0.5 - 0.5 * cos((2.0*M_PI*i) / mWindowSize);
|
||||
|
||||
if (mDoProfile) {
|
||||
for (i = 0; i < mSpectrumSize; i++)
|
||||
for (size_t i = 0; i < mSpectrumSize; i++)
|
||||
mNoiseThreshold[i] = float(0);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::Cleanup()
|
||||
{
|
||||
int i;
|
||||
|
||||
EndFFT(hFFT);
|
||||
|
||||
if (mDoProfile) {
|
||||
ApplyFreqSmoothing(mNoiseThreshold);
|
||||
ApplyFreqSmoothing(mNoiseThreshold.get());
|
||||
}
|
||||
|
||||
for(i = 0; i < mHistoryLen; i++) {
|
||||
delete[] mSpectrums[i];
|
||||
delete[] mGains[i];
|
||||
delete[] mRealFFTs[i];
|
||||
delete[] mImagFFTs[i];
|
||||
}
|
||||
delete[] mSpectrums;
|
||||
delete[] mGains;
|
||||
delete[] mRealFFTs;
|
||||
delete[] mImagFFTs;
|
||||
mSpectrums.reset();
|
||||
mGains.reset();
|
||||
mRealFFTs.reset();
|
||||
mImagFFTs.reset();
|
||||
|
||||
delete[] mFFTBuffer;
|
||||
delete[] mInWaveBuffer;
|
||||
delete[] mWindow;
|
||||
delete[] mOutOverlapBuffer;
|
||||
mFFTBuffer.reset();
|
||||
mInWaveBuffer.reset();
|
||||
mWindow.reset();
|
||||
mOutOverlapBuffer.reset();
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::StartNewTrack()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i = 0; i < mHistoryLen; i++) {
|
||||
for(j = 0; j < mSpectrumSize; j++) {
|
||||
for(size_t i = 0; i < mHistoryLen; i++) {
|
||||
for(size_t j = 0; j < mSpectrumSize; j++) {
|
||||
mSpectrums[i][j] = 0;
|
||||
mGains[i][j] = mNoiseAttenFactor;
|
||||
mRealFFTs[i][j] = 0.0;
|
||||
|
@ -356,7 +335,7 @@ void EffectNoiseRemoval::StartNewTrack()
|
|||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < mWindowSize; j++)
|
||||
for(size_t j = 0; j < mWindowSize; j++)
|
||||
mOutOverlapBuffer[j] = 0.0;
|
||||
|
||||
mInputPos = 0;
|
||||
|
@ -366,17 +345,15 @@ void EffectNoiseRemoval::StartNewTrack()
|
|||
|
||||
void EffectNoiseRemoval::ProcessSamples(size_t len, float *buffer)
|
||||
{
|
||||
int i;
|
||||
|
||||
while(len && mOutSampleCount < mInSampleCount) {
|
||||
int avail = wxMin(len, mWindowSize - mInputPos);
|
||||
for(i = 0; i < avail; i++)
|
||||
size_t avail = wxMin(len, mWindowSize - mInputPos);
|
||||
for(size_t i = 0; i < avail; i++)
|
||||
mInWaveBuffer[mInputPos + i] = buffer[i];
|
||||
buffer += avail;
|
||||
len -= avail;
|
||||
mInputPos += avail;
|
||||
|
||||
if (mInputPos == mWindowSize) {
|
||||
if (mInputPos == int(mWindowSize)) {
|
||||
FillFirstHistoryWindow();
|
||||
if (mDoProfile)
|
||||
GetProfile();
|
||||
|
@ -385,7 +362,7 @@ void EffectNoiseRemoval::ProcessSamples(size_t len, float *buffer)
|
|||
RotateHistoryWindows();
|
||||
|
||||
// Rotate halfway for overlap-add
|
||||
for(i = 0; i < mWindowSize / 2; i++) {
|
||||
for(size_t i = 0; i < mWindowSize / 2; i++) {
|
||||
mInWaveBuffer[i] = mInWaveBuffer[i + mWindowSize / 2];
|
||||
}
|
||||
mInputPos = mWindowSize / 2;
|
||||
|
@ -395,12 +372,10 @@ void EffectNoiseRemoval::ProcessSamples(size_t len, float *buffer)
|
|||
|
||||
void EffectNoiseRemoval::FillFirstHistoryWindow()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < mWindowSize; i++)
|
||||
for(size_t i = 0; i < mWindowSize; i++)
|
||||
mFFTBuffer[i] = mInWaveBuffer[i];
|
||||
RealFFTf(mFFTBuffer, hFFT);
|
||||
for(i = 1; i < (mSpectrumSize-1); i++) {
|
||||
RealFFTf(mFFTBuffer.get(), hFFT);
|
||||
for(size_t i = 1; i < (mSpectrumSize-1); i++) {
|
||||
mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ];
|
||||
mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1];
|
||||
mSpectrums[0][i] = mRealFFTs[0][i]*mRealFFTs[0][i] + mImagFFTs[0][i]*mImagFFTs[0][i];
|
||||
|
@ -413,30 +388,24 @@ void EffectNoiseRemoval::FillFirstHistoryWindow()
|
|||
mGains[0][mSpectrumSize-1] = mNoiseAttenFactor;
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline void Rotate(ArraysOf<float> &arrays, size_t historyLen)
|
||||
{
|
||||
Floats temp = std::move( arrays[ historyLen - 1 ] );
|
||||
|
||||
for ( size_t nn = historyLen - 1; nn--; )
|
||||
arrays[ nn + 1 ] = std::move( arrays[ nn ] );
|
||||
arrays[0] = std::move( temp );
|
||||
}
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::RotateHistoryWindows()
|
||||
{
|
||||
int last = mHistoryLen - 1;
|
||||
int i;
|
||||
|
||||
// Remember the last window so we can reuse it
|
||||
float *lastSpectrum = mSpectrums[last];
|
||||
float *lastGain = mGains[last];
|
||||
float *lastRealFFT = mRealFFTs[last];
|
||||
float *lastImagFFT = mImagFFTs[last];
|
||||
|
||||
// Rotate each window forward
|
||||
for(i = last; i >= 1; i--) {
|
||||
mSpectrums[i] = mSpectrums[i-1];
|
||||
mGains[i] = mGains[i-1];
|
||||
mRealFFTs[i] = mRealFFTs[i-1];
|
||||
mImagFFTs[i] = mImagFFTs[i-1];
|
||||
}
|
||||
|
||||
// Reuse the last buffers as the NEW first window
|
||||
mSpectrums[0] = lastSpectrum;
|
||||
mGains[0] = lastGain;
|
||||
mRealFFTs[0] = lastRealFFT;
|
||||
mImagFFTs[0] = lastImagFFT;
|
||||
Rotate(mSpectrums, mHistoryLen);
|
||||
Rotate(mGains, mHistoryLen);
|
||||
Rotate(mRealFFTs, mHistoryLen);
|
||||
Rotate(mImagFFTs, mHistoryLen);
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::FinishTrack()
|
||||
|
@ -447,16 +416,13 @@ void EffectNoiseRemoval::FinishTrack()
|
|||
// Well, not exactly, but not more than mWindowSize/2 extra samples at the end.
|
||||
// We'll DELETE them later in ProcessOne.
|
||||
|
||||
float *empty = new float[mWindowSize / 2];
|
||||
int i;
|
||||
for(i = 0; i < mWindowSize / 2; i++)
|
||||
Floats empty{ mWindowSize / 2 };
|
||||
for(size_t i = 0; i < mWindowSize / 2; i++)
|
||||
empty[i] = 0.0;
|
||||
|
||||
while (mOutSampleCount < mInSampleCount) {
|
||||
ProcessSamples(mWindowSize / 2, empty);
|
||||
ProcessSamples(mWindowSize / 2, empty.get());
|
||||
}
|
||||
|
||||
delete [] empty;
|
||||
}
|
||||
|
||||
void EffectNoiseRemoval::GetProfile()
|
||||
|
@ -467,9 +433,9 @@ void EffectNoiseRemoval::GetProfile()
|
|||
|
||||
int start = mHistoryLen - mMinSignalBlocks;
|
||||
int finish = mHistoryLen;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
for (j = 0; j < mSpectrumSize; j++) {
|
||||
for (size_t j = 0; j < mSpectrumSize; j++) {
|
||||
float min = mSpectrums[start][j];
|
||||
for (i = start+1; i < finish; i++) {
|
||||
if (mSpectrums[i][j] < min)
|
||||
|
@ -484,15 +450,14 @@ void EffectNoiseRemoval::GetProfile()
|
|||
|
||||
void EffectNoiseRemoval::RemoveNoise()
|
||||
{
|
||||
int center = mHistoryLen / 2;
|
||||
int start = center - mMinSignalBlocks/2;
|
||||
int finish = start + mMinSignalBlocks;
|
||||
int i, j;
|
||||
size_t center = mHistoryLen / 2;
|
||||
size_t start = center - mMinSignalBlocks/2;
|
||||
size_t finish = start + mMinSignalBlocks;
|
||||
|
||||
// Raise the gain for elements in the center of the sliding history
|
||||
for (j = 0; j < mSpectrumSize; j++) {
|
||||
for (size_t j = 0; j < mSpectrumSize; j++) {
|
||||
float min = mSpectrums[start][j];
|
||||
for (i = start+1; i < finish; i++) {
|
||||
for (size_t i = start+1; i < finish; i++) {
|
||||
if (mSpectrums[i][j] < min)
|
||||
min = mSpectrums[i][j];
|
||||
}
|
||||
|
@ -507,14 +472,14 @@ void EffectNoiseRemoval::RemoveNoise()
|
|||
// Decay the gain in both directions;
|
||||
// note that mOneBlockAttackDecay is less than 1.0
|
||||
// of linear attenuation per block
|
||||
for (j = 0; j < mSpectrumSize; j++) {
|
||||
for (i = center + 1; i < mHistoryLen; i++) {
|
||||
for (size_t j = 0; j < mSpectrumSize; j++) {
|
||||
for (size_t i = center + 1; i < mHistoryLen; i++) {
|
||||
if (mGains[i][j] < mGains[i - 1][j] * mOneBlockAttackDecay)
|
||||
mGains[i][j] = mGains[i - 1][j] * mOneBlockAttackDecay;
|
||||
if (mGains[i][j] < mNoiseAttenFactor)
|
||||
mGains[i][j] = mNoiseAttenFactor;
|
||||
}
|
||||
for (i = center - 1; i >= 0; i--) {
|
||||
for (size_t i = center; i--;) {
|
||||
if (mGains[i][j] < mGains[i + 1][j] * mOneBlockAttackDecay)
|
||||
mGains[i][j] = mGains[i + 1][j] * mOneBlockAttackDecay;
|
||||
if (mGains[i][j] < mNoiseAttenFactor)
|
||||
|
@ -526,10 +491,10 @@ void EffectNoiseRemoval::RemoveNoise()
|
|||
// Apply frequency smoothing to output gain
|
||||
int out = mHistoryLen - 1; // end of the queue
|
||||
|
||||
ApplyFreqSmoothing(mGains[out]);
|
||||
ApplyFreqSmoothing(mGains[out].get());
|
||||
|
||||
// Apply gain to FFT
|
||||
for (j = 0; j < (mSpectrumSize-1); j++) {
|
||||
for (size_t j = 0; j < (mSpectrumSize-1); j++) {
|
||||
mFFTBuffer[j*2 ] = mRealFFTs[out][j] * mGains[out][j];
|
||||
mFFTBuffer[j*2+1] = mImagFFTs[out][j] * mGains[out][j];
|
||||
}
|
||||
|
@ -537,10 +502,10 @@ void EffectNoiseRemoval::RemoveNoise()
|
|||
mFFTBuffer[1] = mRealFFTs[out][mSpectrumSize-1] * mGains[out][mSpectrumSize-1];
|
||||
|
||||
// Invert the FFT into the output buffer
|
||||
InverseRealFFTf(mFFTBuffer, hFFT);
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT);
|
||||
|
||||
// Overlap-add
|
||||
for(j = 0; j < (mSpectrumSize-1); j++) {
|
||||
for(size_t j = 0; j < (mSpectrumSize-1); j++) {
|
||||
mOutOverlapBuffer[j*2 ] += mFFTBuffer[hFFT->BitReversed[j] ] * mWindow[j*2 ];
|
||||
mOutOverlapBuffer[j*2+1] += mFFTBuffer[hFFT->BitReversed[j]+1] * mWindow[j*2+1];
|
||||
}
|
||||
|
@ -548,11 +513,11 @@ void EffectNoiseRemoval::RemoveNoise()
|
|||
// Output the first half of the overlap buffer, they're done -
|
||||
// and then shift the next half over.
|
||||
if (mOutSampleCount >= 0) { // ...but not if it's the first half-window
|
||||
mOutputTrack->Append((samplePtr)mOutOverlapBuffer, floatSample,
|
||||
mOutputTrack->Append((samplePtr)mOutOverlapBuffer.get(), floatSample,
|
||||
mWindowSize / 2);
|
||||
}
|
||||
mOutSampleCount += mWindowSize / 2;
|
||||
for(j = 0; j < mWindowSize / 2; j++) {
|
||||
for(size_t j = 0; j < mWindowSize / 2; j++) {
|
||||
mOutOverlapBuffer[j] = mOutOverlapBuffer[j + (mWindowSize / 2)];
|
||||
mOutOverlapBuffer[j + (mWindowSize / 2)] = 0.0;
|
||||
}
|
||||
|
@ -571,7 +536,7 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
|
|||
track->GetRate());
|
||||
|
||||
auto bufferSize = track->GetMaxBlockSize();
|
||||
float *buffer = new float[bufferSize];
|
||||
Floats buffer{ bufferSize };
|
||||
|
||||
bool bLoopSuccess = true;
|
||||
auto samplePos = start;
|
||||
|
@ -584,10 +549,10 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
|
|||
);
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr)buffer, floatSample, samplePos, blockSize);
|
||||
track->Get((samplePtr)buffer.get(), floatSample, samplePos, blockSize);
|
||||
|
||||
mInSampleCount += blockSize;
|
||||
ProcessSamples(blockSize, buffer);
|
||||
ProcessSamples(blockSize, buffer.get());
|
||||
|
||||
samplePos += blockSize;
|
||||
|
||||
|
@ -599,7 +564,6 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
|
|||
}
|
||||
|
||||
FinishTrack();
|
||||
delete [] buffer;
|
||||
|
||||
if (!mDoProfile) {
|
||||
// Flush the output WaveTrack (since it's buffered)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Effect.h"
|
||||
|
||||
#include "../MemoryX.h"
|
||||
#include "../SampleFormat.h"
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/slider.h>
|
||||
|
||||
|
@ -70,12 +71,12 @@ private:
|
|||
// Parameters chosen before the first phase
|
||||
double mSampleRate;
|
||||
size_t mWindowSize;
|
||||
int mSpectrumSize;
|
||||
size_t mSpectrumSize;
|
||||
float mMinSignalTime; // in secs
|
||||
|
||||
// The frequency-indexed noise threshold derived during the first
|
||||
// phase of analysis
|
||||
float *mNoiseThreshold; // length is mSpectrumSize
|
||||
Floats mNoiseThreshold; // length is mSpectrumSize
|
||||
|
||||
// Parameters that affect the noise removal, regardless of how the
|
||||
// noise profile was extracted
|
||||
|
@ -106,22 +107,22 @@ private:
|
|||
int mInputPos;
|
||||
|
||||
HFFT hFFT;
|
||||
float *mFFTBuffer; // mWindowSize
|
||||
float *mWindow; // mWindowSize
|
||||
Floats mFFTBuffer; // mWindowSize
|
||||
Floats mWindow; // mWindowSize
|
||||
|
||||
int mFreqSmoothingBins;
|
||||
int mAttackDecayBlocks;
|
||||
float mOneBlockAttackDecay;
|
||||
float mNoiseAttenFactor;
|
||||
float mSensitivityFactor;
|
||||
int mMinSignalBlocks;
|
||||
int mHistoryLen;
|
||||
float *mInWaveBuffer; // mWindowSize
|
||||
float *mOutOverlapBuffer; // mWindowSize
|
||||
float **mSpectrums; // mHistoryLen x mSpectrumSize
|
||||
float **mGains; // mHistoryLen x mSpectrumSize
|
||||
float **mRealFFTs; // mHistoryLen x mWindowSize
|
||||
float **mImagFFTs; // mHistoryLen x mWindowSize
|
||||
size_t mMinSignalBlocks;
|
||||
size_t mHistoryLen;
|
||||
Floats mInWaveBuffer; // mWindowSize
|
||||
Floats mOutOverlapBuffer; // mWindowSize
|
||||
ArraysOf<float> mSpectrums; // mHistoryLen x mSpectrumSize
|
||||
ArraysOf<float> mGains; // mHistoryLen x mSpectrumSize
|
||||
ArraysOf<float> mRealFFTs; // mHistoryLen x mWindowSize
|
||||
ArraysOf<float> mImagFFTs; // mHistoryLen x mWindowSize
|
||||
|
||||
friend class NoiseRemovalDialog;
|
||||
};
|
||||
|
|
|
@ -384,7 +384,7 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg,
|
|||
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
float *buffer = new float[track->GetMaxBlockSize()];
|
||||
Floats buffer{ track->GetMaxBlockSize() };
|
||||
|
||||
mSum = 0.0; // dc offset inits
|
||||
mCount = 0;
|
||||
|
@ -401,10 +401,10 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg,
|
|||
);
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer, floatSample, s, block);
|
||||
track->Get((samplePtr) buffer.get(), floatSample, s, block);
|
||||
|
||||
//Process the buffer.
|
||||
AnalyzeData(buffer, block);
|
||||
AnalyzeData(buffer.get(), block);
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
|
@ -417,9 +417,6 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg,
|
|||
}
|
||||
}
|
||||
|
||||
//Clean up the buffer
|
||||
delete[] buffer;
|
||||
|
||||
offset = -mSum / mCount.as_double(); // calculate actual offset (amount that needs to be added on)
|
||||
|
||||
//Return true because the effect processing succeeded ... unless cancelled
|
||||
|
@ -446,7 +443,7 @@ bool EffectNormalize::ProcessOne(
|
|||
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
float *buffer = new float[track->GetMaxBlockSize()];
|
||||
Floats buffer{ track->GetMaxBlockSize() };
|
||||
|
||||
//Go through the track one buffer at a time. s counts which
|
||||
//sample the current buffer starts at.
|
||||
|
@ -460,13 +457,13 @@ bool EffectNormalize::ProcessOne(
|
|||
);
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer, floatSample, s, block);
|
||||
track->Get((samplePtr) buffer.get(), floatSample, s, block);
|
||||
|
||||
//Process the buffer.
|
||||
ProcessData(buffer, block, offset);
|
||||
ProcessData(buffer.get(), block, offset);
|
||||
|
||||
//Copy the newly-changed samples back onto the track.
|
||||
track->Set((samplePtr) buffer, floatSample, s, block);
|
||||
track->Set((samplePtr) buffer.get(), floatSample, s, block);
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
|
@ -478,8 +475,6 @@ bool EffectNormalize::ProcessOne(
|
|||
break;
|
||||
}
|
||||
}
|
||||
//Clean up the buffer
|
||||
delete[] buffer;
|
||||
|
||||
//Return true because the effect processing succeeded ... unless cancelled
|
||||
return rc;
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
//in_bufsize is also a half of a FFT buffer (in samples)
|
||||
virtual ~PaulStretch();
|
||||
|
||||
void process(float *smps,int nsmps);
|
||||
void process(float *smps, size_t nsmps);
|
||||
|
||||
size_t get_nsamples();//how many samples are required to be added in the pool next time
|
||||
size_t get_nsamples_for_fill();//how many samples are required to be added for a complete buffer refill (at start of the song or after seek)
|
||||
|
@ -59,24 +59,20 @@ private:
|
|||
|
||||
public:
|
||||
const size_t out_bufsize;
|
||||
float *const out_buf;
|
||||
const Floats out_buf;
|
||||
|
||||
private:
|
||||
float *const old_out_smp_buf;
|
||||
const Floats old_out_smp_buf;
|
||||
|
||||
public:
|
||||
const size_t poolsize;//how many samples are inside the input_pool size (need to know how many samples to fill when seeking)
|
||||
|
||||
private:
|
||||
float *const in_pool;//de marimea in_bufsize
|
||||
const Floats in_pool;//de marimea in_bufsize
|
||||
|
||||
double remained_samples;//how many fraction of samples has remained (0..1)
|
||||
|
||||
float *const fft_smps;
|
||||
float *const fft_c;
|
||||
float *const fft_s;
|
||||
float *const fft_freq;
|
||||
float *const fft_tmp;
|
||||
const Floats fft_smps, fft_c, fft_s, fft_freq, fft_tmp;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -329,58 +325,59 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun
|
|||
auto nget = stretch.get_nsamples_for_fill();
|
||||
|
||||
auto bufsize = stretch.poolsize;
|
||||
float *buffer0 = new float[bufsize];
|
||||
float *bufferptr0 = buffer0;
|
||||
Floats buffer0{ bufsize };
|
||||
float *bufferptr0 = buffer0.get();
|
||||
bool first_time = true;
|
||||
|
||||
const auto fade_len = std::min<size_t>(100, bufsize / 2 - 1);
|
||||
float *fade_track_smps = new float[fade_len];
|
||||
decltype(len) s = 0;
|
||||
bool cancelled = false;
|
||||
|
||||
while (s < len) {
|
||||
track->Get((samplePtr)bufferptr0, floatSample, start + s, nget);
|
||||
stretch.process(buffer0, nget);
|
||||
{
|
||||
Floats fade_track_smps{ fade_len };
|
||||
decltype(len) s=0;
|
||||
|
||||
if (first_time) {
|
||||
stretch.process(buffer0, 0);
|
||||
};
|
||||
while (s < len) {
|
||||
track->Get((samplePtr)bufferptr0, floatSample, start + s, nget);
|
||||
stretch.process(buffer0.get(), nget);
|
||||
|
||||
s += nget;
|
||||
|
||||
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 (first_time) {
|
||||
stretch.process(buffer0.get(), 0);
|
||||
};
|
||||
};
|
||||
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;
|
||||
auto 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);
|
||||
s += nget;
|
||||
|
||||
nget = stretch.get_nsamples();
|
||||
if (TrackProgress(count,
|
||||
s.as_double() / len.as_double()
|
||||
)) {
|
||||
cancelled=true;
|
||||
break;
|
||||
if (first_time){//blend the the start of the selection
|
||||
track->Get((samplePtr)fade_track_smps.get(), floatSample, start, fade_len);
|
||||
first_time = false;
|
||||
for (size_t 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.get(), floatSample, end - fade_len, fade_len);
|
||||
for (size_t i = 0; i < fade_len; i++){
|
||||
float fi = (float)i / (float)fade_len;
|
||||
auto 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.get(), floatSample, stretch.out_bufsize);
|
||||
|
||||
nget = stretch.get_nsamples();
|
||||
if (TrackProgress(count,
|
||||
s.as_double() / len.as_double()
|
||||
)) {
|
||||
cancelled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] fade_track_smps;
|
||||
outputTrack->Flush();
|
||||
|
||||
track->Clear(t0,t1);
|
||||
|
@ -389,8 +386,6 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun
|
|||
m_t1 = mT0 + outputTrack->GetEndTime();
|
||||
}
|
||||
|
||||
delete []buffer0;
|
||||
|
||||
return !cancelled;
|
||||
}
|
||||
catch ( const std::bad_alloc& ) {
|
||||
|
@ -407,32 +402,24 @@ PaulStretch::PaulStretch(float rap_, size_t in_bufsize_, float samplerate_ )
|
|||
, rap { std::max(1.0f, rap_) }
|
||||
, in_bufsize { in_bufsize_ }
|
||||
, out_bufsize { std::max(size_t{ 8 }, in_bufsize) }
|
||||
, out_buf { new float[out_bufsize] }
|
||||
, old_out_smp_buf { new float[out_bufsize * 2] { 0.0f } }
|
||||
, out_buf { out_bufsize }
|
||||
, old_out_smp_buf { out_bufsize * 2, true }
|
||||
, poolsize { in_bufsize_ * 2 }
|
||||
, in_pool { new float[poolsize] { 0.0f } }
|
||||
, in_pool { poolsize, true }
|
||||
, remained_samples { 0.0 }
|
||||
, fft_smps { new float[poolsize] { 0.0f } }
|
||||
, fft_s { new float[poolsize] { 0.0f } }
|
||||
, fft_c { new float[poolsize] { 0.0f } }
|
||||
, fft_freq { new float[poolsize] { 0.0f } }
|
||||
, fft_tmp { new float[poolsize] }
|
||||
, fft_smps { poolsize, true }
|
||||
, fft_s { poolsize, true }
|
||||
, fft_c { poolsize, true }
|
||||
, fft_freq { poolsize, true }
|
||||
, fft_tmp { poolsize }
|
||||
{
|
||||
}
|
||||
|
||||
PaulStretch::~PaulStretch()
|
||||
{
|
||||
delete [] out_buf;
|
||||
delete [] old_out_smp_buf;
|
||||
delete [] in_pool;
|
||||
delete [] fft_smps;
|
||||
delete [] fft_c;
|
||||
delete [] fft_s;
|
||||
delete [] fft_freq;
|
||||
delete [] fft_tmp;
|
||||
}
|
||||
|
||||
void PaulStretch::process(float *smps,int nsmps)
|
||||
void PaulStretch::process(float *smps, size_t nsmps)
|
||||
{
|
||||
//add NEW samples to the pool
|
||||
if ((smps != NULL) && (nsmps != 0)) {
|
||||
|
@ -446,20 +433,20 @@ void PaulStretch::process(float *smps,int nsmps)
|
|||
in_pool[i] = in_pool[i + nsmps];
|
||||
|
||||
//add NEW samples to the pool
|
||||
for (int i = 0; i < nsmps; i++)
|
||||
for (size_t i = 0; i < nsmps; i++)
|
||||
in_pool[i + nleft] = smps[i];
|
||||
}
|
||||
|
||||
//get the samples from the pool
|
||||
for (size_t i = 0; i < poolsize; i++)
|
||||
fft_smps[i] = in_pool[i];
|
||||
WindowFunc(eWinFuncHanning, poolsize, fft_smps);
|
||||
WindowFunc(eWinFuncHanning, poolsize, fft_smps.get());
|
||||
|
||||
RealFFT(poolsize, fft_smps, fft_c, fft_s);
|
||||
RealFFT(poolsize, fft_smps.get(), fft_c.get(), fft_s.get());
|
||||
|
||||
for (size_t i = 0; i < poolsize / 2; i++)
|
||||
fft_freq[i] = sqrt(fft_c[i] * fft_c[i] + fft_s[i] * fft_s[i]);
|
||||
process_spectrum(fft_freq);
|
||||
process_spectrum(fft_freq.get());
|
||||
|
||||
|
||||
//put randomize phases to frequencies and do a IFFT
|
||||
|
@ -477,7 +464,7 @@ void PaulStretch::process(float *smps,int nsmps)
|
|||
fft_c[0] = fft_s[0] = 0.0;
|
||||
fft_c[poolsize / 2] = fft_s[poolsize / 2] = 0.0;
|
||||
|
||||
FFT(poolsize, true, fft_c, fft_s, fft_smps, fft_tmp);
|
||||
FFT(poolsize, true, fft_c.get(), fft_s.get(), fft_smps.get(), fft_tmp.get());
|
||||
|
||||
float max = 0.0, max2 = 0.0;
|
||||
for (size_t i = 0; i < poolsize; i++) {
|
||||
|
|
|
@ -138,11 +138,10 @@ bool EffectRepair::ProcessOne(int count, WaveTrack * track,
|
|||
size_t len,
|
||||
size_t repairStart, size_t repairLen)
|
||||
{
|
||||
float *buffer = new float[len];
|
||||
track->Get((samplePtr) buffer, floatSample, start, len);
|
||||
InterpolateAudio(buffer, len, repairStart, repairLen);
|
||||
Floats buffer{ len };
|
||||
track->Get((samplePtr) buffer.get(), floatSample, start, len);
|
||||
InterpolateAudio(buffer.get(), len, repairStart, repairLen);
|
||||
track->Set((samplePtr)&buffer[repairStart], floatSample,
|
||||
start + repairStart, repairLen);
|
||||
delete[] buffer;
|
||||
return !TrackProgress(count, 1.0); // TrackProgress returns true on Cancel.
|
||||
}
|
||||
|
|
|
@ -222,8 +222,8 @@ bool EffectReverse::ProcessOneClip(int count, WaveTrack *track,
|
|||
|
||||
auto blockSize = track->GetMaxBlockSize();
|
||||
float tmp;
|
||||
float *buffer1 = new float[blockSize];
|
||||
float *buffer2 = new float[blockSize];
|
||||
Floats buffer1{ blockSize };
|
||||
Floats buffer2{ blockSize };
|
||||
|
||||
auto originalLen = originalEnd - originalStart;
|
||||
|
||||
|
@ -232,15 +232,15 @@ bool EffectReverse::ProcessOneClip(int count, WaveTrack *track,
|
|||
limitSampleBufferSize( track->GetBestBlockSize(first), len / 2 );
|
||||
auto second = first + (len - block);
|
||||
|
||||
track->Get((samplePtr)buffer1, floatSample, first, block);
|
||||
track->Get((samplePtr)buffer2, floatSample, second, block);
|
||||
track->Get((samplePtr)buffer1.get(), floatSample, first, block);
|
||||
track->Get((samplePtr)buffer2.get(), floatSample, second, block);
|
||||
for (decltype(block) i = 0; i < block; i++) {
|
||||
tmp = buffer1[i];
|
||||
buffer1[i] = buffer2[block-i-1];
|
||||
buffer2[block-i-1] = tmp;
|
||||
}
|
||||
track->Set((samplePtr)buffer1, floatSample, first, block);
|
||||
track->Set((samplePtr)buffer2, floatSample, second, block);
|
||||
track->Set((samplePtr)buffer1.get(), floatSample, first, block);
|
||||
track->Set((samplePtr)buffer2.get(), floatSample, second, block);
|
||||
|
||||
len -= 2 * block;
|
||||
first += block;
|
||||
|
@ -252,8 +252,5 @@ bool EffectReverse::ProcessOneClip(int count, WaveTrack *track,
|
|||
}
|
||||
}
|
||||
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ BEGIN_EVENT_TABLE(EffectScienFilter, wxEvtHandler)
|
|||
END_EVENT_TABLE()
|
||||
|
||||
EffectScienFilter::EffectScienFilter()
|
||||
: mpBiquad{ size_t( MAX_Order / 2 ), true }
|
||||
{
|
||||
mOrder = DEF_Order;
|
||||
mFilterType = DEF_Type;
|
||||
|
@ -170,18 +171,10 @@ EffectScienFilter::EffectScienFilter()
|
|||
|
||||
mLoFreq = 20; // Lowest frequency to display in response graph
|
||||
mNyquist = 44100.0 / 2.0; // only used during initialization, updated when effect is used
|
||||
|
||||
mpBiquad = new BiquadStruct[MAX_Order / 2];
|
||||
memset(mpBiquad, 0, sizeof(BiquadStruct) * MAX_Order / 2);
|
||||
for (int i = 0; i < MAX_Order / 2; i++)
|
||||
{
|
||||
mpBiquad[i].fNumerCoeffs[0] = 1.0; // straight-through
|
||||
}
|
||||
}
|
||||
|
||||
EffectScienFilter::~EffectScienFilter()
|
||||
{
|
||||
delete [] mpBiquad;
|
||||
}
|
||||
|
||||
// IdentInterface implementation
|
||||
|
|
|
@ -100,7 +100,7 @@ private:
|
|||
int mFilterSubtype; // lowpass, highpass
|
||||
int mOrder;
|
||||
int mOrderIndex;
|
||||
BiquadStruct *mpBiquad;
|
||||
ArrayOf<BiquadStruct> mpBiquad;
|
||||
|
||||
double mdBMax;
|
||||
double mdBMin;
|
||||
|
|
|
@ -88,7 +88,7 @@ bool EffectSimpleMono::ProcessOne(WaveTrack * track,
|
|||
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
float *buffer = new float[track->GetMaxBlockSize()];
|
||||
Floats buffer{ track->GetMaxBlockSize() };
|
||||
|
||||
//Go through the track one buffer at a time. s counts which
|
||||
//sample the current buffer starts at.
|
||||
|
@ -100,19 +100,17 @@ bool EffectSimpleMono::ProcessOne(WaveTrack * track,
|
|||
limitSampleBufferSize( track->GetBestBlockSize(s), end - s );
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer, floatSample, s, block);
|
||||
track->Get((samplePtr) buffer.get(), floatSample, s, block);
|
||||
|
||||
//Process the buffer. If it fails, clean up and exit.
|
||||
if (!ProcessSimpleMono(buffer, block)) {
|
||||
delete[]buffer;
|
||||
|
||||
if (!ProcessSimpleMono(buffer.get(), block)) {
|
||||
//Return false because the effect failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
//Processing succeeded. copy the newly-changed samples back
|
||||
//onto the track.
|
||||
track->Set((samplePtr) buffer, floatSample, s, block);
|
||||
track->Set((samplePtr) buffer.get(), floatSample, s, block);
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
|
@ -121,14 +119,10 @@ bool EffectSimpleMono::ProcessOne(WaveTrack * track,
|
|||
if (TrackProgress(mCurTrackNum,
|
||||
(s - start).as_double() /
|
||||
len)) {
|
||||
delete[]buffer;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Clean up the buffer
|
||||
delete[]buffer;
|
||||
|
||||
//Return true because the effect processing succeeded.
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -182,58 +182,55 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
|||
//to make it a double now than it is to do it later
|
||||
auto len = (end - start).as_double();
|
||||
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
float *buffer = new float[track->GetMaxBlockSize()];
|
||||
{
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
Floats buffer{ track->GetMaxBlockSize() };
|
||||
|
||||
//Go through the track one buffer at a time. s counts which
|
||||
//sample the current buffer starts at.
|
||||
auto s = start;
|
||||
while (s < end) {
|
||||
//Get a block of samples (smaller than the size of the buffer)
|
||||
const auto block =
|
||||
limitSampleBufferSize( track->GetBestBlockSize(s), end - s );
|
||||
//Go through the track one buffer at a time. s counts which
|
||||
//sample the current buffer starts at.
|
||||
auto s = start;
|
||||
while (s < end) {
|
||||
//Get a block of samples (smaller than the size of the buffer)
|
||||
const auto block =
|
||||
limitSampleBufferSize( track->GetBestBlockSize(s), end - s );
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer, floatSample, s, block);
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr)buffer.get(), floatSample, s, block);
|
||||
|
||||
//Add samples to SoundTouch
|
||||
mSoundTouch->putSamples(buffer, block);
|
||||
//Add samples to SoundTouch
|
||||
mSoundTouch->putSamples(buffer.get(), block);
|
||||
|
||||
//Get back samples from SoundTouch
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0) {
|
||||
float *buffer2 = new float[outputCount];
|
||||
mSoundTouch->receiveSamples(buffer2, outputCount);
|
||||
outputTrack->Append((samplePtr)buffer2, floatSample, outputCount);
|
||||
delete[] buffer2;
|
||||
//Get back samples from SoundTouch
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0) {
|
||||
Floats buffer2{ outputCount };
|
||||
mSoundTouch->receiveSamples(buffer2.get(), outputCount);
|
||||
outputTrack->Append((samplePtr)buffer2.get(), floatSample, outputCount);
|
||||
}
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
|
||||
//Update the Progress meter
|
||||
if (TrackProgress(mCurTrackNum, (s - start).as_double() / len))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += block;
|
||||
// Tell SoundTouch to finish processing any remaining samples
|
||||
mSoundTouch->flush(); // this should only be used for changeTempo - it dumps data otherwise with pRateTransposer->clear();
|
||||
|
||||
//Update the Progress meter
|
||||
if (TrackProgress(mCurTrackNum, (s - start).as_double() / len))
|
||||
return false;
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0) {
|
||||
Floats buffer2{ outputCount };
|
||||
mSoundTouch->receiveSamples(buffer2.get(), outputCount);
|
||||
outputTrack->Append((samplePtr)buffer2.get(), floatSample, outputCount);
|
||||
}
|
||||
|
||||
// Flush the output WaveTrack (since it's buffered, too)
|
||||
outputTrack->Flush();
|
||||
}
|
||||
|
||||
// Tell SoundTouch to finish processing any remaining samples
|
||||
mSoundTouch->flush(); // this should only be used for changeTempo - it dumps data otherwise with pRateTransposer->clear();
|
||||
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0) {
|
||||
float *buffer2 = new float[outputCount];
|
||||
mSoundTouch->receiveSamples(buffer2, outputCount);
|
||||
outputTrack->Append((samplePtr)buffer2, floatSample, outputCount);
|
||||
delete[] buffer2;
|
||||
}
|
||||
|
||||
// Flush the output WaveTrack (since it's buffered, too)
|
||||
outputTrack->Flush();
|
||||
|
||||
// Clean up the buffer
|
||||
delete[]buffer;
|
||||
|
||||
// Take the output track and insert it in place of the original
|
||||
// sample data
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, false, &warper);
|
||||
|
@ -249,7 +246,7 @@ bool EffectSoundTouch::ProcessStereo(
|
|||
WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end, const TimeWarper &warper)
|
||||
{
|
||||
mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate()+0.5));
|
||||
mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate() + 0.5));
|
||||
|
||||
auto outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
|
||||
leftTrack->GetRate());
|
||||
|
@ -267,75 +264,70 @@ bool EffectSoundTouch::ProcessStereo(
|
|||
// because Soundtouch wants them interleaved, i.e., each
|
||||
// Soundtouch sample is left-right pair.
|
||||
auto maxBlockSize = leftTrack->GetMaxBlockSize();
|
||||
float* leftBuffer = new float[maxBlockSize];
|
||||
float* rightBuffer = new float[maxBlockSize];
|
||||
float* soundTouchBuffer = new float[maxBlockSize * 2];
|
||||
{
|
||||
Floats leftBuffer{ maxBlockSize };
|
||||
Floats rightBuffer{ maxBlockSize };
|
||||
Floats soundTouchBuffer{ maxBlockSize * 2 };
|
||||
|
||||
// Go through the track one stereo buffer at a time.
|
||||
// sourceSampleCount counts the sample at which the current buffer starts,
|
||||
// per channel.
|
||||
auto sourceSampleCount = start;
|
||||
while (sourceSampleCount < end) {
|
||||
//Get a block of samples (smaller than the size of the buffer)
|
||||
//Adjust the block size if it is the final block in the track
|
||||
auto blockSize = limitSampleBufferSize(
|
||||
leftTrack->GetBestBlockSize(sourceSampleCount),
|
||||
end - sourceSampleCount
|
||||
);
|
||||
// Go through the track one stereo buffer at a time.
|
||||
// sourceSampleCount counts the sample at which the current buffer starts,
|
||||
// per channel.
|
||||
auto sourceSampleCount = start;
|
||||
while (sourceSampleCount < end) {
|
||||
auto blockSize = limitSampleBufferSize(
|
||||
leftTrack->GetBestBlockSize(sourceSampleCount),
|
||||
end - sourceSampleCount
|
||||
);
|
||||
|
||||
// Get the samples from the tracks and put them in the buffers.
|
||||
leftTrack->Get((samplePtr)(leftBuffer), floatSample, sourceSampleCount, blockSize);
|
||||
rightTrack->Get((samplePtr)(rightBuffer), floatSample, sourceSampleCount, blockSize);
|
||||
// Get the samples from the tracks and put them in the buffers.
|
||||
leftTrack->Get((samplePtr)(leftBuffer.get()), floatSample, sourceSampleCount, blockSize);
|
||||
rightTrack->Get((samplePtr)(rightBuffer.get()), floatSample, sourceSampleCount, blockSize);
|
||||
|
||||
// Interleave into soundTouchBuffer.
|
||||
for (decltype(blockSize) index = 0; index < blockSize; index++) {
|
||||
soundTouchBuffer[index*2] = leftBuffer[index];
|
||||
soundTouchBuffer[(index*2)+1] = rightBuffer[index];
|
||||
// Interleave into soundTouchBuffer.
|
||||
for (decltype(blockSize) index = 0; index < blockSize; index++) {
|
||||
soundTouchBuffer[index * 2] = leftBuffer[index];
|
||||
soundTouchBuffer[(index * 2) + 1] = rightBuffer[index];
|
||||
}
|
||||
|
||||
//Add samples to SoundTouch
|
||||
mSoundTouch->putSamples(soundTouchBuffer.get(), blockSize);
|
||||
|
||||
//Get back samples from SoundTouch
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0)
|
||||
this->ProcessStereoResults(outputCount, outputLeftTrack.get(), outputRightTrack.get());
|
||||
|
||||
//Increment sourceSampleCount one blockfull of samples
|
||||
sourceSampleCount += blockSize;
|
||||
|
||||
//Update the Progress meter
|
||||
// mCurTrackNum is left track. Include right track.
|
||||
int nWhichTrack = mCurTrackNum;
|
||||
double frac = (sourceSampleCount - start).as_double() / len;
|
||||
if (frac < 0.5)
|
||||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
else
|
||||
{
|
||||
nWhichTrack++;
|
||||
frac -= 0.5;
|
||||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
}
|
||||
if (TrackProgress(nWhichTrack, frac))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Add samples to SoundTouch
|
||||
mSoundTouch->putSamples(soundTouchBuffer, blockSize);
|
||||
// Tell SoundTouch to finish processing any remaining samples
|
||||
mSoundTouch->flush();
|
||||
|
||||
//Get back samples from SoundTouch
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0)
|
||||
this->ProcessStereoResults(outputCount, outputLeftTrack.get(), outputRightTrack.get());
|
||||
|
||||
//Increment sourceSampleCount one blockfull of samples
|
||||
sourceSampleCount += blockSize;
|
||||
|
||||
//Update the Progress meter
|
||||
// mCurTrackNum is left track. Include right track.
|
||||
int nWhichTrack = mCurTrackNum;
|
||||
double frac = (sourceSampleCount - start).as_double() / len;
|
||||
if (frac < 0.5)
|
||||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
else
|
||||
{
|
||||
nWhichTrack++;
|
||||
frac -= 0.5;
|
||||
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
|
||||
}
|
||||
if (TrackProgress(nWhichTrack, frac))
|
||||
return false;
|
||||
// Flush the output WaveTracks (since they're buffered, too)
|
||||
outputLeftTrack->Flush();
|
||||
outputRightTrack->Flush();
|
||||
}
|
||||
|
||||
// Tell SoundTouch to finish processing any remaining samples
|
||||
mSoundTouch->flush();
|
||||
|
||||
unsigned int outputCount = mSoundTouch->numSamples();
|
||||
if (outputCount > 0)
|
||||
this->ProcessStereoResults(outputCount, outputLeftTrack.get(), outputRightTrack.get());
|
||||
|
||||
// Flush the output WaveTracks (since they're buffered, too)
|
||||
outputLeftTrack->Flush();
|
||||
outputRightTrack->Flush();
|
||||
|
||||
// Clean up the buffers.
|
||||
delete [] leftBuffer;
|
||||
delete [] rightBuffer;
|
||||
delete [] soundTouchBuffer;
|
||||
|
||||
// Take the output tracks and insert in place of the original
|
||||
// sample data.
|
||||
leftTrack->ClearAndPaste(
|
||||
|
@ -357,24 +349,20 @@ bool EffectSoundTouch::ProcessStereoResults(const unsigned int outputCount,
|
|||
WaveTrack* outputLeftTrack,
|
||||
WaveTrack* outputRightTrack)
|
||||
{
|
||||
float* outputSoundTouchBuffer = new float[outputCount*2];
|
||||
mSoundTouch->receiveSamples(outputSoundTouchBuffer, outputCount);
|
||||
Floats outputSoundTouchBuffer{ outputCount * 2 };
|
||||
mSoundTouch->receiveSamples(outputSoundTouchBuffer.get(), outputCount);
|
||||
|
||||
// Dis-interleave outputSoundTouchBuffer into separate track buffers.
|
||||
float* outputLeftBuffer = new float[outputCount];
|
||||
float* outputRightBuffer = new float[outputCount];
|
||||
Floats outputLeftBuffer{ outputCount };
|
||||
Floats outputRightBuffer{ outputCount };
|
||||
for (unsigned int index = 0; index < outputCount; index++)
|
||||
{
|
||||
outputLeftBuffer[index] = outputSoundTouchBuffer[index*2];
|
||||
outputRightBuffer[index] = outputSoundTouchBuffer[(index*2)+1];
|
||||
}
|
||||
|
||||
outputLeftTrack->Append((samplePtr)outputLeftBuffer, floatSample, outputCount);
|
||||
outputRightTrack->Append((samplePtr)outputRightBuffer, floatSample, outputCount);
|
||||
|
||||
delete[] outputSoundTouchBuffer;
|
||||
delete[] outputLeftBuffer;
|
||||
delete[] outputRightBuffer;
|
||||
outputLeftTrack->Append((samplePtr)outputLeftBuffer.get(), floatSample, outputCount);
|
||||
outputRightTrack->Append((samplePtr)outputRightBuffer.get(), floatSample, outputCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -138,13 +138,13 @@ bool EffectStereoToMono::ProcessOne(int count)
|
|||
|
||||
auto idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
|
||||
auto index = mStart;
|
||||
float *leftBuffer = new float[idealBlockLen];
|
||||
float *rightBuffer = new float[idealBlockLen];
|
||||
Floats leftBuffer { idealBlockLen };
|
||||
Floats rightBuffer{ idealBlockLen };
|
||||
bool bResult = true;
|
||||
|
||||
while (index < mEnd) {
|
||||
bResult &= mLeftTrack->Get((samplePtr)leftBuffer, floatSample, index, idealBlockLen);
|
||||
bResult &= mRightTrack->Get((samplePtr)rightBuffer, floatSample, index, idealBlockLen);
|
||||
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);
|
||||
bResult &= mRightTrack->Get((samplePtr)rightBuffer.get(), floatSample, index, idealBlockLen);
|
||||
auto limit = limitSampleBufferSize( idealBlockLen, mEnd - index );
|
||||
for (decltype(limit) i = 0; i < limit; ++i) {
|
||||
index++;
|
||||
|
@ -153,7 +153,7 @@ bool EffectStereoToMono::ProcessOne(int count)
|
|||
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
|
||||
leftBuffer[i] = curMonoFrame;
|
||||
}
|
||||
bResult &= mOutTrack->Append((samplePtr)leftBuffer, floatSample, limit);
|
||||
bResult &= mOutTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit);
|
||||
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
|
||||
return false;
|
||||
}
|
||||
|
@ -167,9 +167,6 @@ bool EffectStereoToMono::ProcessOne(int count)
|
|||
mLeftTrack->SetChannel(Track::MonoChannel);
|
||||
mOutputTracks->Remove(mRightTrack);
|
||||
|
||||
delete [] leftBuffer;
|
||||
delete [] rightBuffer;
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -500,13 +500,13 @@ bool EffectTruncSilence::DoRemoval
|
|||
}
|
||||
|
||||
// Perform cross-fade in memory
|
||||
float *buf1 = new float[blendFrames];
|
||||
float *buf2 = new float[blendFrames];
|
||||
Floats buf1{ blendFrames };
|
||||
Floats buf2{ blendFrames };
|
||||
auto t1 = wt->TimeToLongSamples(cutStart) - blendFrames / 2;
|
||||
auto t2 = wt->TimeToLongSamples(cutEnd) - blendFrames / 2;
|
||||
|
||||
wt->Get((samplePtr)buf1, floatSample, t1, blendFrames);
|
||||
wt->Get((samplePtr)buf2, floatSample, t2, blendFrames);
|
||||
wt->Get((samplePtr)buf1.get(), floatSample, t1, blendFrames);
|
||||
wt->Get((samplePtr)buf2.get(), floatSample, t2, blendFrames);
|
||||
|
||||
for (decltype(blendFrames) i = 0; i < blendFrames; ++i)
|
||||
{
|
||||
|
@ -518,10 +518,7 @@ bool EffectTruncSilence::DoRemoval
|
|||
wt->Clear(cutStart, cutEnd);
|
||||
|
||||
// Write cross-faded data
|
||||
wt->Set((samplePtr)buf1, floatSample, t1, blendFrames);
|
||||
|
||||
delete [] buf1;
|
||||
delete [] buf2;
|
||||
wt->Set((samplePtr)buf1.get(), floatSample, t1, blendFrames);
|
||||
}
|
||||
else
|
||||
// Non-wave tracks: just do a sync-lock adjust
|
||||
|
@ -560,7 +557,7 @@ bool EffectTruncSilence::Analyze(RegionList& silenceList,
|
|||
RegionList::iterator rit(silenceList.begin());
|
||||
|
||||
// Allocate buffer
|
||||
float *buffer = new float[blockLen];
|
||||
Floats buffer{ blockLen };
|
||||
|
||||
// Loop through current track
|
||||
while (*index < end) {
|
||||
|
@ -579,10 +576,8 @@ bool EffectTruncSilence::Analyze(RegionList& silenceList,
|
|||
(*index - start).as_double() /
|
||||
(end - start).as_double()) /
|
||||
(double)GetNumWaveTracks());
|
||||
if (cancelled) {
|
||||
delete [] buffer;
|
||||
if (cancelled)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Optimization: if not in a silent region skip ahead to the next one
|
||||
|
@ -630,7 +625,7 @@ bool EffectTruncSilence::Analyze(RegionList& silenceList,
|
|||
auto count = limitSampleBufferSize( blockLen, end - *index );
|
||||
|
||||
// Fill buffer
|
||||
wt->Get((samplePtr)(buffer), floatSample, *index, count);
|
||||
wt->Get((samplePtr)(buffer.get()), floatSample, *index, count);
|
||||
|
||||
// Look for silenceList in current block
|
||||
for (decltype(count) i = 0; i < count; ++i) {
|
||||
|
@ -680,7 +675,6 @@ bool EffectTruncSilence::Analyze(RegionList& silenceList,
|
|||
// Next block
|
||||
*index += count;
|
||||
}
|
||||
delete [] buffer;
|
||||
|
||||
if (inputLength) {
|
||||
*inputLength = std::min<double>(*inputLength, *minInputLength);
|
||||
|
|
|
@ -100,7 +100,6 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveTrack * track,
|
|||
sampleCount start, sampleCount end)
|
||||
{
|
||||
bool ret;
|
||||
float *tmpfloat;
|
||||
|
||||
//Get the length of the buffer (as double). len is
|
||||
//used simple to calculate a progress meter, so it is easier
|
||||
|
@ -110,26 +109,22 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveTrack * track,
|
|||
|
||||
//Initiate a processing buffer. This buffer will (most likely)
|
||||
//be shorter than the length of the track being processed.
|
||||
float *buffer1 = new float[maxblock];
|
||||
float *buffer2 = new float[maxblock];
|
||||
Floats buffer1{ maxblock };
|
||||
Floats buffer2{ maxblock };
|
||||
auto samples1 = limitSampleBufferSize(
|
||||
std::min( maxblock, track->GetBestBlockSize(start) ), end - start );
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer1, floatSample, start, samples1);
|
||||
track->Get((samplePtr) buffer1.get(), floatSample, start, samples1);
|
||||
|
||||
// Process the first buffer with a NULL previous buffer
|
||||
if (mPass == 0)
|
||||
ret = TwoBufferProcessPass1(NULL, 0, buffer1, samples1);
|
||||
ret = TwoBufferProcessPass1(NULL, 0, buffer1.get(), samples1);
|
||||
else
|
||||
ret = TwoBufferProcessPass2(NULL, 0, buffer1, samples1);
|
||||
if (!ret) {
|
||||
delete[]buffer1;
|
||||
delete[]buffer2;
|
||||
|
||||
ret = TwoBufferProcessPass2(NULL, 0, buffer1.get(), samples1);
|
||||
if (!ret)
|
||||
//Return false because the effect failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
//Go through the track one buffer at a time. s counts which
|
||||
//sample the current buffer starts at.
|
||||
|
@ -142,23 +137,20 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveTrack * track,
|
|||
);
|
||||
|
||||
//Get the samples from the track and put them in the buffer
|
||||
track->Get((samplePtr) buffer2, floatSample, s, samples2);
|
||||
track->Get((samplePtr)buffer2.get(), floatSample, s, samples2);
|
||||
|
||||
//Process the buffer. If it fails, clean up and exit.
|
||||
if (mPass == 0)
|
||||
ret = TwoBufferProcessPass1(buffer1, samples1, buffer2, samples2);
|
||||
ret = TwoBufferProcessPass1(buffer1.get(), samples1, buffer2.get(), samples2);
|
||||
else
|
||||
ret = TwoBufferProcessPass2(buffer1, samples1, buffer2, samples2);
|
||||
if (!ret) {
|
||||
delete[]buffer1;
|
||||
delete[]buffer2;
|
||||
ret = TwoBufferProcessPass2(buffer1.get(), samples1, buffer2.get(), samples2);
|
||||
if (!ret)
|
||||
//Return false because the effect failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
//Processing succeeded. copy the newly-changed samples back
|
||||
//onto the track.
|
||||
track->Set((samplePtr) buffer1, floatSample, s-samples1, samples1);
|
||||
track->Set((samplePtr)buffer1.get(), floatSample, s - samples1, samples1);
|
||||
|
||||
//Increment s one blockfull of samples
|
||||
s += samples2;
|
||||
|
@ -172,41 +164,29 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveTrack * track,
|
|||
ret = TotalProgress(
|
||||
(mCurTrackNum + (s-start).as_double()/len + GetNumWaveTracks()*mPass) /
|
||||
(GetNumWaveTracks()*2));
|
||||
if (ret) {
|
||||
delete[]buffer1;
|
||||
delete[]buffer2;
|
||||
if (ret)
|
||||
//Return false because the effect failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rotate the buffers
|
||||
tmpfloat = buffer1;
|
||||
buffer1 = buffer2;
|
||||
buffer2 = tmpfloat;
|
||||
buffer1.swap(buffer2);
|
||||
|
||||
std::swap(samples1, samples2);
|
||||
}
|
||||
|
||||
// Send the last buffer with a NULL pointer for the current buffer
|
||||
if (mPass == 0)
|
||||
ret = TwoBufferProcessPass1(buffer1, samples1, NULL, 0);
|
||||
ret = TwoBufferProcessPass1(buffer1.get(), samples1, NULL, 0);
|
||||
else
|
||||
ret = TwoBufferProcessPass2(buffer1, samples1, NULL, 0);
|
||||
ret = TwoBufferProcessPass2(buffer1.get(), samples1, NULL, 0);
|
||||
|
||||
if (!ret) {
|
||||
delete[]buffer1;
|
||||
delete[]buffer2;
|
||||
if (!ret)
|
||||
//Return false because the effect failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
//Processing succeeded. copy the newly-changed samples back
|
||||
//onto the track.
|
||||
track->Set((samplePtr) buffer1, floatSample, s-samples1, samples1);
|
||||
|
||||
//Clean up the buffer
|
||||
delete[]buffer1;
|
||||
delete[]buffer2;
|
||||
track->Set((samplePtr)buffer1.get(), floatSample, s - samples1, samples1);
|
||||
|
||||
//Return true because the effect processing succeeded.
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue