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:
commit
3d29ba12a6
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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()
|
||||||
|
24
src/Mix.cpp
24
src/Mix.cpp
@ -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?
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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 ;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user