1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-10 17:11:17 +02:00

Various precautions, efficiencies, fixes of unreported bugs

This commit is contained in:
Paul Licameli 2017-03-09 09:29:51 -05:00
commit 3d29ba12a6
25 changed files with 170 additions and 128 deletions

View File

@ -914,13 +914,12 @@ void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event))
// find which project owns the blockfile // find which project owns the blockfile
// note: there may be more than 1, but just go with the first one. // note: there may be more than 1, but just go with the first one.
//size_t numProjects = gAudacityProjects.size(); //size_t numProjects = gAudacityProjects.size();
AudacityProject *offendingProject {}; AProjectHolder offendingProject;
wxString missingFileName; wxString missingFileName;
{ {
ODLocker locker { &m_LastMissingBlockFileLock }; ODLocker locker { &m_LastMissingBlockFileLock };
offendingProject = offendingProject = m_LastMissingBlockFileProject.lock();
AProjectHolder{ m_LastMissingBlockFileProject }.get();
missingFileName = m_LastMissingBlockFilePath; missingFileName = m_LastMissingBlockFilePath;
} }
@ -944,7 +943,7 @@ locations of the missing files."), missingFileName.c_str());
if (offendingProject->GetMissingAliasFileDialog()) { if (offendingProject->GetMissingAliasFileDialog()) {
offendingProject->GetMissingAliasFileDialog()->Raise(); offendingProject->GetMissingAliasFileDialog()->Raise();
} else { } else {
ShowAliasMissingDialog(offendingProject, _("Files Missing"), ShowAliasMissingDialog(offendingProject.get(), _("Files Missing"),
errorMessage, wxT(""), true); errorMessage, wxT(""), true);
} }
} }

View File

@ -354,12 +354,12 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
srand(randSeed); srand(randSeed);
int nChunks, chunkSize; size_t nChunks, chunkSize;
//chunkSize = 7500 + (rand() % 1000); //chunkSize = 7500 + (rand() % 1000);
chunkSize = 200 + (rand() % 100); chunkSize = 200 + (rand() % 100);
nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short)); nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short));
while(nChunks < 20 || chunkSize > (blockSize*1024)/4) { while(nChunks < 20 || chunkSize > ((unsigned long)(blockSize)*1024)/4) {
chunkSize = (chunkSize / 2) + (rand() % 100); chunkSize = std::max( size_t(1), (chunkSize / 2) + (rand() % 100) );
nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short)); nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short));
} }
@ -374,7 +374,6 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
int trials = numEdits; int trials = numEdits;
short *small1 = new short[nChunks]; short *small1 = new short[nChunks];
short *small2 = new short[nChunks];
short *block = new short[chunkSize]; short *block = new short[chunkSize];
Printf(wxT("Preparing...\n")); Printf(wxT("Preparing...\n"));
@ -416,8 +415,13 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
timer.Start(); timer.Start();
for (z = 0; z < trials; z++) { for (z = 0; z < trials; z++) {
int x0 = rand() % nChunks; // First chunk to cut
int xlen = 1 + (rand() % (nChunks - x0)); // 0 <= x0 < nChunks
const size_t x0 = rand() % nChunks;
// Number of chunks to cut
// 1 <= xlen <= nChunks - x0
const size_t xlen = 1 + (rand() % (nChunks - x0));
if (mEditDetail) if (mEditDetail)
Printf(wxT("Cut: %d - %d \n"), x0 * chunkSize, (x0 + xlen) * chunkSize); Printf(wxT("Cut: %d - %d \n"), x0 * chunkSize, (x0 + xlen) * chunkSize);
@ -431,7 +435,10 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
goto fail; goto fail;
} }
int y0 = rand() % (nChunks - xlen); // Position to paste
// 0 <= y0 <= nChunks - xlen
const size_t y0 = rand() % (nChunks - xlen + 1);
if (mEditDetail) if (mEditDetail)
Printf(wxT("Paste: %d\n"), y0 * chunkSize); Printf(wxT("Paste: %d\n"), y0 * chunkSize);
@ -447,18 +454,12 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
t->GetClipByIndex(0)->GetSequence()->GetNumSamples().as_long_long()); t->GetClipByIndex(0)->GetSequence()->GetNumSamples().as_long_long());
goto fail; goto fail;
} }
// Copy
for (i = 0; i < xlen; i++) // Permute small1 correspondingly to the cut and paste
small2[i] = small1[x0 + i]; auto first = &small1[0];
// Delete if (x0 + xlen < nChunks)
for (i = 0; i < (nChunks - x0 - xlen); i++) std::rotate( first + x0, first + x0 + xlen, first + nChunks );
small1[x0 + i] = small1[x0 + xlen + i]; std::rotate( first + y0, first + nChunks - xlen, first + nChunks );
// Insert
for (i = 0; i < (nChunks - xlen - y0); i++)
small1[nChunks - i - 1] = small1[nChunks - i - 1 - xlen];
// Paste
for (i = 0; i < xlen; i++)
small1[y0 + i] = small2[i];
} }
elapsed = timer.Time(); elapsed = timer.Time();
@ -534,7 +535,6 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
success: success:
delete[]small1; delete[]small1;
delete[]small2;
delete[]block; delete[]block;
dd.reset(); dd.reset();

View File

@ -266,6 +266,10 @@ void LabelTrack::WarpLabels(const TimeWarper &warper) {
warper.Warp(labelStruct.getT0()), warper.Warp(labelStruct.getT0()),
warper.Warp(labelStruct.getT1())); warper.Warp(labelStruct.getT1()));
} }
// This should not be needed, assuming the warper is nondecreasing, but
// let's not assume too much.
SortLabels();
} }
void LabelTrack::ResetFlags() void LabelTrack::ResetFlags()

View File

@ -136,9 +136,9 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
mixRight = trackFactory->NewWaveTrack(format, rate); mixRight = trackFactory->NewWaveTrack(format, rate);
if (oneinput) { if (oneinput) {
if (usefulIter.First()->GetLink() != NULL) // we have linked track if (usefulIter.First()->GetLink() != NULL) // we have linked track
mixLeft->SetName(usefulIter.First()->GetLink()->GetName()); /* set name to match input track's right channel!*/ mixRight->SetName(usefulIter.First()->GetLink()->GetName()); /* set name to match input track's right channel!*/
else else
mixLeft->SetName(usefulIter.First()->GetName()); /* set name to that of sole input channel */ mixRight->SetName(usefulIter.First()->GetName()); /* set name to that of sole input channel */
} }
else else
mixRight->SetName(_("Mix")); mixRight->SetName(_("Mix"));
@ -456,7 +456,10 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
if (getLen > 0) { if (getLen > 0) {
if (backwards) { if (backwards) {
auto results = cache.Get(floatSample, *pos - (getLen - 1), getLen); auto results = cache.Get(floatSample, *pos - (getLen - 1), getLen);
memcpy(&queue[*queueLen], results, sizeof(float) * getLen); if (results)
memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
else
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
track->GetEnvelopeValues(mEnvValues, track->GetEnvelopeValues(mEnvValues,
getLen, getLen,
@ -465,7 +468,10 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
} }
else { else {
auto results = cache.Get(floatSample, *pos, getLen); auto results = cache.Get(floatSample, *pos, getLen);
memcpy(&queue[*queueLen], results, sizeof(float) * getLen); if (results)
memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
else
memset(&queue[*queueLen], 0, sizeof(float) * getLen);
track->GetEnvelopeValues(mEnvValues, track->GetEnvelopeValues(mEnvValues,
getLen, getLen,
@ -571,7 +577,10 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
if (backwards) { if (backwards) {
auto results = cache.Get(floatSample, *pos - (slen - 1), slen); auto results = cache.Get(floatSample, *pos - (slen - 1), slen);
memcpy(mFloatBuffer, results, sizeof(float) * slen); if (results)
memcpy(mFloatBuffer, results, sizeof(float) * slen);
else
memset(mFloatBuffer, 0, sizeof(float) * slen);
track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate); track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate);
for(decltype(slen) i = 0; i < slen; i++) for(decltype(slen) i = 0; i < slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here? mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
@ -581,7 +590,10 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
} }
else { else {
auto results = cache.Get(floatSample, *pos, slen); auto results = cache.Get(floatSample, *pos, slen);
memcpy(mFloatBuffer, results, sizeof(float) * slen); if (results)
memcpy(mFloatBuffer, results, sizeof(float) * slen);
else
memset(mFloatBuffer, 0, sizeof(float) * slen);
track->GetEnvelopeValues(mEnvValues, slen, t); track->GetEnvelopeValues(mEnvValues, slen, t);
for(decltype(slen) i = 0; i < slen; i++) for(decltype(slen) i = 0; i < slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here? mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?

View File

@ -110,7 +110,6 @@ Track(projDirManager)
SetName(GetDefaultName()); SetName(GetDefaultName());
mSeq = NULL; mSeq = NULL;
mSerializationBuffer = NULL;
mSerializationLength = 0; mSerializationLength = 0;
#ifdef EXPERIMENTAL_MIDI_OUT #ifdef EXPERIMENTAL_MIDI_OUT
@ -125,9 +124,6 @@ Track(projDirManager)
NoteTrack::~NoteTrack() NoteTrack::~NoteTrack()
{ {
if (mSerializationBuffer) {
delete [] mSerializationBuffer;
}
} }
Track::Holder NoteTrack::Duplicate() const Track::Holder NoteTrack::Duplicate() const
@ -143,13 +139,15 @@ Track::Holder NoteTrack::Duplicate() const
SonifyBeginSerialize(); SonifyBeginSerialize();
assert(!mSerializationBuffer); assert(!mSerializationBuffer);
// serialize from this to duplicate's mSerializationBuffer // serialize from this to duplicate's mSerializationBuffer
mSeq->serialize((void**)&duplicate->mSerializationBuffer, void *buffer;
mSeq->serialize(&buffer,
&duplicate->mSerializationLength); &duplicate->mSerializationLength);
duplicate->mSerializationBuffer.reset( (char*)buffer );
SonifyEndSerialize(); SonifyEndSerialize();
} else if (mSerializationBuffer) { } else if (mSerializationBuffer) {
SonifyBeginUnserialize(); SonifyBeginUnserialize();
assert(!mSeq); assert(!mSeq);
std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(mSerializationBuffer, std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(mSerializationBuffer.get(),
mSerializationLength) }; mSerializationLength) };
assert(alg_track->get_type() == 's'); assert(alg_track->get_type() == 's');
duplicate->mSeq.reset(static_cast<Alg_seq*>(alg_track.release())); duplicate->mSeq.reset(static_cast<Alg_seq*>(alg_track.release()));
@ -198,9 +196,8 @@ void NoteTrack::WarpAndTransposeNotes(double t0, double t1,
const auto nt = static_cast<NoteTrack*>(unt.get()); const auto nt = static_cast<NoteTrack*>(unt.get());
wxASSERT(!mSeq && nt->mSeq && !nt->mSerializationBuffer); wxASSERT(!mSeq && nt->mSeq && !nt->mSerializationBuffer);
// swap mSeq and Buffer between this and nt // swap mSeq and Buffer between this and nt
nt->mSerializationBuffer = mSerializationBuffer; nt->mSerializationBuffer = std::move(mSerializationBuffer);
nt->mSerializationLength = mSerializationLength; nt->mSerializationLength = mSerializationLength;
mSerializationBuffer = NULL;
mSerializationLength = 0; mSerializationLength = 0;
mSeq = std::move(nt->mSeq); mSeq = std::move(nt->mSeq);
} }

View File

@ -198,7 +198,7 @@ class AUDACITY_DLL_API NoteTrack final : public Track {
// mSeq variable. (TrackArtist should check to make sure this // mSeq variable. (TrackArtist should check to make sure this
// flip-flop from mSeq to mSerializationBuffer happened an // flip-flop from mSeq to mSerializationBuffer happened an
// even number of times, otherwise mSeq will be NULL). // even number of times, otherwise mSeq will be NULL).
mutable char *mSerializationBuffer; // NULL means no buffer mutable std::unique_ptr<char[]> mSerializationBuffer; // NULL means no buffer
long mSerializationLength; long mSerializationLength;
#ifdef EXPERIMENTAL_MIDI_OUT #ifdef EXPERIMENTAL_MIDI_OUT

View File

@ -2829,12 +2829,11 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
// JKC: Previously this indirected via seq->, a NULL pointer. // JKC: Previously this indirected via seq->, a NULL pointer.
// This was actually OK, since unserialize is a static function. // This was actually OK, since unserialize is a static function.
// Alg_seq:: is clearer. // Alg_seq:: is clearer.
std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(track->mSerializationBuffer, std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(track->mSerializationBuffer.get(),
track->mSerializationLength) }; track->mSerializationLength) };
assert(alg_track->get_type() == 's'); assert(alg_track->get_type() == 's');
const_cast<NoteTrack*>(track)->mSeq.reset(seq = static_cast<Alg_seq*>(alg_track.release())); const_cast<NoteTrack*>(track)->mSeq.reset(seq = static_cast<Alg_seq*>(alg_track.release()));
free(track->mSerializationBuffer); track->mSerializationBuffer.reset();
track->mSerializationBuffer = NULL;
} }
assert(seq); assert(seq);
int visibleChannels = track->mVisibleChannels; int visibleChannels = track->mVisibleChannels;

View File

@ -854,12 +854,16 @@ bool SpecCache::CalculateOneSpectrum
myLen) myLen)
); );
if (copy) if (copy) {
memcpy(adj, useBuffer, myLen * sizeof(float)); if (useBuffer)
memcpy(adj, useBuffer, myLen * sizeof(float));
else
memset(adj, 0, myLen * sizeof(float));
}
} }
} }
if (copy) if (copy || !useBuffer)
useBuffer = scratch; useBuffer = scratch;
if (autocorrelation) { if (autocorrelation) {

View File

@ -2661,9 +2661,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
// Request starts in the second buffer and extends past it. // Request starts in the second buffer and extends past it.
// Discard the first buffer. // Discard the first buffer.
// (But don't deallocate the buffer space.) // (But don't deallocate the buffer space.)
float *save = mBuffers[0].data; mBuffers[0] .swap ( mBuffers[1] );
mBuffers[0] = mBuffers[1];
mBuffers[1].data = save;
fillSecond = true; fillSecond = true;
mNValidBuffers = 1; mNValidBuffers = 1;
} }
@ -2678,9 +2676,7 @@ constSamplePtr WaveTrackCache::Get(sampleFormat format,
// refill the first. // refill the first.
// (This case might be useful when marching backwards through // (This case might be useful when marching backwards through
// the track, as with scrubbing.) // the track, as with scrubbing.)
float *save = mBuffers[1].data; mBuffers[0] .swap ( mBuffers[1] );
mBuffers[1] = mBuffers[0];
mBuffers[0].data = save;
fillFirst = true; fillFirst = true;
fillSecond = false; fillSecond = false;
// Cache is not in a consistent state yet // Cache is not in a consistent state yet

View File

@ -646,6 +646,13 @@ private:
Buffer() : data(0), start(0), len(0) {} Buffer() : data(0), start(0), len(0) {}
void Free() { delete[] data; data = 0; start = 0; len = 0; } void Free() { delete[] data; data = 0; start = 0; len = 0; }
sampleCount end() const { return start + len; } sampleCount end() const { return start + len; }
void swap ( Buffer &other )
{
std::swap( data, other.data );
std::swap( start, other.start );
std::swap( len, other.len );
}
}; };
const WaveTrack *mPTrack; const WaveTrack *mPTrack;

View File

@ -680,7 +680,8 @@ bool Effect::HideUI()
bool Effect::CloseUI() bool Effect::CloseUI()
{ {
mUIParent->RemoveEventHandler(this); if (mUIParent)
mUIParent->RemoveEventHandler(this);
mUIParent = NULL; mUIParent = NULL;
mUIDialog = NULL; mUIDialog = NULL;

View File

@ -194,7 +194,9 @@ bool EffectNormalize::Process()
else else
msg = topMsg + _("Analyzing first track of stereo pair: ") + trackName; msg = topMsg + _("Analyzing first track of stereo pair: ") + trackName;
float offset, min, max; float offset, min, max;
AnalyseTrack(track, msg, curTrackNum, offset, min, max); if (! ( bGoodResult =
AnalyseTrack(track, msg, curTrackNum, offset, min, max) ) )
break;
if(!track->GetLinked() || mStereoInd) { if(!track->GetLinked() || mStereoInd) {
// mono or 'stereo tracks independently' // mono or 'stereo tracks independently'
float extent = wxMax(fabs(max), fabs(min)); float extent = wxMax(fabs(max), fabs(min));
@ -220,7 +222,9 @@ bool EffectNormalize::Process()
track = (WaveTrack *) iter.Next(); // get the next one track = (WaveTrack *) iter.Next(); // get the next one
msg = topMsg + _("Analyzing second track of stereo pair: ") + trackName; msg = topMsg + _("Analyzing second track of stereo pair: ") + trackName;
float offset2, min2, max2; float offset2, min2, max2;
AnalyseTrack(track, msg, curTrackNum + 1, offset2, min2, max2); if ( ! ( bGoodResult =
AnalyseTrack(track, msg, curTrackNum + 1, offset2, min2, max2) ) )
break;
float extent = wxMax(fabs(min), fabs(max)); float extent = wxMax(fabs(min), fabs(max));
extent = wxMax(extent, fabs(min2)); extent = wxMax(extent, fabs(min2));
extent = wxMax(extent, fabs(max2)); extent = wxMax(extent, fabs(max2));
@ -325,7 +329,7 @@ bool EffectNormalize::TransferDataFromWindow()
// EffectNormalize implementation // EffectNormalize implementation
void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg, bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
int curTrackNum, int curTrackNum,
float &offset, float &min, float &max) float &offset, float &min, float &max)
{ {
@ -334,7 +338,9 @@ void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
// TODO: should we restrict the flags to just the relevant block files (for selections) // TODO: should we restrict the flags to just the relevant block files (for selections)
while (track->GetODFlags()) { while (track->GetODFlags()) {
// update the gui // update the gui
mProgress->Update(0, wxT("Waiting for waveform to finish computing...")); if (ProgressResult::Cancelled == mProgress->Update(
0, wxT("Waiting for waveform to finish computing...")) )
return false;
wxMilliSleep(100); wxMilliSleep(100);
} }
@ -344,11 +350,13 @@ void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
} }
if(mDC) { if(mDC) {
AnalyseDC(track, msg, curTrackNum, offset); auto rc = AnalyseDC(track, msg, curTrackNum, offset);
min += offset; min += offset;
max += offset; max += offset;
return rc;
} else { } else {
offset = 0.0; offset = 0.0;
return true;
} }
} }

View File

@ -58,7 +58,7 @@ private:
bool ProcessOne( bool ProcessOne(
WaveTrack * t, const wxString &msg, int curTrackNum, float offset); WaveTrack * t, const wxString &msg, int curTrackNum, float offset);
void AnalyseTrack(const WaveTrack * track, const wxString &msg, bool AnalyseTrack(const WaveTrack * track, const wxString &msg,
int curTrackNum, int curTrackNum,
float &offset, float &min, float &max); float &offset, float &min, float &max);
void AnalyzeData(float *buffer, size_t len); void AnalyzeData(float *buffer, size_t len);

View File

@ -731,7 +731,7 @@ void LV2Effect::SetSampleRate(double rate)
{ {
LV2_Options_Option options[2]; // 2 for empty terminating option LV2_Options_Option options[2]; // 2 for empty terminating option
memset(&options, 0, sizeof(options)); memset(&options, 0, sizeof(options));
memcpy(&options, mSampleRateOption, sizeof(*mSampleRateOption)); memcpy(&options, &mOptions[mSampleRateOption], sizeof(mOptions[0]));
if (mMaster) if (mMaster)
{ {
@ -753,7 +753,7 @@ size_t LV2Effect::SetBlockSize(size_t maxBlockSize)
{ {
LV2_Options_Option options[2]; // 2 for empty terminating option LV2_Options_Option options[2]; // 2 for empty terminating option
memset(&options, 0, sizeof(options)); memset(&options, 0, sizeof(options));
memcpy(&options, mBlockSizeOption, sizeof(*mBlockSizeOption)); memcpy(&options, &mOptions[mBlockSizeOption], sizeof(mOptions[0]));
if (mMaster) if (mMaster)
{ {
@ -1342,7 +1342,7 @@ bool LV2Effect::SaveParameters(const wxString & group)
return mHost->SetPrivateConfig(group, wxT("Parameters"), parms); return mHost->SetPrivateConfig(group, wxT("Parameters"), parms);
} }
LV2_Options_Option *LV2Effect::AddOption(const char *key, uint32_t size, const char *type, void *value) size_t LV2Effect::AddOption(const char *key, uint32_t size, const char *type, void *value)
{ {
int ndx = mNumOptions; int ndx = mNumOptions;
@ -1360,7 +1360,7 @@ LV2_Options_Option *LV2Effect::AddOption(const char *key, uint32_t size, const c
mOptions[ndx].value = value; mOptions[ndx].value = value;
} }
return &mOptions[ndx]; return ndx;
} }
LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data) LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data)

View File

@ -204,7 +204,7 @@ private:
static int ui_resize(LV2UI_Feature_Handle handle, int width, int height); static int ui_resize(LV2UI_Feature_Handle handle, int width, int height);
int UIResize(int width, int height); int UIResize(int width, int height);
LV2_Options_Option *AddOption(const char *key, uint32_t size, const char *type, void *value); size_t AddOption(const char *key, uint32_t size, const char *type, void *value);
LV2_Feature *AddFeature(const char *uri, void *data); LV2_Feature *AddFeature(const char *uri, void *data);
bool BuildFancy(); bool BuildFancy();
@ -295,8 +295,8 @@ private:
LV2UI_Resize mUIResizeFeature; LV2UI_Resize mUIResizeFeature;
LV2_Extension_Data_Feature mExtDataFeature; LV2_Extension_Data_Feature mExtDataFeature;
LV2_Options_Option *mBlockSizeOption; size_t mBlockSizeOption;
LV2_Options_Option *mSampleRateOption; size_t mSampleRateOption;
LV2_Options_Interface *mOptionsInterface; LV2_Options_Interface *mOptionsInterface;
LV2_Options_Option *mOptions; LV2_Options_Option *mOptions;

View File

@ -942,7 +942,7 @@ bool NyquistEffect::ProcessOne()
float maxPeakLevel = 0.0; // Deprecated as of 2.1.3 float maxPeakLevel = 0.0; // Deprecated as of 2.1.3
wxString clips, peakString, rmsString; wxString clips, peakString, rmsString;
for (int i = 0; i < mCurNumChannels; i++) { for (size_t i = 0; i < mCurNumChannels; i++) {
auto ca = mCurTrack[i]->SortedClipArray(); auto ca = mCurTrack[i]->SortedClipArray();
float maxPeak = 0.0; float maxPeak = 0.0;
@ -1019,7 +1019,7 @@ bool NyquistEffect::ProcessOne()
nyx_set_audio_params(mCurTrack[0]->GetRate(), curLen); nyx_set_audio_params(mCurTrack[0]->GetRate(), curLen);
nyx_set_input_audio(StaticGetCallback, (void *)this, nyx_set_input_audio(StaticGetCallback, (void *)this,
mCurNumChannels, (int)mCurNumChannels,
curLen, mCurTrack[0]->GetRate()); curLen, mCurTrack[0]->GetRate());
} }
@ -1200,7 +1200,7 @@ bool NyquistEffect::ProcessOne()
} }
int outChannels = nyx_get_audio_num_channels(); int outChannels = nyx_get_audio_num_channels();
if (outChannels > mCurNumChannels) { if (outChannels > (int)mCurNumChannels) {
wxMessageBox(_("Nyquist returned too many audio channels.\n"), wxMessageBox(_("Nyquist returned too many audio channels.\n"),
wxT("Nyquist"), wxT("Nyquist"),
wxOK | wxCENTRE, mUIParent); wxOK | wxCENTRE, mUIParent);
@ -1225,7 +1225,7 @@ bool NyquistEffect::ProcessOne()
for (i = 0; i < outChannels; i++) { for (i = 0; i < outChannels; i++) {
sampleFormat format = mCurTrack[i]->GetSampleFormat(); sampleFormat format = mCurTrack[i]->GetSampleFormat();
if (outChannels == mCurNumChannels) { if (outChannels == (int)mCurNumChannels) {
rate = mCurTrack[i]->GetRate(); rate = mCurTrack[i]->GetRate();
} }
@ -1261,7 +1261,7 @@ bool NyquistEffect::ProcessOne()
for (i = 0; i < mCurNumChannels; i++) { for (i = 0; i < mCurNumChannels; i++) {
WaveTrack *out; WaveTrack *out;
if (outChannels == mCurNumChannels) { if (outChannels == (int)mCurNumChannels) {
out = mOutputTrack[i].get(); out = mOutputTrack[i].get();
} }
else { else {

View File

@ -205,7 +205,7 @@ private:
int mVersion; int mVersion;
NyqControlArray mControls; NyqControlArray mControls;
int mCurNumChannels; // See bug 1566 unsigned mCurNumChannels;
WaveTrack *mCurTrack[2]; WaveTrack *mCurTrack[2];
sampleCount mCurStart[2]; sampleCount mCurStart[2];
sampleCount mCurLen; sampleCount mCurLen;

View File

@ -933,7 +933,7 @@ ProgressResult ExportMultiple::ExportMultipleByTrack(bool byName,
} }
// Restore the selection states // Restore the selection states
for (auto pTrack : mSelected) for (auto pTrack : selected)
pTrack->SetSelected(true); pTrack->SetSelected(true);
return ok ; return ok ;

View File

@ -113,9 +113,6 @@ private:
int mNumLabels; int mNumLabels;
int mNumWaveTracks; int mNumWaveTracks;
// PRL: This is never populated anywhere?
std::vector<Track*> mSelected;
int mFilterIndex; /**< The index in the drop-down list of export int mFilterIndex; /**< The index in the drop-down list of export
formats (mFormat) of the selected export format. formats (mFormat) of the selected export format.
This list includes all possible This list includes all possible

View File

@ -451,17 +451,16 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
if (maxBlock < 1) if (maxBlock < 1)
return ProgressResult::Failed; return ProgressResult::Failed;
SampleBuffer srcbuffer; SampleBuffer srcbuffer, buffer;
wxASSERT(mInfo.channels >= 0); wxASSERT(mInfo.channels >= 0);
while (NULL == srcbuffer.Allocate(maxBlock * mInfo.channels, mFormat).ptr()) while (NULL == srcbuffer.Allocate(maxBlock * mInfo.channels, mFormat).ptr() ||
NULL == buffer.Allocate(maxBlock, mFormat).ptr())
{ {
maxBlock /= 2; maxBlock /= 2;
if (maxBlock < 1) if (maxBlock < 1)
return ProgressResult::Failed; return ProgressResult::Failed;
} }
SampleBuffer buffer(maxBlock, mFormat);
decltype(fileTotalFrames) framescompleted = 0; decltype(fileTotalFrames) framescompleted = 0;
long block; long block;

View File

@ -71,12 +71,9 @@ void ODComputeSummaryTask::DoSomeInternal()
mBlockFilesMutex.Lock(); mBlockFilesMutex.Lock();
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++) for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
{ {
const auto &bf = mBlockFiles[0]; const auto bf = mBlockFiles[0].lock();
//first check to see if the ref count is at least 2. It should have one if(bf)
//from when we added it to this instance's mBlockFiles array, and one from
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
if(bf.use_count() >= 2)
{ {
bf->DoWriteSummary(); bf->DoWriteSummary();
success = true; success = true;
@ -85,6 +82,7 @@ void ODComputeSummaryTask::DoSomeInternal()
} }
else else
{ {
// The block file disappeared.
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles //the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
//because now there is less work to do. //because now there is less work to do.
mMaxBlockFiles--; mMaxBlockFiles--;
@ -164,7 +162,7 @@ void ODComputeSummaryTask::CalculatePercentComplete()
///by default left to right, or frome the point the user has clicked. ///by default left to right, or frome the point the user has clicked.
void ODComputeSummaryTask::Update() void ODComputeSummaryTask::Update()
{ {
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > tempBlocks; std::vector< std::weak_ptr< ODPCMAliasBlockFile > > tempBlocks;
mWaveTrackMutex.Lock(); mWaveTrackMutex.Lock();
@ -207,10 +205,14 @@ void ODComputeSummaryTask::Update()
)); ));
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor. //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
while(insertCursor<(int)tempBlocks.size()&& {
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() < std::shared_ptr< ODPCMAliasBlockFile > ptr;
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset()) while(insertCursor < (int)tempBlocks.size() &&
insertCursor++; (!(ptr = tempBlocks[insertCursor].lock()) ||
ptr->GetStart() + ptr->GetClipOffset() <
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset()))
insertCursor++;
}
tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile); tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile);
} }
@ -232,7 +234,7 @@ void ODComputeSummaryTask::Update()
///Computes the summary calculation queue order of the blockfiles ///Computes the summary calculation queue order of the blockfiles
void ODComputeSummaryTask::OrderBlockFiles void ODComputeSummaryTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks) (std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
{ {
mBlockFiles.clear(); mBlockFiles.clear();
//Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs) //Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
@ -242,27 +244,29 @@ void ODComputeSummaryTask::OrderBlockFiles
//find the startpoint //find the startpoint
auto processStartSample = GetDemandSample(); auto processStartSample = GetDemandSample();
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--) std::shared_ptr< ODPCMAliasBlockFile > firstBlock;
for(auto i = unorderedBlocks.size(); i--;)
{ {
//check to see if the refcount is at least two before we add it to the list. auto ptr = unorderedBlocks[i].lock();
//There should be one Ref() from the one added by this ODTask, and one from the track. if(ptr)
//If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i].use_count() >= 2)
{ {
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference //test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
//and add ones that are closer. //and add ones that are closer.
if(mBlockFiles.size() && if(firstBlock &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample && ptr->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample || ( firstBlock->GetGlobalEnd() < processStartSample ||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) ptr->GetGlobalStart() <= firstBlock->GetGlobalStart())
) )
{ {
//insert at the front of the list if we get blockfiles that are after the demand sample //insert at the front of the list if we get blockfiles that are after the demand sample
mBlockFiles.insert(mBlockFiles.begin()+0,unorderedBlocks[i]); firstBlock = ptr;
mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
} }
else else
{ {
//otherwise no priority //otherwise no priority
if ( !firstBlock )
firstBlock = ptr;
mBlockFiles.push_back(unorderedBlocks[i]); mBlockFiles.push_back(unorderedBlocks[i]);
} }
if(mMaxBlockFiles< (int) mBlockFiles.size()) if(mMaxBlockFiles< (int) mBlockFiles.size())
@ -270,7 +274,8 @@ void ODComputeSummaryTask::OrderBlockFiles
} }
else else
{ {
//Otherwise, let it be deleted and forget about it. // The block file disappeared.
// Let it be deleted and forget about it.
} }
} }
} }

View File

@ -65,7 +65,7 @@ protected:
///Orders the input as either On-Demand or default layered order. ///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles void OrderBlockFiles
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks); (std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks);
///tells us whether or not Update has been run at least once. ///tells us whether or not Update has been run at least once.
void MarkUpdateRan(); void MarkUpdateRan();
@ -73,7 +73,7 @@ protected:
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it. //mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
ODLock mBlockFilesMutex; ODLock mBlockFilesMutex;
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles; std::vector< std::weak_ptr< ODPCMAliasBlockFile > > mBlockFiles;
int mMaxBlockFiles; int mMaxBlockFiles;
ODLock mHasUpdateRanMutex; ODLock mHasUpdateRanMutex;
bool mHasUpdateRan; bool mHasUpdateRan;

View File

@ -48,16 +48,13 @@ void ODDecodeTask::DoSomeInternal()
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++) for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
{ {
const auto &bf = mBlockFiles[0]; const auto bf = mBlockFiles[0].lock();
int ret = 1; int ret = 1;
//first check to see if the ref count is at least 2. It should have one if(bf)
//from when we added it to this instance's mBlockFiles array, and one from
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
if(bf.use_count()>=2)
{ {
//OD TODO: somehow pass the bf a reference to the decoder that manages it's file. //OD TODO: somehow pass the bf a reference to the decoder that manages its file.
//we need to ensure that the filename won't change or be moved. We do this by calling LockRead(), //we need to ensure that the filename won't change or be moved. We do this by calling LockRead(),
//which the dirmanager::EnsureSafeFilename also does. //which the dirmanager::EnsureSafeFilename also does.
bf->LockRead(); bf->LockRead();
@ -77,6 +74,7 @@ void ODDecodeTask::DoSomeInternal()
} }
else else
{ {
// The block file disappeared.
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles //the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
//because now there is less work to do. //because now there is less work to do.
mMaxBlockFiles--; mMaxBlockFiles--;
@ -123,7 +121,7 @@ bool ODDecodeTask::SeekingAllowed()
///by default creates the order of the wavetrack to load. ///by default creates the order of the wavetrack to load.
void ODDecodeTask::Update() void ODDecodeTask::Update()
{ {
std::vector< std::shared_ptr< ODDecodeBlockFile > > tempBlocks; std::vector< std::weak_ptr< ODDecodeBlockFile > > tempBlocks;
mWaveTrackMutex.Lock(); mWaveTrackMutex.Lock();
@ -162,12 +160,16 @@ void ODDecodeTask::Update()
)); ));
//these will always be linear within a sequence-lets take advantage of this by keeping a cursor. //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
while(insertCursor<(int)tempBlocks.size()&& {
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() < std::shared_ptr< ODDecodeBlockFile > ptr;
oddbFile->GetStart() + oddbFile->GetClipOffset()) while(insertCursor < (int)tempBlocks.size() &&
insertCursor++; (!(ptr = tempBlocks[insertCursor].lock()) ||
ptr->GetStart() + ptr->GetClipOffset() <
oddbFile->GetStart() + oddbFile->GetClipOffset()))
insertCursor++;
}
tempBlocks.insert(tempBlocks.begin()+insertCursor++, oddbFile); tempBlocks.insert(tempBlocks.begin() + insertCursor++, oddbFile);
} }
} }
@ -185,7 +187,7 @@ void ODDecodeTask::Update()
///Orders the input as either On-Demand or default layered order. ///Orders the input as either On-Demand or default layered order.
void ODDecodeTask::OrderBlockFiles void ODDecodeTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks) (std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks)
{ {
mBlockFiles.clear(); mBlockFiles.clear();
//TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs) //TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
@ -194,28 +196,30 @@ void ODDecodeTask::OrderBlockFiles
//find the startpoint //find the startpoint
auto processStartSample = GetDemandSample(); auto processStartSample = GetDemandSample();
for(int i= ((int)unorderedBlocks.size())-1;i>= 0;i--) std::shared_ptr< ODDecodeBlockFile > firstBlock;
for(auto i = unorderedBlocks.size(); i--; )
{ {
//check to see if the refcount is at least two before we add it to the list. auto ptr = unorderedBlocks[i].lock();
//There should be one Ref() from the one added by this ODTask, and one from the track. if(ptr)
//If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i].use_count() >= 2)
{ {
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference //test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
//and add ones that are closer. //and add ones that are closer.
//since the order is linear right to left, this will add blocks so that the ones on the right side of the target //since the order is linear right to left, this will add blocks so that the ones on the right side of the target
//are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed. //are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed.
if(mBlockFiles.size() && if(mBlockFiles.size() &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample && ptr->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample || ( firstBlock->GetGlobalEnd() < processStartSample ||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) ) ptr->GetGlobalStart() <= firstBlock->GetGlobalStart()) )
{ {
//insert at the front of the list if we get blockfiles that are after the demand sample //insert at the front of the list if we get blockfiles that are after the demand sample
mBlockFiles.insert(mBlockFiles.begin()+0,unorderedBlocks[i]); firstBlock = ptr;
mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
} }
else else
{ {
//otherwise no priority //otherwise no priority
if ( !firstBlock )
firstBlock = ptr;
mBlockFiles.push_back(unorderedBlocks[i]); mBlockFiles.push_back(unorderedBlocks[i]);
} }
if(mMaxBlockFiles< (int) mBlockFiles.size()) if(mMaxBlockFiles< (int) mBlockFiles.size())
@ -223,6 +227,7 @@ void ODDecodeTask::OrderBlockFiles
} }
else else
{ {
// The block file disappeared.
} }
} }

View File

@ -86,10 +86,10 @@ protected:
///Orders the input as either On-Demand or default layered order. ///Orders the input as either On-Demand or default layered order.
void OrderBlockFiles void OrderBlockFiles
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks); (std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks);
std::vector<std::shared_ptr<ODDecodeBlockFile>> mBlockFiles; std::vector<std::weak_ptr<ODDecodeBlockFile>> mBlockFiles;
std::vector<movable_ptr<ODFileDecoder>> mDecoders; std::vector<movable_ptr<ODFileDecoder>> mDecoders;
int mMaxBlockFiles; int mMaxBlockFiles;

View File

@ -886,7 +886,16 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
#ifdef EXPERIMENTAL_DA #ifdef EXPERIMENTAL_DA
shifted = !shifted; shifted = !shifted;
#endif #endif
if(it.First() == NULL) bool hasWave = false;
for (auto t = it.First(); t; t = it.Next()) {
if (t->GetKind() == Track::Wave) {
hasWave = true;
break;
}
}
if(!hasWave)
// Treat append-record like record, when there was no given wave track
// to append onto.
shifted = false; shifted = false;
double t0 = p->GetSel0(); double t0 = p->GetSel0();