1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 14:52:34 +02:00

WaveTrack::Get, WaveClip::GetSamples take a mayThrow=true argument...

... and pass non-default in all needed places.

Don't throw, don't put up error dialogs, in drawing or hit-test code.
This commit is contained in:
Paul Licameli 2017-03-20 10:54:03 -04:00
parent 98d1468a01
commit 39b8d99a56
10 changed files with 88 additions and 60 deletions

View File

@ -566,7 +566,9 @@ void FreqWindow::GetAudio()
// dataLen is not more than 10 * 2 ^ 20
mDataLen = dataLen.as_size_t();
mData = Floats{ mDataLen };
track->Get((samplePtr)mData.get(), floatSample, start, mDataLen);
// Don't allow throw for bad reads
track->Get((samplePtr)mData.get(), floatSample, start, mDataLen,
fillZero, false);
}
else {
if (track->GetRate() != mRate) {
@ -577,7 +579,9 @@ void FreqWindow::GetAudio()
}
auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0());
Floats buffer2{ mDataLen };
track->Get((samplePtr)buffer2.get(), floatSample, start, mDataLen);
// Again, stop exceptions
track->Get((samplePtr)buffer2.get(), floatSample, start, mDataLen,
fillZero, false);
for (size_t i = 0; i < mDataLen; i++)
mData[i] += buffer2[i];
}

View File

