No naked array new!
This commit is contained in:
commit
c5007d846e
|
@ -1705,10 +1705,11 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
|
|||
mPlayMode = options.playLooped ? PLAY_LOOPED : PLAY_STRAIGHT;
|
||||
mCutPreviewGapStart = options.cutPreviewGapStart;
|
||||
mCutPreviewGapLen = options.cutPreviewGapLen;
|
||||
mPlaybackBuffers = NULL;
|
||||
mPlaybackMixers = NULL;
|
||||
mCaptureBuffers = NULL;
|
||||
mResample = NULL;
|
||||
|
||||
mPlaybackBuffers.reset();
|
||||
mPlaybackMixers.reset();
|
||||
mCaptureBuffers.reset();
|
||||
mResample.reset();
|
||||
|
||||
double playbackTime = 4.0;
|
||||
|
||||
|
@ -1859,12 +1860,8 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
|
|||
auto playbackMixBufferSize =
|
||||
mPlaybackSamplesToCopy;
|
||||
|
||||
mPlaybackBuffers = new RingBuffer* [mPlaybackTracks.size()];
|
||||
mPlaybackMixers = new Mixer* [mPlaybackTracks.size()];
|
||||
|
||||
// Set everything to zero in case we have to DELETE these due to a memory exception.
|
||||
memset(mPlaybackBuffers, 0, sizeof(RingBuffer*)*mPlaybackTracks.size());
|
||||
memset(mPlaybackMixers, 0, sizeof(Mixer*)*mPlaybackTracks.size());
|
||||
mPlaybackBuffers.reinit(mPlaybackTracks.size());
|
||||
mPlaybackMixers.reinit(mPlaybackTracks.size());
|
||||
|
||||
const Mixer::WarpOptions &warpOptions =
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
||||
|
@ -1878,10 +1875,11 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
|
|||
|
||||
for (unsigned int i = 0; i < mPlaybackTracks.size(); i++)
|
||||
{
|
||||
mPlaybackBuffers[i] = new RingBuffer(floatSample, playbackBufferSize);
|
||||
mPlaybackBuffers[i] = std::make_unique<RingBuffer>(floatSample, playbackBufferSize);
|
||||
|
||||
// MB: use normal time for the end time, not warped time!
|
||||
mPlaybackMixers[i] = new Mixer(WaveTrackConstArray{ mPlaybackTracks[i] },
|
||||
mPlaybackMixers[i] = std::make_unique<Mixer>
|
||||
(WaveTrackConstArray{ mPlaybackTracks[i] },
|
||||
warpOptions,
|
||||
mT0, mT1, 1,
|
||||
playbackMixBufferSize, false,
|
||||
|
@ -1904,19 +1902,16 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
|
|||
return 0;
|
||||
}
|
||||
|
||||
mCaptureBuffers = new RingBuffer* [mCaptureTracks.size()];
|
||||
mResample = new Resample* [mCaptureTracks.size()];
|
||||
mCaptureBuffers.reinit(mCaptureTracks.size());
|
||||
mResample.reinit(mCaptureTracks.size());
|
||||
mFactor = sampleRate / mRate;
|
||||
|
||||
// Set everything to zero in case we have to DELETE these due to a memory exception.
|
||||
memset(mCaptureBuffers, 0, sizeof(RingBuffer*)*mCaptureTracks.size());
|
||||
memset(mResample, 0, sizeof(Resample*)*mCaptureTracks.size());
|
||||
|
||||
for( unsigned int i = 0; i < mCaptureTracks.size(); i++ )
|
||||
{
|
||||
mCaptureBuffers[i] = new RingBuffer( mCaptureTracks[i]->GetSampleFormat(),
|
||||
mCaptureBuffers[i] = std::make_unique<RingBuffer>
|
||||
( mCaptureTracks[i]->GetSampleFormat(),
|
||||
captureBufferSize );
|
||||
mResample[i] = new Resample(true, mFactor, mFactor); // constant rate resampling
|
||||
mResample[i] = std::make_unique<Resample>(true, mFactor, mFactor); // constant rate resampling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2087,37 +2082,10 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers)
|
|||
EffectManager::Get().RealtimeFinalize();
|
||||
}
|
||||
|
||||
if(mPlaybackBuffers)
|
||||
{
|
||||
for (unsigned int i = 0; i < mPlaybackTracks.size(); i++)
|
||||
delete mPlaybackBuffers[i];
|
||||
delete [] mPlaybackBuffers;
|
||||
mPlaybackBuffers = NULL;
|
||||
}
|
||||
|
||||
if(mPlaybackMixers)
|
||||
{
|
||||
for (unsigned int i = 0; i < mPlaybackTracks.size(); i++)
|
||||
delete mPlaybackMixers[i];
|
||||
delete [] mPlaybackMixers;
|
||||
mPlaybackMixers = NULL;
|
||||
}
|
||||
|
||||
if(mCaptureBuffers)
|
||||
{
|
||||
for (unsigned int i = 0; i < mCaptureTracks.size(); i++)
|
||||
delete mCaptureBuffers[i];
|
||||
delete [] mCaptureBuffers;
|
||||
mCaptureBuffers = NULL;
|
||||
}
|
||||
|
||||
if(mResample)
|
||||
{
|
||||
for (unsigned int i = 0; i < mCaptureTracks.size(); i++)
|
||||
delete mResample[i];
|
||||
delete [] mResample;
|
||||
mResample = NULL;
|
||||
}
|
||||
mPlaybackBuffers.reset();
|
||||
mPlaybackMixers.reset();
|
||||
mCaptureBuffers.reset();
|
||||
mResample.reset();
|
||||
|
||||
if(!bOnlyBuffers)
|
||||
{
|
||||
|
@ -2443,14 +2411,8 @@ void AudioIO::StopStream()
|
|||
|
||||
if (mPlaybackTracks.size() > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < mPlaybackTracks.size(); i++)
|
||||
{
|
||||
delete mPlaybackBuffers[i];
|
||||
delete mPlaybackMixers[i];
|
||||
}
|
||||
|
||||
delete[] mPlaybackBuffers;
|
||||
delete[] mPlaybackMixers;
|
||||
mPlaybackBuffers.reset();
|
||||
mPlaybackMixers.reset();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2458,6 +2420,9 @@ void AudioIO::StopStream()
|
|||
//
|
||||
if (mCaptureTracks.size() > 0)
|
||||
{
|
||||
mCaptureBuffers.reset();
|
||||
mResample.reset();
|
||||
|
||||
//
|
||||
// We only apply latency correction when we actually played back
|
||||
// tracks during the recording. If we did not play back tracks,
|
||||
|
@ -2473,9 +2438,6 @@ void AudioIO::StopStream()
|
|||
|
||||
for (unsigned int i = 0; i < mCaptureTracks.size(); i++)
|
||||
{
|
||||
delete mCaptureBuffers[i];
|
||||
delete mResample[i];
|
||||
|
||||
WaveTrack* track = mCaptureTracks[i];
|
||||
track->Flush();
|
||||
|
||||
|
@ -2521,9 +2483,6 @@ void AudioIO::StopStream()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] mCaptureBuffers;
|
||||
delete[] mResample;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4378,7 +4337,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
|
|||
bool selected = false;
|
||||
int group = 0;
|
||||
int chanCnt = 0;
|
||||
int maxLen = 0;
|
||||
decltype(framesPerBuffer) maxLen = 0;
|
||||
for (unsigned t = 0; t < numPlaybackTracks; t++)
|
||||
{
|
||||
const WaveTrack *vt = gAudioIO->mPlaybackTracks[t];
|
||||
|
@ -4410,7 +4369,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
|
|||
|
||||
#define ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END
|
||||
#ifdef ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END
|
||||
int len = 0;
|
||||
decltype(framesPerBuffer) len = 0;
|
||||
// this is original code prior to r10680 -RBD
|
||||
if (cut)
|
||||
{
|
||||
|
|
|
@ -555,13 +555,13 @@ private:
|
|||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
std::unique_ptr<AudioThread> mMidiThread;
|
||||
#endif
|
||||
Resample **mResample;
|
||||
RingBuffer **mCaptureBuffers;
|
||||
ArrayOf<std::unique_ptr<Resample>> mResample;
|
||||
ArrayOf<std::unique_ptr<RingBuffer>> mCaptureBuffers;
|
||||
WaveTrackArray mCaptureTracks;
|
||||
RingBuffer **mPlaybackBuffers;
|
||||
ArrayOf<std::unique_ptr<RingBuffer>> mPlaybackBuffers;
|
||||
ConstWaveTrackArray mPlaybackTracks;
|
||||
|
||||
Mixer **mPlaybackMixers;
|
||||
ArrayOf<std::unique_ptr<Mixer>> mPlaybackMixers;
|
||||
volatile int mStreamToken;
|
||||
static int mNextStreamToken;
|
||||
double mFactor;
|
||||
|
|
|
@ -641,9 +641,8 @@ void AutoSaveFile::CheckSpace(wxMemoryOutputStream & os)
|
|||
if (left == 0)
|
||||
{
|
||||
size_t origPos = buf->GetIntPosition();
|
||||
char *temp = new char[mAllocSize];
|
||||
buf->Write(temp, mAllocSize);
|
||||
delete[] temp;
|
||||
ArrayOf<char> temp{ mAllocSize };
|
||||
buf->Write(temp.get(), mAllocSize);
|
||||
buf->SetIntPosition(origPos);
|
||||
}
|
||||
}
|
||||
|
@ -739,54 +738,54 @@ bool AutoSaveFile::Decode(const wxString & fileName)
|
|||
return true;
|
||||
}
|
||||
|
||||
len = file.Length() - len;
|
||||
char *buf = new char[len];
|
||||
|
||||
if (file.Read(buf, len) != len)
|
||||
{
|
||||
delete[] buf;
|
||||
return false;
|
||||
}
|
||||
|
||||
wxMemoryInputStream in(buf, len);
|
||||
|
||||
file.Close();
|
||||
|
||||
// Decode to a temporary file to preserve the orignal.
|
||||
wxString tempName = fn.CreateTempFileName(fnPath);
|
||||
bool opened = false;
|
||||
|
||||
XMLFileWriter out;
|
||||
|
||||
// JKC: ANSWER-ME: Is the try catch actually doing anything?
|
||||
// If it is useful, why are we not using it everywhere?
|
||||
// If it isn't useful, why are we doing it here?
|
||||
try
|
||||
wxString tempName;
|
||||
len = file.Length() - len;
|
||||
{
|
||||
out.Open(tempName, wxT("wb"));
|
||||
opened = out.IsOpened();
|
||||
}
|
||||
catch (const XMLFileWriterException&)
|
||||
{
|
||||
}
|
||||
using Chars = ArrayOf < char >;
|
||||
using WxChars = ArrayOf < wxChar >;
|
||||
Chars buf{ len };
|
||||
|
||||
if (!opened)
|
||||
{
|
||||
delete[] buf;
|
||||
|
||||
wxRemoveFile(tempName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
mIds.clear();
|
||||
|
||||
while (!in.Eof() && !out.Error())
|
||||
{
|
||||
short id;
|
||||
|
||||
switch (in.GetC())
|
||||
if (file.Read(buf.get(), len) != len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wxMemoryInputStream in(buf.get(), len);
|
||||
|
||||
file.Close();
|
||||
|
||||
// Decode to a temporary file to preserve the original.
|
||||
tempName = fn.CreateTempFileName(fnPath);
|
||||
bool opened = false;
|
||||
|
||||
// JKC: ANSWER-ME: Is the try catch actually doing anything?
|
||||
// If it is useful, why are we not using it everywhere?
|
||||
// If it isn't useful, why are we doing it here?
|
||||
try
|
||||
{
|
||||
out.Open(tempName, wxT("wb"));
|
||||
opened = out.IsOpened();
|
||||
}
|
||||
catch (const XMLFileWriterException&)
|
||||
{
|
||||
}
|
||||
|
||||
if (!opened)
|
||||
{
|
||||
wxRemoveFile(tempName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
mIds.clear();
|
||||
|
||||
while (!in.Eof() && !out.Error())
|
||||
{
|
||||
short id;
|
||||
|
||||
switch (in.GetC())
|
||||
{
|
||||
case FT_Push:
|
||||
{
|
||||
mIdStack.Add(mIds);
|
||||
|
@ -807,11 +806,10 @@ bool AutoSaveFile::Decode(const wxString & fileName)
|
|||
|
||||
in.Read(&id, sizeof(id));
|
||||
in.Read(&len, sizeof(len));
|
||||
wxChar *name = new wxChar[len / sizeof(wxChar)];
|
||||
in.Read(name, len);
|
||||
WxChars name{ len / sizeof(wxChar) };
|
||||
in.Read(name.get(), len);
|
||||
|
||||
mIds[id] = wxString(name, len / sizeof(wxChar));
|
||||
delete[] name;
|
||||
mIds[id] = wxString(name.get(), len / sizeof(wxChar));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -837,11 +835,10 @@ bool AutoSaveFile::Decode(const wxString & fileName)
|
|||
|
||||
in.Read(&id, sizeof(id));
|
||||
in.Read(&len, sizeof(len));
|
||||
wxChar *val = new wxChar[len / sizeof(wxChar)];
|
||||
in.Read(val, len);
|
||||
WxChars val{ len / sizeof(wxChar) };
|
||||
in.Read(val.get(), len);
|
||||
|
||||
out.WriteAttr(mIds[id], wxString(val, len / sizeof(wxChar)));
|
||||
delete[] val;
|
||||
out.WriteAttr(mIds[id], wxString(val.get(), len / sizeof(wxChar)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -931,11 +928,10 @@ bool AutoSaveFile::Decode(const wxString & fileName)
|
|||
int len;
|
||||
|
||||
in.Read(&len, sizeof(len));
|
||||
wxChar *val = new wxChar[len / sizeof(wxChar)];
|
||||
in.Read(val, len);
|
||||
WxChars val{ len / sizeof(wxChar) };
|
||||
in.Read(val.get(), len);
|
||||
|
||||
out.WriteData(wxString(val, len / sizeof(wxChar)));
|
||||
delete[] val;
|
||||
out.WriteData(wxString(val.get(), len / sizeof(wxChar)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -944,22 +940,20 @@ bool AutoSaveFile::Decode(const wxString & fileName)
|
|||
int len;
|
||||
|
||||
in.Read(&len, sizeof(len));
|
||||
wxChar *val = new wxChar[len / sizeof(wxChar)];
|
||||
in.Read(val, len);
|
||||
WxChars val{ len / sizeof(wxChar) };
|
||||
in.Read(val.get(), len);
|
||||
|
||||
out.Write(wxString(val, len / sizeof(wxChar)));
|
||||
delete[] val;
|
||||
out.Write(wxString(val.get(), len / sizeof(wxChar)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
wxASSERT(true);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
|
||||
bool error = out.Error();
|
||||
|
||||
out.Close();
|
||||
|
|
|
@ -373,28 +373,29 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
|||
|
||||
int trials = numEdits;
|
||||
|
||||
short *small1 = new short[nChunks];
|
||||
short *block = new short[chunkSize];
|
||||
using Shorts = ArrayOf < short > ;
|
||||
Shorts small1{ nChunks };
|
||||
Shorts block{ chunkSize };
|
||||
|
||||
Printf(wxT("Preparing...\n"));
|
||||
|
||||
wxTheApp->Yield();
|
||||
FlushPrint();
|
||||
|
||||
int i, b, v;
|
||||
int v;
|
||||
int bad;
|
||||
int z;
|
||||
long elapsed;
|
||||
wxString tempStr;
|
||||
wxStopWatch timer;
|
||||
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
for (size_t i = 0; i < nChunks; i++) {
|
||||
v = short(rand());
|
||||
small1[i] = v;
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
for (size_t b = 0; b < chunkSize; b++)
|
||||
block[b] = v;
|
||||
|
||||
t->Append((samplePtr)block, int16Sample, chunkSize);
|
||||
t->Append((samplePtr)block.get(), int16Sample, chunkSize);
|
||||
}
|
||||
t->Flush();
|
||||
|
||||
|
@ -486,10 +487,10 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
|||
|
||||
bad = 0;
|
||||
timer.Start();
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
for (size_t i = 0; i < nChunks; i++) {
|
||||
v = small1[i];
|
||||
t->Get((samplePtr)block, int16Sample, i * chunkSize, chunkSize);
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
t->Get((samplePtr)block.get(), int16Sample, i * chunkSize, chunkSize);
|
||||
for (size_t b = 0; b < chunkSize; b++)
|
||||
if (block[b] != v) {
|
||||
bad++;
|
||||
if (bad < 10)
|
||||
|
@ -512,10 +513,10 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
|||
|
||||
timer.Start();
|
||||
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
for (size_t i = 0; i < nChunks; i++) {
|
||||
v = small1[i];
|
||||
t->Get((samplePtr)block, int16Sample, i * chunkSize, chunkSize);
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
t->Get((samplePtr)block.get(), int16Sample, i * chunkSize, chunkSize);
|
||||
for (size_t b = 0; b < chunkSize; b++)
|
||||
if (block[b] != v)
|
||||
bad++;
|
||||
}
|
||||
|
@ -534,8 +535,6 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
|||
Printf(wxT("TEST FAILED!!!\n"));
|
||||
|
||||
success:
|
||||
delete[]small1;
|
||||
delete[]block;
|
||||
|
||||
dd.reset();
|
||||
|
||||
|
|
|
@ -193,13 +193,11 @@ void *BlockFile::CalcSummary(samplePtr buffer, size_t len,
|
|||
float *summary64K = (float *)(fullSummary.get() + mSummaryInfo.offset64K);
|
||||
float *summary256 = (float *)(fullSummary.get() + mSummaryInfo.offset256);
|
||||
|
||||
float *fbuffer = new float[len];
|
||||
Floats fbuffer{ len };
|
||||
CopySamples(buffer, format,
|
||||
(samplePtr)fbuffer, floatSample, len);
|
||||
(samplePtr)fbuffer.get(), floatSample, len);
|
||||
|
||||
CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);
|
||||
|
||||
delete[] fbuffer;
|
||||
CalcSummaryFromBuffer(fbuffer.get(), len, summary256, summary64K);
|
||||
|
||||
return fullSummary.get();
|
||||
}
|
||||
|
@ -436,14 +434,14 @@ bool BlockFile::Read256(float *buffer,
|
|||
{
|
||||
wxASSERT(start >= 0);
|
||||
|
||||
char *summary = new char[mSummaryInfo.totalSummaryBytes];
|
||||
ArrayOf<char> summary{ mSummaryInfo.totalSummaryBytes };
|
||||
// FIXME: TRAP_ERR ReadSummary() could return fail.
|
||||
this->ReadSummary(summary);
|
||||
this->ReadSummary(summary.get());
|
||||
|
||||
start = std::min( start, mSummaryInfo.frames256 );
|
||||
len = std::min( len, mSummaryInfo.frames256 - start );
|
||||
|
||||
CopySamples(summary + mSummaryInfo.offset256 + (start * mSummaryInfo.bytesPerFrame),
|
||||
CopySamples(summary.get() + mSummaryInfo.offset256 + (start * mSummaryInfo.bytesPerFrame),
|
||||
mSummaryInfo.format,
|
||||
(samplePtr)buffer, floatSample, len * mSummaryInfo.fields);
|
||||
|
||||
|
@ -456,8 +454,6 @@ bool BlockFile::Read256(float *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
delete[] summary;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -475,14 +471,14 @@ bool BlockFile::Read64K(float *buffer,
|
|||
{
|
||||
wxASSERT(start >= 0);
|
||||
|
||||
char *summary = new char[mSummaryInfo.totalSummaryBytes];
|
||||
ArrayOf<char> summary{ mSummaryInfo.totalSummaryBytes };
|
||||
// FIXME: TRAP_ERR ReadSummary() could return fail.
|
||||
this->ReadSummary(summary);
|
||||
this->ReadSummary(summary.get());
|
||||
|
||||
start = std::min( start, mSummaryInfo.frames64K );
|
||||
len = std::min( len, mSummaryInfo.frames64K - start );
|
||||
|
||||
CopySamples(summary + mSummaryInfo.offset64K +
|
||||
CopySamples(summary.get() + mSummaryInfo.offset64K +
|
||||
(start * mSummaryInfo.bytesPerFrame),
|
||||
mSummaryInfo.format,
|
||||
(samplePtr)buffer, floatSample, len*mSummaryInfo.fields);
|
||||
|
@ -496,8 +492,6 @@ bool BlockFile::Read64K(float *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
delete[] summary;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
66
src/FFT.cpp
66
src/FFT.cpp
|
@ -39,7 +39,10 @@
|
|||
* 9: Gaussian(a=4.5)
|
||||
*/
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "FFT.h"
|
||||
#include "MemoryX.h"
|
||||
#include "SampleFormat.h"
|
||||
|
||||
#include <wx/intl.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -49,7 +52,7 @@
|
|||
#include "RealFFTf.h"
|
||||
#include "Experimental.h"
|
||||
|
||||
static int **gFFTBitTable = NULL;
|
||||
static ArraysOf<int> gFFTBitTable;
|
||||
static const size_t MaxFastBits = 16;
|
||||
|
||||
/* Declare Static functions */
|
||||
|
@ -94,15 +97,14 @@ int ReverseBits(size_t index, size_t NumBits)
|
|||
|
||||
void InitFFT()
|
||||
{
|
||||
gFFTBitTable = new int *[MaxFastBits];
|
||||
gFFTBitTable.reinit(MaxFastBits);
|
||||
|
||||
size_t len = 2;
|
||||
for (size_t b = 1; b <= MaxFastBits; b++) {
|
||||
|
||||
gFFTBitTable[b - 1] = new int[len];
|
||||
|
||||
auto &array = gFFTBitTable[b - 1];
|
||||
array.reinit(len);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
gFFTBitTable[b - 1][i] = ReverseBits(i, b);
|
||||
array[i] = ReverseBits(i, b);
|
||||
|
||||
len <<= 1;
|
||||
}
|
||||
|
@ -110,12 +112,7 @@ void InitFFT()
|
|||
|
||||
void DeinitFFT()
|
||||
{
|
||||
if (gFFTBitTable) {
|
||||
for (size_t b = 1; b <= MaxFastBits; b++) {
|
||||
delete[] gFFTBitTable[b-1];
|
||||
}
|
||||
delete[] gFFTBitTable;
|
||||
}
|
||||
gFFTBitTable.reset();
|
||||
// Deallocate any unused RealFFTf tables
|
||||
CleanupFFT();
|
||||
}
|
||||
|
@ -233,31 +230,30 @@ void FFT(size_t NumSamples,
|
|||
|
||||
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
|
||||
{
|
||||
size_t i;
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
float *pFFT = new float[NumSamples];
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
for(i = 0; i < NumSamples; i++)
|
||||
for(size_t i = 0; i < NumSamples; i++)
|
||||
pFFT[i] = RealIn[i];
|
||||
|
||||
// Perform the FFT
|
||||
RealFFTf(pFFT, hFFT);
|
||||
RealFFTf(pFFT.get(), hFFT);
|
||||
|
||||
// Copy the data into the real and imaginary outputs
|
||||
for(i = 1; i < (NumSamples / 2); i++) {
|
||||
for (size_t i = 1; i<(NumSamples / 2); i++) {
|
||||
RealOut[i]=pFFT[hFFT->BitReversed[i] ];
|
||||
ImagOut[i]=pFFT[hFFT->BitReversed[i]+1];
|
||||
}
|
||||
// Handle the (real-only) DC and Fs/2 bins
|
||||
RealOut[0] = pFFT[0];
|
||||
RealOut[i] = pFFT[1];
|
||||
ImagOut[0] = ImagOut[i] = 0;
|
||||
RealOut[NumSamples / 2] = pFFT[1];
|
||||
ImagOut[0] = ImagOut[NumSamples / 2] = 0;
|
||||
// Fill in the upper half using symmetry properties
|
||||
for(i++ ; i < NumSamples; i++) {
|
||||
for(size_t i = NumSamples / 2 + 1; i < NumSamples; i++) {
|
||||
RealOut[i] = RealOut[NumSamples-i];
|
||||
ImagOut[i] = -ImagOut[NumSamples-i];
|
||||
}
|
||||
delete [] pFFT;
|
||||
|
||||
ReleaseFFT(hFFT);
|
||||
}
|
||||
|
||||
|
@ -275,29 +271,27 @@ void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *Imag
|
|||
void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
|
||||
float *RealOut)
|
||||
{
|
||||
size_t i;
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
float *pFFT = new float[NumSamples];
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
for(i = 0; i < (NumSamples / 2); i++)
|
||||
for (size_t i = 0; i < (NumSamples / 2); i++)
|
||||
pFFT[2*i ] = RealIn[i];
|
||||
if(ImagIn == NULL) {
|
||||
for(i = 0; i < (NumSamples/2); i++)
|
||||
for (size_t i = 0; i < (NumSamples / 2); i++)
|
||||
pFFT[2*i+1] = 0;
|
||||
} else {
|
||||
for(i = 0; i < (NumSamples/2); i++)
|
||||
for (size_t i = 0; i < (NumSamples / 2); i++)
|
||||
pFFT[2*i+1] = ImagIn[i];
|
||||
}
|
||||
// Put the fs/2 component in the imaginary part of the DC bin
|
||||
pFFT[1] = RealIn[i];
|
||||
pFFT[1] = RealIn[NumSamples / 2];
|
||||
|
||||
// Perform the FFT
|
||||
InverseRealFFTf(pFFT, hFFT);
|
||||
InverseRealFFTf(pFFT.get(), hFFT);
|
||||
|
||||
// Copy the data to the (purely real) output buffer
|
||||
ReorderToTime(hFFT, pFFT, RealOut);
|
||||
ReorderToTime(hFFT, pFFT.get(), RealOut);
|
||||
|
||||
delete [] pFFT;
|
||||
ReleaseFFT(hFFT);
|
||||
}
|
||||
|
||||
|
@ -314,25 +308,23 @@ void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
|
|||
|
||||
void PowerSpectrum(size_t NumSamples, const float *In, float *Out)
|
||||
{
|
||||
size_t i;
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
float *pFFT = new float[NumSamples];
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
for(i = 0; i < NumSamples; i++)
|
||||
for (size_t i = 0; i<NumSamples; i++)
|
||||
pFFT[i] = In[i];
|
||||
|
||||
// Perform the FFT
|
||||
RealFFTf(pFFT, hFFT);
|
||||
RealFFTf(pFFT.get(), hFFT);
|
||||
|
||||
// Copy the data into the real and imaginary outputs
|
||||
for(i = 1; i < NumSamples / 2; i++) {
|
||||
for (size_t i = 1; i<NumSamples / 2; i++) {
|
||||
Out[i]= (pFFT[hFFT->BitReversed[i] ]*pFFT[hFFT->BitReversed[i] ])
|
||||
+ (pFFT[hFFT->BitReversed[i]+1]*pFFT[hFFT->BitReversed[i]+1]);
|
||||
}
|
||||
// Handle the (real-only) DC and Fs/2 bins
|
||||
Out[0] = pFFT[0]*pFFT[0];
|
||||
Out[i] = pFFT[1]*pFFT[1];
|
||||
delete [] pFFT;
|
||||
Out[NumSamples / 2] = pFFT[1]*pFFT[1];
|
||||
ReleaseFFT(hFFT);
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,6 @@ FreqWindow::FreqWindow(wxWindow * parent, wxWindowID id,
|
|||
const wxPoint & pos)
|
||||
: wxDialogWrapper(parent, id, title, pos, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX),
|
||||
mData(NULL),
|
||||
mAnalyst(std::make_unique<SpectrumAnalyst>())
|
||||
{
|
||||
SetName(GetTitle());
|
||||
|
@ -514,8 +513,6 @@ FreqWindow::FreqWindow(wxWindow * parent, wxWindowID id,
|
|||
|
||||
FreqWindow::~FreqWindow()
|
||||
{
|
||||
if (mData)
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
bool FreqWindow::Show(bool show)
|
||||
|
@ -546,10 +543,7 @@ bool FreqWindow::Show(bool show)
|
|||
|
||||
void FreqWindow::GetAudio()
|
||||
{
|
||||
if (mData) {
|
||||
delete [] mData;
|
||||
mData = NULL;
|
||||
}
|
||||
mData.reset();
|
||||
mDataLen = 0;
|
||||
|
||||
int selcount = 0;
|
||||
|
@ -571,23 +565,21 @@ void FreqWindow::GetAudio()
|
|||
else
|
||||
// dataLen is not more than 10 * 2 ^ 20
|
||||
mDataLen = dataLen.as_size_t();
|
||||
mData = new float[mDataLen];
|
||||
track->Get((samplePtr)mData, floatSample, start, mDataLen);
|
||||
mData = Floats{ mDataLen };
|
||||
track->Get((samplePtr)mData.get(), floatSample, start, mDataLen);
|
||||
}
|
||||
else {
|
||||
if (track->GetRate() != mRate) {
|
||||
wxMessageBox(_("To plot the spectrum, all selected tracks must be the same sample rate."));
|
||||
delete[] mData;
|
||||
mData = NULL;
|
||||
mData.reset();
|
||||
mDataLen = 0;
|
||||
return;
|
||||
}
|
||||
auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0());
|
||||
float *buffer2 = new float[mDataLen];
|
||||
track->Get((samplePtr)buffer2, floatSample, start, mDataLen);
|
||||
Floats buffer2{ mDataLen };
|
||||
track->Get((samplePtr)buffer2.get(), floatSample, start, mDataLen);
|
||||
for (size_t i = 0; i < mDataLen; i++)
|
||||
mData[i] += buffer2[i];
|
||||
delete[] buffer2;
|
||||
}
|
||||
selcount++;
|
||||
}
|
||||
|
@ -1000,7 +992,7 @@ void FreqWindow::Recalc()
|
|||
wxYieldIfNeeded();
|
||||
|
||||
mAnalyst->Calculate(alg, windowFunc, mWindowSize, mRate,
|
||||
mData, mDataLen,
|
||||
mData.get(), mDataLen,
|
||||
&mYMin, &mYMax, mProgress);
|
||||
}
|
||||
if (hadFocus) {
|
||||
|
@ -1202,22 +1194,22 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
auto half = mWindowSize / 2;
|
||||
mProcessed.resize(mWindowSize);
|
||||
|
||||
float *in = new float[mWindowSize];
|
||||
float *out = new float[mWindowSize];
|
||||
float *out2 = new float[mWindowSize];
|
||||
float *win = new float[mWindowSize];
|
||||
Floats in{ mWindowSize };
|
||||
Floats out{ mWindowSize };
|
||||
Floats out2{ mWindowSize };
|
||||
Floats win{ mWindowSize };
|
||||
|
||||
for (size_t i = 0; i < mWindowSize; i++) {
|
||||
mProcessed[i] = 0.0f;
|
||||
win[i] = 1.0f;
|
||||
}
|
||||
|
||||
WindowFunc(windowFunc, mWindowSize, win);
|
||||
WindowFunc(windowFunc, mWindowSize, win.get());
|
||||
|
||||
// Scale window such that an amplitude of 1.0 in the time domain
|
||||
// shows an amplitude of 0dB in the frequency domain
|
||||
double wss = 0;
|
||||
for(size_t i = 0; i < mWindowSize; i++)
|
||||
for (size_t i = 0; i<mWindowSize; i++)
|
||||
wss += win[i];
|
||||
if(wss > 0)
|
||||
wss = 4.0 / (wss*wss);
|
||||
|
@ -1236,7 +1228,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
|
||||
switch (alg) {
|
||||
case Spectrum:
|
||||
PowerSpectrum(mWindowSize, in, out);
|
||||
PowerSpectrum(mWindowSize, in.get(), out.get());
|
||||
|
||||
for (size_t i = 0; i < half; i++)
|
||||
mProcessed[i] += out[i];
|
||||
|
@ -1247,7 +1239,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
case EnhancedAutocorrelation:
|
||||
|
||||
// Take FFT
|
||||
RealFFT(mWindowSize, in, out, out2);
|
||||
RealFFT(mWindowSize, in.get(), out.get(), out2.get());
|
||||
// Compute power
|
||||
for (size_t i = 0; i < mWindowSize; i++)
|
||||
in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);
|
||||
|
@ -1265,7 +1257,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
in[i] = pow(in[i], 1.0f / 3.0f);
|
||||
}
|
||||
// Take FFT
|
||||
RealFFT(mWindowSize, in, out, out2);
|
||||
RealFFT(mWindowSize, in.get(), out.get(), out2.get());
|
||||
|
||||
// Take real part of result
|
||||
for (size_t i = 0; i < half; i++)
|
||||
|
@ -1273,7 +1265,8 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
break;
|
||||
|
||||
case Cepstrum:
|
||||
RealFFT(mWindowSize, in, out, out2);
|
||||
RealFFT(mWindowSize, in.get(), out.get(), out2.get());
|
||||
|
||||
// Compute log power
|
||||
// Set a sane lower limit assuming maximum time amplitude of 1.0
|
||||
{
|
||||
|
@ -1288,7 +1281,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
in[i] = log(power);
|
||||
}
|
||||
// Take IFFT
|
||||
InverseRealFFT(mWindowSize, in, NULL, out);
|
||||
InverseRealFFT(mWindowSize, in.get(), NULL, out.get());
|
||||
|
||||
// Take real part of result
|
||||
for (size_t i = 0; i < half; i++)
|
||||
|
@ -1407,11 +1400,6 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
|
|||
break;
|
||||
}
|
||||
|
||||
delete[]in;
|
||||
delete[]out;
|
||||
delete[]out2;
|
||||
delete[]win;
|
||||
|
||||
if (pYMin)
|
||||
*pYMin = mYMin;
|
||||
if (pYMax)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <wx/textctrl.h>
|
||||
#include <wx/utils.h>
|
||||
#include "widgets/Ruler.h"
|
||||
#include "SampleFormat.h"
|
||||
|
||||
class wxStatusBar;
|
||||
class wxButton;
|
||||
|
@ -198,7 +199,7 @@ private:
|
|||
|
||||
double mRate;
|
||||
size_t mDataLen;
|
||||
float *mData;
|
||||
Floats mData;
|
||||
size_t mWindowSize;
|
||||
|
||||
bool mLogAxis;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "InterpolateAudio.h"
|
||||
#include "Matrix.h"
|
||||
#include "SampleFormat.h"
|
||||
|
||||
static inline int imin(int x, int y)
|
||||
{
|
||||
|
@ -78,11 +79,10 @@ static void LinearInterpolateAudio(float *buffer, int len,
|
|||
|
||||
// Here's the main interpolate function, using
|
||||
// Least Squares AutoRegression (LSAR):
|
||||
void InterpolateAudio(float *buffer, int len,
|
||||
int firstBad, int numBad)
|
||||
void InterpolateAudio(float *buffer, const size_t len,
|
||||
size_t firstBad, size_t numBad)
|
||||
{
|
||||
int N = len;
|
||||
int i, row, col;
|
||||
const auto N = len;
|
||||
|
||||
wxASSERT(len > 0 &&
|
||||
firstBad >= 0 &&
|
||||
|
@ -97,34 +97,35 @@ void InterpolateAudio(float *buffer, int len,
|
|||
// performs poorly when interpolating to the left. If
|
||||
// we're asked to interpolate the left side of a buffer,
|
||||
// we just reverse the problem and try it that way.
|
||||
float *buffer2 = new float[len];
|
||||
for(i=0; i<len; i++)
|
||||
Floats buffer2{ len };
|
||||
for(size_t i=0; i<len; i++)
|
||||
buffer2[len-1-i] = buffer[i];
|
||||
InterpolateAudio(buffer2, len, len-numBad, numBad);
|
||||
for(i=0; i<len; i++)
|
||||
InterpolateAudio(buffer2.get(), len, len-numBad, numBad);
|
||||
for(size_t i=0; i<len; i++)
|
||||
buffer[len-1-i] = buffer2[i];
|
||||
delete[] buffer2;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector s(len, buffer);
|
||||
|
||||
// Choose P, the order of the autoregression equation
|
||||
int P = imin(numBad * 3, 50);
|
||||
P = imin(P, imax(firstBad - 1, len - (firstBad + numBad) - 1));
|
||||
const int IP =
|
||||
imin(imin(numBad * 3, 50), imax(firstBad - 1, len - (firstBad + numBad) - 1));
|
||||
|
||||
if (P < 3) {
|
||||
if (IP < 3 || IP >= N) {
|
||||
LinearInterpolateAudio(buffer, len, firstBad, numBad);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t P(IP);
|
||||
|
||||
// Add a tiny amount of random noise to the input signal -
|
||||
// this sounds like a bad idea, but the amount we're adding
|
||||
// is only about 1 bit in 16-bit audio, and it's an extremely
|
||||
// effective way to avoid nearly-singular matrices. If users
|
||||
// run it more than once they get slightly different results;
|
||||
// this is sometimes even advantageous.
|
||||
for(i=0; i<N; i++)
|
||||
for(size_t i=0; i<N; i++)
|
||||
s[i] += (rand()-(RAND_MAX/2))/(RAND_MAX*10000.0);
|
||||
|
||||
// Solve for the best autoregression coefficients
|
||||
|
@ -133,10 +134,10 @@ void InterpolateAudio(float *buffer, int len,
|
|||
Matrix X(P, P);
|
||||
Vector b(P);
|
||||
|
||||
for(i=0; i<len-P; i++)
|
||||
for(size_t i = 0; i + P < len; i++)
|
||||
if (i+P < firstBad || i >= (firstBad + numBad))
|
||||
for(row=0; row<P; row++) {
|
||||
for(col=0; col<P; col++)
|
||||
for(size_t row=0; row<P; row++) {
|
||||
for(size_t col=0; col<P; col++)
|
||||
X[row][col] += (s[i+row] * s[i+col]);
|
||||
b[row] += s[i+P] * s[i+row];
|
||||
}
|
||||
|
@ -151,14 +152,14 @@ void InterpolateAudio(float *buffer, int len,
|
|||
}
|
||||
|
||||
// This vector now contains the autoregression coefficients
|
||||
Vector a = Xinv * b;
|
||||
const Vector &a = Xinv * b;
|
||||
|
||||
// Create a matrix (a "Toeplitz" matrix, as it turns out)
|
||||
// which encodes the autoregressive relationship between
|
||||
// elements of the sequence.
|
||||
Matrix A(N-P, N);
|
||||
for(row=0; row<N-P; row++) {
|
||||
for(col=0; col<P; col++)
|
||||
for(size_t row=0; row<N-P; row++) {
|
||||
for(size_t col=0; col<P; col++)
|
||||
A[row][row+col] = -a[col];
|
||||
A[row][row+P] = 1;
|
||||
}
|
||||
|
@ -175,10 +176,10 @@ void InterpolateAudio(float *buffer, int len,
|
|||
firstBad+numBad, N-(firstBad+numBad));
|
||||
Matrix Ak = MatrixConcatenateCols(A_left, A_right);
|
||||
|
||||
Vector s_left = VectorSubset(s, 0, firstBad);
|
||||
Vector s_right = VectorSubset(s, firstBad+numBad,
|
||||
const Vector &s_left = VectorSubset(s, 0, firstBad);
|
||||
const Vector &s_right = VectorSubset(s, firstBad+numBad,
|
||||
N-(firstBad+numBad));
|
||||
Vector sk = VectorConcatenate(s_left, s_right);
|
||||
const Vector &sk = VectorConcatenate(s_left, s_right);
|
||||
|
||||
// Do some linear algebra to find the best possible
|
||||
// values that fill in the "bad" area
|
||||
|
@ -195,9 +196,9 @@ void InterpolateAudio(float *buffer, int len,
|
|||
Matrix X4 = MatrixMultiply(X3, Ak);
|
||||
// This vector contains our best guess as to the
|
||||
// unknown values
|
||||
Vector su = X4 * sk;
|
||||
const Vector &su = X4 * sk;
|
||||
|
||||
// Put the results into the return buffer
|
||||
for(i=0; i<numBad; i++)
|
||||
for(size_t i=0; i<numBad; i++)
|
||||
buffer[firstBad+i] = (float)su[i];
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// side (6x the number of bad samples on either side is great). However,
|
||||
// it will work with less data, and with the bad samples on one end or
|
||||
// the other.
|
||||
void AUDACITY_DLL_API InterpolateAudio(float *buffer, int len,
|
||||
int firstBad, int numBad);
|
||||
void AUDACITY_DLL_API InterpolateAudio(float *buffer, size_t len,
|
||||
size_t firstBad, size_t numBad);
|
||||
|
||||
#endif // __AUDACITY_INTERPOLATE_AUDIO__
|
||||
|
|
214
src/Matrix.cpp
214
src/Matrix.cpp
|
@ -17,89 +17,74 @@
|
|||
|
||||
Vector::Vector()
|
||||
{
|
||||
mCopy = false;
|
||||
mN = 0;
|
||||
mData = NULL;
|
||||
}
|
||||
|
||||
Vector::Vector(int len, double *data, bool copy)
|
||||
Vector::Vector(unsigned len, double *data)
|
||||
: mN{ len }
|
||||
, mData(len)
|
||||
{
|
||||
mN = len;
|
||||
mCopy = copy;
|
||||
if (mCopy || !data) {
|
||||
mCopy = true;
|
||||
mData = new double[mN];
|
||||
int i;
|
||||
for(i=0; i<mN; i++)
|
||||
if (data)
|
||||
mData[i] = data[i];
|
||||
else
|
||||
mData[i] = 0.0;
|
||||
}
|
||||
else {
|
||||
mCopy = false;
|
||||
mData = data;
|
||||
}
|
||||
if (data)
|
||||
std::copy(data, data + len, mData.get());
|
||||
else
|
||||
std::fill(mData.get(), mData.get() + len, 0.0);
|
||||
}
|
||||
|
||||
Vector::Vector(unsigned len, float *data)
|
||||
: mN{ len }
|
||||
, mData{ len }
|
||||
{
|
||||
if (data)
|
||||
std::copy(data, data + len, mData.get());
|
||||
else
|
||||
std::fill(mData.get(), mData.get() + len, 0.0);
|
||||
}
|
||||
|
||||
Vector& Vector::operator=(const Vector &other)
|
||||
{
|
||||
wxASSERT(Len() == other.Len());
|
||||
int i;
|
||||
for(i=0; i<Len(); i++)
|
||||
mData[i] = other.mData[i];
|
||||
std::copy(other.mData.get(), other.mData.get() + mN, mData.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector::Vector(const Vector &other)
|
||||
: mN{ other.Len() }
|
||||
, mData{ mN }
|
||||
{
|
||||
CopyFrom(other);
|
||||
}
|
||||
|
||||
void Vector::CopyFrom(const Vector &other)
|
||||
{
|
||||
mN = other.Len();
|
||||
mCopy = true;
|
||||
mData = new double[mN];
|
||||
int i;
|
||||
for(i=0; i<mN; i++)
|
||||
mData[i] = other.mData[i];
|
||||
std::copy(other.mData.get(), other.mData.get() + mN, mData.get());
|
||||
}
|
||||
|
||||
Vector::~Vector()
|
||||
{
|
||||
if (mCopy)
|
||||
delete[] mData;
|
||||
}
|
||||
|
||||
Vector::Vector(int len, float *data)
|
||||
void Vector::Reinit(unsigned len)
|
||||
{
|
||||
mCopy = true;
|
||||
mN = len;
|
||||
mData = new double[mN];
|
||||
int i;
|
||||
for(i=0; i<mN; i++)
|
||||
mData[i] = (double)data[i];
|
||||
Vector temp(len);
|
||||
Swap(temp);
|
||||
}
|
||||
|
||||
void Vector::Swap(Vector &that)
|
||||
{
|
||||
std::swap(mN, that.mN);
|
||||
mData.swap(that.mData);
|
||||
}
|
||||
|
||||
double Vector::Sum() const
|
||||
{
|
||||
int i;
|
||||
double sum = 0.0;
|
||||
for(i=0; i<Len(); i++)
|
||||
for(unsigned i = 0; i < Len(); i++)
|
||||
sum += mData[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
Matrix::Matrix(int rows, int cols, double **data)
|
||||
Matrix::Matrix(unsigned rows, unsigned cols, double **data)
|
||||
: mRows{ rows }
|
||||
, mCols{ cols }
|
||||
, mRowVec{ mRows }
|
||||
{
|
||||
mRows = rows;
|
||||
mCols = cols;
|
||||
mRowVec = new Vector *[mRows];
|
||||
int i, j;
|
||||
for(i=0; i<mRows; i++) {
|
||||
mRowVec[i] = new Vector(mCols);
|
||||
for(j=0; j<mCols; j++) {
|
||||
for(unsigned i = 0; i < mRows; i++) {
|
||||
mRowVec[i].Reinit( mCols );
|
||||
for(unsigned j = 0; j < mCols; j++) {
|
||||
if (data)
|
||||
(*this)[i][j] = data[i][j];
|
||||
else
|
||||
|
@ -123,44 +108,26 @@ void Matrix::CopyFrom(const Matrix &other)
|
|||
{
|
||||
mRows = other.mRows;
|
||||
mCols = other.mCols;
|
||||
mRowVec = new Vector *[mRows];
|
||||
int i;
|
||||
for(i=0; i<mRows; i++) {
|
||||
mRowVec[i] = new Vector(mCols);
|
||||
*mRowVec[i] = *other.mRowVec[i];
|
||||
mRowVec.reinit(mRows);
|
||||
for (unsigned i = 0; i < mRows; i++) {
|
||||
mRowVec[i].Reinit( mCols );
|
||||
mRowVec[i] = other.mRowVec[i];
|
||||
}
|
||||
}
|
||||
|
||||
Matrix::~Matrix()
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<mRows; i++)
|
||||
delete mRowVec[i];
|
||||
delete[] mRowVec;
|
||||
}
|
||||
|
||||
void Matrix::SwapRows(int i, int j)
|
||||
void Matrix::SwapRows(unsigned i, unsigned j)
|
||||
{
|
||||
Vector *tmp = mRowVec[i];
|
||||
mRowVec[i] = mRowVec[j];
|
||||
mRowVec[j] = tmp;
|
||||
mRowVec[i].Swap(mRowVec[j]);
|
||||
}
|
||||
|
||||
double Matrix::Sum() const
|
||||
{
|
||||
int i, j;
|
||||
double sum = 0.0;
|
||||
for(i=0; i<Rows(); i++)
|
||||
for(j=0; j<Cols(); j++)
|
||||
sum += (*mRowVec[i])[j];
|
||||
return sum;
|
||||
}
|
||||
|
||||
Matrix IdentityMatrix(int N)
|
||||
Matrix IdentityMatrix(unsigned N)
|
||||
{
|
||||
Matrix M(N, N);
|
||||
int i;
|
||||
for(i=0; i<N; i++)
|
||||
for(unsigned i = 0; i < N; i++)
|
||||
M[i][i] = 1.0;
|
||||
return M;
|
||||
}
|
||||
|
@ -169,8 +136,7 @@ Vector operator+(const Vector &left, const Vector &right)
|
|||
{
|
||||
wxASSERT(left.Len() == right.Len());
|
||||
Vector v(left.Len());
|
||||
int i;
|
||||
for(i=0; i<left.Len(); i++)
|
||||
for(unsigned i = 0; i < left.Len(); i++)
|
||||
v[i] = left[i] + right[i];
|
||||
return v;
|
||||
}
|
||||
|
@ -179,8 +145,7 @@ Vector operator-(const Vector &left, const Vector &right)
|
|||
{
|
||||
wxASSERT(left.Len() == right.Len());
|
||||
Vector v(left.Len());
|
||||
int i;
|
||||
for(i=0; i<left.Len(); i++)
|
||||
for(unsigned i = 0; i < left.Len(); i++)
|
||||
v[i] = left[i] - right[i];
|
||||
return v;
|
||||
}
|
||||
|
@ -189,8 +154,7 @@ Vector operator*(const Vector &left, const Vector &right)
|
|||
{
|
||||
wxASSERT(left.Len() == right.Len());
|
||||
Vector v(left.Len());
|
||||
int i;
|
||||
for(i=0; i<left.Len(); i++)
|
||||
for(unsigned i = 0; i < left.Len(); i++)
|
||||
v[i] = left[i] * right[i];
|
||||
return v;
|
||||
}
|
||||
|
@ -198,17 +162,15 @@ Vector operator*(const Vector &left, const Vector &right)
|
|||
Vector operator*(const Vector &left, double right)
|
||||
{
|
||||
Vector v(left.Len());
|
||||
int i;
|
||||
for(i=0; i<left.Len(); i++)
|
||||
for(unsigned i = 0; i < left.Len(); i++)
|
||||
v[i] = left[i] * right;
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector VectorSubset(const Vector &other, int start, int len)
|
||||
Vector VectorSubset(const Vector &other, unsigned start, unsigned len)
|
||||
{
|
||||
Vector v(len);
|
||||
int i;
|
||||
for(i=0; i<len; i++)
|
||||
for(unsigned i = 0; i < len; i++)
|
||||
v[i] = other[start+i];
|
||||
return v;
|
||||
}
|
||||
|
@ -216,10 +178,9 @@ Vector VectorSubset(const Vector &other, int start, int len)
|
|||
Vector VectorConcatenate(const Vector& left, const Vector& right)
|
||||
{
|
||||
Vector v(left.Len() + right.Len());
|
||||
int i;
|
||||
for(i=0; i<left.Len(); i++)
|
||||
for(unsigned i = 0; i < left.Len(); i++)
|
||||
v[i] = left[i];
|
||||
for(i=0; i<right.Len(); i++)
|
||||
for(unsigned i = 0; i < right.Len(); i++)
|
||||
v[i + left.Len()] = right[i];
|
||||
return v;
|
||||
}
|
||||
|
@ -228,10 +189,9 @@ Vector operator*(const Vector &left, const Matrix &right)
|
|||
{
|
||||
wxASSERT(left.Len() == right.Rows());
|
||||
Vector v(right.Cols());
|
||||
int i, j;
|
||||
for(i=0; i<right.Cols(); i++) {
|
||||
for(unsigned i = 0; i < right.Cols(); i++) {
|
||||
v[i] = 0.0;
|
||||
for(j=0; j<right.Rows(); j++)
|
||||
for(unsigned j = 0; j < right.Rows(); j++)
|
||||
v[i] += left[j] * right[j][i];
|
||||
}
|
||||
return v;
|
||||
|
@ -241,10 +201,9 @@ Vector operator*(const Matrix &left, const Vector &right)
|
|||
{
|
||||
wxASSERT(left.Cols() == right.Len());
|
||||
Vector v(left.Rows());
|
||||
int i, j;
|
||||
for(i=0; i<left.Rows(); i++) {
|
||||
for(unsigned i = 0; i < left.Rows(); i++) {
|
||||
v[i] = 0.0;
|
||||
for(j=0; j<left.Cols(); j++)
|
||||
for(unsigned j = 0; j < left.Cols(); j++)
|
||||
v[i] += left[i][j] * right[j];
|
||||
}
|
||||
return v;
|
||||
|
@ -255,9 +214,8 @@ Matrix operator+(const Matrix &left, const Matrix &right)
|
|||
wxASSERT(left.Rows() == right.Rows());
|
||||
wxASSERT(left.Cols() == right.Cols());
|
||||
Matrix M(left.Rows(), left.Cols());
|
||||
int i, j;
|
||||
for(i=0; i<left.Rows(); i++)
|
||||
for(j=0; j<left.Cols(); j++)
|
||||
for(unsigned i = 0; i < left.Rows(); i++)
|
||||
for(unsigned j = 0; j < left.Cols(); j++)
|
||||
M[i][j] = left[i][j] + right[i][j];
|
||||
return M;
|
||||
}
|
||||
|
@ -265,9 +223,8 @@ Matrix operator+(const Matrix &left, const Matrix &right)
|
|||
Matrix operator*(const Matrix &left, const double right)
|
||||
{
|
||||
Matrix M(left.Rows(), left.Cols());
|
||||
int i, j;
|
||||
for(i=0; i<left.Rows(); i++)
|
||||
for(j=0; j<left.Cols(); j++)
|
||||
for(unsigned i = 0; i < left.Rows(); i++)
|
||||
for(unsigned j = 0; j < left.Cols(); j++)
|
||||
M[i][j] = left[i][j] * right;
|
||||
return M;
|
||||
}
|
||||
|
@ -277,9 +234,8 @@ Matrix ScalarMultiply(const Matrix &left, const Matrix &right)
|
|||
wxASSERT(left.Rows() == right.Rows());
|
||||
wxASSERT(left.Cols() == right.Cols());
|
||||
Matrix M(left.Rows(), left.Cols());
|
||||
int i, j;
|
||||
for(i=0; i<left.Rows(); i++)
|
||||
for(j=0; j<left.Cols(); j++)
|
||||
for(unsigned i = 0; i < left.Rows(); i++)
|
||||
for(unsigned j = 0; j < left.Cols(); j++)
|
||||
M[i][j] = left[i][j] * right[i][j];
|
||||
return M;
|
||||
}
|
||||
|
@ -288,23 +244,22 @@ Matrix MatrixMultiply(const Matrix &left, const Matrix &right)
|
|||
{
|
||||
wxASSERT(left.Cols() == right.Rows());
|
||||
Matrix M(left.Rows(), right.Cols());
|
||||
int i, j, k;
|
||||
for(i=0; i<left.Rows(); i++)
|
||||
for(j=0; j<right.Cols(); j++) {
|
||||
for(unsigned i = 0; i < left.Rows(); i++)
|
||||
for(unsigned j = 0; j < right.Cols(); j++) {
|
||||
M[i][j] = 0.0;
|
||||
for(k=0; k<left.Cols(); k++)
|
||||
for(unsigned k = 0; k < left.Cols(); k++)
|
||||
M[i][j] += left[i][k] * right[k][j];
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
Matrix MatrixSubset(const Matrix &input,
|
||||
int startRow, int numRows, int startCol, int numCols)
|
||||
unsigned startRow, unsigned numRows,
|
||||
unsigned startCol, unsigned numCols)
|
||||
{
|
||||
Matrix M(numRows, numCols);
|
||||
int i, j;
|
||||
for(i=0; i<numRows; i++)
|
||||
for(j=0; j<numCols; j++)
|
||||
for(unsigned i = 0; i < numRows; i++)
|
||||
for(unsigned j = 0; j < numCols; j++)
|
||||
M[i][j] = input[startRow+i][startCol+j];
|
||||
return M;
|
||||
}
|
||||
|
@ -313,11 +268,10 @@ Matrix MatrixConcatenateCols(const Matrix& left, const Matrix& right)
|
|||
{
|
||||
wxASSERT(left.Rows() == right.Rows());
|
||||
Matrix M(left.Rows(), left.Cols() + right.Cols());
|
||||
int i, j;
|
||||
for(i=0; i<left.Rows(); i++) {
|
||||
for(j=0; j<left.Cols(); j++)
|
||||
for(unsigned i = 0; i < left.Rows(); i++) {
|
||||
for(unsigned j = 0; j < left.Cols(); j++)
|
||||
M[i][j] = left[i][j];
|
||||
for(j=0; j<right.Cols(); j++)
|
||||
for(unsigned j = 0; j < right.Cols(); j++)
|
||||
M[i][j+left.Cols()] = right[i][j];
|
||||
}
|
||||
return M;
|
||||
|
@ -326,9 +280,8 @@ Matrix MatrixConcatenateCols(const Matrix& left, const Matrix& right)
|
|||
Matrix TransposeMatrix(const Matrix& other)
|
||||
{
|
||||
Matrix M(other.Cols(), other.Rows());
|
||||
int i, j;
|
||||
for(i=0; i<other.Rows(); i++)
|
||||
for(j=0; j<other.Cols(); j++)
|
||||
for(unsigned i = 0; i < other.Rows(); i++)
|
||||
for(unsigned j = 0; j < other.Cols(); j++)
|
||||
M[j][i] = other[i][j];
|
||||
return M;
|
||||
}
|
||||
|
@ -340,20 +293,19 @@ bool InvertMatrix(const Matrix& input, Matrix& Minv)
|
|||
// Returns true if successful
|
||||
|
||||
wxASSERT(input.Rows() == input.Cols());
|
||||
int N = input.Rows();
|
||||
int i, j, k;
|
||||
auto N = input.Rows();
|
||||
|
||||
Matrix M = input;
|
||||
Minv = IdentityMatrix(N);
|
||||
|
||||
// Do the elimination one column at a time
|
||||
for(i=0; i<N; i++) {
|
||||
for(unsigned i = 0; i < N; i++) {
|
||||
// Pivot the row with the largest absolute value in
|
||||
// column i, into row i
|
||||
double absmax = 0.0;
|
||||
int argmax=0;
|
||||
int argmax = 0;
|
||||
|
||||
for(j=i; j<N; j++)
|
||||
for(unsigned j = i; j < N; j++)
|
||||
if (fabs(M[j][i]) > absmax) {
|
||||
absmax = fabs(M[j][i]);
|
||||
argmax = j;
|
||||
|
@ -375,13 +327,13 @@ bool InvertMatrix(const Matrix& input, Matrix& Minv)
|
|||
Minv[i] = Minv[i] * factor;
|
||||
|
||||
// Eliminate the rest of the column
|
||||
for(j=0; j<N; j++) {
|
||||
if (j==i)
|
||||
for(unsigned j = 0; j < N; j++) {
|
||||
if (j == i)
|
||||
continue;
|
||||
if (fabs(M[j][i]) > 0) {
|
||||
// Subtract a multiple of row i from row j
|
||||
double factor = M[j][i];
|
||||
for(k=0; k<N; k++) {
|
||||
for(unsigned k = 0; k < N; k++) {
|
||||
M[j][k] -= (M[i][k] * factor);
|
||||
Minv[j][k] -= (Minv[i][k] * factor);
|
||||
}
|
||||
|
|
53
src/Matrix.h
53
src/Matrix.h
|
@ -26,6 +26,8 @@
|
|||
#ifndef __AUDACITY_MATRIX__
|
||||
#define __AUDACITY_MATRIX__
|
||||
|
||||
#include "SampleFormat.h"
|
||||
|
||||
class Matrix;
|
||||
|
||||
class Vector
|
||||
|
@ -33,63 +35,61 @@ class Vector
|
|||
public:
|
||||
Vector();
|
||||
Vector(const Vector& copyFrom);
|
||||
Vector(int len, double *data=NULL, bool copy=true);
|
||||
Vector(int len, float *data);
|
||||
Vector(unsigned len, double *data=NULL);
|
||||
Vector(unsigned len, float *data);
|
||||
Vector& operator=(const Vector &other);
|
||||
virtual ~Vector();
|
||||
~Vector();
|
||||
|
||||
inline double& operator[](int i) { return mData[i]; }
|
||||
inline double operator[](int i) const { return mData[i]; }
|
||||
inline int Len() const { return mN; }
|
||||
void Reinit(unsigned len);
|
||||
void Swap(Vector &that);
|
||||
|
||||
inline double& operator[](unsigned i) { return mData[i]; }
|
||||
inline double operator[](unsigned i) const { return mData[i]; }
|
||||
inline unsigned Len() const { return mN; }
|
||||
|
||||
double Sum() const;
|
||||
|
||||
private:
|
||||
void CopyFrom(const Vector &other);
|
||||
|
||||
int mN;
|
||||
double *mData;
|
||||
bool mCopy;
|
||||
unsigned mN{ 0 };
|
||||
Doubles mData;
|
||||
};
|
||||
|
||||
class Matrix
|
||||
{
|
||||
public:
|
||||
Matrix(const Matrix& copyFrom);
|
||||
Matrix(int rows, int cols, double **data=NULL);
|
||||
virtual ~Matrix();
|
||||
Matrix(unsigned rows, unsigned cols, double **data=NULL);
|
||||
~Matrix();
|
||||
|
||||
Matrix& operator=(const Matrix& other);
|
||||
|
||||
inline Vector& operator[](int i) { return *mRowVec[i]; }
|
||||
inline Vector& operator[](int i) const { return *mRowVec[i]; }
|
||||
inline int Rows() const { return mRows; }
|
||||
inline int Cols() const { return mCols; }
|
||||
inline Vector& operator[](unsigned i) { return mRowVec[i]; }
|
||||
inline Vector& operator[](unsigned i) const { return mRowVec[i]; }
|
||||
inline unsigned Rows() const { return mRows; }
|
||||
inline unsigned Cols() const { return mCols; }
|
||||
|
||||
void SwapRows(int i, int j);
|
||||
|
||||
double Sum() const;
|
||||
void SwapRows(unsigned i, unsigned j);
|
||||
|
||||
private:
|
||||
void CopyFrom(const Matrix& other);
|
||||
|
||||
int mRows;
|
||||
int mCols;
|
||||
Vector **mRowVec;
|
||||
unsigned mRows;
|
||||
unsigned mCols;
|
||||
ArrayOf<Vector> mRowVec;
|
||||
};
|
||||
|
||||
bool InvertMatrix(const Matrix& input, Matrix& Minv);
|
||||
|
||||
Matrix TransposeMatrix(const Matrix& M);
|
||||
|
||||
Matrix IdentityMatrix(int N);
|
||||
Matrix IdentityMatrix(unsigned N);
|
||||
|
||||
Vector operator+(const Vector &left, const Vector &right);
|
||||
Vector operator-(const Vector &left, const Vector &right);
|
||||
Vector operator*(const Vector &left, const Vector &right);
|
||||
Vector operator*(const Vector &left, double right);
|
||||
|
||||
Vector VectorSubset(const Vector &other, int start, int len);
|
||||
Vector VectorSubset(const Vector &other, unsigned start, unsigned len);
|
||||
Vector VectorConcatenate(const Vector& left, const Vector& right);
|
||||
|
||||
Vector operator*(const Vector &left, const Matrix &right);
|
||||
|
@ -103,7 +103,8 @@ Matrix ScalarMultiply(const Matrix &left, const Matrix &right);
|
|||
Matrix MatrixMultiply(const Matrix &left, const Matrix &right);
|
||||
|
||||
Matrix MatrixSubset(const Matrix &M,
|
||||
int startRow, int numRows, int startCol, int numCols);
|
||||
unsigned startRow, unsigned numRows,
|
||||
unsigned startCol, unsigned numCols);
|
||||
|
||||
Matrix MatrixConcatenateCols(const Matrix& left, const Matrix& right);
|
||||
|
||||
|
|
|
@ -3439,12 +3439,8 @@ void AudacityProject::OnPlaySpeedDec()
|
|||
double AudacityProject::NearestZeroCrossing(double t0)
|
||||
{
|
||||
// Window is 1/100th of a second.
|
||||
int windowSize = (int)(GetRate() / 100);
|
||||
float *dist = new float[windowSize];
|
||||
int i, j;
|
||||
|
||||
for(i=0; i<windowSize; i++)
|
||||
dist[i] = 0.0;
|
||||
auto windowSize = size_t(std::max(1.0, GetRate() / 100));
|
||||
Floats dist{ windowSize, true };
|
||||
|
||||
TrackListIterator iter(GetTracks());
|
||||
Track *track = iter.First();
|
||||
|
@ -3454,26 +3450,26 @@ double AudacityProject::NearestZeroCrossing(double t0)
|
|||
continue;
|
||||
}
|
||||
WaveTrack *one = (WaveTrack *)track;
|
||||
int oneWindowSize = (int)(one->GetRate() / 100);
|
||||
float *oneDist = new float[oneWindowSize];
|
||||
auto oneWindowSize = size_t(std::max(1.0, one->GetRate() / 100));
|
||||
Floats oneDist{ oneWindowSize };
|
||||
auto s = one->TimeToLongSamples(t0);
|
||||
// fillTwo to ensure that missing values are treated as 2, and hence do not
|
||||
// get used as zero crossings.
|
||||
one->Get((samplePtr)oneDist, floatSample,
|
||||
s - oneWindowSize/2, oneWindowSize, fillTwo);
|
||||
one->Get((samplePtr)oneDist.get(), floatSample,
|
||||
s - (int)oneWindowSize/2, oneWindowSize, fillTwo);
|
||||
|
||||
// Start by penalizing downward motion. We prefer upward
|
||||
// zero crossings.
|
||||
if (oneDist[1] - oneDist[0] < 0)
|
||||
oneDist[0] = oneDist[0]*6 + (oneDist[0] > 0 ? 0.3 : -0.3);
|
||||
for(i=1; i<oneWindowSize; i++)
|
||||
for(size_t i=1; i<oneWindowSize; i++)
|
||||
if (oneDist[i] - oneDist[i-1] < 0)
|
||||
oneDist[i] = oneDist[i]*6 + (oneDist[i] > 0 ? 0.3 : -0.3);
|
||||
|
||||
// Taking the absolute value -- apply a tiny LPF so square waves work.
|
||||
float newVal, oldVal = oneDist[0];
|
||||
oneDist[0] = fabs(.75 * oneDist[0] + .25 * oneDist[1]);
|
||||
for(i=1; i<oneWindowSize-1; i++)
|
||||
for(size_t i=1; i + 1 < oneWindowSize; i++)
|
||||
{
|
||||
newVal = fabs(.25 * oldVal + .5 * oneDist[i] + .25 * oneDist[i+1]);
|
||||
oldVal = oneDist[i];
|
||||
|
@ -3485,7 +3481,8 @@ double AudacityProject::NearestZeroCrossing(double t0)
|
|||
// TODO: The mixed rate zero crossing code is broken,
|
||||
// if oneWindowSize > windowSize we'll miss out some
|
||||
// samples - so they will still be zero, so we'll use them.
|
||||
for(i=0; i<windowSize; i++) {
|
||||
for(size_t i = 0; i < windowSize; i++) {
|
||||
size_t j;
|
||||
if (windowSize != oneWindowSize)
|
||||
j = i * (oneWindowSize-1) / (windowSize-1);
|
||||
else
|
||||
|
@ -3493,26 +3490,23 @@ double AudacityProject::NearestZeroCrossing(double t0)
|
|||
|
||||
dist[i] += oneDist[j];
|
||||
// Apply a small penalty for distance from the original endpoint
|
||||
dist[i] += 0.1 * (abs(i - windowSize/2)) / float(windowSize/2);
|
||||
dist[i] += 0.1 * (abs(int(i) - int(windowSize/2))) / float(windowSize/2);
|
||||
}
|
||||
|
||||
delete [] oneDist;
|
||||
track = iter.Next();
|
||||
}
|
||||
|
||||
// Find minimum
|
||||
int argmin = 0;
|
||||
float min = 3.0;
|
||||
for(i=0; i<windowSize; i++) {
|
||||
for(size_t i=0; i<windowSize; i++) {
|
||||
if (dist[i] < min) {
|
||||
argmin = i;
|
||||
min = dist[i];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] dist;
|
||||
|
||||
return t0 + (argmin - windowSize/2)/GetRate();
|
||||
return t0 + (argmin - (int)windowSize/2)/GetRate();
|
||||
}
|
||||
|
||||
void AudacityProject::OnZeroCrossing()
|
||||
|
|
148
src/Mix.cpp
148
src/Mix.cpp
|
@ -244,18 +244,24 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
|||
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality, MixerSpec *mixerSpec)
|
||||
{
|
||||
int i;
|
||||
: mNumInputTracks { inputTracks.size() }
|
||||
|
||||
const auto numInputTracks = inputTracks.size();
|
||||
// This is the number of samples grabbed in one go from a track
|
||||
// and placed in a queue, when mixing with resampling.
|
||||
// (Should we use WaveTrack::GetBestBlockSize instead?)
|
||||
, mQueueMaxLen{ 65536 }
|
||||
, mSampleQueue{ mNumInputTracks, mQueueMaxLen }
|
||||
|
||||
, mNumChannels{ static_cast<size_t>(numOutChannels) }
|
||||
, mGains{ mNumChannels }
|
||||
{
|
||||
mHighQuality = highQuality;
|
||||
mNumInputTracks = numInputTracks;
|
||||
mInputTrack = new WaveTrackCache[mNumInputTracks];
|
||||
mInputTrack.reinit(mNumInputTracks);
|
||||
|
||||
// mSamplePos holds for each track the next sample position not
|
||||
// yet processed.
|
||||
mSamplePos = new sampleCount[mNumInputTracks];
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
mSamplePos.reinit(mNumInputTracks);
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mInputTrack[i].SetTrack(inputTracks[i]);
|
||||
mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime);
|
||||
}
|
||||
|
@ -263,14 +269,12 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
|||
mT0 = startTime;
|
||||
mT1 = stopTime;
|
||||
mTime = startTime;
|
||||
mNumChannels = numOutChannels;
|
||||
mBufferSize = outBufferSize;
|
||||
mInterleaved = outInterleaved;
|
||||
mRate = outRate;
|
||||
mSpeed = 1.0;
|
||||
mFormat = outFormat;
|
||||
mApplyTrackGains = true;
|
||||
mGains = new float[mNumChannels];
|
||||
if( mixerSpec && mixerSpec->GetNumChannels() == mNumChannels &&
|
||||
mixerSpec->GetNumTracks() == mNumInputTracks )
|
||||
mMixerSpec = mixerSpec;
|
||||
|
@ -286,18 +290,13 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
|||
mInterleavedBufferSize = mBufferSize;
|
||||
}
|
||||
|
||||
mBuffer = new SampleBuffer[mNumBuffers];
|
||||
mTemp = new SampleBuffer[mNumBuffers];
|
||||
mBuffer.reinit(mNumBuffers);
|
||||
mTemp.reinit(mNumBuffers);
|
||||
for (int c = 0; c < mNumBuffers; c++) {
|
||||
mBuffer[c].Allocate(mInterleavedBufferSize, mFormat);
|
||||
mTemp[c].Allocate(mInterleavedBufferSize, floatSample);
|
||||
}
|
||||
mFloatBuffer = new float[mInterleavedBufferSize];
|
||||
|
||||
// This is the number of samples grabbed in one go from a track
|
||||
// and placed in a queue, when mixing with resampling.
|
||||
// (Should we use WaveTrack::GetBestBlockSize instead?)
|
||||
mQueueMaxLen = 65536;
|
||||
mFloatBuffer = Floats{ mInterleavedBufferSize };
|
||||
|
||||
// But cut the queue into blocks of this finer size
|
||||
// for variable rate resampling. Each block is resampled at some
|
||||
|
@ -305,13 +304,12 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
|||
mProcessLen = 1024;
|
||||
|
||||
// Position in each queue of the start of the next block to resample.
|
||||
mQueueStart = new int[mNumInputTracks];
|
||||
mQueueStart.reinit(mNumInputTracks);
|
||||
|
||||
// For each queue, the number of available samples after the queue start.
|
||||
mQueueLen = new int[mNumInputTracks];
|
||||
mSampleQueue = new float *[mNumInputTracks];
|
||||
mResample = new Resample*[mNumInputTracks];
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
mQueueLen.reinit(mNumInputTracks);
|
||||
mResample.reinit(mNumInputTracks);
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
|
||||
double minFactor, maxFactor;
|
||||
if (mTimeTrack) {
|
||||
|
@ -332,36 +330,17 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
|||
minFactor = maxFactor = factor;
|
||||
}
|
||||
|
||||
mResample[i] = new Resample(mHighQuality, minFactor, maxFactor);
|
||||
mSampleQueue[i] = new float[mQueueMaxLen];
|
||||
mResample[i] = std::make_unique<Resample>(mHighQuality, minFactor, maxFactor);
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
}
|
||||
|
||||
const auto envLen = std::max(mQueueMaxLen, mInterleavedBufferSize);
|
||||
mEnvValues = new double[envLen];
|
||||
mEnvValues.reinit(envLen);
|
||||
}
|
||||
|
||||
Mixer::~Mixer()
|
||||
{
|
||||
int i;
|
||||
|
||||
delete[] mBuffer;
|
||||
delete[] mTemp;
|
||||
delete[] mInputTrack;
|
||||
delete[] mEnvValues;
|
||||
delete[] mFloatBuffer;
|
||||
delete[] mGains;
|
||||
delete[] mSamplePos;
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
delete mResample[i];
|
||||
delete[] mSampleQueue[i];
|
||||
}
|
||||
delete[] mResample;
|
||||
delete[] mSampleQueue;
|
||||
delete[] mQueueStart;
|
||||
delete[] mQueueLen;
|
||||
}
|
||||
|
||||
void Mixer::ApplyTrackGains(bool apply)
|
||||
|
@ -461,7 +440,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
|||
else
|
||||
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
|
||||
|
||||
track->GetEnvelopeValues(mEnvValues,
|
||||
track->GetEnvelopeValues(mEnvValues.get(),
|
||||
getLen,
|
||||
(*pos - (getLen- 1)).as_double() / trackRate);
|
||||
*pos -= getLen;
|
||||
|
@ -473,7 +452,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
|||
else
|
||||
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
|
||||
|
||||
track->GetEnvelopeValues(mEnvValues,
|
||||
track->GetEnvelopeValues(mEnvValues.get(),
|
||||
getLen,
|
||||
(*pos).as_double() / trackRate);
|
||||
|
||||
|
@ -532,7 +511,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
|||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < mNumChannels; c++) {
|
||||
for (size_t c = 0; c < mNumChannels; c++) {
|
||||
if (mApplyTrackGains) {
|
||||
mGains[c] = track->GetChannelGain(c);
|
||||
}
|
||||
|
@ -543,9 +522,9 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
|||
|
||||
MixBuffers(mNumChannels,
|
||||
channelFlags,
|
||||
mGains,
|
||||
(samplePtr)mFloatBuffer,
|
||||
mTemp,
|
||||
mGains.get(),
|
||||
(samplePtr)mFloatBuffer.get(),
|
||||
mTemp.get(),
|
||||
out,
|
||||
mInterleaved);
|
||||
|
||||
|
@ -557,7 +536,6 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
|
|||
{
|
||||
const WaveTrack *const track = cache.GetTrack();
|
||||
auto slen = mMaxOut;
|
||||
int c;
|
||||
const double t = ( *pos ).as_double() / track->GetRate();
|
||||
const double trackEndTime = track->GetEndTime();
|
||||
const double trackStartTime = track->GetStartTime();
|
||||
|
@ -578,37 +556,37 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
|
|||
if (backwards) {
|
||||
auto results = cache.Get(floatSample, *pos - (slen - 1), slen);
|
||||
if (results)
|
||||
memcpy(mFloatBuffer, results, sizeof(float) * slen);
|
||||
memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
|
||||
else
|
||||
memset(mFloatBuffer, 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate);
|
||||
memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues.get(), slen, t - (slen - 1) / mRate);
|
||||
for(decltype(slen) i = 0; i < slen; i++)
|
||||
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
|
||||
ReverseSamples((samplePtr)mFloatBuffer, floatSample, 0, slen);
|
||||
ReverseSamples((samplePtr)mFloatBuffer.get(), floatSample, 0, slen);
|
||||
|
||||
*pos -= slen;
|
||||
}
|
||||
else {
|
||||
auto results = cache.Get(floatSample, *pos, slen);
|
||||
if (results)
|
||||
memcpy(mFloatBuffer, results, sizeof(float) * slen);
|
||||
memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
|
||||
else
|
||||
memset(mFloatBuffer, 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues, slen, t);
|
||||
memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
|
||||
track->GetEnvelopeValues(mEnvValues.get(), slen, t);
|
||||
for(decltype(slen) i = 0; i < slen; i++)
|
||||
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
|
||||
|
||||
*pos += slen;
|
||||
}
|
||||
|
||||
for(c=0; c<mNumChannels; c++)
|
||||
for(size_t c=0; c<mNumChannels; c++)
|
||||
if (mApplyTrackGains)
|
||||
mGains[c] = track->GetChannelGain(c);
|
||||
else
|
||||
mGains[c] = 1.0;
|
||||
|
||||
MixBuffers(mNumChannels, channelFlags, mGains,
|
||||
(samplePtr)mFloatBuffer, mTemp, slen, mInterleaved);
|
||||
MixBuffers(mNumChannels, channelFlags, mGains.get(),
|
||||
(samplePtr)mFloatBuffer.get(), mTemp.get(), slen, mInterleaved);
|
||||
|
||||
return slen;
|
||||
}
|
||||
|
@ -620,28 +598,27 @@ size_t Mixer::Process(size_t maxToProcess)
|
|||
//if (mT >= mT1)
|
||||
// return 0;
|
||||
|
||||
int i, j;
|
||||
decltype(Process(0)) maxOut = 0;
|
||||
int *channelFlags = new int[mNumChannels];
|
||||
ArrayOf<int> channelFlags{ mNumChannels };
|
||||
|
||||
mMaxOut = maxToProcess;
|
||||
|
||||
Clear();
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
const WaveTrack *const track = mInputTrack[i].GetTrack();
|
||||
for(j=0; j<mNumChannels; j++)
|
||||
for(size_t j=0; j<mNumChannels; j++)
|
||||
channelFlags[j] = 0;
|
||||
|
||||
if( mMixerSpec ) {
|
||||
//ignore left and right when downmixing is not required
|
||||
for( j = 0; j < mNumChannels; j++ )
|
||||
for(size_t j = 0; j < mNumChannels; j++ )
|
||||
channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
switch(track->GetChannel()) {
|
||||
case Track::MonoChannel:
|
||||
default:
|
||||
for(j=0; j<mNumChannels; j++)
|
||||
for(size_t j=0; j<mNumChannels; j++)
|
||||
channelFlags[j] = 1;
|
||||
break;
|
||||
case Track::LeftChannel:
|
||||
|
@ -657,12 +634,12 @@ size_t Mixer::Process(size_t maxToProcess)
|
|||
}
|
||||
if (mbVariableRates || track->GetRate() != mRate)
|
||||
maxOut = std::max(maxOut,
|
||||
MixVariableRates(channelFlags, mInputTrack[i],
|
||||
&mSamplePos[i], mSampleQueue[i],
|
||||
&mQueueStart[i], &mQueueLen[i], mResample[i]));
|
||||
MixVariableRates(channelFlags.get(), mInputTrack[i],
|
||||
&mSamplePos[i], mSampleQueue[i].get(),
|
||||
&mQueueStart[i], &mQueueLen[i], mResample[i].get()));
|
||||
else
|
||||
maxOut = std::max(maxOut,
|
||||
MixSameRate(channelFlags, mInputTrack[i], &mSamplePos[i]));
|
||||
MixSameRate(channelFlags.get(), mInputTrack[i], &mSamplePos[i]));
|
||||
|
||||
double t = mSamplePos[i].as_double() / (double)track->GetRate();
|
||||
if (mT0 > mT1)
|
||||
|
@ -673,7 +650,7 @@ size_t Mixer::Process(size_t maxToProcess)
|
|||
mTime = std::min(std::max(t, mTime), mT1);
|
||||
}
|
||||
if(mInterleaved) {
|
||||
for(int c=0; c<mNumChannels; c++) {
|
||||
for(size_t c=0; c<mNumChannels; c++) {
|
||||
CopySamples(mTemp[0].ptr() + (c * SAMPLE_SIZE(floatSample)),
|
||||
floatSample,
|
||||
mBuffer[0].ptr() + (c * SAMPLE_SIZE(mFormat)),
|
||||
|
@ -685,7 +662,7 @@ size_t Mixer::Process(size_t maxToProcess)
|
|||
}
|
||||
}
|
||||
else {
|
||||
for(int c=0; c<mNumBuffers; c++) {
|
||||
for(size_t c=0; c<mNumBuffers; c++) {
|
||||
CopySamples(mTemp[c].ptr(),
|
||||
floatSample,
|
||||
mBuffer[c].ptr(),
|
||||
|
@ -697,8 +674,6 @@ size_t Mixer::Process(size_t maxToProcess)
|
|||
// MB: this doesn't take warping into account, replaced with code based on mSamplePos
|
||||
//mT += (maxOut / mRate);
|
||||
|
||||
delete [] channelFlags;
|
||||
|
||||
return maxOut;
|
||||
}
|
||||
|
||||
|
@ -719,14 +694,12 @@ double Mixer::MixGetCurrentTime()
|
|||
|
||||
void Mixer::Restart()
|
||||
{
|
||||
int i;
|
||||
|
||||
mTime = mT0;
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++)
|
||||
for(size_t i=0; i<mNumInputTracks; i++)
|
||||
mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mT0);
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
}
|
||||
|
@ -734,8 +707,6 @@ void Mixer::Restart()
|
|||
|
||||
void Mixer::Reposition(double t)
|
||||
{
|
||||
int i;
|
||||
|
||||
mTime = t;
|
||||
const bool backwards = (mT1 < mT0);
|
||||
if (backwards)
|
||||
|
@ -743,7 +714,7 @@ void Mixer::Reposition(double t)
|
|||
else
|
||||
mTime = std::max(mT0, (std::min(mT1, mTime)));
|
||||
|
||||
for(i=0; i<mNumInputTracks; i++) {
|
||||
for(size_t i=0; i<mNumInputTracks; i++) {
|
||||
mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mTime);
|
||||
mQueueStart[i] = 0;
|
||||
mQueueLen[i] = 0;
|
||||
|
@ -789,22 +760,11 @@ MixerSpec::MixerSpec( const MixerSpec &mixerSpec )
|
|||
|
||||
void MixerSpec::Alloc()
|
||||
{
|
||||
mMap = new bool*[ mNumTracks ];
|
||||
for( int i = 0; i < mNumTracks; i++ )
|
||||
mMap[ i ] = new bool[ mMaxNumChannels ];
|
||||
mMap.reinit(mNumTracks, mMaxNumChannels);
|
||||
}
|
||||
|
||||
MixerSpec::~MixerSpec()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void MixerSpec::Free()
|
||||
{
|
||||
for( int i = 0; i < mNumTracks; i++ )
|
||||
delete[] mMap[ i ];
|
||||
|
||||
delete[] mMap;
|
||||
}
|
||||
|
||||
bool MixerSpec::SetNumChannels( unsigned newNumChannels )
|
||||
|
@ -830,8 +790,6 @@ bool MixerSpec::SetNumChannels( unsigned newNumChannels )
|
|||
|
||||
MixerSpec& MixerSpec::operator=( const MixerSpec &mixerSpec )
|
||||
{
|
||||
Free();
|
||||
|
||||
mNumTracks = mixerSpec.mNumTracks;
|
||||
mNumChannels = mixerSpec.mNumChannels;
|
||||
mMaxNumChannels = mixerSpec.mMaxNumChannels;
|
||||
|
|
30
src/Mix.h
30
src/Mix.h
|
@ -51,10 +51,9 @@ class AUDACITY_DLL_API MixerSpec
|
|||
unsigned mNumTracks, mNumChannels, mMaxNumChannels;
|
||||
|
||||
void Alloc();
|
||||
void Free();
|
||||
|
||||
public:
|
||||
bool **mMap;
|
||||
public:
|
||||
ArraysOf<bool> mMap;
|
||||
|
||||
MixerSpec( unsigned numTracks, unsigned maxNumChannels );
|
||||
MixerSpec( const MixerSpec &mixerSpec );
|
||||
|
@ -150,38 +149,37 @@ class AUDACITY_DLL_API Mixer {
|
|||
Resample * pResample);
|
||||
|
||||
private:
|
||||
// Input
|
||||
int mNumInputTracks;
|
||||
WaveTrackCache *mInputTrack;
|
||||
|
||||
// Input
|
||||
size_t mNumInputTracks;
|
||||
ArrayOf<WaveTrackCache> mInputTrack;
|
||||
bool mbVariableRates;
|
||||
const TimeTrack *mTimeTrack;
|
||||
sampleCount *mSamplePos;
|
||||
ArrayOf<sampleCount> mSamplePos;
|
||||
bool mApplyTrackGains;
|
||||
float *mGains;
|
||||
double *mEnvValues;
|
||||
Doubles mEnvValues;
|
||||
double mT0; // Start time
|
||||
double mT1; // Stop time (none if mT0==mT1)
|
||||
double mTime; // Current time (renamed from mT to mTime for consistency with AudioIO - mT represented warped time there)
|
||||
Resample **mResample;
|
||||
float **mSampleQueue;
|
||||
int *mQueueStart;
|
||||
int *mQueueLen;
|
||||
ArrayOf<std::unique_ptr<Resample>> mResample;
|
||||
size_t mQueueMaxLen;
|
||||
FloatBuffers mSampleQueue;
|
||||
ArrayOf<int> mQueueStart;
|
||||
ArrayOf<int> mQueueLen;
|
||||
size_t mProcessLen;
|
||||
MixerSpec *mMixerSpec;
|
||||
|
||||
// Output
|
||||
size_t mMaxOut;
|
||||
unsigned mNumChannels;
|
||||
Floats mGains;
|
||||
unsigned mNumBuffers;
|
||||
size_t mBufferSize;
|
||||
size_t mInterleavedBufferSize;
|
||||
sampleFormat mFormat;
|
||||
bool mInterleaved;
|
||||
SampleBuffer *mBuffer;
|
||||
SampleBuffer *mTemp;
|
||||
float *mFloatBuffer;
|
||||
ArrayOf<SampleBuffer> mBuffer, mTemp;
|
||||
Floats mFloatBuffer;
|
||||
double mRate;
|
||||
double mSpeed;
|
||||
bool mHighQuality;
|
||||
|
|
|
@ -568,12 +568,12 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
|
|||
// stored in blockfiles, rather than calculating them, but for now, changing it to use the
|
||||
// original Meter::UpdateDisplay(). New code is below the previous (now commented out).
|
||||
//
|
||||
//const int kFramesPerBuffer = 4;
|
||||
//const size_t kFramesPerBuffer = 4;
|
||||
//float min; // dummy, since it's not shown in meters
|
||||
//float* maxLeft = new float[kFramesPerBuffer];
|
||||
//float* rmsLeft = new float[kFramesPerBuffer];
|
||||
//float* maxRight = new float[kFramesPerBuffer];
|
||||
//float* rmsRight = new float[kFramesPerBuffer];
|
||||
//Floats maxLeft{kFramesPerBuffer};
|
||||
//Floats rmsLeft{kFramesPerBuffer};
|
||||
//Floats maxRight{kFramesPerBuffer};
|
||||
//Floats rmsRight{kFramesPerBuffer};
|
||||
//
|
||||
//#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
// bool bSuccess = (mLeftTrack != NULL);
|
||||
|
@ -628,10 +628,6 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
|
|||
// mLeftTrack->TimeToLongSamples(t1 - t0));
|
||||
//}
|
||||
//
|
||||
//delete[] maxLeft;
|
||||
//delete[] rmsLeft;
|
||||
//delete[] maxRight;
|
||||
//delete[] rmsRight;
|
||||
|
||||
auto startSample = (sampleCount)((mLeftTrack->GetRate() * t0) + 0.5);
|
||||
auto scnFrames = (sampleCount)((mLeftTrack->GetRate() * (t1 - t0)) + 0.5);
|
||||
|
@ -640,22 +636,22 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
|
|||
// in about 1/20 second (ticks of TrackPanel timer), so this won't overflow
|
||||
auto nFrames = scnFrames.as_size_t();
|
||||
|
||||
float* meterFloatsArray = NULL;
|
||||
float* tempFloatsArray = new float[nFrames];
|
||||
bool bSuccess = mLeftTrack->Get((samplePtr)tempFloatsArray, floatSample, startSample, nFrames);
|
||||
Floats tempFloatsArray{ size_t(nFrames) };
|
||||
decltype(tempFloatsArray) meterFloatsArray;
|
||||
bool bSuccess = mLeftTrack->Get((samplePtr)tempFloatsArray.get(), floatSample, startSample, nFrames);
|
||||
if (bSuccess)
|
||||
{
|
||||
// We always pass a stereo sample array to the meter, as it shows 2 channels.
|
||||
// Mono shows same in both meters.
|
||||
// Since we're not mixing, need to duplicate same signal for "right" channel in mono case.
|
||||
meterFloatsArray = new float[2 * nFrames];
|
||||
meterFloatsArray = Floats{ 2 * nFrames };
|
||||
|
||||
// Interleave for stereo. Left/mono first.
|
||||
for (int index = 0; index < nFrames; index++)
|
||||
meterFloatsArray[2 * index] = tempFloatsArray[index];
|
||||
|
||||
if (mRightTrack)
|
||||
bSuccess = mRightTrack->Get((samplePtr)tempFloatsArray, floatSample, startSample, nFrames);
|
||||
bSuccess = mRightTrack->Get((samplePtr)tempFloatsArray.get(), floatSample, startSample, nFrames);
|
||||
|
||||
if (bSuccess)
|
||||
// Interleave right channel, or duplicate same signal for "right" channel in mono case.
|
||||
|
@ -686,13 +682,10 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
|
|||
else if (meterFloatsArray[index] > 1.0)
|
||||
meterFloatsArray[index] = 1.0;
|
||||
|
||||
mMeter->UpdateDisplay(2, nFrames, meterFloatsArray);
|
||||
mMeter->UpdateDisplay(2, nFrames, meterFloatsArray.get());
|
||||
}
|
||||
else
|
||||
this->ResetMeter(false);
|
||||
|
||||
delete[] meterFloatsArray;
|
||||
delete[] tempFloatsArray;
|
||||
}
|
||||
|
||||
// private
|
||||
|
|
|
@ -2794,9 +2794,8 @@ wxString PluginManager::ConvertID(const PluginID & ID)
|
|||
if (ID.StartsWith(wxT("base64:")))
|
||||
{
|
||||
wxString id = ID.Mid(7);
|
||||
char *buf = new char[id.Length() / 4 * 3];
|
||||
id = wxString::FromUTF8(buf, b64decode(id, buf));
|
||||
delete [] buf;
|
||||
ArrayOf<char> buf{ id.Length() / 4 * 3 };
|
||||
id = wxString::FromUTF8(buf.get(), b64decode(id, buf.get()));
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ Profiler::~Profiler()
|
|||
{
|
||||
if(mTasks[i]->mNumHits>0)
|
||||
{
|
||||
fprintf(log,"Task: %s\n(begins at line %d in %s)\n\n",mTasks[i]->mDescription,mTasks[i]->mLine,mTasks[i]->mFileName);
|
||||
fprintf(log,"Task: %s\n(begins at line %d in %s)\n\n",mTasks[i]->mDescription.get(), mTasks[i]->mLine, mTasks[i]->mFileName.get());
|
||||
fprintf(log,"Number of times run: %d\n",mTasks[i]->mNumHits);
|
||||
fprintf(log,"Total run time (seconds): %f\n", (double)mTasks[i]->mCumTime/CLOCKS_PER_SEC);
|
||||
fprintf(log,"Average run time (seconds): %f\n",mTasks[i]->ComputeAverageRunTime());
|
||||
|
@ -91,7 +91,7 @@ TaskProfile* Profiler::GetOrCreateTaskProfile(const char* fileName, int lineNum)
|
|||
{
|
||||
for(int i=0;i<(int)mTasks.size();i++)
|
||||
{
|
||||
if(strcmp(fileName,mTasks[i]->mFileName)==0 && lineNum == mTasks[i]->mLine)
|
||||
if(strcmp(fileName, mTasks[i]->mFileName.get())==0 && lineNum == mTasks[i]->mLine)
|
||||
return mTasks[i].get();
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ TaskProfile* Profiler::GetTaskProfileByDescription(const char* description)
|
|||
{
|
||||
for(int i=0;i<(int)mTasks.size();i++)
|
||||
{
|
||||
if(strcmp(description,mTasks[i]->mDescription)==0)
|
||||
if(strcmp(description, mTasks[i]->mDescription.get())==0)
|
||||
return mTasks[i].get();
|
||||
}
|
||||
|
||||
|
@ -116,18 +116,12 @@ TaskProfile* Profiler::GetTaskProfileByDescription(const char* description)
|
|||
///Task Profile
|
||||
TaskProfile::TaskProfile()
|
||||
{
|
||||
mFileName = NULL;
|
||||
mCumTime=0;
|
||||
mNumHits=0;
|
||||
}
|
||||
|
||||
TaskProfile::~TaskProfile()
|
||||
{
|
||||
if(mFileName)
|
||||
{
|
||||
delete [] mFileName;
|
||||
delete [] mDescription;
|
||||
}
|
||||
}
|
||||
|
||||
///start the task timer.
|
||||
|
@ -135,10 +129,10 @@ void TaskProfile::Begin(const char* fileName, int lineNum, const char* taskDescr
|
|||
{
|
||||
if(!mFileName)
|
||||
{
|
||||
mFileName = new char[strlen(fileName)+1];
|
||||
strcpy(mFileName,fileName);
|
||||
mDescription = new char[strlen(taskDescription)+1];
|
||||
strcpy(mDescription,taskDescription);
|
||||
mFileName.reinit( strlen(fileName) + 1 );
|
||||
strcpy(mFileName.get(), fileName);
|
||||
mDescription.reinit( strlen(taskDescription) + 1 );
|
||||
strcpy(mDescription.get(), taskDescription);
|
||||
mLine = lineNum;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,9 +79,9 @@ class Profiler
|
|||
|
||||
double ComputeAverageRunTime();
|
||||
|
||||
char* mFileName;
|
||||
ArrayOf<char> mFileName;
|
||||
int mLine;
|
||||
char* mDescription;
|
||||
ArrayOf<char> mDescription;
|
||||
int mNumHits;
|
||||
clock_t mCumTime;
|
||||
clock_t mLastTime;
|
||||
|
|
|
@ -383,19 +383,17 @@ public:
|
|||
Size dataSize = 0;
|
||||
GetFlavorDataSize((DragReference)m_currentDrag, theItem, theType, &dataSize);
|
||||
|
||||
Ptr theData = new char[dataSize];
|
||||
GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData, &dataSize, 0L);
|
||||
ArrayOf<char> theData{ dataSize };
|
||||
GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData.get(), &dataSize, 0L);
|
||||
|
||||
wxString name;
|
||||
if (theType == kDragPromisedFlavorFindFile) {
|
||||
name = wxMacFSSpec2MacFilename((FSSpec *)theData);
|
||||
name = wxMacFSSpec2MacFilename((FSSpec *)theData.get());
|
||||
}
|
||||
else if (theType == kDragFlavorTypeHFS) {
|
||||
name = wxMacFSSpec2MacFilename(&((HFSFlavor *)theData)->fileSpec);
|
||||
name = wxMacFSSpec2MacFilename(&((HFSFlavor *)theData.get())->fileSpec);
|
||||
}
|
||||
|
||||
delete[] theData;
|
||||
|
||||
if (!firstFileAdded) {
|
||||
// reset file list
|
||||
((wxFileDataObject*)GetDataObject())->SetData(0, "");
|
||||
|
|
|
@ -94,9 +94,9 @@ void TableUsage(int iMask)
|
|||
SinCosTable::SinCosTable() :
|
||||
mSinCosTablePow(13)
|
||||
{
|
||||
int tableSize=1<<mSinCosTablePow;
|
||||
mSinCosTable=new SinCosStruct[tableSize];
|
||||
for(int i=0;i<tableSize;i++) {
|
||||
size_t tableSize=1<<mSinCosTablePow;
|
||||
mSinCosTable.reinit(tableSize);
|
||||
for(size_t i=0;i<tableSize;i++) {
|
||||
mSinCosTable[i].mSin=(float)-sin(((float)i)*M_PI/tableSize);
|
||||
mSinCosTable[i].mCos=(float)-cos(((float)i)*M_PI/tableSize);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __realfftf48x_h
|
||||
#define __realfftf48x_h
|
||||
|
||||
#include "MemoryX.h"
|
||||
|
||||
#define fft_type float
|
||||
|
||||
int SmallRB(int bits, int numberBits);
|
||||
|
@ -87,9 +89,8 @@ typedef struct {
|
|||
class SinCosTable {
|
||||
public:
|
||||
int mSinCosTablePow;
|
||||
SinCosStruct *mSinCosTable;
|
||||
ArrayOf<SinCosStruct> mSinCosTable;
|
||||
SinCosTable();
|
||||
~SinCosTable(){ delete [] mSinCosTable; };
|
||||
};
|
||||
|
||||
int SmallRB(int bits, int numberBits);
|
||||
|
|
|
@ -1308,7 +1308,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
// ... unless the mNumSamples ceiling applies, and then there are other defenses
|
||||
const auto s1 =
|
||||
std::min(mNumSamples, std::max(1 + where[len - 1], where[len]));
|
||||
float *temp = new float[mMaxSamples];
|
||||
Floats temp{ mMaxSamples };
|
||||
|
||||
decltype(len) pixel = 0;
|
||||
|
||||
|
@ -1400,13 +1400,13 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
default:
|
||||
case 1:
|
||||
// Read samples
|
||||
Read((samplePtr)temp, floatSample, seqBlock, startPosition, num);
|
||||
Read((samplePtr)temp.get(), floatSample, seqBlock, startPosition, num);
|
||||
break;
|
||||
case 256:
|
||||
// Read triples
|
||||
//check to see if summary data has been computed
|
||||
if (seqBlock.f->IsSummaryAvailable())
|
||||
seqBlock.f->Read256(temp, startPosition, num);
|
||||
seqBlock.f->Read256(temp.get(), startPosition, num);
|
||||
else
|
||||
//otherwise, mark the display as not yet computed
|
||||
blockStatus = -1 - b;
|
||||
|
@ -1415,7 +1415,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
// Read triples
|
||||
//check to see if summary data has been computed
|
||||
if (seqBlock.f->IsSummaryAvailable())
|
||||
seqBlock.f->Read64K(temp, startPosition, num);
|
||||
seqBlock.f->Read64K(temp.get(), startPosition, num);
|
||||
else
|
||||
//otherwise, mark the display as not yet computed
|
||||
blockStatus = -1 - b;
|
||||
|
@ -1431,7 +1431,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
auto midPosition = ((whereNow - start) / divisor).as_size_t();
|
||||
int diff(midPosition - filePosition);
|
||||
if (diff > 0) {
|
||||
MinMaxSumsq values(temp, diff, divisor);
|
||||
MinMaxSumsq values(temp.get(), diff, divisor);
|
||||
const int lastPixel = pixel - 1;
|
||||
float &lastMin = min[lastPixel];
|
||||
lastMin = std::min(lastMin, values.min);
|
||||
|
@ -1471,7 +1471,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
rmsDenom = (positionX - filePosition);
|
||||
wxASSERT(rmsDenom > 0);
|
||||
const float *const pv =
|
||||
temp + (filePosition - startPosition) * (divisor == 1 ? 1 : 3);
|
||||
temp.get() + (filePosition - startPosition) * (divisor == 1 ? 1 : 3);
|
||||
MinMaxSumsq values(pv, rmsDenom, divisor);
|
||||
|
||||
// Assign results
|
||||
|
@ -1493,8 +1493,6 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
|||
|
||||
wxASSERT(pixel == len);
|
||||
|
||||
delete[] temp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,10 +291,7 @@ bool SnapManager::SnapToPoints(Track *currentTrack,
|
|||
return true;
|
||||
}
|
||||
|
||||
// indexInThisTrack is ONLY used if count > 0
|
||||
// and is initialised then, so we can 'initialise' it
|
||||
// to anything to keep compiler quiet.
|
||||
size_t indexInThisTrack = left;
|
||||
size_t indexInThisTrack = 0;
|
||||
size_t countInThisTrack = 0;
|
||||
for (i = left; i <= right; ++i)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "FFT.h"
|
||||
|
||||
#include "Experimental.h"
|
||||
#include "SampleFormat.h"
|
||||
|
||||
bool ComputeSpectrum(const float * data, size_t width,
|
||||
size_t windowSize,
|
||||
|
@ -31,15 +32,15 @@ bool ComputeSpectrum(const float * data, size_t width,
|
|||
if (!data || !output)
|
||||
return true;
|
||||
|
||||
float *processed = new float[windowSize];
|
||||
Floats processed{ windowSize };
|
||||
|
||||
for (size_t i = 0; i < windowSize; i++)
|
||||
processed[i] = float(0.0);
|
||||
auto half = windowSize / 2;
|
||||
|
||||
float *in = new float[windowSize];
|
||||
float *out = new float[windowSize];
|
||||
float *out2 = new float[windowSize];
|
||||
Floats in{ windowSize };
|
||||
Floats out{ windowSize };
|
||||
Floats out2{ windowSize };
|
||||
|
||||
size_t start = 0;
|
||||
unsigned windows = 0;
|
||||
|
@ -47,11 +48,11 @@ bool ComputeSpectrum(const float * data, size_t width,
|
|||
for (size_t i = 0; i < windowSize; i++)
|
||||
in[i] = data[start + i];
|
||||
|
||||
WindowFunc(windowFunc, windowSize, in);
|
||||
WindowFunc(windowFunc, windowSize, in.get());
|
||||
|
||||
if (autocorrelation) {
|
||||
// Take FFT
|
||||
RealFFT(windowSize, in, out, out2);
|
||||
RealFFT(windowSize, in.get(), out.get(), out2.get());
|
||||
// Compute power
|
||||
for (size_t i = 0; i < windowSize; i++)
|
||||
in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);
|
||||
|
@ -63,10 +64,10 @@ bool ComputeSpectrum(const float * data, size_t width,
|
|||
in[i] = powf(in[i], 1.0f / 3.0f);
|
||||
|
||||
// Take FFT
|
||||
RealFFT(windowSize, in, out, out2);
|
||||
RealFFT(windowSize, in.get(), out.get(), out2.get());
|
||||
}
|
||||
else
|
||||
PowerSpectrum(windowSize, in, out);
|
||||
PowerSpectrum(windowSize, in.get(), out.get());
|
||||
|
||||
// Take real part of result
|
||||
for (size_t i = 0; i < half; i++)
|
||||
|
@ -120,10 +121,6 @@ bool ComputeSpectrum(const float * data, size_t width,
|
|||
|
||||
for(size_t i = 0; i < half; i++)
|
||||
output[i] = processed[i];
|
||||
delete[]in;
|
||||
delete[]out;
|
||||
delete[]out2;
|
||||
delete[]processed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -251,8 +251,8 @@ void TimeTrack::Draw(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo) cons
|
|||
mRuler->SetFlip(GetHeight() > 75 ? true : true); // MB: so why don't we just call Invalidate()? :)
|
||||
mRuler->Draw(dc, this);
|
||||
|
||||
double *envValues = new double[mid.width];
|
||||
GetEnvelope()->GetValues(envValues, mid.width, 0, zoomInfo);
|
||||
Doubles envValues{ size_t(mid.width) };
|
||||
GetEnvelope()->GetValues(envValues.get(), mid.width, 0, zoomInfo);
|
||||
|
||||
dc.SetPen(AColor::envelopePen);
|
||||
|
||||
|
@ -267,9 +267,6 @@ void TimeTrack::Draw(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo) cons
|
|||
int thisy = r.y + (int)y;
|
||||
AColor::Line(dc, mid.x + x, thisy - 1, mid.x + x, thisy+2);
|
||||
}
|
||||
|
||||
if (envValues)
|
||||
delete[]envValues;
|
||||
}
|
||||
|
||||
void TimeTrack::testMe()
|
||||
|
|
|
@ -1159,13 +1159,13 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
|
|||
int lasth2 = std::numeric_limits<int>::min();
|
||||
int h1;
|
||||
int h2;
|
||||
int *r1 = new int[rect.width];
|
||||
int *r2 = new int[rect.width];
|
||||
int *clipped = NULL;
|
||||
ArrayOf<int> r1{ size_t(rect.width) };
|
||||
ArrayOf<int> r2{ size_t(rect.width) };
|
||||
ArrayOf<int> clipped;
|
||||
int clipcnt = 0;
|
||||
|
||||
if (mShowClipping) {
|
||||
clipped = new int[rect.width];
|
||||
clipped.reinit( size_t(rect.width) );
|
||||
}
|
||||
|
||||
long pixAnimOffset = (long)fabs((double)(wxDateTime::Now().GetTicks() * -10)) +
|
||||
|
@ -1296,13 +1296,6 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
|
|||
AColor::Line(dc, xx, rect.y, xx, rect.y + rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (mShowClipping) {
|
||||
delete[] clipped;
|
||||
}
|
||||
|
||||
delete [] r1;
|
||||
delete [] r2;
|
||||
}
|
||||
|
||||
void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &rect,
|
||||
|
@ -1330,16 +1323,16 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
|
|||
if (slen <= 0)
|
||||
return;
|
||||
|
||||
float *buffer = new float[slen];
|
||||
clip->GetSamples((samplePtr)buffer, floatSample, s0, slen);
|
||||
Floats buffer{ size_t(slen) };
|
||||
clip->GetSamples((samplePtr)buffer.get(), floatSample, s0, slen);
|
||||
|
||||
int *xpos = new int[slen];
|
||||
int *ypos = new int[slen];
|
||||
int *clipped = NULL;
|
||||
ArrayOf<int> xpos{ size_t(slen) };
|
||||
ArrayOf<int> ypos{ size_t(slen) };
|
||||
ArrayOf<int> clipped;
|
||||
int clipcnt = 0;
|
||||
|
||||
if (mShowClipping)
|
||||
clipped = new int[slen];
|
||||
clipped.reinit( size_t(slen) );
|
||||
|
||||
dc.SetPen(muted ? muteSamplePen : samplePen);
|
||||
|
||||
|
@ -1394,14 +1387,6 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
|
|||
AColor::Line(dc, rect.x + s, rect.y, rect.x + s, rect.y + rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (mShowClipping) {
|
||||
delete [] clipped;
|
||||
}
|
||||
|
||||
delete[]buffer;
|
||||
delete[]xpos;
|
||||
delete[]ypos;
|
||||
}
|
||||
|
||||
void TrackArtist::DrawEnvelope(wxDC &dc, const wxRect &rect, const double env[],
|
||||
|
@ -2216,8 +2201,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||
scale2 = (lmax - lmin) / log2,
|
||||
lmin2 = lmin / log2;
|
||||
|
||||
bool *yGrid;
|
||||
yGrid = new bool[mid.height];
|
||||
ArrayOf<bool> yGrid{size_t(mid.height)};
|
||||
for (int yy = 0; yy < mid.height; ++yy) {
|
||||
float n = (float(yy) / mid.height*scale2 - lmin2) * 12;
|
||||
float n2 = (float(yy + 1) / mid.height*scale2 - lmin2) * 12;
|
||||
|
@ -2286,8 +2270,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||
i0 = expf(lmin) / binUnit,
|
||||
i1 = expf(scale + lmin) / binUnit,
|
||||
minColor = 0.0f;
|
||||
const int maxTableSize = 1024;
|
||||
int *indexes = new int[maxTableSize];
|
||||
const size_t maxTableSize = 1024;
|
||||
ArrayOf<int> indexes{ maxTableSize };
|
||||
#endif //EXPERIMENTAL_FIND_NOTES
|
||||
|
||||
#ifdef _OPENMP
|
||||
|
@ -2525,10 +2509,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
|||
memDC.SelectObject(converted);
|
||||
|
||||
dc.Blit(mid.x, mid.y, mid.width, mid.height, &memDC, 0, 0, wxCOPY, FALSE);
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
delete[] yGrid;
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
}
|
||||
|
||||
#ifdef USE_MIDI
|
||||
|
|
|
@ -4553,20 +4553,18 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
|||
// SMOOTHING_PROPORTION_MAX and at the far bounds is SMOOTHING_PROPORTION_MIN
|
||||
|
||||
//Get the region of samples around the selected point
|
||||
int sampleRegionSize = 1 + 2 * (SMOOTHING_KERNEL_RADIUS + SMOOTHING_BRUSH_RADIUS);
|
||||
float *sampleRegion = new float[sampleRegionSize];
|
||||
float * newSampleRegion = new float[1 + 2 * SMOOTHING_BRUSH_RADIUS];
|
||||
size_t sampleRegionSize = 1 + 2 * (SMOOTHING_KERNEL_RADIUS + SMOOTHING_BRUSH_RADIUS);
|
||||
Floats sampleRegion{ sampleRegionSize };
|
||||
Floats newSampleRegion{ 1 + 2 * (size_t)SMOOTHING_BRUSH_RADIUS };
|
||||
|
||||
//Get a sample from the track to do some tricks on.
|
||||
mDrawingTrack->Get((samplePtr)sampleRegion, floatSample,
|
||||
mDrawingTrack->Get((samplePtr)sampleRegion.get(), floatSample,
|
||||
mDrawingStartSample - SMOOTHING_KERNEL_RADIUS - SMOOTHING_BRUSH_RADIUS,
|
||||
sampleRegionSize);
|
||||
int i, j;
|
||||
|
||||
//Go through each point of the smoothing brush and apply a smoothing operation.
|
||||
for(j = -SMOOTHING_BRUSH_RADIUS; j <= SMOOTHING_BRUSH_RADIUS; j++){
|
||||
for(auto j = -SMOOTHING_BRUSH_RADIUS; j <= SMOOTHING_BRUSH_RADIUS; j++){
|
||||
float sumOfSamples = 0;
|
||||
for (i= -SMOOTHING_KERNEL_RADIUS; i <= SMOOTHING_KERNEL_RADIUS; i++){
|
||||
for (auto i = -SMOOTHING_KERNEL_RADIUS; i <= SMOOTHING_KERNEL_RADIUS; i++){
|
||||
//Go through each point of the smoothing kernel and find the average
|
||||
|
||||
//The average is a weighted average, scaled by a weighting kernel that is simply triangular
|
||||
|
@ -4591,7 +4589,7 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
|||
|
||||
float prob;
|
||||
|
||||
for(j=-SMOOTHING_BRUSH_RADIUS; j <= SMOOTHING_BRUSH_RADIUS; j++){
|
||||
for(auto j = -SMOOTHING_BRUSH_RADIUS; j <= SMOOTHING_BRUSH_RADIUS; j++){
|
||||
|
||||
prob = SMOOTHING_PROPORTION_MAX - (float)abs(j)/SMOOTHING_BRUSH_RADIUS * (SMOOTHING_PROPORTION_MAX - SMOOTHING_PROPORTION_MIN);
|
||||
|
||||
|
@ -4600,11 +4598,7 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event )
|
|||
sampleRegion[SMOOTHING_BRUSH_RADIUS + SMOOTHING_KERNEL_RADIUS + j] * (1 - prob);
|
||||
}
|
||||
//Set the sample to the point of the mouse event
|
||||
mDrawingTrack->Set((samplePtr)newSampleRegion, floatSample, mDrawingStartSample - SMOOTHING_BRUSH_RADIUS, 1 + 2 * SMOOTHING_BRUSH_RADIUS);
|
||||
|
||||
//Clean this up right away to avoid a memory leak
|
||||
delete[] sampleRegion;
|
||||
delete[] newSampleRegion;
|
||||
mDrawingTrack->Set((samplePtr)newSampleRegion.get(), floatSample, mDrawingStartSample - SMOOTHING_BRUSH_RADIUS, 1 + 2 * SMOOTHING_BRUSH_RADIUS);
|
||||
|
||||
mDrawingLastDragSampleValue = 0;
|
||||
}
|
||||
|
|
|
@ -149,8 +149,9 @@ sampleCount VoiceKey::OnForward (
|
|||
|
||||
//To speed things up, create a local buffer to store things in, to avoid the costly t.Get();
|
||||
//Only go through the first SignalWindowSizeInt samples, and choose the first that trips the key.
|
||||
float *buffer = new float[remaining];
|
||||
t.Get((samplePtr)buffer, floatSample, lastsubthresholdsample, remaining);
|
||||
Floats buffer{ remaining };
|
||||
t.Get((samplePtr)buffer.get(), floatSample,
|
||||
lastsubthresholdsample, remaining);
|
||||
|
||||
|
||||
|
||||
|
@ -226,7 +227,6 @@ sampleCount VoiceKey::OnForward (
|
|||
}
|
||||
|
||||
//When we get here, i+lastsubthresholdsample is the best guess for where the word starts
|
||||
delete [] buffer;
|
||||
return i + lastsubthresholdsample;
|
||||
}
|
||||
else {
|
||||
|
@ -299,8 +299,9 @@ sampleCount VoiceKey::OnBackward (
|
|||
|
||||
//To speed things up, create a local buffer to store things in, to avoid the costly t.Get();
|
||||
//Only go through the first mSilentWindowSizeInt samples, and choose the first that trips the key.
|
||||
float *buffer = new float[remaining];
|
||||
t.Get((samplePtr)buffer, floatSample, lastsubthresholdsample-remaining, remaining);
|
||||
Floats buffer{ remaining };
|
||||
t.Get((samplePtr)buffer.get(), floatSample,
|
||||
lastsubthresholdsample - remaining, remaining);
|
||||
|
||||
//Initialize these trend markers atrend and ztrend. They keep track of the
|
||||
//up/down trends at the start and end of the evaluation window.
|
||||
|
@ -364,7 +365,6 @@ sampleCount VoiceKey::OnBackward (
|
|||
}
|
||||
|
||||
//When we get here, i+lastsubthresholdsample is the best guess for where the word starts
|
||||
delete [] buffer;
|
||||
return lastsubthresholdsample - remaining + i;
|
||||
}
|
||||
else {
|
||||
|
@ -435,8 +435,9 @@ sampleCount VoiceKey::OffForward (
|
|||
|
||||
//To speed things up, create a local buffer to store things in, to avoid the costly t.Get();
|
||||
//Only go through the first SilentWindowSizeInt samples, and choose the first that trips the key.
|
||||
float *buffer = new float[remaining];
|
||||
t.Get((samplePtr)buffer, floatSample, lastsubthresholdsample, remaining);
|
||||
Floats buffer{ remaining };
|
||||
t.Get((samplePtr)buffer.get(), floatSample,
|
||||
lastsubthresholdsample, remaining);
|
||||
|
||||
//Initialize these trend markers atrend and ztrend. They keep track of the
|
||||
//up/down trends at the start and end of the evaluation window.
|
||||
|
@ -500,7 +501,6 @@ sampleCount VoiceKey::OffForward (
|
|||
}
|
||||
|
||||
//When we get here, i+lastsubthresholdsample is the best guess for where the word starts
|
||||
delete [] buffer;
|
||||
return i + lastsubthresholdsample;
|
||||
}
|
||||
else {
|
||||
|
@ -572,8 +572,8 @@ sampleCount VoiceKey::OffBackward (
|
|||
|
||||
//To speed things up, create a local buffer to store things in, to avoid the costly t.Get();
|
||||
//Only go through the first SilentWindowSizeInt samples, and choose the first that trips the key.
|
||||
float *buffer = new float[remaining];
|
||||
t.Get((samplePtr)buffer, floatSample,
|
||||
Floats buffer{ remaining };
|
||||
t.Get((samplePtr)buffer.get(), floatSample,
|
||||
lastsubthresholdsample - remaining, remaining);
|
||||
|
||||
//Initialize these trend markers atrend and ztrend. They keep track of the
|
||||
|
@ -641,7 +641,6 @@ sampleCount VoiceKey::OffBackward (
|
|||
}
|
||||
|
||||
//When we get here, i+lastsubthresholdsample is the best guess for where the word starts
|
||||
delete [] buffer;
|
||||
return lastsubthresholdsample - remaining + i;
|
||||
}
|
||||
else {
|
||||
|
@ -849,14 +848,14 @@ double VoiceKey::TestEnergy (
|
|||
auto originalLen = len; //Keep track of the length of block to process (its not the length of t)
|
||||
const auto blockSize = limitSampleBufferSize(
|
||||
t.GetMaxBlockSize(), len); //Determine size of sampling buffer
|
||||
float *buffer = new float[blockSize]; //Get a sampling buffer
|
||||
Floats buffer{ blockSize }; //Get a sampling buffer
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
//Figure out how much to grab
|
||||
auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len );
|
||||
|
||||
t.Get((samplePtr)buffer,floatSample, s,block); //grab the block;
|
||||
t.Get((samplePtr)buffer.get(), floatSample, s,block); //grab the block;
|
||||
|
||||
//Now, go through the block and calculate energy
|
||||
for(decltype(block) i = 0; i< block; i++)
|
||||
|
@ -868,7 +867,6 @@ double VoiceKey::TestEnergy (
|
|||
s += block;
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
return sum / originalLen.as_double();
|
||||
}
|
||||
|
||||
|
@ -894,13 +892,13 @@ double VoiceKey::TestSignChanges(
|
|||
unsigned long signchanges = 1;
|
||||
int currentsign=0;
|
||||
|
||||
float *buffer = new float[blockSize]; //Get a sampling buffer
|
||||
Floats buffer{ blockSize }; //Get a sampling buffer
|
||||
|
||||
while(len > 0) {
|
||||
//Figure out how much to grab
|
||||
auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len );
|
||||
|
||||
t.Get((samplePtr)buffer,floatSample, s,block); //grab the block;
|
||||
t.Get((samplePtr)buffer.get(), floatSample, s, block); //grab the block;
|
||||
|
||||
if (len == originalLen)
|
||||
{
|
||||
|
@ -922,7 +920,6 @@ double VoiceKey::TestSignChanges(
|
|||
len -= block;
|
||||
s += block;
|
||||
}
|
||||
delete [] buffer;
|
||||
return (double)signchanges / originalLen.as_double();
|
||||
}
|
||||
|
||||
|
@ -952,13 +949,13 @@ double VoiceKey::TestDirectionChanges(
|
|||
float lastval=float(0);
|
||||
int lastdirection=1;
|
||||
|
||||
float *buffer = new float[blockSize]; //Get a sampling buffer
|
||||
Floats buffer{ blockSize }; //Get a sampling buffer
|
||||
|
||||
while(len > 0) {
|
||||
//Figure out how much to grab
|
||||
auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len );
|
||||
|
||||
t.Get((samplePtr)buffer,floatSample, s,block); //grab the block;
|
||||
t.Get((samplePtr)buffer.get(), floatSample, s, block); //grab the block;
|
||||
|
||||
if (len == originalLen) {
|
||||
//The first time through, set stuff up special.
|
||||
|
@ -980,7 +977,6 @@ double VoiceKey::TestDirectionChanges(
|
|||
len -= block;
|
||||
s += block;
|
||||
}
|
||||
delete [] buffer;
|
||||
return (double)directionchanges/originalLen.as_double();
|
||||
}
|
||||
|
||||
|
|
|
@ -691,29 +691,31 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
|
|||
//wxCriticalSectionLocker locker(mAppendCriticalSection);
|
||||
|
||||
if (right > left) {
|
||||
float *b;
|
||||
Floats b;
|
||||
float *pb{};
|
||||
// left is nonnegative and at most mAppendBufferLen:
|
||||
auto sLeft = left.as_size_t();
|
||||
// The difference is at most mAppendBufferLen:
|
||||
size_t len = ( right - left ).as_size_t();
|
||||
|
||||
if (seqFormat == floatSample)
|
||||
b = &((float *)mAppendBuffer.ptr())[sLeft];
|
||||
pb = &((float *)mAppendBuffer.ptr())[sLeft];
|
||||
else {
|
||||
b = new float[len];
|
||||
b.reinit(len);
|
||||
pb = b.get();
|
||||
CopySamples(mAppendBuffer.ptr() + sLeft * SAMPLE_SIZE(seqFormat),
|
||||
seqFormat,
|
||||
(samplePtr)b, floatSample, len);
|
||||
(samplePtr)pb, floatSample, len);
|
||||
}
|
||||
|
||||
float theMax, theMin, sumsq;
|
||||
{
|
||||
const float val = b[0];
|
||||
const float val = pb[0];
|
||||
theMax = theMin = val;
|
||||
sumsq = val * val;
|
||||
}
|
||||
for(decltype(len) j = 1; j < len; j++) {
|
||||
const float val = b[j];
|
||||
const float val = pb[j];
|
||||
theMax = std::max(theMax, val);
|
||||
theMin = std::min(theMin, val);
|
||||
sumsq += val * val;
|
||||
|
@ -724,9 +726,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
|
|||
rms[i] = (float)sqrt(sumsq / len);
|
||||
bl[i] = 1; //for now just fake it.
|
||||
|
||||
if (seqFormat != floatSample)
|
||||
delete[] b;
|
||||
|
||||
didUpdate=true;
|
||||
}
|
||||
}
|
||||
|
@ -934,21 +933,21 @@ bool SpecCache::CalculateOneSpectrum
|
|||
std::copy(scratch, scratch2, scratch3);
|
||||
|
||||
{
|
||||
const float *const window = settings.window;
|
||||
const float *const window = settings.window.get();
|
||||
for (size_t ii = 0; ii < fftLen; ++ii)
|
||||
scratch[ii] *= window[ii];
|
||||
RealFFTf(scratch, hFFT);
|
||||
}
|
||||
|
||||
{
|
||||
const float *const dWindow = settings.dWindow;
|
||||
const float *const dWindow = settings.dWindow.get();
|
||||
for (size_t ii = 0; ii < fftLen; ++ii)
|
||||
scratch2[ii] *= dWindow[ii];
|
||||
RealFFTf(scratch2, hFFT);
|
||||
}
|
||||
|
||||
{
|
||||
const float *const tWindow = settings.tWindow;
|
||||
const float *const tWindow = settings.tWindow.get();
|
||||
for (size_t ii = 0; ii < fftLen; ++ii)
|
||||
scratch3[ii] *= tWindow[ii];
|
||||
RealFFTf(scratch3, hFFT);
|
||||
|
@ -1025,7 +1024,7 @@ bool SpecCache::CalculateOneSpectrum
|
|||
|
||||
// This function mutates useBuffer
|
||||
ComputeSpectrumUsingRealFFTf
|
||||
(useBuffer, settings.hFFT, settings.window, fftLen, results);
|
||||
(useBuffer, settings.hFFT, settings.window.get(), fftLen, results);
|
||||
if (!gainFactors.empty()) {
|
||||
// Apply a frequency-dependant gain factor
|
||||
for (size_t ii = 0; ii < nBins; ++ii)
|
||||
|
@ -1825,9 +1824,9 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
|
|||
double factor = (double)rate / (double)mRate;
|
||||
::Resample resample(true, factor, factor); // constant rate resampling
|
||||
|
||||
size_t bufsize = 65536;
|
||||
float* inBuffer = new float[bufsize];
|
||||
float* outBuffer = new float[bufsize];
|
||||
const size_t bufsize = 65536;
|
||||
Floats inBuffer{ bufsize };
|
||||
Floats outBuffer{ bufsize };
|
||||
sampleCount pos = 0;
|
||||
bool error = false;
|
||||
int outGenerated = 0;
|
||||
|
@ -1847,14 +1846,14 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
|
|||
|
||||
bool isLast = ((pos + inLen) == numSamples);
|
||||
|
||||
if (!mSequence->Get((samplePtr)inBuffer, floatSample, pos, inLen))
|
||||
if (!mSequence->Get((samplePtr)inBuffer.get(), floatSample, pos, inLen))
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto results = resample.Process(factor, inBuffer, inLen, isLast,
|
||||
outBuffer, bufsize);
|
||||
const auto results = resample.Process(factor, inBuffer.get(), inLen, isLast,
|
||||
outBuffer.get(), bufsize);
|
||||
outGenerated = results.second;
|
||||
|
||||
pos += results.first;
|
||||
|
@ -1865,7 +1864,7 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!newSequence->Append((samplePtr)outBuffer, floatSample,
|
||||
if (!newSequence->Append((samplePtr)outBuffer.get(), floatSample,
|
||||
outGenerated))
|
||||
{
|
||||
error = true;
|
||||
|
@ -1886,9 +1885,6 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
|
|||
}
|
||||
}
|
||||
|
||||
delete[] inBuffer;
|
||||
delete[] outBuffer;
|
||||
|
||||
if (!error)
|
||||
{
|
||||
mSequence = std::move(newSequence);
|
||||
|
|
|
@ -118,22 +118,17 @@ public:
|
|||
class SpecPxCache {
|
||||
public:
|
||||
SpecPxCache(size_t cacheLen)
|
||||
: len{ cacheLen }
|
||||
, values{ len }
|
||||
{
|
||||
len = cacheLen;
|
||||
values = new float[len];
|
||||
valid = false;
|
||||
scaleType = 0;
|
||||
range = gain = -1;
|
||||
minFreq = maxFreq = -1;
|
||||
}
|
||||
|
||||
~SpecPxCache()
|
||||
{
|
||||
delete[] values;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
float *values;
|
||||
Floats values;
|
||||
bool valid;
|
||||
|
||||
int scaleType;
|
||||
|
|
|
@ -1425,8 +1425,8 @@ bool WaveTrack::InsertSilence(double t, double len)
|
|||
bool WaveTrack::Disjoin(double t0, double t1)
|
||||
{
|
||||
auto minSamples = TimeToLongSamples( WAVETRACK_MERGE_POINT_TOLERANCE );
|
||||
size_t maxAtOnce = 1048576;
|
||||
float *buffer = new float[ maxAtOnce ];
|
||||
const size_t maxAtOnce = 1048576;
|
||||
Floats buffer{ maxAtOnce };
|
||||
Regions regions;
|
||||
|
||||
wxBusyCursor busy;
|
||||
|
@ -1457,7 +1457,7 @@ bool WaveTrack::Disjoin(double t0, double t1)
|
|||
{
|
||||
auto numSamples = limitSampleBufferSize( maxAtOnce, len - done );
|
||||
|
||||
clip->GetSamples( ( samplePtr )buffer, floatSample, start + done,
|
||||
clip->GetSamples( ( samplePtr )buffer.get(), floatSample, start + done,
|
||||
numSamples );
|
||||
for( decltype(numSamples) i = 0; i < numSamples; i++ )
|
||||
{
|
||||
|
@ -1498,7 +1498,6 @@ bool WaveTrack::Disjoin(double t0, double t1)
|
|||
SplitDelete(region.start, region.end );
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2609,7 +2608,6 @@ void WaveTrack::SetAutoSaveIdent(int ident)
|
|||
|
||||
WaveTrackCache::~WaveTrackCache()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void WaveTrackCache::SetTrack(const WaveTrack *pTrack)
|
||||
|
@ -2620,8 +2618,8 @@ void WaveTrackCache::SetTrack(const WaveTrack *pTrack)
|
|||
if (!mPTrack ||
|
||||
mPTrack->GetMaxBlockSize() != mBufferSize) {
|
||||
Free();
|
||||
mBuffers[0].data = new float[mBufferSize];
|
||||
mBuffers[1].data = new float[mBufferSize];
|
||||
mBuffers[0].data = Floats{ mBufferSize };
|
||||
mBuffers[1].data = Floats{ mBufferSize };
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2682,7 +2680,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
|
|||
if (start0 >= 0) {
|
||||
const auto len0 = mPTrack->GetBestBlockSize(start0);
|
||||
wxASSERT(len0 <= mBufferSize);
|
||||
if (!mPTrack->Get(samplePtr(mBuffers[0].data), floatSample, start0, len0))
|
||||
if (!mPTrack->Get(samplePtr(mBuffers[0].data.get()), floatSample, start0, len0))
|
||||
return 0;
|
||||
mBuffers[0].start = start0;
|
||||
mBuffers[0].len = len0;
|
||||
|
@ -2708,7 +2706,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
|
|||
if (start1 == end0) {
|
||||
const auto len1 = mPTrack->GetBestBlockSize(start1);
|
||||
wxASSERT(len1 <= mBufferSize);
|
||||
if (!mPTrack->Get(samplePtr(mBuffers[1].data), floatSample, start1, len1))
|
||||
if (!mPTrack->Get(samplePtr(mBuffers[1].data.get()), floatSample, start1, len1))
|
||||
return 0;
|
||||
mBuffers[1].start = start1;
|
||||
mBuffers[1].len = len1;
|
||||
|
@ -2755,7 +2753,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
|
|||
// All is contiguous already. We can completely avoid copying
|
||||
// leni is nonnegative, therefore start falls within mBuffers[ii],
|
||||
// so starti is bounded between 0 and buffer length
|
||||
return samplePtr(mBuffers[ii].data + starti.as_size_t() );
|
||||
return samplePtr(mBuffers[ii].data.get() + starti.as_size_t() );
|
||||
}
|
||||
else if (leni > 0) {
|
||||
// leni is nonnegative, therefore start falls within mBuffers[ii]
|
||||
|
@ -2767,7 +2765,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
|
|||
// leni is positive and not more than remaining
|
||||
const size_t size = sizeof(float) * leni.as_size_t();
|
||||
// starti is less than mBuffers[ii].len and nonnegative
|
||||
memcpy(buffer, mBuffers[ii].data + starti.as_size_t(), size);
|
||||
memcpy(buffer, mBuffers[ii].data.get() + starti.as_size_t(), size);
|
||||
wxASSERT( leni <= remaining );
|
||||
remaining -= leni.as_size_t();
|
||||
start += leni;
|
||||
|
|
|
@ -622,7 +622,15 @@ class AUDACITY_DLL_API WaveTrack final : public Track {
|
|||
// one block file).
|
||||
class WaveTrackCache {
|
||||
public:
|
||||
explicit WaveTrackCache(const WaveTrack *pTrack = 0)
|
||||
WaveTrackCache()
|
||||
: mPTrack(0)
|
||||
, mBufferSize(0)
|
||||
, mOverlapBuffer()
|
||||
, mNValidBuffers(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit WaveTrackCache(const WaveTrack *pTrack)
|
||||
: mPTrack(0)
|
||||
, mBufferSize(0)
|
||||
, mOverlapBuffer()
|
||||
|
@ -645,17 +653,17 @@ private:
|
|||
void Free();
|
||||
|
||||
struct Buffer {
|
||||
float *data;
|
||||
Floats data;
|
||||
sampleCount start;
|
||||
sampleCount len;
|
||||
|
||||
Buffer() : data(0), start(0), len(0) {}
|
||||
void Free() { delete[] data; data = 0; start = 0; len = 0; }
|
||||
Buffer() : start(0), len(0) {}
|
||||
void Free() { data.reset(); start = 0; len = 0; }
|
||||
sampleCount end() const { return start + len; }
|
||||
|
||||
void swap ( Buffer &other )
|
||||
{
|
||||
std::swap( data, other.data );
|
||||
data .swap ( other.data );
|
||||
std::swap( start, other.start );
|
||||
std::swap( len, other.len );
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ void ComputeLegacySummaryInfo(const wxFileName &fileName,
|
|||
// 64K summary data
|
||||
//
|
||||
|
||||
float *summary = new float[info->frames64K * fields];
|
||||
Floats summary{ info->frames64K * fields };
|
||||
SampleBuffer data(info->frames64K * fields,
|
||||
info->format);
|
||||
|
||||
|
@ -100,7 +100,7 @@ void ComputeLegacySummaryInfo(const wxFileName &fileName,
|
|||
int count = read / info->bytesPerFrame;
|
||||
|
||||
CopySamples(data.ptr(), info->format,
|
||||
(samplePtr)summary, floatSample, count);
|
||||
(samplePtr)summary.get(), floatSample, count);
|
||||
|
||||
(*min) = FLT_MAX;
|
||||
(*max) = FLT_MIN;
|
||||
|
@ -118,8 +118,6 @@ void ComputeLegacySummaryInfo(const wxFileName &fileName,
|
|||
(*rms) = sqrt(sumsq / count);
|
||||
else
|
||||
(*rms) = 0;
|
||||
|
||||
delete[] summary;
|
||||
}
|
||||
|
||||
/// Construct a LegacyBlockFile memory structure that will point to an
|
||||
|
|
|
@ -369,9 +369,8 @@ void ODDecodeBlockFile::SetFileName(wxFileNameWrapper &&name)
|
|||
mFileName=std::move(name);
|
||||
/* mchinen oct 9 2009 don't think we need the char* but leaving it in for now just as a reminder that we might
|
||||
if wxFileName isn't threadsafe.
|
||||
delete [] mFileNameChar;
|
||||
mFileNameChar = new char[strlen(mFileName.GetFullPath().mb_str(wxConvUTF8))+1];
|
||||
strcpy(mFileNameChar,mFileName.GetFullPath().mb_str(wxConvUTF8)); */
|
||||
mFileNameChar.reinit(strlen(mFileName.GetFullPath().mb_str(wxConvUTF8))+1);
|
||||
strcpy(mFileNameChar.get(), mFileName.GetFullPath().mb_str(wxConvUTF8)); */
|
||||
mFileNameMutex.Unlock();
|
||||
}
|
||||
|
||||
|
@ -409,6 +408,7 @@ void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len,
|
|||
float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
|
||||
float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);
|
||||
|
||||
Floats floats;
|
||||
float *fbuffer;
|
||||
|
||||
//mchinen: think we can hack this - don't allocate and copy if we don't need to.,
|
||||
|
@ -418,18 +418,14 @@ void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len,
|
|||
}
|
||||
else
|
||||
{
|
||||
fbuffer = new float[len];
|
||||
floats.reinit(len);
|
||||
fbuffer = floats.get();
|
||||
CopySamples(buffer, format,
|
||||
(samplePtr)fbuffer, floatSample, len);
|
||||
}
|
||||
|
||||
BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);
|
||||
|
||||
//if we've used the float sample..
|
||||
if(format!=floatSample)
|
||||
{
|
||||
delete[] fbuffer;
|
||||
}
|
||||
return localFullSummary;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,24 +379,25 @@ void ODPCMAliasBlockFile::WriteSummary()
|
|||
// wxFFile summaryFile(mFileName.GetFullPath(), wxT("wb"));
|
||||
|
||||
// ...and we use fopen instead.
|
||||
FILE* summaryFile{};
|
||||
wxString sFullPath = mFileName.GetFullPath();
|
||||
char* fileNameChar = new char[strlen(sFullPath.mb_str(wxConvFile)) + 1];
|
||||
strcpy(fileNameChar, sFullPath.mb_str(wxConvFile));
|
||||
FILE* summaryFile = fopen(fileNameChar, "wb");
|
||||
{
|
||||
ArrayOf < char > fileNameChar{ strlen(sFullPath.mb_str(wxConvFile)) + 1 };
|
||||
strcpy(fileNameChar.get(), sFullPath.mb_str(wxConvFile));
|
||||
summaryFile = fopen(fileNameChar.get(), "wb");
|
||||
|
||||
mFileNameMutex.Unlock();
|
||||
mFileNameMutex.Unlock();
|
||||
|
||||
// JKC ANSWER-ME: Whay is IsOpened() commented out?
|
||||
if( !summaryFile){//.IsOpened() ){
|
||||
// JKC ANSWER-ME: Whay is IsOpened() commented out?
|
||||
if (!summaryFile){//.IsOpened() ){
|
||||
|
||||
// Never silence the Log w.r.t write errors; they always count
|
||||
//however, this is going to be called from a non-main thread,
|
||||
//and wxLog calls are not thread safe.
|
||||
printf("Unable to write summary data to file: %s", fileNameChar);
|
||||
delete [] fileNameChar;
|
||||
return;
|
||||
// Never silence the Log w.r.t write errors; they always count
|
||||
//however, this is going to be called from a non-main thread,
|
||||
//and wxLog calls are not thread safe.
|
||||
printf("Unable to write summary data to file: %s", fileNameChar.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
delete [] fileNameChar;
|
||||
|
||||
// To build the summary data, call ReadData (implemented by the
|
||||
// derived classes) to get the sample data
|
||||
|
@ -449,6 +450,7 @@ void *ODPCMAliasBlockFile::CalcSummary(samplePtr buffer, size_t len,
|
|||
float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
|
||||
float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);
|
||||
|
||||
Floats floats;
|
||||
float *fbuffer;
|
||||
|
||||
//mchinen: think we can hack this - don't allocate and copy if we don't need to.,
|
||||
|
@ -458,18 +460,14 @@ void *ODPCMAliasBlockFile::CalcSummary(samplePtr buffer, size_t len,
|
|||
}
|
||||
else
|
||||
{
|
||||
fbuffer = new float[len];
|
||||
floats.reinit(len);
|
||||
fbuffer = floats.get();
|
||||
CopySamples(buffer, format,
|
||||
(samplePtr)fbuffer, floatSample, len);
|
||||
}
|
||||
|
||||
BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);
|
||||
|
||||
//if we've used the float sample..
|
||||
if(format!=floatSample)
|
||||
{
|
||||
delete[] fbuffer;
|
||||
}
|
||||
return localFullSummary;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,13 +124,13 @@ SimpleBlockFile::SimpleBlockFile(wxFileNameWrapper &&baseFileName,
|
|||
mCache.needWrite = true;
|
||||
mCache.format = format;
|
||||
const auto sampleDataSize = sampleLen * SAMPLE_SIZE(format);
|
||||
mCache.sampleData = new char[sampleDataSize];
|
||||
memcpy(mCache.sampleData, sampleData, sampleDataSize);
|
||||
mCache.sampleData.reinit(sampleDataSize);
|
||||
memcpy(mCache.sampleData.get(), sampleData, sampleDataSize);
|
||||
ArrayOf<char> cleanup;
|
||||
void* summaryData = BlockFile::CalcSummary(sampleData, sampleLen,
|
||||
format, cleanup);
|
||||
mCache.summaryData = new char[mSummaryInfo.totalSummaryBytes];
|
||||
memcpy(mCache.summaryData, summaryData,
|
||||
format, cleanup);
|
||||
mCache.summaryData.reinit(mSummaryInfo.totalSummaryBytes);
|
||||
memcpy(mCache.summaryData.get(), summaryData,
|
||||
mSummaryInfo.totalSummaryBytes);
|
||||
}
|
||||
}
|
||||
|
@ -155,11 +155,6 @@ SimpleBlockFile::SimpleBlockFile(wxFileNameWrapper &&existingFile, size_t len,
|
|||
|
||||
SimpleBlockFile::~SimpleBlockFile()
|
||||
{
|
||||
if (mCache.active)
|
||||
{
|
||||
delete[] mCache.sampleData;
|
||||
delete[] (char *)mCache.summaryData;
|
||||
}
|
||||
}
|
||||
|
||||
bool SimpleBlockFile::WriteSimpleBlockFile(
|
||||
|
@ -317,18 +312,18 @@ void SimpleBlockFile::FillCache()
|
|||
file.Close();
|
||||
|
||||
// Read samples into cache
|
||||
mCache.sampleData = new char[mLen * SAMPLE_SIZE(mCache.format)];
|
||||
if (ReadData(mCache.sampleData, mCache.format, 0, mLen) != mLen)
|
||||
mCache.sampleData.reinit(mLen * SAMPLE_SIZE(mCache.format));
|
||||
if (ReadData(mCache.sampleData.get(), mCache.format, 0, mLen) != mLen)
|
||||
{
|
||||
// Could not read all samples
|
||||
delete mCache.sampleData;
|
||||
mCache.sampleData.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read summary data into cache
|
||||
mCache.summaryData = new char[mSummaryInfo.totalSummaryBytes];
|
||||
if (!ReadSummary(mCache.summaryData))
|
||||
memset(mCache.summaryData, 0, mSummaryInfo.totalSummaryBytes);
|
||||
mCache.summaryData.reinit(mSummaryInfo.totalSummaryBytes);
|
||||
if (!ReadSummary(mCache.summaryData.get()))
|
||||
memset(mCache.summaryData.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
|
||||
// Cache is active but already on disk
|
||||
mCache.active = true;
|
||||
|
@ -346,7 +341,7 @@ bool SimpleBlockFile::ReadSummary(void *data)
|
|||
if (mCache.active)
|
||||
{
|
||||
//wxLogDebug("SimpleBlockFile::ReadSummary(): Summary is already in cache.");
|
||||
memcpy(data, mCache.summaryData, mSummaryInfo.totalSummaryBytes);
|
||||
memcpy(data, mCache.summaryData.get(), mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -398,7 +393,7 @@ size_t SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
|
|||
|
||||
len = std::min(len, std::max(start, mLen) - start);
|
||||
CopySamples(
|
||||
(samplePtr)(((char*)mCache.sampleData) +
|
||||
(samplePtr)(mCache.sampleData.get() +
|
||||
start * SAMPLE_SIZE(mCache.format)),
|
||||
mCache.format, data, format, len);
|
||||
return len;
|
||||
|
@ -540,7 +535,6 @@ auto SimpleBlockFile::GetSpaceUsage() const -> DiskByteCount
|
|||
|
||||
void SimpleBlockFile::Recover(){
|
||||
wxFFile file(mFileName.GetFullPath(), wxT("wb"));
|
||||
//int i;
|
||||
|
||||
if( !file.IsOpened() ){
|
||||
// Can't do anything else.
|
||||
|
@ -572,8 +566,8 @@ void SimpleBlockFile::WriteCacheToDisk()
|
|||
if (!GetNeedWriteCacheToDisk())
|
||||
return;
|
||||
|
||||
if (WriteSimpleBlockFile(mCache.sampleData, mLen, mCache.format,
|
||||
mCache.summaryData))
|
||||
if (WriteSimpleBlockFile(mCache.sampleData.get(), mLen, mCache.format,
|
||||
mCache.summaryData.get()))
|
||||
mCache.needWrite = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ struct SimpleBlockFileCache {
|
|||
bool active;
|
||||
bool needWrite;
|
||||
sampleFormat format;
|
||||
samplePtr sampleData;
|
||||
void* summaryData;
|
||||
ArrayOf<char> sampleData, summaryData;
|
||||
|
||||
SimpleBlockFileCache() {}
|
||||
};
|
||||
|
||||
// The AU formats we care about
|
||||
|
|
|
@ -99,8 +99,9 @@ bool CompareAudioCommand::Apply(CommandExecutionContext context)
|
|||
|
||||
// Initialize buffers for track data to be analyzed
|
||||
auto buffSize = std::min(mTrack0->GetMaxBlockSize(), mTrack1->GetMaxBlockSize());
|
||||
float *buff0 = new float[buffSize];
|
||||
float *buff1 = new float[buffSize];
|
||||
|
||||
Floats buff0{ buffSize };
|
||||
Floats buff1{ buffSize };
|
||||
|
||||
// Compare tracks block by block
|
||||
auto s0 = mTrack0->TimeToLongSamples(mT0);
|
||||
|
@ -113,8 +114,8 @@ bool CompareAudioCommand::Apply(CommandExecutionContext context)
|
|||
auto block = limitSampleBufferSize(
|
||||
mTrack0->GetBestBlockSize(position), s1 - position
|
||||
);
|
||||
mTrack0->Get((samplePtr)buff0, floatSample, position, block);
|
||||
mTrack1->Get((samplePtr)buff1, floatSample, position, block);
|
||||
mTrack0->Get((samplePtr)buff0.get(), floatSample, position, block);
|
||||
mTrack1->Get((samplePtr)buff1.get(), floatSample, position, block);
|
||||
|
||||
for (decltype(block) buffPos = 0; buffPos < block; ++buffPos)
|
||||
{
|
||||
|
@ -131,9 +132,6 @@ bool CompareAudioCommand::Apply(CommandExecutionContext context)
|
|||
);
|
||||
}
|
||||
|
||||
delete [] buff0;
|
||||
delete [] buff1;
|
||||
|
||||
// Output the results
|
||||
double errorSeconds = mTrack0->LongSamplesToTime(errorCount);
|
||||
Status(wxString::Format(wxT("%li"), errorCount));
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -114,11 +114,6 @@ Effect::Effect()
|
|||
mNumAudioIn = 0;
|
||||
mNumAudioOut = 0;
|
||||
|
||||
mInBuffer = NULL;
|
||||
mOutBuffer = NULL;
|
||||
mInBufPos = NULL;
|
||||
mOutBufPos = NULL;
|
||||
|
||||
mBufferSize = 0;
|
||||
mBlockSize = 0;
|
||||
mNumChannels = 0;
|
||||
|
@ -1290,8 +1285,8 @@ bool Effect::ProcessPass()
|
|||
bool editClipCanMove;
|
||||
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true);
|
||||
|
||||
mInBuffer = NULL;
|
||||
mOutBuffer = NULL;
|
||||
mInBuffer.reset();
|
||||
mOutBuffer.reset();
|
||||
|
||||
ChannelName map[3];
|
||||
|
||||
|
@ -1391,28 +1386,10 @@ bool Effect::ProcessPass()
|
|||
// If the buffer size has changed, then (re)allocate the buffers
|
||||
if (prevBufferSize != mBufferSize)
|
||||
{
|
||||
// Get rid of any previous buffers
|
||||
if (mInBuffer)
|
||||
{
|
||||
for (size_t i = 0; i < mNumAudioIn; i++)
|
||||
{
|
||||
if (mInBuffer[i])
|
||||
{
|
||||
delete [] mInBuffer[i];
|
||||
}
|
||||
}
|
||||
delete [] mInBuffer;
|
||||
delete [] mInBufPos;
|
||||
}
|
||||
|
||||
// Always create the number of input buffers the client expects even if we don't have
|
||||
// the same number of channels.
|
||||
mInBufPos = new float *[mNumAudioIn];
|
||||
mInBuffer = new float *[mNumAudioIn];
|
||||
for (size_t i = 0; i < mNumAudioIn; i++)
|
||||
{
|
||||
mInBuffer[i] = new float[mBufferSize];
|
||||
}
|
||||
mInBufPos.reinit( mNumAudioIn );
|
||||
mInBuffer.reinit( mNumAudioIn, mBufferSize );
|
||||
|
||||
// We won't be using more than the first 2 buffers, so clear the rest (if any)
|
||||
for (size_t i = 2; i < mNumAudioIn; i++)
|
||||
|
@ -1423,42 +1400,24 @@ bool Effect::ProcessPass()
|
|||
}
|
||||
}
|
||||
|
||||
// Get rid of any previous buffers
|
||||
if (mOutBuffer)
|
||||
{
|
||||
for (size_t i = 0; i < mNumAudioOut; i++)
|
||||
{
|
||||
if (mOutBuffer[i])
|
||||
{
|
||||
delete [] mOutBuffer[i];
|
||||
}
|
||||
}
|
||||
delete [] mOutBuffer;
|
||||
delete [] mOutBufPos;
|
||||
}
|
||||
|
||||
// Always create the number of output buffers the client expects even if we don't have
|
||||
// the same number of channels.
|
||||
mOutBufPos = new float *[mNumAudioOut];
|
||||
mOutBuffer = new float *[mNumAudioOut];
|
||||
for (size_t i = 0; i < mNumAudioOut; i++)
|
||||
{
|
||||
// Output buffers get an extra mBlockSize worth to give extra room if
|
||||
// the plugin adds latency
|
||||
mOutBuffer[i] = new float[mBufferSize + mBlockSize];
|
||||
}
|
||||
mOutBufPos.reinit( mNumAudioOut );
|
||||
// Output buffers get an extra mBlockSize worth to give extra room if
|
||||
// the plugin adds latency
|
||||
mOutBuffer.reinit( mNumAudioOut, mBufferSize + mBlockSize );
|
||||
}
|
||||
|
||||
// (Re)Set the input buffer positions
|
||||
for (size_t i = 0; i < mNumAudioIn; i++)
|
||||
{
|
||||
mInBufPos[i] = mInBuffer[i];
|
||||
mInBufPos[i] = mInBuffer[i].get();
|
||||
}
|
||||
|
||||
// (Re)Set the output buffer positions
|
||||
for (size_t i = 0; i < mNumAudioOut; i++)
|
||||
{
|
||||
mOutBufPos[i] = mOutBuffer[i];
|
||||
mOutBufPos[i] = mOutBuffer[i].get();
|
||||
}
|
||||
|
||||
// Clear unused input buffers
|
||||
|
@ -1481,29 +1440,10 @@ bool Effect::ProcessPass()
|
|||
count++;
|
||||
}
|
||||
|
||||
if (mOutBuffer)
|
||||
{
|
||||
for (size_t i = 0; i < mNumAudioOut; i++)
|
||||
{
|
||||
delete [] mOutBuffer[i];
|
||||
}
|
||||
delete [] mOutBuffer;
|
||||
delete [] mOutBufPos;
|
||||
mOutBuffer = NULL;
|
||||
mOutBufPos = NULL;
|
||||
}
|
||||
|
||||
if (mInBuffer)
|
||||
{
|
||||
for (size_t i = 0; i < mNumAudioIn; i++)
|
||||
{
|
||||
delete [] mInBuffer[i];
|
||||
}
|
||||
delete [] mInBuffer;
|
||||
delete [] mInBufPos;
|
||||
mInBuffer = NULL;
|
||||
mInBufPos = NULL;
|
||||
}
|
||||
mOutBuffer.reset();
|
||||
mOutBufPos.reset();
|
||||
mInBuffer.reset();
|
||||
mInBufPos.reset();
|
||||
|
||||
if (bGoodResult && GetType() == EffectTypeGenerate)
|
||||
{
|
||||
|
@ -1598,16 +1538,16 @@ bool Effect::ProcessTrack(int count,
|
|||
limitSampleBufferSize( mBufferSize, inputRemaining );
|
||||
|
||||
// Fill the input buffers
|
||||
left->Get((samplePtr) mInBuffer[0], floatSample, inLeftPos, inputBufferCnt);
|
||||
left->Get((samplePtr) mInBuffer[0].get(), floatSample, inLeftPos, inputBufferCnt);
|
||||
if (right)
|
||||
{
|
||||
right->Get((samplePtr) mInBuffer[1], floatSample, inRightPos, inputBufferCnt);
|
||||
right->Get((samplePtr) mInBuffer[1].get(), floatSample, inRightPos, inputBufferCnt);
|
||||
}
|
||||
|
||||
// Reset the input buffer positions
|
||||
for (size_t i = 0; i < mNumChannels; i++)
|
||||
{
|
||||
mInBufPos[i] = mInBuffer[i];
|
||||
mInBufPos[i] = mInBuffer[i].get();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1654,7 +1594,7 @@ bool Effect::ProcessTrack(int count,
|
|||
// Reset the input buffer positions
|
||||
for (size_t i = 0; i < mNumChannels; i++)
|
||||
{
|
||||
mInBufPos[i] = mInBuffer[i];
|
||||
mInBufPos[i] = mInBuffer[i].get();
|
||||
|
||||
// And clear
|
||||
for (size_t j = 0; j < mBlockSize; j++)
|
||||
|
@ -1670,7 +1610,7 @@ bool Effect::ProcessTrack(int count,
|
|||
decltype(curBlockSize) processed;
|
||||
try
|
||||
{
|
||||
processed = ProcessBlock(mInBufPos, mOutBufPos, curBlockSize);
|
||||
processed = ProcessBlock(mInBufPos.get(), mOutBufPos.get(), curBlockSize);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -1745,32 +1685,32 @@ bool Effect::ProcessTrack(int count,
|
|||
if (isProcessor)
|
||||
{
|
||||
// Write them out
|
||||
left->Set((samplePtr) mOutBuffer[0], floatSample, outLeftPos, outputBufferCnt);
|
||||
left->Set((samplePtr) mOutBuffer[0].get(), floatSample, outLeftPos, outputBufferCnt);
|
||||
if (right)
|
||||
{
|
||||
if (chans >= 2)
|
||||
{
|
||||
right->Set((samplePtr) mOutBuffer[1], floatSample, outRightPos, outputBufferCnt);
|
||||
right->Set((samplePtr) mOutBuffer[1].get(), floatSample, outRightPos, outputBufferCnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
right->Set((samplePtr) mOutBuffer[0], floatSample, outRightPos, outputBufferCnt);
|
||||
right->Set((samplePtr) mOutBuffer[0].get(), floatSample, outRightPos, outputBufferCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isGenerator)
|
||||
{
|
||||
genLeft->Append((samplePtr) mOutBuffer[0], floatSample, outputBufferCnt);
|
||||
genLeft->Append((samplePtr) mOutBuffer[0].get(), floatSample, outputBufferCnt);
|
||||
if (genRight)
|
||||
{
|
||||
genRight->Append((samplePtr) mOutBuffer[1], floatSample, outputBufferCnt);
|
||||
genRight->Append((samplePtr) mOutBuffer[1].get(), floatSample, outputBufferCnt);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the output buffer positions
|
||||
for (size_t i = 0; i < chans; i++)
|
||||
{
|
||||
mOutBufPos[i] = mOutBuffer[i];
|
||||
mOutBufPos[i] = mOutBuffer[i].get();
|
||||
}
|
||||
|
||||
// Bump to the next track position
|
||||
|
@ -1806,25 +1746,25 @@ bool Effect::ProcessTrack(int count,
|
|||
{
|
||||
if (isProcessor)
|
||||
{
|
||||
left->Set((samplePtr) mOutBuffer[0], floatSample, outLeftPos, outputBufferCnt);
|
||||
left->Set((samplePtr) mOutBuffer[0].get(), floatSample, outLeftPos, outputBufferCnt);
|
||||
if (right)
|
||||
{
|
||||
if (chans >= 2)
|
||||
{
|
||||
right->Set((samplePtr) mOutBuffer[1], floatSample, outRightPos, outputBufferCnt);
|
||||
right->Set((samplePtr) mOutBuffer[1].get(), floatSample, outRightPos, outputBufferCnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
right->Set((samplePtr) mOutBuffer[0], floatSample, outRightPos, outputBufferCnt);
|
||||
right->Set((samplePtr) mOutBuffer[0].get(), floatSample, outRightPos, outputBufferCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isGenerator)
|
||||
{
|
||||
genLeft->Append((samplePtr) mOutBuffer[0], floatSample, outputBufferCnt);
|
||||
genLeft->Append((samplePtr) mOutBuffer[0].get(), floatSample, outputBufferCnt);
|
||||
if (genRight)
|
||||
{
|
||||
genRight->Append((samplePtr) mOutBuffer[1], floatSample, outputBufferCnt);
|
||||
genRight->Append((samplePtr) mOutBuffer[1].get(), floatSample, outputBufferCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class wxWindow;
|
|||
#include "audacity/EffectInterface.h"
|
||||
|
||||
#include "../Experimental.h"
|
||||
#include "../SampleFormat.h"
|
||||
#include "../SelectedRegion.h"
|
||||
#include "../Shuttle.h"
|
||||
#include "../Internat.h"
|
||||
|
@ -504,10 +505,10 @@ private:
|
|||
size_t mNumAudioIn;
|
||||
size_t mNumAudioOut;
|
||||
|
||||
float **mInBuffer;
|
||||
float **mOutBuffer;
|
||||
float **mInBufPos;
|
||||
float **mOutBufPos;
|
||||
FloatBuffers mInBuffer, mOutBuffer;
|
||||
|
||||
using Positions = ArrayOf < float* > ; // Array of non-owning pointers into the above
|
||||
Positions mInBufPos, mOutBufPos;
|
||||
|
||||
size_t mBufferSize;
|
||||
size_t mBlockSize;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "../Audacity.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/stopwatch.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
@ -397,6 +398,7 @@ void EffectManager::RealtimeSetEffects(const EffectArray & effects)
|
|||
}
|
||||
}
|
||||
|
||||
// Get rid of the old chain
|
||||
// And install the NEW one
|
||||
mRealtimeEffects = effects;
|
||||
|
||||
|
@ -407,7 +409,7 @@ void EffectManager::RealtimeSetEffects(const EffectArray & effects)
|
|||
|
||||
bool EffectManager::RealtimeIsActive()
|
||||
{
|
||||
return mRealtimeEffects.GetCount() != 0;
|
||||
return mRealtimeEffects.size() != 0;
|
||||
}
|
||||
|
||||
bool EffectManager::RealtimeIsSuspended()
|
||||
|
@ -434,7 +436,7 @@ void EffectManager::RealtimeAddEffect(Effect *effect)
|
|||
}
|
||||
|
||||
// Add to list of active effects
|
||||
mRealtimeEffects.Add(effect);
|
||||
mRealtimeEffects.push_back(effect);
|
||||
|
||||
// Allow RealtimeProcess() to, well, process
|
||||
RealtimeResume();
|
||||
|
@ -452,7 +454,10 @@ void EffectManager::RealtimeRemoveEffect(Effect *effect)
|
|||
}
|
||||
|
||||
// Remove from list of active effects
|
||||
mRealtimeEffects.Remove(effect);
|
||||
auto end = mRealtimeEffects.end();
|
||||
auto found = std::find(mRealtimeEffects.begin(), end, effect);
|
||||
if (found != end)
|
||||
mRealtimeEffects.erase(found);
|
||||
|
||||
// Allow RealtimeProcess() to, well, process
|
||||
RealtimeResume();
|
||||
|
@ -472,10 +477,8 @@ void EffectManager::RealtimeInitialize()
|
|||
mRealtimeActive = true;
|
||||
|
||||
// Tell each effect to get ready for action
|
||||
for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeInitialize();
|
||||
}
|
||||
for (auto e : mRealtimeEffects)
|
||||
e->RealtimeInitialize();
|
||||
|
||||
// Get things moving
|
||||
RealtimeResume();
|
||||
|
@ -483,10 +486,8 @@ void EffectManager::RealtimeInitialize()
|
|||
|
||||
void EffectManager::RealtimeAddProcessor(int group, unsigned chans, float rate)
|
||||
{
|
||||
for (size_t i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeAddProcessor(group, chans, rate);
|
||||
}
|
||||
for (auto e : mRealtimeEffects)
|
||||
e->RealtimeAddProcessor(group, chans, rate);
|
||||
|
||||
mRealtimeChans.push_back(chans);
|
||||
mRealtimeRates.Add(rate);
|
||||
|
@ -501,10 +502,8 @@ void EffectManager::RealtimeFinalize()
|
|||
mRealtimeLatency = 0;
|
||||
|
||||
// Tell each effect to clean up as well
|
||||
for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeFinalize();
|
||||
}
|
||||
for (auto e : mRealtimeEffects)
|
||||
e->RealtimeFinalize();
|
||||
|
||||
// Reset processor parameters
|
||||
mRealtimeChans.clear();
|
||||
|
@ -529,10 +528,8 @@ void EffectManager::RealtimeSuspend()
|
|||
mRealtimeSuspended = true;
|
||||
|
||||
// And make sure the effects don't either
|
||||
for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeSuspend();
|
||||
}
|
||||
for (auto e : mRealtimeEffects)
|
||||
e->RealtimeSuspend();
|
||||
|
||||
mRealtimeLock.Leave();
|
||||
}
|
||||
|
@ -549,10 +546,8 @@ void EffectManager::RealtimeResume()
|
|||
}
|
||||
|
||||
// Tell the effects to get ready for more action
|
||||
for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeResume();
|
||||
}
|
||||
for (auto e : mRealtimeEffects)
|
||||
e->RealtimeResume();
|
||||
|
||||
// And we should too
|
||||
mRealtimeSuspended = false;
|
||||
|
@ -572,12 +567,10 @@ void EffectManager::RealtimeProcessStart()
|
|||
// have been suspended.
|
||||
if (!mRealtimeSuspended)
|
||||
{
|
||||
for (size_t i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
for (auto e : mRealtimeEffects)
|
||||
{
|
||||
if (mRealtimeEffects[i]->IsRealtimeActive())
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeProcessStart();
|
||||
}
|
||||
if (e->IsRealtimeActive())
|
||||
e->RealtimeProcessStart();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,7 +587,7 @@ size_t EffectManager::RealtimeProcess(int group, unsigned chans, float **buffers
|
|||
|
||||
// Can be suspended because of the audio stream being paused or because effects
|
||||
// have been suspended, so allow the samples to pass as-is.
|
||||
if (mRealtimeSuspended || mRealtimeEffects.IsEmpty())
|
||||
if (mRealtimeSuspended || mRealtimeEffects.empty())
|
||||
{
|
||||
mRealtimeLock.Leave();
|
||||
return numSamples;
|
||||
|
@ -619,11 +612,11 @@ size_t EffectManager::RealtimeProcess(int group, unsigned chans, float **buffers
|
|||
// Now call each effect in the chain while swapping buffer pointers to feed the
|
||||
// output of one effect as the input to the next effect
|
||||
size_t called = 0;
|
||||
for (size_t i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
for (auto e : mRealtimeEffects)
|
||||
{
|
||||
if (mRealtimeEffects[i]->IsRealtimeActive())
|
||||
if (e->IsRealtimeActive())
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeProcess(group, chans, ibuf, obuf, numSamples);
|
||||
e->RealtimeProcess(group, chans, ibuf, obuf, numSamples);
|
||||
called++;
|
||||
}
|
||||
|
||||
|
@ -671,12 +664,10 @@ void EffectManager::RealtimeProcessEnd()
|
|||
// have been suspended.
|
||||
if (!mRealtimeSuspended)
|
||||
{
|
||||
for (size_t i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++)
|
||||
for (auto e : mRealtimeEffects)
|
||||
{
|
||||
if (mRealtimeEffects[i]->IsRealtimeActive())
|
||||
{
|
||||
mRealtimeEffects[i]->RealtimeProcessEnd();
|
||||
}
|
||||
if (e->IsRealtimeActive())
|
||||
e->RealtimeProcessEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ effects.
|
|||
|
||||
#include "../Experimental.h"
|
||||
|
||||
#include <vector>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/event.h>
|
||||
|
@ -33,7 +34,7 @@ effects.
|
|||
#include "../PluginManager.h"
|
||||
#include "Effect.h"
|
||||
|
||||
WX_DEFINE_USER_EXPORTED_ARRAY(Effect *, EffectArray, class AUDACITY_DLL_API);
|
||||
using EffectArray = std::vector <Effect*> ;
|
||||
WX_DECLARE_STRING_HASH_MAP_WITH_DECL(Effect *, EffectMap, class AUDACITY_DLL_API);
|
||||
WX_DECLARE_STRING_HASH_MAP_WITH_DECL(std::shared_ptr<Effect>, EffectOwnerMap, class AUDACITY_DLL_API);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#if defined(EXPERIMENTAL_EFFECTS_RACK)
|
||||
|
||||
#include "../MemoryX.h"
|
||||
#include <wx/access.h>
|
||||
#include <wx/defs.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
|
@ -162,7 +163,7 @@ EffectRack::~EffectRack()
|
|||
{
|
||||
gPrefs->DeleteGroup(wxT("/EffectsRack"));
|
||||
|
||||
for (size_t i = 0, cnt = mEffects.GetCount(); i < cnt; i++)
|
||||
for (size_t i = 0, cnt = mEffects.size(); i < cnt; i++)
|
||||
{
|
||||
if (mFavState[i])
|
||||
{
|
||||
|
@ -177,7 +178,7 @@ EffectRack::~EffectRack()
|
|||
|
||||
void EffectRack::Add(Effect *effect, bool active, bool favorite)
|
||||
{
|
||||
if (mEffects.Index(effect) != wxNOT_FOUND)
|
||||
if (mEffects.end() != std::find(mEffects.begin(), mEffects.end(), effect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -254,7 +255,7 @@ void EffectRack::Add(Effect *effect, bool active, bool favorite)
|
|||
Fit();
|
||||
Update();
|
||||
|
||||
mEffects.Add(effect);
|
||||
mEffects.push_back(effect);
|
||||
mNumEffects++;
|
||||
|
||||
if (!mTimer.IsRunning())
|
||||
|
@ -289,7 +290,7 @@ void EffectRack::OnApply(wxCommandEvent & WXUNUSED(evt))
|
|||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
|
||||
for (size_t i = 0, cnt = mEffects.GetCount(); i < cnt; i++)
|
||||
for (size_t i = 0, cnt = mEffects.size(); i < cnt; i++)
|
||||
{
|
||||
if (mPowerState[i])
|
||||
{
|
||||
|
@ -408,11 +409,11 @@ void EffectRack::OnRemove(wxCommandEvent & evt)
|
|||
return;
|
||||
}
|
||||
|
||||
mEffects.RemoveAt(index);
|
||||
mEffects.erase(mEffects.begin() + index);
|
||||
mPowerState.RemoveAt(index);
|
||||
mFavState.RemoveAt(index);
|
||||
|
||||
if (mEffects.GetCount() == 0)
|
||||
if (mEffects.size() == 0)
|
||||
{
|
||||
if (mTimer.IsRunning())
|
||||
{
|
||||
|
@ -489,8 +490,8 @@ int EffectRack::GetEffectIndex(wxWindow *win)
|
|||
void EffectRack::MoveRowUp(int row)
|
||||
{
|
||||
Effect *effect = mEffects[row];
|
||||
mEffects.RemoveAt(row);
|
||||
mEffects.Insert(effect, row - 1);
|
||||
mEffects.erase(mEffects.begin() + row);
|
||||
mEffects.insert(mEffects.begin() + row - 1, effect);
|
||||
|
||||
int state = mPowerState[row];
|
||||
mPowerState.RemoveAt(row);
|
||||
|
@ -525,11 +526,11 @@ void EffectRack::UpdateActive()
|
|||
|
||||
if (!mBypassing)
|
||||
{
|
||||
for (size_t i = 0, cnt = mEffects.GetCount(); i < cnt; i++)
|
||||
for (size_t i = 0, cnt = mEffects.size(); i < cnt; i++)
|
||||
{
|
||||
if (mPowerState[i])
|
||||
{
|
||||
mActive.Add(mEffects[i]);
|
||||
mActive.push_back(mEffects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,16 +121,16 @@ bool BlockGenerator::GenerateTrack(WaveTrack *tmp,
|
|||
bool bGoodResult = true;
|
||||
numSamples = track.TimeToLongSamples(GetDuration());
|
||||
decltype(numSamples) i = 0;
|
||||
float *data = new float[tmp->GetMaxBlockSize()];
|
||||
Floats data{ tmp->GetMaxBlockSize() };
|
||||
|
||||
while ((i < numSamples) && bGoodResult) {
|
||||
const auto block =
|
||||
limitSampleBufferSize( tmp->GetBestBlockSize(i), numSamples - i );
|
||||
|
||||
GenerateBlock(data, track, block);
|
||||
GenerateBlock(data.get(), track, block);
|
||||
|
||||
// Add the generated data to the temporary track
|
||||
tmp->Append((samplePtr)data, floatSample, block);
|
||||
tmp->Append((samplePtr)data.get(), floatSample, block);
|
||||
i += block;
|
||||
|
||||
// Update the progress meter
|
||||
|
@ -139,6 +139,5 @@ bool BlockGenerator::GenerateTrack(WaveTrack *tmp,
|
|||
numSamples.as_double()))
|
||||
bGoodResult = false;
|
||||
}
|
||||
delete[] data;
|
||||
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;
|
||||
|
|
|
@ -1108,10 +1108,6 @@ VSTEffect::VSTEffect(const wxString & path, VSTEffect *master)
|
|||
// UI
|
||||
|
||||
mGui = false;
|
||||
mNames = NULL;
|
||||
mSliders = NULL;
|
||||
mDisplays = NULL;
|
||||
mLabels = NULL;
|
||||
mContainer = NULL;
|
||||
|
||||
// If we're a slave then go ahead a load immediately
|
||||
|
@ -1128,26 +1124,6 @@ VSTEffect::~VSTEffect()
|
|||
mDialog->Close();
|
||||
}
|
||||
|
||||
if (mNames)
|
||||
{
|
||||
delete [] mNames;
|
||||
}
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
}
|
||||
|
||||
if (mDisplays)
|
||||
{
|
||||
delete [] mDisplays;
|
||||
}
|
||||
|
||||
if (mLabels)
|
||||
{
|
||||
delete [] mLabels;
|
||||
}
|
||||
|
||||
Unload();
|
||||
}
|
||||
|
||||
|
@ -1289,7 +1265,9 @@ bool VSTEffect::SetHost(EffectHostInterface *host)
|
|||
|
||||
if (mHost)
|
||||
{
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), mUserBlockSize, 8192);
|
||||
int userBlockSize;
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), userBlockSize, 8192);
|
||||
mUserBlockSize = std::max( 1, userBlockSize );
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
|
||||
|
||||
mBlockSize = mUserBlockSize;
|
||||
|
@ -1330,7 +1308,7 @@ int VSTEffect::GetMidiOutCount()
|
|||
|
||||
size_t VSTEffect::SetBlockSize(size_t maxBlockSize)
|
||||
{
|
||||
mBlockSize = std::min((int)maxBlockSize, mUserBlockSize);
|
||||
mBlockSize = std::min( maxBlockSize, mUserBlockSize );
|
||||
return mBlockSize;
|
||||
}
|
||||
|
||||
|
@ -1424,26 +1402,16 @@ void VSTEffect::SetChannelCount(unsigned numChannels)
|
|||
|
||||
bool VSTEffect::RealtimeInitialize()
|
||||
{
|
||||
mMasterIn = new float *[mAudioIns];
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
mMasterIn[i] = new float[mBlockSize];
|
||||
memset(mMasterIn[i], 0, mBlockSize * sizeof(float));
|
||||
}
|
||||
|
||||
mMasterOut = new float *[mAudioOuts];
|
||||
for (int i = 0; i < mAudioOuts; i++)
|
||||
{
|
||||
mMasterOut[i] = new float[mBlockSize];
|
||||
}
|
||||
mMasterIn.reinit( mAudioIns, mBlockSize, true );
|
||||
mMasterOut.reinit( mAudioOuts, mBlockSize );
|
||||
|
||||
return ProcessInitialize(0, NULL);
|
||||
}
|
||||
|
||||
bool VSTEffect::RealtimeAddProcessor(unsigned numChannels, float sampleRate)
|
||||
{
|
||||
VSTEffect *slave = new VSTEffect(mPath, this);
|
||||
mSlaves.Add(slave);
|
||||
mSlaves.push_back(make_movable<VSTEffect>(mPath, this));
|
||||
VSTEffect *const slave = mSlaves.back().get();
|
||||
|
||||
slave->SetBlockSize(mBlockSize);
|
||||
slave->SetChannelCount(numChannels);
|
||||
|
@ -1478,24 +1446,13 @@ bool VSTEffect::RealtimeAddProcessor(unsigned numChannels, float sampleRate)
|
|||
|
||||
bool VSTEffect::RealtimeFinalize()
|
||||
{
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->ProcessFinalize();
|
||||
delete mSlaves[i];
|
||||
}
|
||||
mSlaves.Clear();
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->ProcessFinalize();
|
||||
mSlaves.clear();
|
||||
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
delete [] mMasterIn[i];
|
||||
}
|
||||
delete [] mMasterIn;
|
||||
mMasterIn.reset();
|
||||
|
||||
for (int i = 0; i < mAudioOuts; i++)
|
||||
{
|
||||
delete [] mMasterOut[i];
|
||||
}
|
||||
delete [] mMasterOut;
|
||||
mMasterOut.reset();
|
||||
|
||||
return ProcessFinalize();
|
||||
}
|
||||
|
@ -1504,10 +1461,8 @@ bool VSTEffect::RealtimeSuspend()
|
|||
{
|
||||
PowerOff();
|
||||
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->PowerOff();
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->PowerOff();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1516,10 +1471,8 @@ bool VSTEffect::RealtimeResume()
|
|||
{
|
||||
PowerOn();
|
||||
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->PowerOn();
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->PowerOn();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1527,9 +1480,7 @@ bool VSTEffect::RealtimeResume()
|
|||
bool VSTEffect::RealtimeProcessStart()
|
||||
{
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
memset(mMasterIn[i], 0, mBlockSize * sizeof(float));
|
||||
}
|
||||
memset(mMasterIn[i].get(), 0, mBlockSize * sizeof(float));
|
||||
|
||||
mNumSamples = 0;
|
||||
|
||||
|
@ -1554,7 +1505,11 @@ size_t VSTEffect::RealtimeProcess(int group, float **inbuf, float **outbuf, size
|
|||
|
||||
bool VSTEffect::RealtimeProcessEnd()
|
||||
{
|
||||
ProcessBlock(mMasterIn, mMasterOut, mNumSamples);
|
||||
// These casts to float** should be safe...
|
||||
ProcessBlock(
|
||||
reinterpret_cast <float**> (mMasterIn.get()),
|
||||
reinterpret_cast <float**> (mMasterOut.get()),
|
||||
mNumSamples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1646,8 +1601,6 @@ bool VSTEffect::GetAutomationParameters(EffectAutomationParameters & parms)
|
|||
|
||||
bool VSTEffect::SetAutomationParameters(EffectAutomationParameters & parms)
|
||||
{
|
||||
size_t slaveCnt = mSlaves.GetCount();
|
||||
|
||||
callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
|
||||
for (int i = 0; i < mAEffect->numParams; i++)
|
||||
{
|
||||
|
@ -1666,10 +1619,8 @@ bool VSTEffect::SetAutomationParameters(EffectAutomationParameters & parms)
|
|||
if (d >= -1.0 && d <= 1.0)
|
||||
{
|
||||
callSetParameter(i, d);
|
||||
for (size_t i = 0; i < slaveCnt; i++)
|
||||
{
|
||||
mSlaves[i]->callSetParameter(i, d);
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->callSetParameter(i, d);
|
||||
}
|
||||
}
|
||||
callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
|
||||
|
@ -1817,29 +1768,10 @@ bool VSTEffect::CloseUI()
|
|||
|
||||
RemoveHandler();
|
||||
|
||||
if (mNames)
|
||||
{
|
||||
delete [] mNames;
|
||||
mNames = NULL;
|
||||
}
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
mSliders = NULL;
|
||||
}
|
||||
|
||||
if (mDisplays)
|
||||
{
|
||||
delete [] mDisplays;
|
||||
mDisplays = NULL;
|
||||
}
|
||||
|
||||
if (mLabels)
|
||||
{
|
||||
delete [] mLabels;
|
||||
mLabels = NULL;
|
||||
}
|
||||
mNames.reset();
|
||||
mSliders.reset();
|
||||
mDisplays.reset();
|
||||
mLabels.reset();
|
||||
|
||||
mUIHost = NULL;
|
||||
mParent = NULL;
|
||||
|
@ -1978,7 +1910,9 @@ void VSTEffect::ShowOptions()
|
|||
if (dlg.ShowModal())
|
||||
{
|
||||
// Reinitialize configuration settings
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), mUserBlockSize, 8192);
|
||||
int userBlockSize;
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("BufferSize"), userBlockSize, 8192);
|
||||
mUserBlockSize = std::max( 1, userBlockSize );
|
||||
mHost->GetSharedConfig(wxT("Options"), wxT("UseLatency"), mUseLatency, true);
|
||||
}
|
||||
}
|
||||
|
@ -2328,14 +2262,13 @@ bool VSTEffect::LoadParameters(const wxString & group)
|
|||
|
||||
if (mHost->GetPrivateConfig(group, wxT("Chunk"), value, wxEmptyString))
|
||||
{
|
||||
char *buf = new char[value.length() / 4 * 3];
|
||||
ArrayOf<char> buf{ value.length() / 4 * 3 };
|
||||
|
||||
int len = VSTEffect::b64decode(value, buf);
|
||||
int len = VSTEffect::b64decode(value, buf.get());
|
||||
if (len)
|
||||
{
|
||||
callSetChunk(true, len, buf, &info);
|
||||
callSetChunk(true, len, buf.get(), &info);
|
||||
}
|
||||
delete [] buf;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2513,10 +2446,8 @@ void VSTEffect::Automate(int index, float value)
|
|||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->callSetParameter(index, value);
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->callSetParameter(index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -2587,10 +2518,8 @@ void VSTEffect::callSetParameter(int index, float value)
|
|||
{
|
||||
mAEffect->setParameter(mAEffect, index, value);
|
||||
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->callSetParameter(index, value);
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->callSetParameter(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2599,10 +2528,8 @@ void VSTEffect::callSetProgram(int index)
|
|||
callDispatcher(effBeginSetProgram, 0, 0, NULL, 0.0);
|
||||
|
||||
callDispatcher(effSetProgram, 0, index, NULL, 0.0);
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->callSetProgram(index);
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->callSetProgram(index);
|
||||
|
||||
callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
|
||||
}
|
||||
|
@ -2643,10 +2570,8 @@ void VSTEffect::callSetChunk(bool isPgm, int len, void *buf, VstPatchChunkInfo *
|
|||
callDispatcher(effSetChunk, isPgm ? 1 : 0, len, buf, 0.0);
|
||||
callDispatcher(effEndSetProgram, 0, 0, NULL, 0.0);
|
||||
|
||||
for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++)
|
||||
{
|
||||
mSlaves[i]->callSetChunk(isPgm, len, buf, info);
|
||||
}
|
||||
for (const auto &slave : mSlaves)
|
||||
slave->callSetChunk(isPgm, len, buf, info);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2847,10 +2772,10 @@ void VSTEffect::BuildPlain()
|
|||
mParent->SetSizer(mainSizer.release());
|
||||
}
|
||||
|
||||
mNames = new wxStaticText *[mAEffect->numParams];
|
||||
mSliders = new wxSlider *[mAEffect->numParams];
|
||||
mDisplays = new wxStaticText *[mAEffect->numParams];
|
||||
mLabels = new wxStaticText *[mAEffect->numParams];
|
||||
mNames.reinit(static_cast<size_t>(mAEffect->numParams));
|
||||
mSliders.reinit(static_cast<size_t>(mAEffect->numParams));
|
||||
mDisplays.reinit(static_cast<size_t>(mAEffect->numParams));
|
||||
mLabels.reinit(static_cast<size_t>(mAEffect->numParams));
|
||||
|
||||
{
|
||||
auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, scroller, _("Effect Settings"));
|
||||
|
@ -3062,7 +2987,7 @@ bool VSTEffect::LoadFXB(const wxFileName & fn)
|
|||
}
|
||||
|
||||
// Allocate memory for the contents
|
||||
unsigned char *data = new unsigned char[f.Length()];
|
||||
ArrayOf<unsigned char> data{ size_t(f.Length()) };
|
||||
if (!data)
|
||||
{
|
||||
wxMessageBox(_("Unable to allocate memory when loading presets file."),
|
||||
|
@ -3071,7 +2996,7 @@ bool VSTEffect::LoadFXB(const wxFileName & fn)
|
|||
mParent);
|
||||
return false;
|
||||
}
|
||||
unsigned char *bptr = data;
|
||||
unsigned char *bptr = data.get();
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -3218,9 +3143,6 @@ bool VSTEffect::LoadFXB(const wxFileName & fn)
|
|||
}
|
||||
} while (false);
|
||||
|
||||
// Get rid of the data
|
||||
delete [] data;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3236,7 +3158,7 @@ bool VSTEffect::LoadFXP(const wxFileName & fn)
|
|||
}
|
||||
|
||||
// Allocate memory for the contents
|
||||
unsigned char *data = new unsigned char[f.Length()];
|
||||
ArrayOf<unsigned char> data{ size_t(f.Length()) };
|
||||
if (!data)
|
||||
{
|
||||
wxMessageBox(_("Unable to allocate memory when loading presets file."),
|
||||
|
@ -3245,7 +3167,7 @@ bool VSTEffect::LoadFXP(const wxFileName & fn)
|
|||
mParent);
|
||||
return false;
|
||||
}
|
||||
unsigned char *bptr = data;
|
||||
unsigned char *bptr = data.get();
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -3271,9 +3193,6 @@ bool VSTEffect::LoadFXP(const wxFileName & fn)
|
|||
ret = LoadFXProgram(&bptr, len, i, false);
|
||||
} while (false);
|
||||
|
||||
// Get rid of the data
|
||||
delete [] data;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3947,15 +3866,14 @@ void VSTEffect::HandleXMLEndTag(const wxChar *tag)
|
|||
{
|
||||
if (mChunk.length())
|
||||
{
|
||||
char *buf = new char[mChunk.length() / 4 * 3];
|
||||
ArrayOf<char> buf{ mChunk.length() / 4 * 3 };
|
||||
|
||||
int len = VSTEffect::b64decode(mChunk, buf);
|
||||
int len = VSTEffect::b64decode(mChunk, buf.get());
|
||||
if (len)
|
||||
{
|
||||
callSetChunk(true, len, buf, &mXMLInfo);
|
||||
callSetChunk(true, len, buf.get(), &mXMLInfo);
|
||||
}
|
||||
|
||||
delete [] buf;
|
||||
mChunk.clear();
|
||||
}
|
||||
mInChunk = false;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "audacity/ModuleInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
#include "../../SampleFormat.h"
|
||||
#include "../../widgets/NumericTextCtrl.h"
|
||||
|
||||
#include "VSTControl.h"
|
||||
|
@ -61,7 +62,7 @@ struct __CFBundle;
|
|||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WX_DEFINE_ARRAY_PTR(VSTEffect *, VSTEffectArray);
|
||||
using VSTEffectArray = std::vector < movable_ptr<VSTEffect> > ;
|
||||
|
||||
DECLARE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW, -1);
|
||||
DECLARE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY, -1);
|
||||
|
@ -268,7 +269,7 @@ private:
|
|||
int mMidiOuts;
|
||||
bool mAutomatable;
|
||||
float mSampleRate;
|
||||
int mUserBlockSize;
|
||||
size_t mUserBlockSize;
|
||||
wxString mName;
|
||||
wxString mVendor;
|
||||
wxString mDescription;
|
||||
|
@ -313,7 +314,7 @@ private:
|
|||
bool mUseLatency;
|
||||
int mBufferDelay;
|
||||
|
||||
int mBlockSize;
|
||||
unsigned mBlockSize;
|
||||
|
||||
int mProcessLevel;
|
||||
bool mHasPower;
|
||||
|
@ -329,8 +330,7 @@ private:
|
|||
VSTEffect *mMaster; // non-NULL if a slave
|
||||
VSTEffectArray mSlaves;
|
||||
unsigned mNumChannels;
|
||||
float **mMasterIn;
|
||||
float **mMasterOut;
|
||||
FloatBuffers mMasterIn, mMasterOut;
|
||||
size_t mNumSamples;
|
||||
|
||||
// UI
|
||||
|
@ -343,10 +343,10 @@ private:
|
|||
VSTControl *mControl;
|
||||
|
||||
NumericTextCtrl *mDuration;
|
||||
wxStaticText **mNames;
|
||||
wxSlider **mSliders;
|
||||
wxStaticText **mDisplays;
|
||||
wxStaticText **mLabels;
|
||||
ArrayOf<wxStaticText *> mNames;
|
||||
ArrayOf<wxSlider *> mSliders;
|
||||
ArrayOf<wxStaticText *> mDisplays;
|
||||
ArrayOf<wxStaticText *> mLabels;
|
||||
|
||||
bool mInSet;
|
||||
bool mInChunk;
|
||||
|
|
|
@ -831,9 +831,6 @@ AudioUnitEffect::AudioUnitEffect(const wxString & path,
|
|||
mDialog = NULL;
|
||||
mParent = NULL;
|
||||
|
||||
mInputList = NULL;
|
||||
mOutputList = NULL;
|
||||
|
||||
mUnitInitialized = false;
|
||||
|
||||
mEventListenerRef = NULL;
|
||||
|
@ -965,17 +962,16 @@ bool AudioUnitEffect::SupportsAutomation()
|
|||
}
|
||||
|
||||
UInt32 cnt = dataSize / sizeof(AudioUnitParameterID);
|
||||
AudioUnitParameterID *array = new AudioUnitParameterID[cnt];
|
||||
ArrayOf < AudioUnitParameterID > array{cnt};
|
||||
|
||||
result = AudioUnitGetProperty(mUnit,
|
||||
kAudioUnitProperty_ParameterList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
array,
|
||||
array.get(),
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -991,20 +987,16 @@ bool AudioUnitEffect::SupportsAutomation()
|
|||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.flags & kAudioUnitParameterFlag_IsWritable)
|
||||
{
|
||||
// All we need is one
|
||||
delete [] array;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] array;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1096,17 +1088,16 @@ bool AudioUnitEffect::SetHost(EffectHostInterface *host)
|
|||
|
||||
// And get them
|
||||
UInt32 cnt = dataSize / sizeof(AudioUnitParameterID);
|
||||
AudioUnitParameterID *array = new AudioUnitParameterID[cnt];
|
||||
ArrayOf<AudioUnitParameterID> array {cnt};
|
||||
|
||||
result = AudioUnitGetProperty(mUnit,
|
||||
kAudioUnitProperty_ParameterList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
array,
|
||||
array.get(),
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1119,13 +1110,10 @@ bool AudioUnitEffect::SetHost(EffectHostInterface *host)
|
|||
&event);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] array;
|
||||
|
||||
event.mEventType = kAudioUnitEvent_PropertyChange;
|
||||
event.mArgument.mProperty.mAudioUnit = mUnit;
|
||||
event.mArgument.mProperty.mPropertyID = kAudioUnitProperty_Latency;
|
||||
|
@ -1246,11 +1234,11 @@ bool AudioUnitEffect::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelN
|
|||
{
|
||||
OSStatus result;
|
||||
|
||||
mInputList = new AudioBufferList[mAudioIns];
|
||||
mInputList->mNumberBuffers = mAudioIns;
|
||||
mInputList.reinit( mAudioIns );
|
||||
mInputList[0].mNumberBuffers = mAudioIns;
|
||||
|
||||
mOutputList = new AudioBufferList[mAudioOuts];
|
||||
mOutputList->mNumberBuffers = mAudioOuts;
|
||||
mOutputList.reinit( mAudioOuts );
|
||||
mOutputList[0].mNumberBuffers = mAudioOuts;
|
||||
|
||||
memset(&mTimeStamp, 0, sizeof(AudioTimeStamp));
|
||||
mTimeStamp.mSampleTime = 0; // This is a double-precision number that should
|
||||
|
@ -1294,35 +1282,26 @@ bool AudioUnitEffect::ProcessFinalize()
|
|||
{
|
||||
mReady = false;
|
||||
|
||||
if (mOutputList)
|
||||
{
|
||||
delete [] mOutputList;
|
||||
mOutputList = NULL;
|
||||
}
|
||||
|
||||
if (mInputList)
|
||||
{
|
||||
delete [] mInputList;
|
||||
mInputList = NULL;
|
||||
}
|
||||
mOutputList.reset();
|
||||
mInputList.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t AudioUnitEffect::ProcessBlock(float **inBlock, float **outBlock, size_t blockLen)
|
||||
{
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
for (size_t i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
mInputList->mBuffers[i].mNumberChannels = 1;
|
||||
mInputList->mBuffers[i].mData = inBlock[i];
|
||||
mInputList->mBuffers[i].mDataByteSize = sizeof(float) * blockLen;
|
||||
mInputList[0].mBuffers[i].mNumberChannels = 1;
|
||||
mInputList[0].mBuffers[i].mData = inBlock[i];
|
||||
mInputList[0].mBuffers[i].mDataByteSize = sizeof(float) * blockLen;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mAudioOuts; i++)
|
||||
for (size_t i = 0; i < mAudioOuts; i++)
|
||||
{
|
||||
mOutputList->mBuffers[i].mNumberChannels = 1;
|
||||
mOutputList->mBuffers[i].mData = outBlock[i];
|
||||
mOutputList->mBuffers[i].mDataByteSize = sizeof(float) * blockLen;
|
||||
mOutputList[0].mBuffers[i].mNumberChannels = 1;
|
||||
mOutputList[0].mBuffers[i].mData = outBlock[i];
|
||||
mOutputList[0].mBuffers[i].mDataByteSize = sizeof(float) * blockLen;
|
||||
}
|
||||
|
||||
AudioUnitRenderActionFlags flags = 0;
|
||||
|
@ -1333,7 +1312,7 @@ size_t AudioUnitEffect::ProcessBlock(float **inBlock, float **outBlock, size_t b
|
|||
&mTimeStamp,
|
||||
0,
|
||||
blockLen,
|
||||
mOutputList);
|
||||
mOutputList.get());
|
||||
if (result != noErr)
|
||||
{
|
||||
printf("Render failed: %d %4.4s\n", (int)result, (char *)&result);
|
||||
|
@ -1347,20 +1326,8 @@ size_t AudioUnitEffect::ProcessBlock(float **inBlock, float **outBlock, size_t b
|
|||
|
||||
bool AudioUnitEffect::RealtimeInitialize()
|
||||
{
|
||||
mMasterIn = new float *[mAudioIns];
|
||||
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
mMasterIn[i] = new float[mBlockSize];
|
||||
memset(mMasterIn[i], 0, mBlockSize * sizeof(float));
|
||||
}
|
||||
|
||||
mMasterOut = new float *[mAudioOuts];
|
||||
for (int i = 0; i < mAudioOuts; i++)
|
||||
{
|
||||
mMasterOut[i] = new float[mBlockSize];
|
||||
}
|
||||
|
||||
mMasterIn.reinit(mAudioIns, mBlockSize, true);
|
||||
mMasterOut.reinit( mAudioOuts, mBlockSize );
|
||||
return ProcessInitialize(0);
|
||||
}
|
||||
|
||||
|
@ -1389,17 +1356,8 @@ bool AudioUnitEffect::RealtimeFinalize()
|
|||
mSlaves[i]->ProcessFinalize();
|
||||
mSlaves.clear();
|
||||
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
delete [] mMasterIn[i];
|
||||
}
|
||||
delete [] mMasterIn;
|
||||
|
||||
for (int i = 0; i < mAudioOuts; i++)
|
||||
{
|
||||
delete [] mMasterOut[i];
|
||||
}
|
||||
delete [] mMasterOut;
|
||||
mMasterIn.reset();
|
||||
mMasterOut.reset();
|
||||
|
||||
return ProcessFinalize();
|
||||
}
|
||||
|
@ -1424,10 +1382,8 @@ bool AudioUnitEffect::RealtimeResume()
|
|||
|
||||
bool AudioUnitEffect::RealtimeProcessStart()
|
||||
{
|
||||
for (int i = 0; i < mAudioIns; i++)
|
||||
{
|
||||
memset(mMasterIn[i], 0, mBlockSize * sizeof(float));
|
||||
}
|
||||
for (size_t i = 0; i < mAudioIns; i++)
|
||||
memset(mMasterIn[i].get(), 0, mBlockSize * sizeof(float));
|
||||
|
||||
mNumSamples = 0;
|
||||
|
||||
|
@ -1441,7 +1397,7 @@ size_t AudioUnitEffect::RealtimeProcess(int group,
|
|||
{
|
||||
wxASSERT(numSamples <= mBlockSize);
|
||||
|
||||
for (int c = 0; c < mAudioIns; c++)
|
||||
for (size_t c = 0; c < mAudioIns; c++)
|
||||
{
|
||||
for (decltype(numSamples) s = 0; s < numSamples; s++)
|
||||
{
|
||||
|
@ -1455,7 +1411,10 @@ size_t AudioUnitEffect::RealtimeProcess(int group,
|
|||
|
||||
bool AudioUnitEffect::RealtimeProcessEnd()
|
||||
{
|
||||
ProcessBlock(mMasterIn, mMasterOut, mNumSamples);
|
||||
ProcessBlock(
|
||||
reinterpret_cast<float**>(mMasterIn.get()),
|
||||
reinterpret_cast<float**>(mMasterOut.get()),
|
||||
mNumSamples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1505,17 +1464,16 @@ bool AudioUnitEffect::GetAutomationParameters(EffectAutomationParameters & parms
|
|||
}
|
||||
|
||||
UInt32 cnt = dataSize / sizeof(AudioUnitParameterID);
|
||||
AudioUnitParameterID *array = new AudioUnitParameterID[cnt];
|
||||
ArrayOf<AudioUnitParameterID> array {cnt};
|
||||
|
||||
result = AudioUnitGetProperty(mUnit,
|
||||
kAudioUnitProperty_ParameterList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
array,
|
||||
array.get(),
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1531,7 +1489,6 @@ bool AudioUnitEffect::GetAutomationParameters(EffectAutomationParameters & parms
|
|||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1554,14 +1511,11 @@ bool AudioUnitEffect::GetAutomationParameters(EffectAutomationParameters & parms
|
|||
&value);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
parms.Write(name, value);
|
||||
}
|
||||
|
||||
delete [] array;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1583,17 +1537,16 @@ bool AudioUnitEffect::SetAutomationParameters(EffectAutomationParameters & parms
|
|||
}
|
||||
|
||||
UInt32 cnt = dataSize / sizeof(AudioUnitParameterID);
|
||||
AudioUnitParameterID *array = new AudioUnitParameterID[cnt];
|
||||
ArrayOf<AudioUnitParameterID> array {cnt};
|
||||
|
||||
result = AudioUnitGetProperty(mUnit,
|
||||
kAudioUnitProperty_ParameterList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
array,
|
||||
array.get(),
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1609,7 +1562,6 @@ bool AudioUnitEffect::SetAutomationParameters(EffectAutomationParameters & parms
|
|||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1628,7 +1580,6 @@ bool AudioUnitEffect::SetAutomationParameters(EffectAutomationParameters & parms
|
|||
double d = 0.0;
|
||||
if (!parms.Read(name, &d))
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1641,13 +1592,10 @@ bool AudioUnitEffect::SetAutomationParameters(EffectAutomationParameters & parms
|
|||
0);
|
||||
if (result != noErr)
|
||||
{
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] array;
|
||||
|
||||
AudioUnitParameter aup;
|
||||
aup.mAudioUnit = mUnit;
|
||||
aup.mParameterID = kAUParameterListener_AnyParameter;
|
||||
|
@ -2064,8 +2012,6 @@ bool AudioUnitEffect::SetRateAndChannels()
|
|||
bool AudioUnitEffect::CopyParameters(AudioUnit srcUnit, AudioUnit dstUnit)
|
||||
{
|
||||
OSStatus result;
|
||||
int numParameters, i;
|
||||
AudioUnitParameterID *parameters;
|
||||
Float32 parameterValue;
|
||||
UInt32 size;
|
||||
|
||||
|
@ -2087,25 +2033,24 @@ bool AudioUnitEffect::CopyParameters(AudioUnit srcUnit, AudioUnit dstUnit)
|
|||
|
||||
// Now get the list of all parameter IDs
|
||||
|
||||
numParameters = size / sizeof(AudioUnitParameterID);
|
||||
parameters = new AudioUnitParameterID[numParameters];
|
||||
auto numParameters = size / sizeof(AudioUnitParameterID);
|
||||
ArrayOf<AudioUnitParameterID> parameters{ numParameters };
|
||||
result = AudioUnitGetProperty(srcUnit,
|
||||
kAudioUnitProperty_ParameterList,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
parameters,
|
||||
parameters.get(),
|
||||
&size);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("Couldn't get parameter list\n");
|
||||
delete[] parameters;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the parameters from the main unit to the unit specific to
|
||||
// this track
|
||||
|
||||
for (i = 0; i < numParameters; i++)
|
||||
for (unsigned i = 0; i < numParameters; i++)
|
||||
{
|
||||
result = AudioUnitGetParameter(srcUnit,
|
||||
parameters[i],
|
||||
|
@ -2130,8 +2075,6 @@ bool AudioUnitEffect::CopyParameters(AudioUnit srcUnit, AudioUnit dstUnit)
|
|||
}
|
||||
}
|
||||
|
||||
delete[] parameters;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2152,9 +2095,7 @@ OSStatus AudioUnitEffect::Render(AudioUnitRenderActionFlags *inActionFlags,
|
|||
AudioBufferList *ioData)
|
||||
{
|
||||
for (int i = 0; i < ioData->mNumberBuffers; i++)
|
||||
{
|
||||
ioData->mBuffers[i].mData = mInputList->mBuffers[i].mData;
|
||||
}
|
||||
ioData->mBuffers[i].mData = mInputList[0].mBuffers[i].mData;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ private:
|
|||
|
||||
EffectHostInterface *mHost;
|
||||
unsigned mAudioIns;
|
||||
int mAudioOuts;
|
||||
unsigned mAudioOuts;
|
||||
bool mInteractive;
|
||||
bool mLatencyDone;
|
||||
UInt32 mBlockSize;
|
||||
|
@ -194,8 +194,8 @@ private:
|
|||
AudioTimeStamp mTimeStamp;
|
||||
bool mReady;
|
||||
|
||||
AudioBufferList *mInputList;
|
||||
AudioBufferList *mOutputList;
|
||||
ArrayOf<AudioBufferList> mInputList;
|
||||
ArrayOf<AudioBufferList> mOutputList;
|
||||
|
||||
EffectUIHostInterface *mUIHost;
|
||||
wxWindow *mParent;
|
||||
|
@ -206,10 +206,9 @@ private:
|
|||
AudioUnitEffect *mMaster; // non-NULL if a slave
|
||||
AudioUnitEffectArray mSlaves;
|
||||
unsigned mNumChannels;
|
||||
float **mMasterIn;
|
||||
float **mMasterOut;
|
||||
ArraysOf<float> mMasterIn, mMasterOut;
|
||||
size_t mNumSamples;
|
||||
|
||||
|
||||
AUEventListenerRef mEventListenerRef;
|
||||
|
||||
friend class AudioUnitEffectExportDialog;
|
||||
|
|
|
@ -556,62 +556,14 @@ LadspaEffect::LadspaEffect(const wxString & path, int index)
|
|||
mSampleRate = 44100;
|
||||
mBlockSize = 0;
|
||||
|
||||
mInputPorts = NULL;
|
||||
mOutputPorts = NULL;
|
||||
mInputControls = NULL;
|
||||
mOutputControls = NULL;
|
||||
|
||||
mLatencyPort = -1;
|
||||
|
||||
mDialog = NULL;
|
||||
mParent = NULL;
|
||||
mSliders = NULL;
|
||||
mFields = NULL;
|
||||
mLabels = NULL;
|
||||
mToggles = NULL;
|
||||
}
|
||||
|
||||
LadspaEffect::~LadspaEffect()
|
||||
{
|
||||
if (mInputPorts)
|
||||
{
|
||||
delete [] mInputPorts;
|
||||
}
|
||||
|
||||
if (mOutputPorts)
|
||||
{
|
||||
delete [] mOutputPorts;
|
||||
}
|
||||
|
||||
if (mInputControls)
|
||||
{
|
||||
delete [] mInputControls;
|
||||
}
|
||||
|
||||
if (mOutputControls)
|
||||
{
|
||||
delete [] mOutputControls;
|
||||
}
|
||||
|
||||
if (mToggles)
|
||||
{
|
||||
delete [] mToggles;
|
||||
}
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
}
|
||||
|
||||
if (mFields)
|
||||
{
|
||||
delete [] mFields;
|
||||
}
|
||||
|
||||
if (mLabels)
|
||||
{
|
||||
delete [] mLabels;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
@ -715,10 +667,10 @@ bool LadspaEffect::SetHost(EffectHostInterface *host)
|
|||
return false;
|
||||
}
|
||||
|
||||
mInputPorts = new unsigned long [mData->PortCount];
|
||||
mOutputPorts = new unsigned long [mData->PortCount];
|
||||
mInputControls = new float [mData->PortCount];
|
||||
mOutputControls = new float [mData->PortCount];
|
||||
mInputPorts.reinit( mData->PortCount );
|
||||
mOutputPorts.reinit( mData->PortCount );
|
||||
mInputControls.reinit( mData->PortCount );
|
||||
mOutputControls.reinit( mData->PortCount );
|
||||
|
||||
for (unsigned long p = 0; p < mData->PortCount; p++)
|
||||
{
|
||||
|
@ -1165,13 +1117,11 @@ bool LadspaEffect::PopulateUI(wxWindow *parent)
|
|||
|
||||
mParent->PushEventHandler(this);
|
||||
|
||||
mToggles = new wxCheckBox *[mData->PortCount];
|
||||
mSliders = new wxSlider *[mData->PortCount];
|
||||
mFields = new wxTextCtrl *[mData->PortCount];
|
||||
mLabels = new wxStaticText *[mData->PortCount];
|
||||
mMeters = new LadspaEffectMeter *[mData->PortCount];
|
||||
|
||||
memset(mFields, 0, mData->PortCount * sizeof(wxTextCtrl *));
|
||||
mToggles.reinit( mData->PortCount );
|
||||
mSliders.reinit( mData->PortCount );
|
||||
mFields.reinit( mData->PortCount, true);
|
||||
mLabels.reinit( mData->PortCount );
|
||||
mMeters.reinit( mData->PortCount );
|
||||
|
||||
wxASSERT(mParent); // To justify safenew
|
||||
wxScrolledWindow *const w = safenew wxScrolledWindow(mParent,
|
||||
|
@ -1505,29 +1455,10 @@ bool LadspaEffect::CloseUI()
|
|||
{
|
||||
mParent->RemoveEventHandler(this);
|
||||
|
||||
if (mToggles)
|
||||
{
|
||||
delete [] mToggles;
|
||||
mToggles = NULL;
|
||||
}
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
mSliders = NULL;
|
||||
}
|
||||
|
||||
if (mFields)
|
||||
{
|
||||
delete [] mFields;
|
||||
mFields = NULL;
|
||||
}
|
||||
|
||||
if (mLabels)
|
||||
{
|
||||
delete [] mLabels;
|
||||
mLabels = NULL;
|
||||
}
|
||||
mToggles.reset();
|
||||
mSliders.reset();
|
||||
mFields.reset();
|
||||
mLabels.reset();
|
||||
|
||||
mUIHost = NULL;
|
||||
mParent = NULL;
|
||||
|
|
|
@ -13,6 +13,7 @@ class wxStaticText;
|
|||
class wxTextCtrl;
|
||||
class wxCheckBox;
|
||||
|
||||
#include "../../MemoryX.h"
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "audacity/EffectInterface.h"
|
||||
|
@ -22,6 +23,7 @@ class wxCheckBox;
|
|||
#include "../../widgets/NumericTextCtrl.h"
|
||||
|
||||
#include "ladspa.h"
|
||||
#include "../../SampleFormat.h"
|
||||
|
||||
#define LADSPAEFFECTS_VERSION wxT("1.0.0.0")
|
||||
#define LADSPAEFFECTS_FAMILY wxT("LADSPA")
|
||||
|
@ -158,20 +160,19 @@ private:
|
|||
|
||||
double mSampleRate;
|
||||
size_t mBlockSize;
|
||||
int mUserBlockSize;
|
||||
|
||||
bool mInteractive;
|
||||
|
||||
unsigned mAudioIns;
|
||||
unsigned long *mInputPorts;
|
||||
ArrayOf<unsigned long> mInputPorts;
|
||||
|
||||
unsigned mAudioOuts;
|
||||
unsigned long *mOutputPorts;
|
||||
ArrayOf<unsigned long> mOutputPorts;
|
||||
|
||||
int mNumInputControls;
|
||||
float *mInputControls;
|
||||
Floats mInputControls;
|
||||
int mNumOutputControls;
|
||||
float *mOutputControls;
|
||||
Floats mOutputControls;
|
||||
|
||||
bool mUseLatency;
|
||||
int mLatencyPort;
|
||||
|
@ -185,11 +186,11 @@ private:
|
|||
NumericTextCtrl *mDuration;
|
||||
wxDialog *mDialog;
|
||||
wxWindow *mParent;
|
||||
wxSlider **mSliders;
|
||||
wxTextCtrl **mFields;
|
||||
wxStaticText **mLabels;
|
||||
wxCheckBox **mToggles;
|
||||
LadspaEffectMeter **mMeters;
|
||||
ArrayOf<wxSlider*> mSliders;
|
||||
ArrayOf<wxTextCtrl*> mFields;
|
||||
ArrayOf<wxStaticText*> mLabels;
|
||||
ArrayOf<wxCheckBox*> mToggles;
|
||||
ArrayOf<LadspaEffectMeter *> mMeters;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
|
|
|
@ -315,15 +315,11 @@ LV2Effect::LV2Effect(const LilvPlugin *plug)
|
|||
mLatency = 0.0;
|
||||
|
||||
mDialog = NULL;
|
||||
mSliders = NULL;
|
||||
mFields = NULL;
|
||||
|
||||
mURIMap = NULL;
|
||||
mNumURIMap = 0;
|
||||
mOptions = NULL;
|
||||
mNumOptions = 0;
|
||||
mFeatures = NULL;
|
||||
mNumFeatures = 0;
|
||||
|
||||
mIdleFeature = NULL;
|
||||
mOptionsInterface = NULL;
|
||||
|
@ -342,15 +338,6 @@ LV2Effect::~LV2Effect()
|
|||
free(mURIMap);
|
||||
}
|
||||
|
||||
if (mFeatures)
|
||||
{
|
||||
for (int i = 0; mFeatures[i] != NULL; i++)
|
||||
{
|
||||
delete mFeatures[i];
|
||||
}
|
||||
free(mFeatures);
|
||||
}
|
||||
|
||||
if (mOptions)
|
||||
{
|
||||
free(mOptions);
|
||||
|
@ -460,10 +447,10 @@ bool LV2Effect::SetHost(EffectHostInterface *host)
|
|||
{
|
||||
mHost = host;
|
||||
|
||||
int numPorts = lilv_plugin_get_num_ports(mPlug);
|
||||
auto numPorts = lilv_plugin_get_num_ports(mPlug);
|
||||
|
||||
// Fail if we don't grok the port types
|
||||
for (int i = 0; i < numPorts; i++)
|
||||
for (size_t i = 0; i < numPorts; i++)
|
||||
{
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index(mPlug, i);
|
||||
|
||||
|
@ -474,176 +461,174 @@ bool LV2Effect::SetHost(EffectHostInterface *host)
|
|||
}
|
||||
}
|
||||
|
||||
// Allocate buffers for the port indices and the default control values
|
||||
float *minimumVals = new float [numPorts];
|
||||
float *maximumVals = new float [numPorts];
|
||||
float *defaultValues = new float [numPorts];
|
||||
|
||||
// Retrieve the port ranges for all ports (some values may be NaN)
|
||||
lilv_plugin_get_port_ranges_float(mPlug,
|
||||
minimumVals,
|
||||
maximumVals,
|
||||
defaultValues);
|
||||
|
||||
// Get info about all ports
|
||||
for (int i = 0; i < numPorts; i++)
|
||||
{
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index(mPlug, i);
|
||||
int index = lilv_port_get_index(mPlug, port);
|
||||
// Allocate buffers for the port indices and the default control values
|
||||
Floats minimumVals{ numPorts };
|
||||
Floats maximumVals{ numPorts };
|
||||
Floats defaultValues{ numPorts };
|
||||
|
||||
// Quick check for audio ports
|
||||
if (lilv_port_is_a(mPlug, port, gAudio))
|
||||
// Retrieve the port ranges for all ports (some values may be NaN)
|
||||
lilv_plugin_get_port_ranges_float(mPlug,
|
||||
minimumVals.get(),
|
||||
maximumVals.get(),
|
||||
defaultValues.get());
|
||||
|
||||
// Get info about all ports
|
||||
for (size_t i = 0; i < numPorts; i++)
|
||||
{
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index(mPlug, i);
|
||||
int index = lilv_port_get_index(mPlug, port);
|
||||
|
||||
// Quick check for audio ports
|
||||
if (lilv_port_is_a(mPlug, port, gAudio))
|
||||
{
|
||||
if (lilv_port_is_a(mPlug, port, gInput))
|
||||
{
|
||||
mAudioInputs.Add(index);
|
||||
}
|
||||
else if (lilv_port_is_a(mPlug, port, gOutput))
|
||||
{
|
||||
mAudioOutputs.Add(index);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only control ports from this point
|
||||
if (!lilv_port_is_a(mPlug, port, gControl))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LV2Port ctrl;
|
||||
ctrl.mIndex = index;
|
||||
|
||||
// Get the port name
|
||||
ctrl.mSymbol = LilvString(lilv_port_get_symbol(mPlug, port));
|
||||
LilvNode *tmpName = lilv_port_get_name(mPlug, port);
|
||||
ctrl.mName = LilvString(tmpName);
|
||||
lilv_node_free(tmpName);
|
||||
|
||||
// Get any unit descriptor
|
||||
LilvNode *unit = lilv_port_get(mPlug, port, gUnit);
|
||||
if (unit)
|
||||
{
|
||||
ctrl.mUnits = LilvString(lilv_world_get(gWorld, unit, gUnitSymbol, NULL));
|
||||
}
|
||||
|
||||
// Get the group to which this port belongs or default to the main group
|
||||
ctrl.mGroup = wxEmptyString;
|
||||
LilvNode *group = lilv_port_get(mPlug, port, gGroup);
|
||||
if (group)
|
||||
{
|
||||
ctrl.mGroup = LilvString(lilv_world_get(gWorld, group, gLabel, NULL));
|
||||
if (ctrl.mGroup.IsEmpty())
|
||||
{
|
||||
ctrl.mGroup = LilvString(lilv_world_get(gWorld, group, gName, NULL));
|
||||
}
|
||||
|
||||
if (ctrl.mGroup.IsEmpty())
|
||||
{
|
||||
ctrl.mGroup = LilvString(group);
|
||||
}
|
||||
}
|
||||
|
||||
// Add it if not previously done
|
||||
if (mGroups.Index(ctrl.mGroup) == wxNOT_FOUND)
|
||||
{
|
||||
mGroups.Add(ctrl.mGroup);
|
||||
}
|
||||
|
||||
// Get the scale points
|
||||
LilvScalePoints *points = lilv_port_get_scale_points(mPlug, port);
|
||||
LILV_FOREACH(scale_points, j, points)
|
||||
{
|
||||
const LilvScalePoint *point = lilv_scale_points_get(points, j);
|
||||
|
||||
ctrl.mScaleValues.Add(lilv_node_as_float(lilv_scale_point_get_value(point)));
|
||||
ctrl.mScaleLabels.Add(LilvString(lilv_scale_point_get_label(point)));
|
||||
}
|
||||
lilv_scale_points_free(points);
|
||||
|
||||
// Collect the value and range info
|
||||
ctrl.mHasLo = !std::isnan(minimumVals[i]);
|
||||
ctrl.mHasHi = !std::isnan(maximumVals[i]);
|
||||
ctrl.mMin = ctrl.mHasLo ? minimumVals[i] : 0.0;
|
||||
ctrl.mMax = ctrl.mHasHi ? maximumVals[i] : 1.0;
|
||||
ctrl.mLo = ctrl.mMin;
|
||||
ctrl.mHi = ctrl.mMax;
|
||||
ctrl.mDef = !std::isnan(defaultValues[i]) ?
|
||||
defaultValues[i] :
|
||||
ctrl.mHasLo ?
|
||||
ctrl.mLo :
|
||||
ctrl.mHasHi ?
|
||||
ctrl.mHi :
|
||||
0.0;
|
||||
ctrl.mVal = ctrl.mDef;
|
||||
|
||||
// Figure out the type of port we have
|
||||
if (lilv_port_is_a(mPlug, port, gInput))
|
||||
{
|
||||
mAudioInputs.Add(index);
|
||||
}
|
||||
else if (lilv_port_is_a(mPlug, port, gOutput))
|
||||
{
|
||||
mAudioOutputs.Add(index);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ctrl.mInput = true;
|
||||
if (lilv_port_has_property(mPlug, port, gToggled))
|
||||
{
|
||||
ctrl.mToggle = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gEnumeration))
|
||||
{
|
||||
ctrl.mEnumeration = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gInteger))
|
||||
{
|
||||
ctrl.mInteger = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gSampleRate))
|
||||
{
|
||||
ctrl.mSampleRate = true;
|
||||
}
|
||||
|
||||
// Only control ports from this point
|
||||
if (!lilv_port_is_a(mPlug, port, gControl))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Trigger properties can be combined with other types, but it
|
||||
// seems mostly to be combined with toggle. So, we turn the
|
||||
// checkbox into a button.
|
||||
if (lilv_port_has_property(mPlug, port, gTrigger))
|
||||
{
|
||||
ctrl.mTrigger = true;
|
||||
}
|
||||
|
||||
LV2Port ctrl;
|
||||
ctrl.mIndex = index;
|
||||
// We'll make the slider logarithmic
|
||||
if (lilv_port_has_property(mPlug, port, gLogarithmic))
|
||||
{
|
||||
ctrl.mLogarithmic = true;
|
||||
}
|
||||
|
||||
// Get the port name
|
||||
ctrl.mSymbol = LilvString(lilv_port_get_symbol(mPlug, port));
|
||||
LilvNode *tmpName = lilv_port_get_name(mPlug, port);
|
||||
ctrl.mName = LilvString(tmpName);
|
||||
lilv_node_free(tmpName);
|
||||
if (lilv_port_has_property(mPlug, port, gEnumeration))
|
||||
{
|
||||
ctrl.mEnumeration = true;
|
||||
}
|
||||
|
||||
// Get any unit descriptor
|
||||
LilvNode *unit = lilv_port_get(mPlug, port, gUnit);
|
||||
if (unit)
|
||||
{
|
||||
ctrl.mUnits = LilvString(lilv_world_get(gWorld, unit, gUnitSymbol, NULL));
|
||||
}
|
||||
|
||||
// Get the group to which this port belongs or default to the main group
|
||||
ctrl.mGroup = wxEmptyString;
|
||||
LilvNode *group = lilv_port_get(mPlug, port, gGroup);
|
||||
if (group)
|
||||
{
|
||||
ctrl.mGroup = LilvString(lilv_world_get(gWorld, group, gLabel, NULL));
|
||||
if (ctrl.mGroup.IsEmpty())
|
||||
{
|
||||
ctrl.mGroup = LilvString(lilv_world_get(gWorld, group, gName, NULL));
|
||||
}
|
||||
|
||||
if (ctrl.mGroup.IsEmpty())
|
||||
{
|
||||
ctrl.mGroup = LilvString(group);
|
||||
}
|
||||
}
|
||||
|
||||
// Add it if not previously done
|
||||
if (mGroups.Index(ctrl.mGroup) == wxNOT_FOUND)
|
||||
{
|
||||
mGroups.Add(ctrl.mGroup);
|
||||
}
|
||||
|
||||
// Get the scale points
|
||||
LilvScalePoints *points = lilv_port_get_scale_points(mPlug, port);
|
||||
LILV_FOREACH(scale_points, j, points)
|
||||
{
|
||||
const LilvScalePoint *point = lilv_scale_points_get(points, j);
|
||||
|
||||
ctrl.mScaleValues.Add(lilv_node_as_float(lilv_scale_point_get_value(point)));
|
||||
ctrl.mScaleLabels.Add(LilvString(lilv_scale_point_get_label(point)));
|
||||
}
|
||||
lilv_scale_points_free(points);
|
||||
|
||||
// Collect the value and range info
|
||||
ctrl.mHasLo = !std::isnan(minimumVals[i]);
|
||||
ctrl.mHasHi = !std::isnan(maximumVals[i]);
|
||||
ctrl.mMin = ctrl.mHasLo ? minimumVals[i] : 0.0;
|
||||
ctrl.mMax = ctrl.mHasHi ? maximumVals[i] : 1.0;
|
||||
ctrl.mLo = ctrl.mMin;
|
||||
ctrl.mHi = ctrl.mMax;
|
||||
ctrl.mDef = !std::isnan(defaultValues[i]) ?
|
||||
defaultValues[i] :
|
||||
ctrl.mHasLo ?
|
||||
ctrl.mLo :
|
||||
ctrl.mHasHi ?
|
||||
ctrl.mHi :
|
||||
0.0;
|
||||
ctrl.mVal = ctrl.mDef;
|
||||
|
||||
// Figure out the type of port we have
|
||||
if (lilv_port_is_a(mPlug, port, gInput))
|
||||
{
|
||||
ctrl.mInput = true;
|
||||
if (lilv_port_has_property(mPlug, port, gToggled))
|
||||
{
|
||||
ctrl.mToggle = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gEnumeration))
|
||||
{
|
||||
ctrl.mEnumeration = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gInteger))
|
||||
{
|
||||
ctrl.mInteger = true;
|
||||
}
|
||||
else if (lilv_port_has_property(mPlug, port, gSampleRate))
|
||||
{
|
||||
ctrl.mSampleRate = true;
|
||||
}
|
||||
|
||||
// Trigger properties can be combined with other types, but it
|
||||
// seems mostly to be combined with toggle. So, we turn the
|
||||
// checkbox into a button.
|
||||
if (lilv_port_has_property(mPlug, port, gTrigger))
|
||||
{
|
||||
ctrl.mTrigger = true;
|
||||
}
|
||||
|
||||
// We'll make the slider logarithmic
|
||||
if (lilv_port_has_property(mPlug, port, gLogarithmic))
|
||||
{
|
||||
ctrl.mLogarithmic = true;
|
||||
}
|
||||
|
||||
if (lilv_port_has_property(mPlug, port, gEnumeration))
|
||||
{
|
||||
ctrl.mEnumeration = true;
|
||||
}
|
||||
|
||||
mControlsMap[ctrl.mIndex] = mControls.GetCount();
|
||||
mGroupMap[ctrl.mGroup].Add(mControls.GetCount());
|
||||
mControls.Add(ctrl);
|
||||
}
|
||||
else if (lilv_port_is_a(mPlug, port, gOutput))
|
||||
{
|
||||
ctrl.mInput = false;
|
||||
if (lilv_port_has_property(mPlug, port, gLatency))
|
||||
{
|
||||
mLatencyPort = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
mControlsMap[ctrl.mIndex] = mControls.GetCount();
|
||||
mGroupMap[ctrl.mGroup].Add(mControls.GetCount());
|
||||
mControls.Add(ctrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just ignore it for now
|
||||
else if (lilv_port_is_a(mPlug, port, gOutput))
|
||||
{
|
||||
ctrl.mInput = false;
|
||||
if (lilv_port_has_property(mPlug, port, gLatency))
|
||||
{
|
||||
mLatencyPort = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
mGroupMap[ctrl.mGroup].Add(mControls.GetCount());
|
||||
mControls.Add(ctrl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just ignore it for now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] minimumVals;
|
||||
delete [] maximumVals;
|
||||
delete [] defaultValues;
|
||||
|
||||
// mHost will be null during registration
|
||||
if (mHost)
|
||||
{
|
||||
|
@ -747,7 +732,7 @@ void LV2Effect::SetSampleRate(double rate)
|
|||
|
||||
size_t LV2Effect::SetBlockSize(size_t maxBlockSize)
|
||||
{
|
||||
mBlockSize = (int) maxBlockSize;
|
||||
mBlockSize = maxBlockSize;
|
||||
|
||||
if (mOptionsInterface && mOptionsInterface->set)
|
||||
{
|
||||
|
@ -837,19 +822,13 @@ size_t LV2Effect::ProcessBlock(float **inbuf, float **outbuf, size_t size)
|
|||
|
||||
bool LV2Effect::RealtimeInitialize()
|
||||
{
|
||||
mMasterIn = new float *[mAudioInputs.GetCount()];
|
||||
mMasterIn.reinit( mAudioInputs.GetCount(), mBlockSize );
|
||||
for (size_t p = 0, cnt = mAudioInputs.GetCount(); p < cnt; p++)
|
||||
{
|
||||
mMasterIn[p] = new float[mBlockSize];
|
||||
lilv_instance_connect_port(mMaster, mAudioInputs[p], mMasterIn[p]);
|
||||
}
|
||||
lilv_instance_connect_port(mMaster, mAudioInputs[p], mMasterIn[p].get());
|
||||
|
||||
mMasterOut = new float *[mAudioOutputs.GetCount()];
|
||||
mMasterOut.reinit( mAudioOutputs.GetCount(), mBlockSize );
|
||||
for (size_t p = 0, cnt = mAudioOutputs.GetCount(); p < cnt; p++)
|
||||
{
|
||||
mMasterOut[p] = new float[mBlockSize];
|
||||
lilv_instance_connect_port(mMaster, mAudioOutputs[p], mMasterOut[p]);
|
||||
}
|
||||
lilv_instance_connect_port(mMaster, mAudioOutputs[p], mMasterOut[p].get());
|
||||
|
||||
lilv_instance_activate(mMaster);
|
||||
|
||||
|
@ -868,17 +847,9 @@ bool LV2Effect::RealtimeFinalize()
|
|||
|
||||
lilv_instance_deactivate(mMaster);
|
||||
|
||||
for (size_t p = 0, cnt = mAudioInputs.GetCount(); p < cnt; p++)
|
||||
{
|
||||
delete [] mMasterIn[p];
|
||||
}
|
||||
delete [] mMasterIn;
|
||||
|
||||
for (size_t p = 0, cnt = mAudioOutputs.GetCount(); p < cnt; p++)
|
||||
{
|
||||
delete [] mMasterOut[p];
|
||||
}
|
||||
delete [] mMasterOut;
|
||||
mMasterIn.reset();
|
||||
|
||||
mMasterOut.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -896,9 +867,7 @@ bool LV2Effect::RealtimeResume()
|
|||
bool LV2Effect::RealtimeProcessStart()
|
||||
{
|
||||
for (size_t p = 0, cnt = mAudioInputs.GetCount(); p < cnt; p++)
|
||||
{
|
||||
memset(mMasterIn[p], 0, mBlockSize * sizeof(float));
|
||||
}
|
||||
memset(mMasterIn[p].get(), 0, mBlockSize * sizeof(float));
|
||||
|
||||
mNumSamples = 0;
|
||||
|
||||
|
@ -1072,8 +1041,6 @@ bool LV2Effect::PopulateUI(wxWindow *parent)
|
|||
|
||||
mParent->PushEventHandler(this);
|
||||
|
||||
mSliders = NULL;
|
||||
mFields = NULL;
|
||||
mSuilHost = NULL;
|
||||
mSuilInstance = NULL;
|
||||
|
||||
|
@ -1145,17 +1112,8 @@ bool LV2Effect::CloseUI()
|
|||
|
||||
mParent->RemoveEventHandler(this);
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
mSliders = NULL;
|
||||
}
|
||||
|
||||
if (mFields)
|
||||
{
|
||||
delete [] mFields;
|
||||
mFields = NULL;
|
||||
}
|
||||
mSliders.reset();
|
||||
mFields.reset();
|
||||
|
||||
if (mSuilInstance)
|
||||
{
|
||||
|
@ -1365,27 +1323,26 @@ size_t LV2Effect::AddOption(const char *key, uint32_t size, const char *type, vo
|
|||
|
||||
LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data)
|
||||
{
|
||||
int ndx = mNumFeatures;
|
||||
mFeatures.resize(mFeatures.size() + 1);
|
||||
|
||||
mNumFeatures += 1;
|
||||
mFeatures = (LV2_Feature **) realloc(mFeatures, mNumFeatures * sizeof(LV2_Feature *));
|
||||
mFeatures[ndx] = NULL;
|
||||
auto &pFeature = mFeatures.back();
|
||||
|
||||
if (uri != NULL)
|
||||
{
|
||||
mFeatures[ndx] = new LV2_Feature;
|
||||
mFeatures[ndx]->URI = uri;
|
||||
mFeatures[ndx]->data = data;
|
||||
pFeature = make_movable<LV2_Feature>();
|
||||
pFeature->URI = uri;
|
||||
pFeature->data = data;
|
||||
}
|
||||
|
||||
return mFeatures[ndx];
|
||||
mFeaturePtrs.push_back(pFeature.get());
|
||||
return pFeature.get();
|
||||
}
|
||||
|
||||
LilvInstance *LV2Effect::InitInstance(float sampleRate)
|
||||
{
|
||||
LilvInstance *handle = lilv_plugin_instantiate(mPlug,
|
||||
sampleRate,
|
||||
mFeatures);
|
||||
mFeaturePtrs.data());
|
||||
if (!handle)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -1521,7 +1478,7 @@ bool LV2Effect::BuildFancy()
|
|||
lilv_node_as_uri(uiType),
|
||||
lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(ui))),
|
||||
lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(ui))),
|
||||
mFeatures);
|
||||
mFeaturePtrs.data());
|
||||
|
||||
lilv_uis_free(uis);
|
||||
|
||||
|
@ -1586,9 +1543,9 @@ bool LV2Effect::BuildPlain()
|
|||
int numCols = 5;
|
||||
|
||||
// Allocate memory for the user parameter controls
|
||||
int ctrlcnt = (int) mControls.GetCount();
|
||||
mSliders = new wxSlider *[ctrlcnt];
|
||||
mFields = new wxTextCtrl *[ctrlcnt];
|
||||
auto ctrlcnt = mControls.GetCount();
|
||||
mSliders.reinit(ctrlcnt);
|
||||
mFields.reinit(ctrlcnt);
|
||||
|
||||
wxSizer *innerSizer;
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#if USE_LV2
|
||||
|
||||
#include "../../MemoryX.h"
|
||||
#include <vector>
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dynarray.h>
|
||||
|
@ -32,6 +35,7 @@
|
|||
#include <lilv/lilv.h>
|
||||
#include <suil/suil.h>
|
||||
|
||||
#include "../../SampleFormat.h"
|
||||
#include "../../widgets/NumericTextCtrl.h"
|
||||
|
||||
#include "LoadLV2.h"
|
||||
|
@ -254,7 +258,7 @@ private:
|
|||
|
||||
EffectHostInterface *mHost;
|
||||
|
||||
int mBlockSize;
|
||||
size_t mBlockSize;
|
||||
double mSampleRate;
|
||||
|
||||
wxLongToLongHashMap mControlsMap;
|
||||
|
@ -274,8 +278,7 @@ private:
|
|||
LilvInstance *mProcess;
|
||||
LV2SlaveArray mSlaves;
|
||||
|
||||
float **mMasterIn;
|
||||
float **mMasterOut;
|
||||
FloatBuffers mMasterIn, mMasterOut;
|
||||
size_t mNumSamples;
|
||||
|
||||
double mLength;
|
||||
|
@ -302,8 +305,8 @@ private:
|
|||
LV2_Options_Option *mOptions;
|
||||
int mNumOptions;
|
||||
|
||||
LV2_Feature **mFeatures;
|
||||
int mNumFeatures;
|
||||
std::vector<movable_ptr<LV2_Feature>> mFeatures;
|
||||
std::vector<LV2_Feature*> mFeaturePtrs;
|
||||
|
||||
LV2_Feature *mInstanceAccessFeature;
|
||||
LV2_Feature *mParentFeature;
|
||||
|
@ -314,8 +317,8 @@ private:
|
|||
SuilInstance *mSuilInstance;
|
||||
|
||||
NumericTextCtrl *mDuration;
|
||||
wxSlider **mSliders;
|
||||
wxTextCtrl **mFields;
|
||||
ArrayOf<wxSlider*> mSliders;
|
||||
ArrayOf<wxTextCtrl*> mFields;
|
||||
|
||||
bool mFactoryPresetsLoaded;
|
||||
wxArrayString mFactoryPresetNames;
|
||||
|
|
|
@ -81,46 +81,10 @@ VampEffect::VampEffect(std::unique_ptr<Vamp::Plugin> &&plugin,
|
|||
{
|
||||
mKey = mPath.BeforeLast(wxT('/')).ToUTF8();
|
||||
mName = mPath.AfterLast(wxT('/'));
|
||||
|
||||
mSliders = NULL;
|
||||
mFields = NULL;
|
||||
mLabels = NULL;
|
||||
mToggles = NULL;
|
||||
mChoices = NULL;
|
||||
mValues = NULL;
|
||||
}
|
||||
|
||||
VampEffect::~VampEffect()
|
||||
{
|
||||
if (mValues)
|
||||
{
|
||||
delete [] mValues;
|
||||
}
|
||||
|
||||
if (mSliders)
|
||||
{
|
||||
delete [] mSliders;
|
||||
}
|
||||
|
||||
if (mFields)
|
||||
{
|
||||
delete [] mFields;
|
||||
}
|
||||
|
||||
if (mLabels)
|
||||
{
|
||||
delete [] mLabels;
|
||||
}
|
||||
|
||||
if (mToggles)
|
||||
{
|
||||
delete [] mToggles;
|
||||
}
|
||||
|
||||
if (mChoices)
|
||||
{
|
||||
delete [] mChoices;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
@ -486,11 +450,7 @@ bool VampEffect::Process()
|
|||
));
|
||||
LabelTrack *ltrack = addedTracks.back()->get();
|
||||
|
||||
float **data = new float *[channels]; // ANSWER-ME: Vigilant Sentry marks this as memory leak, var "data" not deleted.
|
||||
for (int c = 0; c < channels; ++c)
|
||||
{
|
||||
data[c] = new float[block];
|
||||
}
|
||||
FloatBuffers data{ channels, block };
|
||||
|
||||
auto originalLen = len;
|
||||
auto ls = lstart;
|
||||
|
@ -502,12 +462,12 @@ bool VampEffect::Process()
|
|||
|
||||
if (left)
|
||||
{
|
||||
left->Get((samplePtr)data[0], floatSample, ls, request);
|
||||
left->Get((samplePtr)data[0].get(), floatSample, ls, request);
|
||||
}
|
||||
|
||||
if (right)
|
||||
{
|
||||
right->Get((samplePtr)data[1], floatSample, rs, request);
|
||||
right->Get((samplePtr)data[1].get(), floatSample, rs, request);
|
||||
}
|
||||
|
||||
if (request < block)
|
||||
|
@ -528,7 +488,8 @@ bool VampEffect::Process()
|
|||
(int)(mRate + 0.5)
|
||||
);
|
||||
|
||||
Vamp::Plugin::FeatureSet features = mPlugin->process(data, timestamp);
|
||||
Vamp::Plugin::FeatureSet features = mPlugin->process(
|
||||
reinterpret_cast< float** >( data.get() ), timestamp);
|
||||
AddFeatures(ltrack, features);
|
||||
|
||||
if (len > (int)step)
|
||||
|
@ -589,14 +550,14 @@ void VampEffect::PopulateOrExchange(ShuttleGui & S)
|
|||
|
||||
mParameters = mPlugin->getParameterDescriptors();
|
||||
|
||||
int count = mParameters.size();
|
||||
auto count = mParameters.size();
|
||||
|
||||
mToggles = new wxCheckBox *[count];
|
||||
mSliders = new wxSlider *[count];
|
||||
mFields = new wxTextCtrl *[count];
|
||||
mLabels = new wxStaticText *[count];
|
||||
mChoices = new wxChoice *[count];
|
||||
mValues = new float[count];
|
||||
mToggles.reinit( count );
|
||||
mSliders.reinit( count );
|
||||
mFields.reinit( count );
|
||||
mLabels.reinit( count );
|
||||
mChoices.reinit( count );
|
||||
mValues.reinit( count );
|
||||
|
||||
S.SetStyle(wxVSCROLL | wxTAB_TRAVERSAL);
|
||||
wxScrolledWindow *scroller = S.StartScroller(2);
|
||||
|
@ -631,10 +592,10 @@ void VampEffect::PopulateOrExchange(ShuttleGui & S)
|
|||
S.AddSpace(1, 1);
|
||||
}
|
||||
|
||||
for (int p = 0; p < count; p++)
|
||||
for (size_t p = 0; p < count; p++)
|
||||
{
|
||||
wxString tip = wxString::FromUTF8(mParameters[p].description.c_str());
|
||||
wxString unit = wxString::FromUTF8(mParameters[p].unit.c_str());
|
||||
wxString tip = wxString::FromUTF8(mParameters[p].description.c_str());
|
||||
wxString unit = wxString::FromUTF8(mParameters[p].unit.c_str());
|
||||
|
||||
float value = mPlugin->getParameter(mParameters[p].identifier);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <vamp-hostsdk/PluginLoader.h>
|
||||
|
||||
#include "../../SampleFormat.h"
|
||||
#include "../Effect.h"
|
||||
|
||||
class LabelTrack;
|
||||
|
@ -99,13 +100,13 @@ private:
|
|||
|
||||
Vamp::Plugin::ParameterList mParameters;
|
||||
|
||||
float *mValues;
|
||||
Floats mValues;
|
||||
|
||||
wxSlider **mSliders;
|
||||
wxTextCtrl **mFields;
|
||||
wxStaticText **mLabels;
|
||||
wxCheckBox **mToggles;
|
||||
wxChoice **mChoices;
|
||||
ArrayOf<wxSlider *> mSliders;
|
||||
ArrayOf<wxTextCtrl *> mFields;
|
||||
ArrayOf<wxStaticText *> mLabels;
|
||||
ArrayOf<wxCheckBox *> mToggles;
|
||||
ArrayOf<wxChoice *> mChoices;
|
||||
wxChoice *mProgram;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
|
|
@ -996,23 +996,20 @@ ExportMixerPanel::ExportMixerPanel( MixerSpec *mixerSpec,
|
|||
wxArrayString trackNames,wxWindow *parent, wxWindowID id,
|
||||
const wxPoint& pos, const wxSize& size):
|
||||
wxPanelWrapper(parent, id, pos, size)
|
||||
, mMixerSpec{mixerSpec}
|
||||
, mChannelRects{ mMixerSpec->GetMaxNumChannels() }
|
||||
, mTrackRects{ mMixerSpec->GetNumTracks() }
|
||||
{
|
||||
mBitmap = NULL;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mMixerSpec = mixerSpec;
|
||||
mSelectedTrack = mSelectedChannel = -1;
|
||||
|
||||
mTrackRects = new wxRect[ mMixerSpec->GetNumTracks() ];
|
||||
mChannelRects = new wxRect[ mMixerSpec->GetMaxNumChannels() ];
|
||||
|
||||
mTrackNames = trackNames;
|
||||
}
|
||||
|
||||
ExportMixerPanel::~ExportMixerPanel()
|
||||
{
|
||||
delete[] mTrackRects;
|
||||
delete[] mChannelRects;
|
||||
}
|
||||
|
||||
//set the font on memDC such that text can fit in specified width and height
|
||||
|
|
|
@ -234,8 +234,8 @@ private:
|
|||
int mWidth;
|
||||
int mHeight;
|
||||
MixerSpec *mMixerSpec;
|
||||
wxRect *mChannelRects;
|
||||
wxRect *mTrackRects;
|
||||
ArrayOf<wxRect> mChannelRects;
|
||||
ArrayOf<wxRect> mTrackRects;
|
||||
int mSelectedTrack, mSelectedChannel;
|
||||
wxArrayString mTrackNames;
|
||||
int mBoxWidth, mChannelHeight, mTrackHeight;
|
||||
|
|
|
@ -139,7 +139,7 @@ bool ExportFLACOptions::TransferDataFromWindow()
|
|||
// ExportFLAC Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define SAMPLES_PER_RUN 8192
|
||||
#define SAMPLES_PER_RUN 8192u
|
||||
|
||||
/* FLACPP_API_VERSION_CURRENT is 6 for libFLAC++ from flac-1.1.3 (see <FLAC++/export.h>) */
|
||||
#if !defined FLACPP_API_VERSION_CURRENT || FLACPP_API_VERSION_CURRENT < 6
|
||||
|
@ -311,11 +311,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
numChannels, SAMPLES_PER_RUN, false,
|
||||
rate, format, true, mixerSpec);
|
||||
|
||||
int i;
|
||||
FLAC__int32 **tmpsmplbuf = new FLAC__int32*[numChannels];
|
||||
for (i = 0; i < numChannels; i++) {
|
||||
tmpsmplbuf[i] = (FLAC__int32 *) calloc(SAMPLES_PER_RUN, sizeof(FLAC__int32));
|
||||
}
|
||||
ArraysOf<FLAC__int32> tmpsmplbuf{ numChannels, SAMPLES_PER_RUN, true };
|
||||
|
||||
{
|
||||
ProgressDialog progress(wxFileName(fName).GetName(),
|
||||
|
@ -329,7 +325,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
break;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < numChannels; i++) {
|
||||
for (size_t i = 0; i < numChannels; i++) {
|
||||
samplePtr mixed = mixer->GetBuffer(i);
|
||||
if (format == int24Sample) {
|
||||
for (decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
|
||||
|
@ -342,7 +338,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
}
|
||||
}
|
||||
}
|
||||
encoder.process(tmpsmplbuf, samplesThisRun);
|
||||
encoder.process(reinterpret_cast<const FLAC__int32**>(tmpsmplbuf.get()), samplesThisRun);
|
||||
}
|
||||
updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
|
||||
}
|
||||
|
@ -350,12 +346,6 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
encoder.finish();
|
||||
}
|
||||
|
||||
for (i = 0; i < numChannels; i++) {
|
||||
free(tmpsmplbuf[i]);
|
||||
}
|
||||
|
||||
delete[] tmpsmplbuf;
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -251,12 +251,12 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
|
|||
|
||||
// Values taken from the twolame simple encoder sample
|
||||
const int pcmBufferSize = 9216 / 2; // number of samples
|
||||
const int mp2BufferSize = 16384; // bytes
|
||||
const size_t mp2BufferSize = 16384u; // bytes
|
||||
|
||||
// We allocate a buffer which is twice as big as the
|
||||
// input buffer, which should always be enough.
|
||||
// We have to multiply by 4 because one sample is 2 bytes wide!
|
||||
unsigned char* mp2Buffer = new unsigned char[mp2BufferSize];
|
||||
ArrayOf<unsigned char> mp2Buffer{ mp2BufferSize };
|
||||
|
||||
const WaveTrackConstArray waveTracks =
|
||||
tracks->GetWaveTrackConstArray(selectionOnly, false);
|
||||
|
@ -285,10 +285,10 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
|
|||
encodeOptions,
|
||||
pcmBuffer,
|
||||
pcmNumSamples,
|
||||
mp2Buffer,
|
||||
mp2Buffer.get(),
|
||||
mp2BufferSize);
|
||||
|
||||
outFile.Write(mp2Buffer, mp2BufferNumBytes);
|
||||
outFile.Write(mp2Buffer.get(), mp2BufferNumBytes);
|
||||
|
||||
updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
|
||||
}
|
||||
|
@ -296,16 +296,14 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
|
|||
|
||||
int mp2BufferNumBytes = twolame_encode_flush(
|
||||
encodeOptions,
|
||||
mp2Buffer,
|
||||
mp2Buffer.get(),
|
||||
mp2BufferSize);
|
||||
|
||||
if (mp2BufferNumBytes > 0)
|
||||
outFile.Write(mp2Buffer, mp2BufferNumBytes);
|
||||
outFile.Write(mp2Buffer.get(), mp2BufferNumBytes);
|
||||
|
||||
twolame_close(&encodeOptions);
|
||||
|
||||
delete[] mp2Buffer;
|
||||
|
||||
/* Write ID3 tag if it was supposed to be at the end of the file */
|
||||
|
||||
if (id3len && endOfFile)
|
||||
|
|
|
@ -1808,8 +1808,8 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
|
|||
auto updateResult = ProgressResult::Success;
|
||||
long bytes;
|
||||
|
||||
int bufferSize = exporter.GetOutBufferSize();
|
||||
unsigned char *buffer = new unsigned char[bufferSize];
|
||||
size_t bufferSize = std::max(0, exporter.GetOutBufferSize());
|
||||
ArrayOf<unsigned char> buffer{ bufferSize };
|
||||
wxASSERT(buffer);
|
||||
|
||||
const WaveTrackConstArray waveTracks =
|
||||
|
@ -1854,18 +1854,18 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
|
|||
|
||||
if (blockLen < inSamples) {
|
||||
if (channels > 1) {
|
||||
bytes = exporter.EncodeRemainder(mixed, blockLen, buffer);
|
||||
bytes = exporter.EncodeRemainder(mixed, blockLen, buffer.get());
|
||||
}
|
||||
else {
|
||||
bytes = exporter.EncodeRemainderMono(mixed, blockLen, buffer);
|
||||
bytes = exporter.EncodeRemainderMono(mixed, blockLen, buffer.get());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (channels > 1) {
|
||||
bytes = exporter.EncodeBuffer(mixed, buffer);
|
||||
bytes = exporter.EncodeBuffer(mixed, buffer.get());
|
||||
}
|
||||
else {
|
||||
bytes = exporter.EncodeBufferMono(mixed, buffer);
|
||||
bytes = exporter.EncodeBufferMono(mixed, buffer.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1876,16 +1876,16 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
|
|||
break;
|
||||
}
|
||||
|
||||
outFile.Write(buffer, bytes);
|
||||
outFile.Write(buffer.get(), bytes);
|
||||
|
||||
updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
|
||||
}
|
||||
}
|
||||
|
||||
bytes = exporter.FinishStream(buffer);
|
||||
bytes = exporter.FinishStream(buffer.get());
|
||||
|
||||
if (bytes) {
|
||||
outFile.Write(buffer, bytes);
|
||||
outFile.Write(buffer.get(), bytes);
|
||||
}
|
||||
|
||||
// Write ID3 tag if it was supposed to be at the end of the file
|
||||
|
@ -1908,8 +1908,6 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
|
|||
// Close the file
|
||||
outFile.Close();
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ ProgressResult ExportOGG::Export(AudacityProject *project,
|
|||
}
|
||||
else {
|
||||
|
||||
for (int i = 0; i < numChannels; i++) {
|
||||
for (size_t i = 0; i < numChannels; i++) {
|
||||
float *temp = (float *)mixer->GetBuffer(i);
|
||||
memcpy(vorbis_buffer[i], temp, sizeof(float)*SAMPLES_PER_RUN);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,6 @@ FormatClassifier::FormatClassifier(const char* filename) :
|
|||
{
|
||||
FormatClassT fClass;
|
||||
|
||||
// Build buffers
|
||||
mSigBuffer = new float[cSiglen];
|
||||
mAuxBuffer = new float[cSiglen];
|
||||
mRawBuffer = new uint8_t[cSiglen * 8];
|
||||
|
||||
// Define the classification classes
|
||||
fClass.endian = MachineEndianness::Little;
|
||||
fClass.format = MultiFormatReader::Int8;
|
||||
|
@ -71,8 +66,8 @@ FormatClassifier::FormatClassifier(const char* filename) :
|
|||
mClasses.push_back(fClass);
|
||||
|
||||
// Build feature vectors
|
||||
mMonoFeat = new float[mClasses.size()];
|
||||
mStereoFeat = new float[mClasses.size()];
|
||||
mMonoFeat = Floats{ mClasses.size() };
|
||||
mStereoFeat = Floats{ mClasses.size() };
|
||||
|
||||
#ifdef FORMATCLASSIFIER_SIGNAL_DEBUG
|
||||
// Build a debug writer
|
||||
|
@ -95,12 +90,6 @@ FormatClassifier::FormatClassifier(const char* filename) :
|
|||
|
||||
FormatClassifier::~FormatClassifier()
|
||||
{
|
||||
delete[] mSigBuffer;
|
||||
delete[] mAuxBuffer;
|
||||
delete[] mRawBuffer;
|
||||
|
||||
delete[] mMonoFeat;
|
||||
delete[] mStereoFeat;
|
||||
}
|
||||
|
||||
FormatClassifier::FormatClassT FormatClassifier::GetResultFormat()
|
||||
|
@ -168,17 +157,17 @@ void FormatClassifier::Run()
|
|||
|
||||
// Do some simple preprocessing
|
||||
// Remove DC offset
|
||||
float smean = Mean(mSigBuffer, cSiglen);
|
||||
Sub(mSigBuffer, smean, cSiglen);
|
||||
float smean = Mean(mSigBuffer.get(), cSiglen);
|
||||
Sub(mSigBuffer.get(), smean, cSiglen);
|
||||
// Normalize to +- 1.0
|
||||
Abs(mSigBuffer, mAuxBuffer, cSiglen);
|
||||
float smax = Max(mAuxBuffer, cSiglen);
|
||||
Div(mSigBuffer, smax, cSiglen);
|
||||
Abs(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
|
||||
float smax = Max(mAuxBuffer.get(), cSiglen);
|
||||
Div(mSigBuffer.get(), smax, cSiglen);
|
||||
|
||||
// Now actually fill the feature vector
|
||||
// Low to high band power ratio
|
||||
float pLo = mMeter.CalcPower(mSigBuffer, 0.15f, 0.3f);
|
||||
float pHi = mMeter.CalcPower(mSigBuffer, 0.45f, 0.1f);
|
||||
float pLo = mMeter.CalcPower(mSigBuffer.get(), 0.15f, 0.3f);
|
||||
float pHi = mMeter.CalcPower(mSigBuffer.get(), 0.45f, 0.1f);
|
||||
mMonoFeat[n] = pLo / pHi;
|
||||
}
|
||||
|
||||
|
@ -193,24 +182,24 @@ void FormatClassifier::Run()
|
|||
|
||||
// Do some simple preprocessing
|
||||
// Remove DC offset
|
||||
float smean = Mean(mSigBuffer, cSiglen);
|
||||
Sub(mSigBuffer, smean, cSiglen);
|
||||
float smean = Mean(mSigBuffer.get(), cSiglen);
|
||||
Sub(mSigBuffer.get(), smean, cSiglen);
|
||||
// Normalize to +- 1.0
|
||||
Abs(mSigBuffer, mAuxBuffer, cSiglen);
|
||||
float smax = Max(mAuxBuffer, cSiglen);
|
||||
Div(mSigBuffer, smax, cSiglen);
|
||||
Abs(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
|
||||
float smax = Max(mAuxBuffer.get(), cSiglen);
|
||||
Div(mSigBuffer.get(), smax, cSiglen);
|
||||
|
||||
// Now actually fill the feature vector
|
||||
// Low to high band power ratio
|
||||
float pLo = mMeter.CalcPower(mSigBuffer, 0.15f, 0.3f);
|
||||
float pHi = mMeter.CalcPower(mSigBuffer, 0.45f, 0.1f);
|
||||
float pLo = mMeter.CalcPower(mSigBuffer.get(), 0.15f, 0.3f);
|
||||
float pHi = mMeter.CalcPower(mSigBuffer.get(), 0.45f, 0.1f);
|
||||
mStereoFeat[n] = pLo / pHi;
|
||||
}
|
||||
|
||||
// Get the results
|
||||
size_t midx, sidx;
|
||||
float monoMax = Max(mMonoFeat, mClasses.size(), &midx);
|
||||
float stereoMax = Max(mStereoFeat, mClasses.size(), &sidx);
|
||||
float monoMax = Max(mMonoFeat.get(), mClasses.size(), &midx);
|
||||
float stereoMax = Max(mStereoFeat.get(), mClasses.size(), &sidx);
|
||||
|
||||
if (monoMax > stereoMax)
|
||||
{
|
||||
|
@ -233,27 +222,27 @@ void FormatClassifier::ReadSignal(FormatClassT format, size_t stride)
|
|||
mReader.Reset();
|
||||
|
||||
// Do a dummy read of 1024 bytes to skip potential header information
|
||||
mReader.ReadSamples(mRawBuffer, 1024, MultiFormatReader::Uint8, MachineEndianness::Little);
|
||||
mReader.ReadSamples(mRawBuffer.get(), 1024, MultiFormatReader::Uint8, MachineEndianness::Little);
|
||||
|
||||
do
|
||||
{
|
||||
actRead = mReader.ReadSamples(mRawBuffer, cSiglen, stride, format.format, format.endian);
|
||||
actRead = mReader.ReadSamples(mRawBuffer.get(), cSiglen, stride, format.format, format.endian);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
ConvertSamples(mRawBuffer, mSigBuffer, format);
|
||||
ConvertSamples(mRawBuffer.get(), mSigBuffer.get(), format);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actRead == cSiglen)
|
||||
{
|
||||
ConvertSamples(mRawBuffer, mAuxBuffer, format);
|
||||
ConvertSamples(mRawBuffer.get(), mAuxBuffer.get(), format);
|
||||
|
||||
// Integrate signals
|
||||
Add(mSigBuffer, mAuxBuffer, cSiglen);
|
||||
Add(mSigBuffer.get(), mAuxBuffer.get(), cSiglen);
|
||||
|
||||
// Do some dummy reads to break signal coherence
|
||||
mReader.ReadSamples(mRawBuffer, n + 1, stride, format.format, format.endian);
|
||||
mReader.ReadSamples(mRawBuffer.get(), n + 1, stride, format.format, format.endian);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,12 +82,12 @@ private:
|
|||
std::unique_ptr<DebugWriter> mpWriter;
|
||||
#endif
|
||||
|
||||
float* mSigBuffer;
|
||||
float* mAuxBuffer;
|
||||
uint8_t* mRawBuffer;
|
||||
Floats mSigBuffer{ cSiglen };
|
||||
Floats mAuxBuffer{ cSiglen };
|
||||
ArrayOf<uint8_t> mRawBuffer{ cSiglen * 8 };
|
||||
|
||||
float* mMonoFeat;
|
||||
float* mStereoFeat;
|
||||
Floats mMonoFeat;
|
||||
Floats mStereoFeat;
|
||||
|
||||
FormatClassT mResultFormat;
|
||||
unsigned mResultChannels { 0 };
|
||||
|
|
|
@ -252,7 +252,7 @@ void MyFLACFile::error_callback(FLAC__StreamDecoderErrorStatus WXUNUSED(status))
|
|||
FLAC__StreamDecoderWriteStatus MyFLACFile::write_callback(const FLAC__Frame *frame,
|
||||
const FLAC__int32 * const buffer[])
|
||||
{
|
||||
short *tmp=new short[frame->header.blocksize];
|
||||
ArrayOf<short> tmp{ frame->header.blocksize };
|
||||
|
||||
auto iter = mFile->mChannels.begin();
|
||||
for (unsigned int chn=0; chn<mFile->mNumChannels; ++iter, ++chn) {
|
||||
|
@ -261,7 +261,7 @@ FLAC__StreamDecoderWriteStatus MyFLACFile::write_callback(const FLAC__Frame *fra
|
|||
tmp[s]=buffer[chn][s];
|
||||
}
|
||||
|
||||
iter->get()->Append((samplePtr)tmp,
|
||||
iter->get()->Append((samplePtr)tmp.get(),
|
||||
int16Sample,
|
||||
frame->header.blocksize);
|
||||
}
|
||||
|
@ -272,8 +272,6 @@ FLAC__StreamDecoderWriteStatus MyFLACFile::write_callback(const FLAC__Frame *fra
|
|||
}
|
||||
}
|
||||
|
||||
delete [] tmp;
|
||||
|
||||
mFile->mSamplesDone += frame->header.blocksize;
|
||||
|
||||
mFile->mUpdateResult = mFile->mProgress->Update((wxULongLong_t) mFile->mSamplesDone, mFile->mNumSamples != 0 ? (wxULongLong_t)mFile->mNumSamples : 1);
|
||||
|
@ -452,7 +450,7 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
mChannels.resize(mNumChannels);
|
||||
|
||||
auto iter = mChannels.begin();
|
||||
for (int c = 0; c < mNumChannels; ++iter, ++c) {
|
||||
for (size_t c = 0; c < mNumChannels; ++iter, ++c) {
|
||||
*iter = trackFactory->NewWaveTrack(mFormat, mSampleRate);
|
||||
|
||||
if (mNumChannels == 2) {
|
||||
|
@ -500,7 +498,7 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
limitSampleBufferSize( maxBlockSize, fileTotalFrames - i );
|
||||
|
||||
auto iter = mChannels.begin();
|
||||
for (int c = 0; c < mNumChannels; ++c, ++iter)
|
||||
for (size_t c = 0; c < mNumChannels; ++c, ++iter)
|
||||
iter->get()->AppendCoded(mFilename, i, blockLen, c, ODTask::eODFLAC);
|
||||
|
||||
mUpdateResult = mProgress->Update(
|
||||
|
@ -540,7 +538,7 @@ ProgressResult FLACImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
|
||||
tags->Clear();
|
||||
size_t cnt = mFile->mComments.GetCount();
|
||||
for (int c = 0; c < cnt; c++) {
|
||||
for (size_t c = 0; c < cnt; c++) {
|
||||
wxString name = mFile->mComments[c].BeforeFirst(wxT('='));
|
||||
wxString value = mFile->mComments[c].AfterFirst(wxT('='));
|
||||
if (name.Upper() == wxT("DATE") && !tags->HasTag(TAG_YEAR)) {
|
||||
|
|
|
@ -86,7 +86,7 @@ extern "C" {
|
|||
|
||||
#include "../WaveTrack.h"
|
||||
|
||||
#define INPUT_BUFFER_SIZE 65535
|
||||
#define INPUT_BUFFER_SIZE 65535u
|
||||
#define PROGRESS_SCALING_FACTOR 100000
|
||||
|
||||
/* this is a private structure we can use for whatever we like, and it will get
|
||||
|
@ -94,7 +94,7 @@ extern "C" {
|
|||
* things. */
|
||||
struct private_data {
|
||||
wxFile *file; /* the file containing the mp3 data we're feeding the encoder */
|
||||
unsigned char *inputBuffer;
|
||||
ArrayOf<unsigned char> inputBuffer{ INPUT_BUFFER_SIZE };
|
||||
int inputBufferFill; /* amount of data in inputBuffer */
|
||||
TrackFactory *trackFactory;
|
||||
TrackHolders channels;
|
||||
|
@ -152,7 +152,6 @@ private:
|
|||
|
||||
std::unique_ptr<wxFile> mFile;
|
||||
void *mUserData;
|
||||
struct private_data mPrivateData;
|
||||
mad_decoder mDecoder;
|
||||
};
|
||||
|
||||
|
@ -217,33 +216,31 @@ ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
|
||||
/* Prepare decoder data, initialize decoder */
|
||||
|
||||
mPrivateData.file = mFile.get();
|
||||
mPrivateData.inputBuffer = new unsigned char [INPUT_BUFFER_SIZE];
|
||||
mPrivateData.inputBufferFill = 0;
|
||||
mPrivateData.progress = mProgress.get();
|
||||
mPrivateData.updateResult= ProgressResult::Success;
|
||||
mPrivateData.id3checked = false;
|
||||
mPrivateData.numChannels = 0;
|
||||
mPrivateData.trackFactory= trackFactory;
|
||||
mPrivateData.eof = false;
|
||||
private_data privateData;
|
||||
privateData.file = mFile.get();
|
||||
privateData.inputBufferFill = 0;
|
||||
privateData.progress = mProgress.get();
|
||||
privateData.updateResult= ProgressResult::Success;
|
||||
privateData.id3checked = false;
|
||||
privateData.numChannels = 0;
|
||||
privateData.trackFactory= trackFactory;
|
||||
privateData.eof = false;
|
||||
|
||||
mad_decoder_init(&mDecoder, &mPrivateData, input_cb, 0, 0, output_cb, error_cb, 0);
|
||||
mad_decoder_init(&mDecoder, &privateData, input_cb, 0, 0, output_cb, error_cb, 0);
|
||||
|
||||
/* and send the decoder on its way! */
|
||||
|
||||
bool res = (mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC) == 0) &&
|
||||
(mPrivateData.numChannels > 0) &&
|
||||
!(mPrivateData.updateResult == ProgressResult::Cancelled) &&
|
||||
!(mPrivateData.updateResult == ProgressResult::Failed);
|
||||
(privateData.numChannels > 0) &&
|
||||
!(privateData.updateResult == ProgressResult::Cancelled) &&
|
||||
!(privateData.updateResult == ProgressResult::Failed);
|
||||
|
||||
mad_decoder_finish(&mDecoder);
|
||||
|
||||
delete[] mPrivateData.inputBuffer;
|
||||
|
||||
if (!res) {
|
||||
/* failure */
|
||||
/* printf("failure\n"); */
|
||||
return (mPrivateData.updateResult);
|
||||
return (privateData.updateResult);
|
||||
}
|
||||
|
||||
/* success */
|
||||
|
@ -251,15 +248,15 @@ ProgressResult MP3ImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
|
||||
/* copy the WaveTrack pointers into the Track pointer list that
|
||||
* we are expected to fill */
|
||||
for(const auto &channel : mPrivateData.channels) {
|
||||
for(const auto &channel : privateData.channels) {
|
||||
channel->Flush();
|
||||
}
|
||||
outTracks.swap(mPrivateData.channels);
|
||||
outTracks.swap(privateData.channels);
|
||||
|
||||
/* Read in any metadata */
|
||||
ImportID3(tags);
|
||||
|
||||
return mPrivateData.updateResult;
|
||||
return privateData.updateResult;
|
||||
}
|
||||
|
||||
MP3ImportFileHandle::~MP3ImportFileHandle()
|
||||
|
@ -418,8 +415,8 @@ enum mad_flow input_cb(void *_data, struct mad_stream *stream)
|
|||
|
||||
#ifdef USE_LIBID3TAG
|
||||
if (!data->id3checked) {
|
||||
data->file->Read(data->inputBuffer, ID3_TAG_QUERYSIZE);
|
||||
int len = id3_tag_query(data->inputBuffer, ID3_TAG_QUERYSIZE);
|
||||
data->file->Read(data->inputBuffer.get(), ID3_TAG_QUERYSIZE);
|
||||
int len = id3_tag_query(data->inputBuffer.get(), ID3_TAG_QUERYSIZE);
|
||||
if (len > 0) {
|
||||
data->file->Seek(len, wxFromStart);
|
||||
}
|
||||
|
@ -440,14 +437,15 @@ enum mad_flow input_cb(void *_data, struct mad_stream *stream)
|
|||
* -- Rob Leslie, on the mad-dev mailing list */
|
||||
|
||||
int unconsumedBytes;
|
||||
if (stream->next_frame) {
|
||||
if(stream->next_frame ) {
|
||||
/* we must use inputBufferFill instead of INPUT_BUFFER_SIZE here
|
||||
because the final buffer of the file may be only partially
|
||||
filled, and we would otherwise be providing too much input
|
||||
after eof */
|
||||
unconsumedBytes = data->inputBuffer + data->inputBufferFill
|
||||
- stream->next_frame;
|
||||
memmove(data->inputBuffer, stream->next_frame, unconsumedBytes);
|
||||
unconsumedBytes = data->inputBuffer.get() + data->inputBufferFill
|
||||
- stream->next_frame;
|
||||
if (unconsumedBytes > 0)
|
||||
memmove(data->inputBuffer.get(), stream->next_frame, unconsumedBytes);
|
||||
}
|
||||
else
|
||||
unconsumedBytes = 0;
|
||||
|
@ -458,19 +456,19 @@ enum mad_flow input_cb(void *_data, struct mad_stream *stream)
|
|||
/* supply the requisite MAD_BUFFER_GUARD zero bytes to ensure
|
||||
the final frame gets decoded properly, then finish */
|
||||
|
||||
memset(data->inputBuffer + unconsumedBytes, 0, MAD_BUFFER_GUARD);
|
||||
memset(data->inputBuffer.get() + unconsumedBytes, 0, MAD_BUFFER_GUARD);
|
||||
mad_stream_buffer
|
||||
(stream, data->inputBuffer, MAD_BUFFER_GUARD + unconsumedBytes);
|
||||
(stream, data->inputBuffer.get(), MAD_BUFFER_GUARD + unconsumedBytes);
|
||||
|
||||
data->eof = true; /* so on next call, we will tell mad to stop */
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
off_t read = data->file->Read(data->inputBuffer + unconsumedBytes,
|
||||
off_t read = data->file->Read(data->inputBuffer.get() + unconsumedBytes,
|
||||
INPUT_BUFFER_SIZE - unconsumedBytes);
|
||||
|
||||
mad_stream_buffer(stream, data->inputBuffer, read + unconsumedBytes);
|
||||
mad_stream_buffer(stream, data->inputBuffer.get(), read + unconsumedBytes);
|
||||
|
||||
data->inputBufferFill = int(read + unconsumedBytes);
|
||||
|
||||
|
@ -486,7 +484,6 @@ enum mad_flow output_cb(void *_data,
|
|||
{
|
||||
int samplerate;
|
||||
struct private_data *data = (struct private_data *)_data;
|
||||
int smpl;
|
||||
|
||||
samplerate= pcm->samplerate;
|
||||
auto channels = pcm->channels;
|
||||
|
@ -526,24 +523,17 @@ enum mad_flow output_cb(void *_data,
|
|||
* point samples into something we can feed to the WaveTrack. Allocating
|
||||
* big blocks of data like this isn't a great idea, but it's temporary.
|
||||
*/
|
||||
float **channelBuffers = new float* [channels];
|
||||
for(int chn = 0; chn < channels; chn++)
|
||||
channelBuffers[chn] = new float [samples];
|
||||
FloatBuffers channelBuffers{ channels, samples };
|
||||
|
||||
for(smpl = 0; smpl < samples; smpl++)
|
||||
for (size_t smpl = 0; smpl < samples; smpl++)
|
||||
for(int chn = 0; chn < channels; chn++)
|
||||
channelBuffers[chn][smpl] = scale(pcm->samples[chn][smpl]);
|
||||
|
||||
auto iter = data->channels.begin();
|
||||
for (int chn = 0; chn < channels; ++iter, ++chn)
|
||||
iter->get()->Append((samplePtr)channelBuffers[chn],
|
||||
for (int chn = 0; chn < channels; chn++)
|
||||
data->channels[chn]->Append((samplePtr)channelBuffers[chn].get(),
|
||||
floatSample,
|
||||
samples);
|
||||
|
||||
for(int chn = 0; chn < channels; chn++)
|
||||
delete[] channelBuffers[chn];
|
||||
delete[] channelBuffers;
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,11 +106,11 @@ public:
|
|||
: ImportFileHandle(filename),
|
||||
mFile(std::move(file)),
|
||||
mVorbisFile(std::move(vorbisFile))
|
||||
, mStreamUsage{ static_cast<size_t>(mVorbisFile->links) }
|
||||
{
|
||||
mFormat = (sampleFormat)
|
||||
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
|
||||
mStreamUsage = new int[mVorbisFile->links];
|
||||
for (int i = 0; i < mVorbisFile->links; i++)
|
||||
{
|
||||
wxString strinfo;
|
||||
|
@ -153,7 +153,7 @@ private:
|
|||
std::unique_ptr<wxFFile> mFile;
|
||||
std::unique_ptr<OggVorbis_File> mVorbisFile;
|
||||
|
||||
int *mStreamUsage;
|
||||
ArrayOf<int> mStreamUsage;
|
||||
wxArrayString mStreamInfo;
|
||||
std::list<TrackHolders> mChannels;
|
||||
|
||||
|
@ -243,7 +243,7 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
mChannels.resize(mVorbisFile->links);
|
||||
|
||||
int i = -1;
|
||||
for (auto &link: mChannels)
|
||||
for (auto &link : mChannels)
|
||||
{
|
||||
++i;
|
||||
|
||||
|
@ -259,7 +259,7 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
|
||||
link.resize(vi->channels);
|
||||
|
||||
int c = - 1;
|
||||
int c = -1;
|
||||
for (auto &channel : link) {
|
||||
++c;
|
||||
|
||||
|
@ -267,13 +267,13 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
|
||||
if (vi->channels == 2) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
channel->SetChannel(Track::LeftChannel);
|
||||
channel->SetLinked(true);
|
||||
break;
|
||||
case 1:
|
||||
channel->SetChannel(Track::RightChannel);
|
||||
break;
|
||||
case 0:
|
||||
channel->SetChannel(Track::LeftChannel);
|
||||
channel->SetLinked(true);
|
||||
break;
|
||||
case 1:
|
||||
channel->SetChannel(Track::RightChannel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -282,88 +282,88 @@ ProgressResult OggImportFileHandle::Import(TrackFactory *trackFactory, TrackHold
|
|||
}
|
||||
}
|
||||
|
||||
/* The number of bytes to get from the codec in each run */
|
||||
#define CODEC_TRANSFER_SIZE 4096
|
||||
/* The number of bytes to get from the codec in each run */
|
||||
#define CODEC_TRANSFER_SIZE 4096u
|
||||
|
||||
/* The number of samples to read between calls to the callback.
|
||||
* Balance between responsiveness of the GUI and throughput of import. */
|
||||
/* The number of samples to read between calls to the callback.
|
||||
* Balance between responsiveness of the GUI and throughput of import. */
|
||||
#define SAMPLES_PER_CALLBACK 100000
|
||||
|
||||
short *mainBuffer = new short[CODEC_TRANSFER_SIZE];
|
||||
|
||||
/* determine endianness (clever trick courtesy of Nicholas Devillard,
|
||||
* (http://www.eso.org/~ndevilla/endian/) */
|
||||
int testvar = 1, endian;
|
||||
if(*(char *)&testvar)
|
||||
endian = 0; // little endian
|
||||
else
|
||||
endian = 1; // big endian
|
||||
|
||||
/* number of samples currently in each channel's buffer */
|
||||
auto updateResult = ProgressResult::Success;
|
||||
long bytesRead = 0;
|
||||
long samplesRead = 0;
|
||||
int bitstream = 0;
|
||||
int samplesSinceLastCallback = 0;
|
||||
{
|
||||
ArrayOf<short> mainBuffer{ CODEC_TRANSFER_SIZE };
|
||||
|
||||
// You would think that the stream would already be seeked to 0, and
|
||||
// indeed it is if the file is legit. But I had several ogg files on
|
||||
// my hard drive that have malformed headers, and this added call
|
||||
// causes them to be read correctly. Otherwise they have lots of
|
||||
// zeros inserted at the beginning
|
||||
ov_pcm_seek(mVorbisFile.get(), 0);
|
||||
/* determine endianness (clever trick courtesy of Nicholas Devillard,
|
||||
* (http://www.eso.org/~ndevilla/endian/) */
|
||||
int testvar = 1, endian;
|
||||
if (*(char *)&testvar)
|
||||
endian = 0; // little endian
|
||||
else
|
||||
endian = 1; // big endian
|
||||
|
||||
do {
|
||||
/* get data from the decoder */
|
||||
bytesRead = ov_read(mVorbisFile.get(), (char *) mainBuffer,
|
||||
CODEC_TRANSFER_SIZE,
|
||||
endian,
|
||||
2, // word length (2 for 16 bit samples)
|
||||
1, // signed
|
||||
&bitstream);
|
||||
/* number of samples currently in each channel's buffer */
|
||||
long samplesRead = 0;
|
||||
int bitstream = 0;
|
||||
int samplesSinceLastCallback = 0;
|
||||
|
||||
if (bytesRead == OV_HOLE) {
|
||||
wxFileName ff(mFilename);
|
||||
wxLogError(wxT("Ogg Vorbis importer: file %s is malformed, ov_read() reported a hole"),
|
||||
ff.GetFullName().c_str());
|
||||
/* http://lists.xiph.org/pipermail/vorbis-dev/2001-February/003223.html
|
||||
* is the justification for doing this - best effort for malformed file,
|
||||
* hence the message.
|
||||
*/
|
||||
continue;
|
||||
} else if (bytesRead < 0) {
|
||||
/* Malformed Ogg Vorbis file. */
|
||||
/* TODO: Return some sort of meaningful error. */
|
||||
wxLogError(wxT("Ogg Vorbis importer: ov_read() returned error %i"),
|
||||
bytesRead);
|
||||
break;
|
||||
}
|
||||
// You would think that the stream would already be seeked to 0, and
|
||||
// indeed it is if the file is legit. But I had several ogg files on
|
||||
// my hard drive that have malformed headers, and this added call
|
||||
// causes them to be read correctly. Otherwise they have lots of
|
||||
// zeros inserted at the beginning
|
||||
ov_pcm_seek(mVorbisFile.get(), 0);
|
||||
|
||||
samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short);
|
||||
do {
|
||||
/* get data from the decoder */
|
||||
bytesRead = ov_read(mVorbisFile.get(), (char *)mainBuffer.get(),
|
||||
CODEC_TRANSFER_SIZE,
|
||||
endian,
|
||||
2, // word length (2 for 16 bit samples)
|
||||
1, // signed
|
||||
&bitstream);
|
||||
|
||||
/* give the data to the wavetracks */
|
||||
auto iter = mChannels.begin();
|
||||
std::advance(iter, bitstream);
|
||||
if (mStreamUsage[bitstream] != 0)
|
||||
{
|
||||
auto iter2 = iter->begin();
|
||||
for (int c = 0; c < mVorbisFile->vi[bitstream].channels; ++iter2, ++c)
|
||||
iter2->get()->Append((char *)(mainBuffer + c),
|
||||
int16Sample,
|
||||
samplesRead,
|
||||
mVorbisFile->vi[bitstream].channels);
|
||||
}
|
||||
if (bytesRead == OV_HOLE) {
|
||||
wxFileName ff(mFilename);
|
||||
wxLogError(wxT("Ogg Vorbis importer: file %s is malformed, ov_read() reported a hole"),
|
||||
ff.GetFullName().c_str());
|
||||
/* http://lists.xiph.org/pipermail/vorbis-dev/2001-February/003223.html
|
||||
* is the justification for doing this - best effort for malformed file,
|
||||
* hence the message.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
else if (bytesRead < 0) {
|
||||
/* Malformed Ogg Vorbis file. */
|
||||
/* TODO: Return some sort of meaningful error. */
|
||||
wxLogError(wxT("Ogg Vorbis importer: ov_read() returned error %i"),
|
||||
bytesRead);
|
||||
break;
|
||||
}
|
||||
|
||||
samplesSinceLastCallback += samplesRead;
|
||||
if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
|
||||
updateResult = mProgress->Update(ov_time_tell(mVorbisFile.get()),
|
||||
ov_time_total(mVorbisFile.get(), bitstream));
|
||||
samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;
|
||||
samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short);
|
||||
|
||||
}
|
||||
} while (updateResult == ProgressResult::Success && bytesRead != 0);
|
||||
/* give the data to the wavetracks */
|
||||
auto iter = mChannels.begin();
|
||||
std::advance(iter, bitstream);
|
||||
if (mStreamUsage[bitstream] != 0)
|
||||
{
|
||||
auto iter2 = iter->begin();
|
||||
for (int c = 0; c < mVorbisFile->vi[bitstream].channels; ++iter2, ++c)
|
||||
iter2->get()->Append((char *)(mainBuffer.get() + c),
|
||||
int16Sample,
|
||||
samplesRead,
|
||||
mVorbisFile->vi[bitstream].channels);
|
||||
}
|
||||
|
||||
delete[]mainBuffer;
|
||||
samplesSinceLastCallback += samplesRead;
|
||||
if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) {
|
||||
updateResult = mProgress->Update(ov_time_tell(mVorbisFile.get()),
|
||||
ov_time_total(mVorbisFile.get(), bitstream));
|
||||
samplesSinceLastCallback -= SAMPLES_PER_CALLBACK;
|
||||
}
|
||||
} while (updateResult == ProgressResult::Success && bytesRead != 0);
|
||||
}
|
||||
|
||||
auto res = updateResult;
|
||||
if (bytesRead < 0)
|
||||
|
@ -406,7 +406,6 @@ OggImportFileHandle::~OggImportFileHandle()
|
|||
ov_clear(mVorbisFile.get());
|
||||
mFile->Detach(); // so that it doesn't try to close the file (ov_clear()
|
||||
// did that already)
|
||||
delete[] mStreamUsage;
|
||||
}
|
||||
|
||||
#endif /* USE_LIBVORBIS */
|
||||
|
|
|
@ -87,7 +87,7 @@ class ImportRawDialog final : public wxDialogWrapper {
|
|||
wxTextCtrl *mRateText;
|
||||
|
||||
int mNumEncodings;
|
||||
int *mEncodingSubtype;
|
||||
ArrayOf<int> mEncodingSubtype;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
@ -340,7 +340,7 @@ ImportRawDialog::ImportRawDialog(wxWindow * parent,
|
|||
|
||||
num = sf_num_encodings();
|
||||
mNumEncodings = 0;
|
||||
mEncodingSubtype = new int[num];
|
||||
mEncodingSubtype.reinit(static_cast<size_t>(num));
|
||||
|
||||
selection = 0;
|
||||
for (i=0; i<num; i++) {
|
||||
|
@ -464,7 +464,6 @@ ImportRawDialog::ImportRawDialog(wxWindow * parent,
|
|||
|
||||
ImportRawDialog::~ImportRawDialog()
|
||||
{
|
||||
delete[] mEncodingSubtype;
|
||||
}
|
||||
|
||||
void ImportRawDialog::OnOK(wxCommandEvent & WXUNUSED(event))
|
||||
|
|
|
@ -26,23 +26,14 @@ measurements in subbands or in the entire signal band.
|
|||
|
||||
SpecPowerMeter::SpecPowerMeter(size_t sigLen)
|
||||
: mSigLen(sigLen)
|
||||
, mSigI{ sigLen, true }
|
||||
, mSigFR{ sigLen }
|
||||
, mSigFI{ sigLen }
|
||||
{
|
||||
|
||||
// Init buffers
|
||||
mSigI = new float[sigLen];
|
||||
mSigFR = new float[sigLen];
|
||||
mSigFI = new float[sigLen];
|
||||
for (int n = 0; n < sigLen; n++)
|
||||
{
|
||||
mSigI[n] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
SpecPowerMeter::~SpecPowerMeter()
|
||||
{
|
||||
delete[] mSigI;
|
||||
delete[] mSigFR;
|
||||
delete[] mSigFI;
|
||||
}
|
||||
|
||||
float SpecPowerMeter::CalcPower(float* sig, float fc, float bw)
|
||||
|
@ -59,10 +50,10 @@ float SpecPowerMeter::CalcPower(float* sig, float fc, float bw)
|
|||
}
|
||||
|
||||
// Calc the FFT
|
||||
FFT(mSigLen, 0, sig, mSigI, mSigFR, mSigFI);
|
||||
FFT(mSigLen, 0, sig, mSigI.get(), mSigFR.get(), mSigFI.get());
|
||||
|
||||
// Calc the in-band power
|
||||
pwr = CalcBinPower(mSigFR, mSigFI, loBin, hiBin);
|
||||
pwr = CalcBinPower(mSigFR.get(), mSigFI.get(), loBin, hiBin);
|
||||
|
||||
return pwr;
|
||||
}
|
||||
|
|
|
@ -12,14 +12,15 @@
|
|||
#define __AUDACITY_SPECPOWERMETER_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
class SpecPowerMeter
|
||||
{
|
||||
const size_t mSigLen;
|
||||
|
||||
float* mSigI;
|
||||
float* mSigFR;
|
||||
float* mSigFI;
|
||||
Floats mSigI;
|
||||
Floats mSigFR;
|
||||
Floats mSigFI;
|
||||
|
||||
float CalcBinPower(float* sig_f_r, float* sig_f_i, int loBin, int hiBin);
|
||||
int Freq2Bin(float fc);
|
||||
|
|
|
@ -124,7 +124,7 @@ FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *fra
|
|||
|
||||
mDecoder->mDecodeBufferWritePosition+=bytesToCopy;
|
||||
/*
|
||||
short *tmp=new short[frame->header.blocksize];
|
||||
ArrayOf<short> tmp{ frame->header.blocksize };
|
||||
|
||||
for (unsigned int chn=0; chn<mDecoder->mNumChannels; chn++) {
|
||||
if (frame->header.bits_per_sample == 16) {
|
||||
|
@ -132,7 +132,7 @@ FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *fra
|
|||
tmp[s]=buffer[chn][s];
|
||||
}
|
||||
|
||||
mDecoder->mChannels[chn]->Append((samplePtr)tmp,
|
||||
mDecoder->mChannels[chn]->Append((samplePtr)tmp.get(),
|
||||
int16Sample,
|
||||
frame->header.blocksize);
|
||||
}
|
||||
|
@ -142,8 +142,6 @@ FLAC__StreamDecoderWriteStatus ODFLACFile::write_callback(const FLAC__Frame *fra
|
|||
frame->header.blocksize);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] tmp;
|
||||
*/
|
||||
|
||||
mDecoder->mSamplesDone += frame->header.blocksize;
|
||||
|
|
|
@ -352,18 +352,9 @@ void SpectrogramSettings::DestroyWindows()
|
|||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
}
|
||||
if (window != NULL) {
|
||||
delete[] window;
|
||||
window = NULL;
|
||||
}
|
||||
if (dWindow != NULL) {
|
||||
delete[] dWindow;
|
||||
dWindow = NULL;
|
||||
}
|
||||
if (tWindow != NULL) {
|
||||
delete[] tWindow;
|
||||
tWindow = NULL;
|
||||
}
|
||||
window.reset();
|
||||
dWindow.reset();
|
||||
tWindow.reset();
|
||||
}
|
||||
|
||||
|
||||
|
@ -371,13 +362,11 @@ namespace
|
|||
{
|
||||
enum { WINDOW, TWINDOW, DWINDOW };
|
||||
void RecreateWindow(
|
||||
float *&window, int which, size_t fftLen,
|
||||
Floats &window, int which, size_t fftLen,
|
||||
size_t padding, int windowType, size_t windowSize, double &scale)
|
||||
{
|
||||
if (window != NULL)
|
||||
delete[] window;
|
||||
// Create the requested window function
|
||||
window = new float[fftLen];
|
||||
window = Floats{ fftLen };
|
||||
int ii;
|
||||
|
||||
const bool extra = padding > 0;
|
||||
|
@ -397,16 +386,15 @@ namespace
|
|||
// Overwrite middle as needed
|
||||
switch (which) {
|
||||
case WINDOW:
|
||||
NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
NewWindowFunc(windowType, windowSize, extra, window.get() + padding);
|
||||
break;
|
||||
// Future, reassignment
|
||||
case TWINDOW:
|
||||
NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
NewWindowFunc(windowType, windowSize, extra, window.get() + padding);
|
||||
for (int ii = padding, multiplier = -(int)windowSize / 2; ii < endOfWindow; ++ii, ++multiplier)
|
||||
window[ii] *= multiplier;
|
||||
break;
|
||||
case DWINDOW:
|
||||
DerivativeOfWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
DerivativeOfWindowFunc(windowType, windowSize, extra, window.get() + padding);
|
||||
break;
|
||||
default:
|
||||
wxASSERT(false);
|
||||
|
|
|
@ -12,6 +12,7 @@ Paul Licameli
|
|||
#define __AUDACITY_SPECTROGRAM_SETTINGS__
|
||||
|
||||
#include "../Experimental.h"
|
||||
#include "../SampleFormat.h"
|
||||
|
||||
#undef SPECTRAL_SELECTION_GLOBAL_SWITCH
|
||||
|
||||
|
@ -153,10 +154,10 @@ public:
|
|||
|
||||
// Variables used for computing the spectrum
|
||||
mutable FFTParam *hFFT{};
|
||||
mutable float *window{};
|
||||
mutable Floats window;
|
||||
|
||||
// Two other windows for computing reassigned spectrogram
|
||||
mutable float *tWindow{}; // Window times time parameter
|
||||
mutable float *dWindow{}; // Derivative of window
|
||||
mutable Floats tWindow; // Window times time parameter
|
||||
mutable Floats dWindow; // Derivative of window
|
||||
};
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue