1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-05 14:18:53 +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
// note: there may be more than 1, but just go with the first one.
//size_t numProjects = gAudacityProjects.size();
AudacityProject *offendingProject {};
AProjectHolder offendingProject;
wxString missingFileName;
{
ODLocker locker { &m_LastMissingBlockFileLock };
offendingProject =
AProjectHolder{ m_LastMissingBlockFileProject }.get();
offendingProject = m_LastMissingBlockFileProject.lock();
missingFileName = m_LastMissingBlockFilePath;
}
@ -944,7 +943,7 @@ locations of the missing files."), missingFileName.c_str());
if (offendingProject->GetMissingAliasFileDialog()) {
offendingProject->GetMissingAliasFileDialog()->Raise();
} else {
ShowAliasMissingDialog(offendingProject, _("Files Missing"),
ShowAliasMissingDialog(offendingProject.get(), _("Files Missing"),
errorMessage, wxT(""), true);
}
}

View File

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

View File

@ -266,6 +266,10 @@ void LabelTrack::WarpLabels(const TimeWarper &warper) {
warper.Warp(labelStruct.getT0()),
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()

View File

@ -136,9 +136,9 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
mixRight = trackFactory->NewWaveTrack(format, rate);
if (oneinput) {
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
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
mixRight->SetName(_("Mix"));
@ -456,7 +456,10 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
if (getLen > 0) {
if (backwards) {
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,
getLen,
@ -465,7 +468,10 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
}
else {
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,
getLen,
@ -571,7 +577,10 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
if (backwards) {
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);
for(decltype(slen) i = 0; i < slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
@ -581,7 +590,10 @@ size_t Mixer::MixSameRate(int *channelFlags, WaveTrackCache &cache,
}
else {
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);
for(decltype(slen) i = 0; i < slen; i++)
mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?

View File

@ -110,7 +110,6 @@ Track(projDirManager)
SetName(GetDefaultName());
mSeq = NULL;
mSerializationBuffer = NULL;
mSerializationLength = 0;
#ifdef EXPERIMENTAL_MIDI_OUT
@ -125,9 +124,6 @@ Track(projDirManager)
NoteTrack::~NoteTrack()
{
if (mSerializationBuffer) {
delete [] mSerializationBuffer;
}
}
Track::Holder NoteTrack::Duplicate() const
@ -143,13 +139,15 @@ Track::Holder NoteTrack::Duplicate() const
SonifyBeginSerialize();
assert(!mSerializationBuffer);
// serialize from this to duplicate's mSerializationBuffer
mSeq->serialize((void**)&duplicate->mSerializationBuffer,
void *buffer;
mSeq->serialize(&buffer,
&duplicate->mSerializationLength);
duplicate->mSerializationBuffer.reset( (char*)buffer );
SonifyEndSerialize();
} else if (mSerializationBuffer) {
SonifyBeginUnserialize();
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) };
assert(alg_track->get_type() == 's');
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());
wxASSERT(!mSeq && nt->mSeq && !nt->mSerializationBuffer);
// swap mSeq and Buffer between this and nt
nt->mSerializationBuffer = mSerializationBuffer;
nt->mSerializationBuffer = std::move(mSerializationBuffer);
nt->mSerializationLength = mSerializationLength;
mSerializationBuffer = NULL;
mSerializationLength = 0;
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
// flip-flop from mSeq to mSerializationBuffer happened an
// 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;
#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.
// This was actually OK, since unserialize is a static function.
// 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) };
assert(alg_track->get_type() == 's');
const_cast<NoteTrack*>(track)->mSeq.reset(seq = static_cast<Alg_seq*>(alg_track.release()));
free(track->mSerializationBuffer);
track->mSerializationBuffer = NULL;
track->mSerializationBuffer.reset();
}
assert(seq);
int visibleChannels = track->mVisibleChannels;

View File

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

View File

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

View File

@ -646,6 +646,13 @@ private:
Buffer() : data(0), start(0), len(0) {}
void Free() { delete[] data; data = 0; start = 0; len = 0; }
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;

View File

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

View File

@ -194,7 +194,9 @@ bool EffectNormalize::Process()
else
msg = topMsg + _("Analyzing first track of stereo pair: ") + trackName;
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) {
// mono or 'stereo tracks independently'
float extent = wxMax(fabs(max), fabs(min));
@ -220,7 +222,9 @@ bool EffectNormalize::Process()
track = (WaveTrack *) iter.Next(); // get the next one
msg = topMsg + _("Analyzing second track of stereo pair: ") + trackName;
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));
extent = wxMax(extent, fabs(min2));
extent = wxMax(extent, fabs(max2));
@ -325,7 +329,7 @@ bool EffectNormalize::TransferDataFromWindow()
// EffectNormalize implementation
void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
bool EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
int curTrackNum,
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)
while (track->GetODFlags()) {
// 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);
}
@ -344,11 +350,13 @@ void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
}
if(mDC) {
AnalyseDC(track, msg, curTrackNum, offset);
auto rc = AnalyseDC(track, msg, curTrackNum, offset);
min += offset;
max += offset;
return rc;
} else {
offset = 0.0;
return true;
}
}

View File

@ -58,7 +58,7 @@ private:
bool ProcessOne(
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,
float &offset, float &min, float &max);
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
memset(&options, 0, sizeof(options));
memcpy(&options, mSampleRateOption, sizeof(*mSampleRateOption));
memcpy(&options, &mOptions[mSampleRateOption], sizeof(mOptions[0]));
if (mMaster)
{
@ -753,7 +753,7 @@ size_t LV2Effect::SetBlockSize(size_t maxBlockSize)
{
LV2_Options_Option options[2]; // 2 for empty terminating option
memset(&options, 0, sizeof(options));
memcpy(&options, mBlockSizeOption, sizeof(*mBlockSizeOption));
memcpy(&options, &mOptions[mBlockSizeOption], sizeof(mOptions[0]));
if (mMaster)
{
@ -1342,7 +1342,7 @@ bool LV2Effect::SaveParameters(const wxString & group)
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;
@ -1360,7 +1360,7 @@ LV2_Options_Option *LV2Effect::AddOption(const char *key, uint32_t size, const c
mOptions[ndx].value = value;
}
return &mOptions[ndx];
return ndx;
}
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);
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);
bool BuildFancy();
@ -295,8 +295,8 @@ private:
LV2UI_Resize mUIResizeFeature;
LV2_Extension_Data_Feature mExtDataFeature;
LV2_Options_Option *mBlockSizeOption;
LV2_Options_Option *mSampleRateOption;
size_t mBlockSizeOption;
size_t mSampleRateOption;
LV2_Options_Interface *mOptionsInterface;
LV2_Options_Option *mOptions;

View File

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

View File

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

View File

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

View File

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

View File

@ -451,17 +451,16 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
if (maxBlock < 1)
return ProgressResult::Failed;
SampleBuffer srcbuffer;
SampleBuffer srcbuffer, buffer;
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;
if (maxBlock < 1)
return ProgressResult::Failed;
}
SampleBuffer buffer(maxBlock, mFormat);
decltype(fileTotalFrames) framescompleted = 0;
long block;

View File

@ -71,12 +71,9 @@ void ODComputeSummaryTask::DoSomeInternal()
mBlockFilesMutex.Lock();
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
//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)
if(bf)
{
bf->DoWriteSummary();
success = true;
@ -85,6 +82,7 @@ void ODComputeSummaryTask::DoSomeInternal()
}
else
{
// The block file disappeared.
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
//because now there is less work to do.
mMaxBlockFiles--;
@ -164,7 +162,7 @@ void ODComputeSummaryTask::CalculatePercentComplete()
///by default left to right, or frome the point the user has clicked.
void ODComputeSummaryTask::Update()
{
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > tempBlocks;
std::vector< std::weak_ptr< ODPCMAliasBlockFile > > tempBlocks;
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.
while(insertCursor<(int)tempBlocks.size()&&
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() <
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset())
insertCursor++;
{
std::shared_ptr< ODPCMAliasBlockFile > ptr;
while(insertCursor < (int)tempBlocks.size() &&
(!(ptr = tempBlocks[insertCursor].lock()) ||
ptr->GetStart() + ptr->GetClipOffset() <
odpcmaFile->GetStart() + odpcmaFile->GetClipOffset()))
insertCursor++;
}
tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile);
}
@ -232,7 +234,7 @@ void ODComputeSummaryTask::Update()
///Computes the summary calculation queue order of the blockfiles
void ODComputeSummaryTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
(std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
{
mBlockFiles.clear();
//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
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.
//There should be one Ref() from the one added by this ODTask, and one from the track.
//If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i].use_count() >= 2)
auto ptr = unorderedBlocks[i].lock();
if(ptr)
{
//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.
if(mBlockFiles.size() &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart())
if(firstBlock &&
ptr->GetGlobalEnd() >= processStartSample &&
( firstBlock->GetGlobalEnd() < processStartSample ||
ptr->GetGlobalStart() <= firstBlock->GetGlobalStart())
)
{
//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
{
//otherwise no priority
if ( !firstBlock )
firstBlock = ptr;
mBlockFiles.push_back(unorderedBlocks[i]);
}
if(mMaxBlockFiles< (int) mBlockFiles.size())
@ -270,7 +274,8 @@ void ODComputeSummaryTask::OrderBlockFiles
}
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.
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.
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.
ODLock mBlockFilesMutex;
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles;
std::vector< std::weak_ptr< ODPCMAliasBlockFile > > mBlockFiles;
int mMaxBlockFiles;
ODLock mHasUpdateRanMutex;
bool mHasUpdateRan;

View File

@ -48,16 +48,13 @@ void ODDecodeTask::DoSomeInternal()
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;
//first check to see if the ref count is at least 2. It should have one
//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)
if(bf)
{
//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(),
//which the dirmanager::EnsureSafeFilename also does.
bf->LockRead();
@ -77,6 +74,7 @@ void ODDecodeTask::DoSomeInternal()
}
else
{
// The block file disappeared.
//the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
//because now there is less work to do.
mMaxBlockFiles--;
@ -123,7 +121,7 @@ bool ODDecodeTask::SeekingAllowed()
///by default creates the order of the wavetrack to load.
void ODDecodeTask::Update()
{
std::vector< std::shared_ptr< ODDecodeBlockFile > > tempBlocks;
std::vector< std::weak_ptr< ODDecodeBlockFile > > tempBlocks;
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.
while(insertCursor<(int)tempBlocks.size()&&
tempBlocks[insertCursor]->GetStart() + tempBlocks[insertCursor]->GetClipOffset() <
oddbFile->GetStart() + oddbFile->GetClipOffset())
insertCursor++;
{
std::shared_ptr< ODDecodeBlockFile > ptr;
while(insertCursor < (int)tempBlocks.size() &&
(!(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.
void ODDecodeTask::OrderBlockFiles
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks)
(std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks)
{
mBlockFiles.clear();
//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
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.
//There should be one Ref() from the one added by this ODTask, and one from the track.
//If there isn't, then the block was deleted for some reason and we should ignore it.
if(unorderedBlocks[i].use_count() >= 2)
auto ptr = unorderedBlocks[i].lock();
if(ptr)
{
//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.
//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.
if(mBlockFiles.size() &&
unorderedBlocks[i]->GetGlobalEnd() >= processStartSample &&
( mBlockFiles[0]->GetGlobalEnd() < processStartSample ||
unorderedBlocks[i]->GetGlobalStart() <= mBlockFiles[0]->GetGlobalStart()) )
ptr->GetGlobalEnd() >= processStartSample &&
( firstBlock->GetGlobalEnd() < processStartSample ||
ptr->GetGlobalStart() <= firstBlock->GetGlobalStart()) )
{
//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
{
//otherwise no priority
if ( !firstBlock )
firstBlock = ptr;
mBlockFiles.push_back(unorderedBlocks[i]);
}
if(mMaxBlockFiles< (int) mBlockFiles.size())
@ -223,6 +227,7 @@ void ODDecodeTask::OrderBlockFiles
}
else
{
// The block file disappeared.
}
}

View File

@ -86,10 +86,10 @@ protected:
///Orders the input as either On-Demand or default layered order.
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;
int mMaxBlockFiles;

View File

@ -886,7 +886,16 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
#ifdef EXPERIMENTAL_DA
shifted = !shifted;
#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;
double t0 = p->GetSel0();