@ -544,10 +544,11 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
// But this change is consistent with the others for EXPERIMENTAL_MIDI_OUT, so I accept it.
if ((t0 < 0.0) || (t1 < 0.0) || (t0 >= t1) || // bad time value or nothing to show
#ifdef EXPERIMENTAL_MIDI_OUT
((mMixerBoard->HasSolo() || mTrack->GetMute()) && !mTrack->GetSolo()))
((mMixerBoard->HasSolo() || mTrack->GetMute()) && !mTrack->GetSolo())
#else
((mMixerBoard->HasSolo() || mLeftTrack->GetMute()) && !mLeftTrack->GetSolo()))
((mMixerBoard->HasSolo() || mLeftTrack->GetMute()) && !mLeftTrack->GetSolo())
#endif
)
{
//v Vaughan, 2011-02-25: Moved the update back to TrackPanel::OnTimer() as it helps with
// playback issues reported by Bill and noted on Bug 258, so no assert.
@ -636,9 +637,11 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
// in about 1/20 second (ticks of TrackPanel timer), so this won't overflow
auto nFrames = scnFrames.as_size_t();
Floats tempFloatsArray{ size_t(nFrames) };
Floats tempFloatsArray{ nFrames };
decltype(tempFloatsArray) meterFloatsArray;
bool bSuccess = mLeftTrack->Get((samplePtr)tempFloatsArray.get(), floatSample, startSample, nFrames);
// Don't throw on read error in this drawing update routine
bool bSuccess = mLeftTrack->Get((samplePtr)tempFloatsArray.get(),
floatSample, startSample, nFrames, fillZero, false);
if (bSuccess)
{
// We always pass a stereo sample array to the meter, as it shows 2 channels.
@ -651,7 +654,9 @@ void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
meterFloatsArray[2 * index] = tempFloatsArray[index];
if (mRightTrack)
bSuccess = mRightTrack->Get((samplePtr)tempFloatsArray.get(), floatSample, startSample, nFrames);
// Again, don't throw
bSuccess = mRightTrack->Get((samplePtr)tempFloatsArray.get(),
floatSample, startSample, nFrames, fillZero, false);
if (bSuccess)
// Interleave right channel, or duplicate same signal for "right" channel in mono case.

View File

@ -41,6 +41,8 @@
#include <wx/ffile.h>
#include <wx/log.h>
#include "AudacityException.h"
#include "BlockFile.h"
#include "blockfile/ODDecodeBlockFile.h"
#include "DirManager.h"
@ -405,7 +407,7 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
blocklen =
( std::min(s1, block0.start + file->GetLength()) - s0 ).as_size_t();
wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29
Get(b0, buffer.ptr(), mSampleFormat, s0, blocklen);
Get(b0, buffer.ptr(), mSampleFormat, s0, blocklen, true);
dest->Append(buffer.ptr(), mSampleFormat, blocklen);
}
@ -425,7 +427,7 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
blocklen = (s1 - block.start).as_size_t();
wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29
if (blocklen < file->GetLength()) {
Get(b1, buffer.ptr(), mSampleFormat, block.start, blocklen);
Get(b1, buffer.ptr(), mSampleFormat, block.start, blocklen, true);
dest->Append(buffer.ptr(), mSampleFormat, blocklen);
}
else
@ -524,12 +526,12 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
auto sAddedLen = addedLen.as_size_t();
// s lies within block:
auto splitPoint = ( s - block.start ).as_size_t();
Read(buffer.ptr(), mSampleFormat, block, 0, splitPoint);
Read(buffer.ptr(), mSampleFormat, block, 0, splitPoint, true);
src->Get(0, buffer.ptr() + splitPoint*sampleSize,
mSampleFormat, 0, sAddedLen);
mSampleFormat, 0, sAddedLen, true);
Read(buffer.ptr() + (splitPoint + sAddedLen) * sampleSize,
mSampleFormat, block,
splitPoint, length - splitPoint);
splitPoint, length - splitPoint, true);
auto file =
mDirManager->NewSimpleBlockFile(
@ -567,13 +569,13 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
const auto sum = splitLen + sAddedLen;
SampleBuffer sumBuffer(sum, mSampleFormat);
Read(sumBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint);
Read(sumBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint, true);
src->Get(0, sumBuffer.ptr() + splitPoint * sampleSize,
mSampleFormat,
0, sAddedLen);
0, sAddedLen, true);
Read(sumBuffer.ptr() + (splitPoint + sAddedLen) * sampleSize, mSampleFormat,
splitBlock, splitPoint,
splitLen - splitPoint);
splitLen - splitPoint, true);
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
newBlock, splitBlock.start, sumBuffer.ptr(), sum);
@ -598,9 +600,9 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
SampleBuffer sampleBuffer(std::max(leftLen, rightLen), mSampleFormat);
Read(sampleBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint);
Read(sampleBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint, true);
src->Get(0, sampleBuffer.ptr() + splitPoint*sampleSize,
mSampleFormat, 0, srcFirstTwoLen);
mSampleFormat, 0, srcFirstTwoLen, true);
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen);
@ -618,9 +620,9 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
auto lastStart = penultimate.start;
src->Get(srcNumBlocks - 2, sampleBuffer.ptr(), mSampleFormat,
lastStart, srcLastTwoLen);
lastStart, srcLastTwoLen, true);
Read(sampleBuffer.ptr() + srcLastTwoLen * sampleSize, mSampleFormat,
splitBlock, splitPoint, rightSplit);
splitBlock, splitPoint, rightSplit, true);
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
@ -1112,43 +1114,50 @@ int Sequence::FindBlock(sampleCount pos) const
}
bool Sequence::Read(samplePtr buffer, sampleFormat format,
const SeqBlock &b, size_t blockRelativeStart, size_t len)
const
const SeqBlock &b, size_t blockRelativeStart, size_t len,
bool mayThrow)
{
const auto &f = b.f;
wxASSERT(blockRelativeStart + len <= f->GetLength());
auto result = f->ReadData(buffer, format, blockRelativeStart, len);
// Either throws, or of !mayThrow, tells how many were really read
auto result = f->ReadData(buffer, format, blockRelativeStart, len, mayThrow);
if (result != len)
{
wxLogWarning(wxT("Expected to read %ld samples, got %d samples."),
len, result);
ClearSamples(buffer, format, result, len-result);
return false;
}
return true;
}
bool Sequence::Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const
sampleCount start, size_t len, bool mayThrow) const
{
if (start == mNumSamples) {
return len == 0;
}
if (start < 0 || start > mNumSamples ||
start + len > mNumSamples)
start + len > mNumSamples) {
if (mayThrow)
//THROW_INCONSISTENCY_EXCEPTION
;
ClearSamples( buffer, floatSample, 0, len );
return false;
}
int b = FindBlock(start);
return Get(b, buffer, format, start, len);
return Get(b, buffer, format, start, len, mayThrow);
}
bool Sequence::Get(int b, samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const
sampleCount start, size_t len, bool mayThrow) const
{
bool result = true;
while (len) {
const SeqBlock &block = mBlock[b];
// start is in block
@ -1156,15 +1165,15 @@ bool Sequence::Get(int b, samplePtr buffer, sampleFormat format,
// bstart is not more than block length
const auto blen = std::min(len, block.f->GetLength() - bstart);
Read(buffer, format, block, bstart, blen);
if (! Read(buffer, format, block, bstart, blen, mayThrow) )
result = false;
len -= blen;
buffer += (blen * SAMPLE_SIZE(format));
b++;
start += blen;
}
return true;
return result;
}
// Pass NULL to set silence
@ -1211,7 +1220,7 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format,
;
if ( bstart > 0 || blen < fileLength ) {
Read(scratch.ptr(), mSampleFormat, block, 0, fileLength);
Read(scratch.ptr(), mSampleFormat, block, 0, fileLength, true);
if (useBuffer) {
auto sampleSize = SAMPLE_SIZE(mSampleFormat);
@ -1393,7 +1402,8 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
default:
case 1:
// Read samples
Read((samplePtr)temp.get(), floatSample, seqBlock, startPosition, num);
// no-throw for display operations!
Read((samplePtr)temp.get(), floatSample, seqBlock, startPosition, num, false);
break;
case 256:
// Read triples
@ -1526,7 +1536,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
SeqBlock &lastBlock = *pLastBlock;
const auto addLen = std::min(mMaxSamples - length, len);
Read(buffer2.ptr(), mSampleFormat, lastBlock, 0, length);
Read(buffer2.ptr(), mSampleFormat, lastBlock, 0, length, true);
CopySamples(buffer,
format,
@ -1653,12 +1663,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
scratch.Allocate(scratchSize, mSampleFormat);
Read(scratch.ptr(), mSampleFormat, b, 0, pos);
Read(scratch.ptr(), mSampleFormat, b, 0, pos, true);
Read(scratch.ptr() + (pos * sampleSize), mSampleFormat,
b,
// ... and therefore pos + len
// is not more than the length of the block
( pos + len ).as_size_t(), newLen - pos);
( pos + len ).as_size_t(), newLen - pos, true);
b = SeqBlock(
mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat),
@ -1694,7 +1704,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
if (preBufferLen >= mMinSamples || b0 == 0) {
if (!scratch.ptr())
scratch.Allocate(scratchSize, mSampleFormat);
Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen);
Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen, true);
auto pFile =
mDirManager->NewSimpleBlockFile(scratch.ptr(), preBufferLen, mSampleFormat);
@ -1707,9 +1717,9 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
if (!scratch.ptr())
scratch.Allocate(scratchSize, mSampleFormat);
Read(scratch.ptr(), mSampleFormat, prepreBlock, 0, prepreLen);
Read(scratch.ptr(), mSampleFormat, prepreBlock, 0, prepreLen, true);
Read(scratch.ptr() + prepreLen*sampleSize, mSampleFormat,
preBlock, 0, preBufferLen);
preBlock, 0, preBufferLen, true);
newBlock.erase(newBlock.end() - 1);
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
@ -1738,7 +1748,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
scratch.Allocate(postBufferLen, mSampleFormat);
// start + len - 1 lies within postBlock
auto pos = (start + len - postBlock.start).as_size_t();
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen);
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen, true);
auto file =
mDirManager->NewSimpleBlockFile(scratch.ptr(), postBufferLen, mSampleFormat);
@ -1753,9 +1763,9 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
scratch.Allocate(sum, mSampleFormat);
// start + len - 1 lies within postBlock
auto pos = (start + len - postBlock.start).as_size_t();
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen);
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen, true);
Read(scratch.ptr() + (postBufferLen * sampleSize), mSampleFormat,
postpostBlock, 0, postpostLen);
postpostBlock, 0, postpostLen, true);
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
newBlock, start, scratch.ptr(), sum);

View File

@ -86,7 +86,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
sampleCount GetNumSamples() const { return mNumSamples; }
bool Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const;
sampleCount start, size_t len, bool mayThrow) const;
// Note that len is not size_t, because nullptr may be passed for buffer, in
// which case, silence is inserted, possibly a large amount.
@ -249,9 +249,9 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
(DirManager &dirManager,
BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b);
bool Read(samplePtr buffer, sampleFormat format,
static bool Read(samplePtr buffer, sampleFormat format,
const SeqBlock &b,
size_t blockRelativeStart, size_t len) const;
size_t blockRelativeStart, size_t len, bool mayThrow);
// Accumulate NEW block files onto the end of a block array.
// Does not change this sequence. The intent is to use
@ -261,7 +261,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
BlockArray &list, sampleCount start, samplePtr buffer, size_t len);
bool Get(int b, samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const;
sampleCount start, size_t len, bool mayThrow) const;
public:

View File

@ -1324,7 +1324,9 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
return;
Floats buffer{ size_t(slen) };
clip->GetSamples((samplePtr)buffer.get(), floatSample, s0, slen);
clip->GetSamples((samplePtr)buffer.get(), floatSample, s0, slen,
// Suppress exceptions in this drawing operation:
false);
ArrayOf<int> xpos{ size_t(slen) };
ArrayOf<int> ypos{ size_t(slen) };

View File

@ -2513,9 +2513,12 @@ void TrackPanel::StartSnappingFreqSelection (const WaveTrack *pTrack)
end - start ));
const auto effectiveLength = std::max(minLength, length);
frequencySnappingData.resize(effectiveLength, 0.0f);
pTrack->Get(
reinterpret_cast<samplePtr>(&frequencySnappingData[0]),
floatSample, start, length);
floatSample, start, length, fillZero,
// Don't try to cope with exceptions, just read zeroes instead.
false);
// Use same settings as are now used for spectrogram display,
// except, shrink the window as needed so we get some answers
@ -6843,7 +6846,11 @@ bool TrackPanel::HitTestSamples(Track *track, const wxRect &rect, const wxMouseE
// Just get one sample.
float oneSample;
auto s0 = (sampleCount)(tt * rate + 0.5);
wavetrack->Get((samplePtr)&oneSample, floatSample, s0, 1);
if ( !wavetrack->Get(
(samplePtr)&oneSample, floatSample, s0, 1, fillZero,
// Do not propagate exception but return a failure value
false))
return false;
// Get y distance of envelope point from center line (in pixels).
float zoomMin, zoomMax;

View File

@ -401,9 +401,9 @@ void WaveClip::SetOffset(double offset)
}
bool WaveClip::GetSamples(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const
sampleCount start, size_t len, bool mayThrow) const
{
return mSequence->Get(buffer, format, start, len);
return mSequence->Get(buffer, format, start, len, mayThrow);
}
bool WaveClip::SetSamples(samplePtr buffer, sampleFormat format,
@ -1855,7 +1855,7 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
bool isLast = ((pos + inLen) == numSamples);
if (!mSequence->Get((samplePtr)inBuffer.get(), floatSample, pos, inLen))
if (!mSequence->Get((samplePtr)inBuffer.get(), floatSample, pos, inLen, true))
{
error = true;
break;

View File

@ -251,7 +251,7 @@ public:
bool AfterClip(double t) const;
bool GetSamples(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len) const;
sampleCount start, size_t len, bool mayThrow = true) const;
bool SetSamples(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len);

View File

@ -1980,12 +1980,14 @@ float WaveTrack::GetRMS(double t0, double t1, bool mayThrow) const
}
bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len, fillFormat fill ) const
sampleCount start, size_t len, fillFormat fill,
bool mayThrow) const
{
// Simple optimization: When this buffer is completely contained within one clip,
// don't clear anything (because we won't have to). Otherwise, just clear
// everything to be on the safe side.
bool doClear = true;
bool result = true;
for (const auto &clip: mClips)
{
if (start >= clip->GetStartSample() && start+len <= clip->GetEndSample())
@ -2046,15 +2048,12 @@ bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
(samplePtr)(((char*)buffer) +
startDelta.as_size_t() *
SAMPLE_SIZE(format)),
format, inclipDelta, samplesToCopy.as_size_t() ))
{
wxASSERT(false); // should always work
return false;
}
format, inclipDelta, samplesToCopy.as_size_t(), mayThrow ))
result = false;
}
}
return true;
return result;
}
bool WaveTrack::Set(samplePtr buffer, sampleFormat format,

View File

@ -252,7 +252,8 @@ class AUDACITY_DLL_API WaveTrack final : public Track {
/// guaranteed that the same samples are affected.
///
bool Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len, fillFormat fill=fillZero) const;
sampleCount start, size_t len,
fillFormat fill = fillZero, bool mayThrow = true) const;
bool Set(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len);
void GetEnvelopeValues(double *buffer, size_t bufferLen,