mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-17 16:50:26 +02:00
Small improvements in Sequence and BlockFile
This commit is contained in:
commit
715758d869
@ -424,6 +424,8 @@ void BlockFile::GetMinMax(float *outMin, float *outMax, float *outRMS) const
|
||||
/// data provides information about the minimum value, the maximum
|
||||
/// value, and the maximum RMS value for every group of 256 samples in the
|
||||
/// file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
///
|
||||
/// @param *buffer The area where the summary information will be
|
||||
/// written. It must be at least len*3 long.
|
||||
@ -434,54 +436,17 @@ bool BlockFile::Read256(float *buffer,
|
||||
{
|
||||
wxASSERT(start >= 0);
|
||||
|
||||
ArrayOf<char> summary{ mSummaryInfo.totalSummaryBytes };
|
||||
// FIXME: TRAP_ERR ReadSummary() could return fail.
|
||||
this->ReadSummary(summary.get());
|
||||
ArrayOf< char > summary;
|
||||
// In case of failure, summary is filled with zeroes
|
||||
auto result = this->ReadSummary(summary);
|
||||
|
||||
start = std::min( start, mSummaryInfo.frames256 );
|
||||
len = std::min( len, mSummaryInfo.frames256 - start );
|
||||
|
||||
CopySamples(summary.get() + mSummaryInfo.offset256 + (start * mSummaryInfo.bytesPerFrame),
|
||||
mSummaryInfo.format,
|
||||
(samplePtr)buffer, floatSample, len * mSummaryInfo.fields);
|
||||
|
||||
if (mSummaryInfo.fields == 2) {
|
||||
// No RMS info
|
||||
for(auto i = len; i--;) {
|
||||
buffer[3*i+2] = (fabs(buffer[2*i]) + fabs(buffer[2*i+1]))/4.0;
|
||||
buffer[3*i+1] = buffer[2*i+1];
|
||||
buffer[3*i] = buffer[2*i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Retrieves a portion of the 64K summary buffer from this BlockFile. This
|
||||
/// data provides information about the minimum value, the maximum
|
||||
/// value, and the maximum RMS value for every group of 64K samples in the
|
||||
/// file.
|
||||
///
|
||||
/// @param *buffer The area where the summary information will be
|
||||
/// written. It must be at least len*3 long.
|
||||
/// @param start The offset in 64K-sample increments
|
||||
/// @param len The number of 64K-sample summary frames to read
|
||||
bool BlockFile::Read64K(float *buffer,
|
||||
size_t start, size_t len)
|
||||
{
|
||||
wxASSERT(start >= 0);
|
||||
|
||||
ArrayOf<char> summary{ mSummaryInfo.totalSummaryBytes };
|
||||
// FIXME: TRAP_ERR ReadSummary() could return fail.
|
||||
this->ReadSummary(summary.get());
|
||||
|
||||
start = std::min( start, mSummaryInfo.frames64K );
|
||||
len = std::min( len, mSummaryInfo.frames64K - start );
|
||||
|
||||
CopySamples(summary.get() + mSummaryInfo.offset64K +
|
||||
CopySamples(summary.get() + mSummaryInfo.offset256 +
|
||||
(start * mSummaryInfo.bytesPerFrame),
|
||||
mSummaryInfo.format,
|
||||
(samplePtr)buffer, floatSample, len*mSummaryInfo.fields);
|
||||
(samplePtr)buffer, floatSample, len * mSummaryInfo.fields);
|
||||
|
||||
if (mSummaryInfo.fields == 2) {
|
||||
// No RMS info; make guess
|
||||
@ -492,7 +457,46 @@ bool BlockFile::Read64K(float *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Retrieves a portion of the 64K summary buffer from this BlockFile. This
|
||||
/// data provides information about the minimum value, the maximum
|
||||
/// value, and the maximum RMS value for every group of 64K samples in the
|
||||
/// file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
/// @param *buffer The area where the summary information will be
|
||||
/// written. It must be at least len*3 long.
|
||||
/// @param start The offset in 64K-sample increments
|
||||
/// @param len The number of 64K-sample summary frames to read
|
||||
bool BlockFile::Read64K(float *buffer,
|
||||
size_t start, size_t len)
|
||||
{
|
||||
wxASSERT(start >= 0);
|
||||
|
||||
ArrayOf< char > summary;
|
||||
// In case of failure, summary is filled with zeroes
|
||||
auto result = this->ReadSummary(summary);
|
||||
|
||||
start = std::min( start, mSummaryInfo.frames64K );
|
||||
len = std::min( len, mSummaryInfo.frames64K - start );
|
||||
|
||||
CopySamples(summary.get() + mSummaryInfo.offset64K +
|
||||
(start * mSummaryInfo.bytesPerFrame),
|
||||
mSummaryInfo.format,
|
||||
(samplePtr)buffer, floatSample, len * mSummaryInfo.fields);
|
||||
|
||||
if (mSummaryInfo.fields == 2) {
|
||||
// No RMS info; make guess
|
||||
for(auto i = len; i--;) {
|
||||
buffer[3*i+2] = (fabs(buffer[2*i]) + fabs(buffer[2*i+1]))/4.0;
|
||||
buffer[3*i+1] = buffer[2*i+1];
|
||||
buffer[3*i] = buffer[2*i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t BlockFile::CommonReadData(
|
||||
@ -714,11 +718,13 @@ AliasBlockFile::~AliasBlockFile()
|
||||
|
||||
/// Read the summary of this alias block from disk. Since the audio data
|
||||
/// is elsewhere, this consists of reading the entire summary file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
/// @param *data The buffer where the summary data will be stored. It must
|
||||
/// be at least mSummaryInfo.totalSummaryBytes long.
|
||||
bool AliasBlockFile::ReadSummary(void *data)
|
||||
bool AliasBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
|
||||
|
||||
{
|
||||
@ -729,24 +735,28 @@ bool AliasBlockFile::ReadSummary(void *data)
|
||||
if (!summaryFile.IsOpened()){
|
||||
|
||||
// NEW model; we need to return valid data
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
|
||||
// we silence the logging for this operation in this object
|
||||
// after first occurrence of error; it's already reported and
|
||||
// spewing at the user will complicate the user's ability to
|
||||
// deal
|
||||
mSilentLog = TRUE;
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
else mSilentLog = FALSE; // worked properly, any future error is NEW
|
||||
}
|
||||
|
||||
auto read = summaryFile.Read(data, mSummaryInfo.totalSummaryBytes);
|
||||
auto read = summaryFile.Read(data.get(), mSummaryInfo.totalSummaryBytes);
|
||||
if (read != mSummaryInfo.totalSummaryBytes) {
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
FixSummary(data);
|
||||
FixSummary(data.get());
|
||||
|
||||
return (read == mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Modify this block to point at a different file. This is generally
|
||||
|
@ -181,7 +181,7 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
float *summary256, float *summary64K);
|
||||
|
||||
/// Read the summary section of the file. Derived classes implement.
|
||||
virtual bool ReadSummary(void *data) = 0;
|
||||
virtual bool ReadSummary(ArrayOf<char> &data) = 0;
|
||||
|
||||
/// Byte-swap the summary data, in case it was saved by a system
|
||||
/// on a different platform
|
||||
@ -251,7 +251,7 @@ class AliasBlockFile /* not final */ : public BlockFile
|
||||
/// Write the summary to disk, using the derived ReadData() to get the data
|
||||
virtual void WriteSummary();
|
||||
/// Read the summary into a buffer
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
|
||||
wxFileNameWrapper mAliasedFileName;
|
||||
sampleCount mAliasStart;
|
||||
|
122
src/Sequence.cpp
122
src/Sequence.cpp
@ -185,7 +185,8 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
|
||||
// Using Blockify will handle the cases where len > the NEW mMaxSamples. Previous code did not.
|
||||
const auto blockstart = oldSeqBlock.start;
|
||||
const unsigned prevSize = newBlockArray.size();
|
||||
Blockify(newBlockArray, blockstart, bufferNew.ptr(), len);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlockArray, blockstart, bufferNew.ptr(), len);
|
||||
bSuccess = (newBlockArray.size() > prevSize);
|
||||
if (bSuccess)
|
||||
*pbChanged = true;
|
||||
@ -425,7 +426,8 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
|
||||
|
||||
// If there are blocks in the middle, copy the blockfiles directly
|
||||
for (int bb = b0 + 1; bb < b1; ++bb)
|
||||
dest->AppendBlock(mBlock[bb]); // Increase ref count or duplicate file
|
||||
AppendBlock(*dest->mDirManager, dest->mBlock, dest->mNumSamples, mBlock[bb]);
|
||||
// Increase ref count or duplicate file
|
||||
|
||||
// Do the last block
|
||||
if (b1 > b0) {
|
||||
@ -440,7 +442,8 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
|
||||
}
|
||||
else
|
||||
// Special case, copy exactly
|
||||
dest->AppendBlock(block); // Increase ref count or duplicate file
|
||||
AppendBlock(*dest->mDirManager, dest->mBlock, dest->mNumSamples, block);
|
||||
// Increase ref count or duplicate file
|
||||
}
|
||||
|
||||
if (! ConsistencyCheck(wxT("Sequence::Copy()")))
|
||||
@ -507,7 +510,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// minimum size
|
||||
|
||||
for (unsigned int i = 0; i < srcNumBlocks; i++)
|
||||
AppendBlock(srcBlock[i]); // Increase ref count or duplicate file
|
||||
AppendBlock(*mDirManager, mBlock, mNumSamples, srcBlock[i]);
|
||||
// Increase ref count or duplicate file
|
||||
|
||||
return ConsistencyCheck(wxT("Paste branch one"));
|
||||
}
|
||||
@ -583,7 +587,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
splitBlock, splitPoint,
|
||||
splitLen - splitPoint);
|
||||
|
||||
Blockify(newBlock, splitBlock.start, sumBuffer.ptr(), sum);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlock, splitBlock.start, sumBuffer.ptr(), sum);
|
||||
} else {
|
||||
|
||||
// The final case is that we're inserting at least five blocks.
|
||||
@ -609,7 +614,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
src->Get(0, sampleBuffer.ptr() + splitPoint*sampleSize,
|
||||
mSampleFormat, 0, srcFirstTwoLen);
|
||||
|
||||
Blockify(newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen);
|
||||
|
||||
for (i = 2; i < srcNumBlocks - 2; i++) {
|
||||
const SeqBlock &block = srcBlock[i];
|
||||
@ -628,7 +634,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
Read(sampleBuffer.ptr() + srcLastTwoLen * sampleSize, mSampleFormat,
|
||||
splitBlock, splitPoint, rightSplit);
|
||||
|
||||
Blockify(newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
|
||||
}
|
||||
|
||||
// Copy remaining blocks to NEW block array and
|
||||
@ -734,14 +741,16 @@ bool Sequence::AppendCoded(const wxString &fName, sampleCount start,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::AppendBlock(const SeqBlock &b)
|
||||
bool Sequence::AppendBlock
|
||||
(DirManager &mDirManager,
|
||||
BlockArray &mBlock, sampleCount &mNumSamples, const SeqBlock &b)
|
||||
{
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
if (Overflows((mNumSamples.as_double()) + ((double)b.f->GetLength())))
|
||||
return false;
|
||||
|
||||
SeqBlock newBlock(
|
||||
mDirManager->CopyBlockFile(b.f), // Bump ref count if not locked, else copy
|
||||
mDirManager.CopyBlockFile(b.f), // Bump ref count if not locked, else copy
|
||||
mNumSamples
|
||||
);
|
||||
if (!newBlock.f) {
|
||||
@ -1134,29 +1143,6 @@ bool Sequence::Read(samplePtr buffer, sampleFormat format,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::CopyWrite(SampleBuffer &scratch,
|
||||
samplePtr buffer, SeqBlock &b,
|
||||
size_t blockRelativeStart, size_t len)
|
||||
{
|
||||
// We don't ever write to an existing block; to support Undo,
|
||||
// we copy the old block entirely into memory, dereference it,
|
||||
// make the change, and then write the NEW block to disk.
|
||||
|
||||
const auto length = b.f->GetLength();
|
||||
wxASSERT(length <= mMaxSamples);
|
||||
wxASSERT(blockRelativeStart + len <= length);
|
||||
|
||||
auto sampleSize = SAMPLE_SIZE(mSampleFormat);
|
||||
|
||||
Read(scratch.ptr(), mSampleFormat, b, 0, length);
|
||||
memcpy(scratch.ptr() +
|
||||
blockRelativeStart * sampleSize, buffer, len*sampleSize);
|
||||
|
||||
b.f = mDirManager->NewSimpleBlockFile(scratch.ptr(), length, mSampleFormat);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::Get(samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, size_t len) const
|
||||
{
|
||||
@ -1218,32 +1204,50 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format,
|
||||
const auto fileLength = block.f->GetLength();
|
||||
const auto blen = limitSampleBufferSize( fileLength - bstart, len );
|
||||
|
||||
if (buffer) {
|
||||
if (format == mSampleFormat)
|
||||
CopyWrite(scratch, buffer, block, bstart, blen);
|
||||
else {
|
||||
// To do: remove the extra movement. Can we copy-samples within CopyWrite?
|
||||
samplePtr useBuffer = buffer;
|
||||
if (buffer && format != mSampleFormat)
|
||||
{
|
||||
// To do: remove the extra movement.
|
||||
CopySamples(buffer, format, temp.ptr(), mSampleFormat, blen);
|
||||
CopyWrite(scratch, temp.ptr(), block, bstart, blen);
|
||||
useBuffer = temp.ptr();
|
||||
}
|
||||
buffer += (blen * SAMPLE_SIZE(format));
|
||||
}
|
||||
else {
|
||||
// If it's a full block of silence
|
||||
if (start == block.start &&
|
||||
blen == fileLength) {
|
||||
|
||||
block.f = make_blockfile<SilentBlockFile>(blen);
|
||||
// We don't ever write to an existing block; to support Undo,
|
||||
// we copy the old block entirely into memory, dereference it,
|
||||
// make the change, and then write the NEW block to disk.
|
||||
|
||||
if (!(fileLength <= mMaxSamples &&
|
||||
bstart + blen <= fileLength))
|
||||
//THROW_INCONSISTENCY_EXCEPTION
|
||||
wxASSERT(false)
|
||||
;
|
||||
|
||||
if ( bstart > 0 || blen < fileLength ) {
|
||||
Read(scratch.ptr(), mSampleFormat, block, 0, fileLength);
|
||||
|
||||
if (useBuffer) {
|
||||
auto sampleSize = SAMPLE_SIZE(mSampleFormat);
|
||||
memcpy(scratch.ptr() +
|
||||
bstart * sampleSize, useBuffer, blen * sampleSize);
|
||||
}
|
||||
else
|
||||
ClearSamples(scratch.ptr(), mSampleFormat, bstart, blen);
|
||||
|
||||
block.f = mDirManager->NewSimpleBlockFile(
|
||||
scratch.ptr(), fileLength, mSampleFormat);
|
||||
}
|
||||
else {
|
||||
// Odd partial blocks of silence at start or end.
|
||||
temp.Allocate(blen, format);
|
||||
ClearSamples(temp.ptr(), format, 0, blen);
|
||||
// Otherwise write silence just to the portion of the block
|
||||
CopyWrite(scratch, temp.ptr(), block, bstart, blen);
|
||||
}
|
||||
// Avoid reading the disk when the replacement is total
|
||||
if (useBuffer)
|
||||
block.f = mDirManager->NewSimpleBlockFile(
|
||||
useBuffer, fileLength, mSampleFormat);
|
||||
else
|
||||
block.f = make_blockfile<SilentBlockFile>(fileLength);
|
||||
}
|
||||
|
||||
if( buffer )
|
||||
buffer += (blen * SAMPLE_SIZE(format));
|
||||
|
||||
len -= blen;
|
||||
start += blen;
|
||||
b++;
|
||||
@ -1407,6 +1411,8 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
||||
// Read triples
|
||||
//check to see if summary data has been computed
|
||||
if (seqBlock.f->IsSummaryAvailable())
|
||||
// Ignore the return value.
|
||||
// This function fills with zeroes if read fails
|
||||
seqBlock.f->Read256(temp.get(), startPosition, num);
|
||||
else
|
||||
//otherwise, mark the display as not yet computed
|
||||
@ -1416,6 +1422,8 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
||||
// Read triples
|
||||
//check to see if summary data has been computed
|
||||
if (seqBlock.f->IsSummaryAvailable())
|
||||
// Ignore the return value.
|
||||
// This function fills with zeroes if read fails
|
||||
seqBlock.f->Read64K(temp.get(), startPosition, num);
|
||||
else
|
||||
//otherwise, mark the display as not yet computed
|
||||
@ -1593,7 +1601,9 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sequence::Blockify(BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
|
||||
void Sequence::Blockify
|
||||
(DirManager &mDirManager, size_t mMaxSamples, sampleFormat mSampleFormat,
|
||||
BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
|
||||
{
|
||||
if (len <= 0)
|
||||
return;
|
||||
@ -1608,7 +1618,7 @@ void Sequence::Blockify(BlockArray &list, sampleCount start, samplePtr buffer, s
|
||||
int newLen = ((i + 1) * len / num) - offset;
|
||||
samplePtr bufStart = buffer + (offset * SAMPLE_SIZE(mSampleFormat));
|
||||
|
||||
b.f = mDirManager->NewSimpleBlockFile(bufStart, newLen, mSampleFormat);
|
||||
b.f = mDirManager.NewSimpleBlockFile(bufStart, newLen, mSampleFormat);
|
||||
|
||||
list.push_back(b);
|
||||
}
|
||||
@ -1714,7 +1724,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
preBlock, 0, preBufferLen);
|
||||
|
||||
newBlock.erase(newBlock.end() - 1);
|
||||
Blockify(newBlock, prepreBlock.start, scratch.ptr(), sum);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlock, prepreBlock.start, scratch.ptr(), sum);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1758,7 +1769,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
Read(scratch.ptr() + (postBufferLen * sampleSize), mSampleFormat,
|
||||
postpostBlock, 0, postpostLen);
|
||||
|
||||
Blockify(newBlock, start, scratch.ptr(), sum);
|
||||
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
|
||||
newBlock, start, scratch.ptr(), sum);
|
||||
b1++;
|
||||
}
|
||||
}
|
||||
|
@ -246,17 +246,20 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
|
||||
int FindBlock(sampleCount pos) const;
|
||||
|
||||
bool AppendBlock(const SeqBlock &b);
|
||||
static bool AppendBlock
|
||||
(DirManager &dirManager,
|
||||
BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b);
|
||||
|
||||
bool Read(samplePtr buffer, sampleFormat format,
|
||||
const SeqBlock &b,
|
||||
size_t blockRelativeStart, size_t len) const;
|
||||
|
||||
bool CopyWrite(SampleBuffer &scratch,
|
||||
samplePtr buffer, SeqBlock &b,
|
||||
size_t blockRelativeStart, size_t len);
|
||||
|
||||
void Blockify(BlockArray &list, sampleCount start, samplePtr buffer, size_t len);
|
||||
// Accumulate NEW block files onto the end of a block array.
|
||||
// Does not change this sequence. The intent is to use
|
||||
// CommitChangesIfConsistent later.
|
||||
static void Blockify
|
||||
(DirManager &dirManager, size_t maxSamples, sampleFormat format,
|
||||
BlockArray &list, sampleCount start, samplePtr buffer, size_t len);
|
||||
|
||||
bool Get(int b, samplePtr buffer, sampleFormat format,
|
||||
sampleCount start, size_t len) const;
|
||||
|
@ -151,11 +151,13 @@ LegacyBlockFile::~LegacyBlockFile()
|
||||
}
|
||||
|
||||
/// Read the summary section of the disk file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
/// @param *data The buffer to write the data to. It must be at least
|
||||
/// mSummaryinfo.totalSummaryBytes long.
|
||||
bool LegacyBlockFile::ReadSummary(void *data)
|
||||
bool LegacyBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
|
||||
size_t read;
|
||||
{
|
||||
@ -163,20 +165,25 @@ bool LegacyBlockFile::ReadSummary(void *data)
|
||||
if (mSilentLog)
|
||||
silence.create();
|
||||
|
||||
if (!summaryFile.IsOpened()){
|
||||
if (!summaryFile.IsOpened()) {
|
||||
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
|
||||
mSilentLog = TRUE;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
read = summaryFile.Read(data.get(), mSummaryInfo.totalSummaryBytes);
|
||||
}
|
||||
mSilentLog = FALSE;
|
||||
|
||||
if (read != mSummaryInfo.totalSummaryBytes) {
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
read = summaryFile.Read(data, mSummaryInfo.totalSummaryBytes);
|
||||
}
|
||||
mSilentLog=FALSE;
|
||||
|
||||
return (read == mSummaryInfo.totalSummaryBytes);
|
||||
}
|
||||
|
||||
/// Read the data portion of the block file using libsndfile. Convert it
|
||||
|
@ -48,7 +48,7 @@ class LegacyBlockFile final : public BlockFile {
|
||||
// Reading
|
||||
|
||||
/// Read the summary section of the disk file
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
/// Read the data section of the disk file
|
||||
size_t ReadData(samplePtr data, sampleFormat format,
|
||||
size_t start, size_t len) const override;
|
||||
|
@ -126,6 +126,7 @@ void ODDecodeBlockFile::GetMinMax(float *outMin, float *outMax, float *outRMS) c
|
||||
}
|
||||
|
||||
/// Returns the 256 byte summary data block
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
bool ODDecodeBlockFile::Read256(float *buffer, size_t start, size_t len)
|
||||
{
|
||||
if(IsSummaryAvailable())
|
||||
@ -134,13 +135,13 @@ bool ODDecodeBlockFile::Read256(float *buffer, size_t start, size_t len)
|
||||
}
|
||||
else
|
||||
{
|
||||
//this should not be reached (client should check IsSummaryAvailable()==true before this.
|
||||
buffer = NULL;
|
||||
return true;
|
||||
ClearSamples((samplePtr)buffer, floatSample, 0, len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the 64K summary data block
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
bool ODDecodeBlockFile::Read64K(float *buffer, size_t start, size_t len)
|
||||
{
|
||||
if(IsSummaryAvailable())
|
||||
@ -149,8 +150,8 @@ bool ODDecodeBlockFile::Read64K(float *buffer, size_t start, size_t len)
|
||||
}
|
||||
else
|
||||
{
|
||||
//this should not be reached (client should check IsSummaryAvailable()==true before this.
|
||||
return true;
|
||||
ClearSamples((samplePtr)buffer, floatSample, 0, len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,17 +451,19 @@ size_t ODDecodeBlockFile::ReadData(samplePtr data, sampleFormat format,
|
||||
|
||||
/// Read the summary of this alias block from disk. Since the audio data
|
||||
/// is elsewhere, this consists of reading the entire summary file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
/// @param *data The buffer where the summary data will be stored. It must
|
||||
/// be at least mSummaryInfo.totalSummaryBytes long.
|
||||
bool ODDecodeBlockFile::ReadSummary(void *data)
|
||||
bool ODDecodeBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
//I dont think we need to add a mutex here because only the main thread changes filenames and calls ReadSummarz
|
||||
//I dont think we need to add a mutex here because only the main thread changes filenames and calls ReadSummary
|
||||
if(IsSummaryAvailable())
|
||||
return SimpleBlockFile::ReadSummary(data);
|
||||
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
///set the decoder,
|
||||
|
@ -112,7 +112,7 @@ class ODDecodeBlockFile final : public SimpleBlockFile
|
||||
size_t start, size_t len) const override;
|
||||
|
||||
/// Read the summary into a buffer
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
|
||||
///Returns the type of audiofile this blockfile is loaded from.
|
||||
unsigned int GetDecodeType() /* not override */ const { return mType; }
|
||||
|
@ -155,7 +155,8 @@ void ODPCMAliasBlockFile::GetMinMax(float *outMin, float *outMax, float *outRMS)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the 256 byte summary data block. Clients should check to see if the summary is available before trying to read it with this call.
|
||||
/// Returns the 256 byte summary data block.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
bool ODPCMAliasBlockFile::Read256(float *buffer, size_t start, size_t len)
|
||||
{
|
||||
if(IsSummaryAvailable())
|
||||
@ -165,12 +166,13 @@ bool ODPCMAliasBlockFile::Read256(float *buffer, size_t start, size_t len)
|
||||
else
|
||||
{
|
||||
//return nothing.
|
||||
buffer = NULL;
|
||||
return true;
|
||||
ClearSamples((samplePtr)buffer, floatSample, 0, len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the 64K summary data block. Clients should check to see if the summary is available before trying to read it with this call.
|
||||
/// Returns the 64K summary data block.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
bool ODPCMAliasBlockFile::Read64K(float *buffer, size_t start, size_t len)
|
||||
{
|
||||
if(IsSummaryAvailable())
|
||||
@ -180,8 +182,8 @@ bool ODPCMAliasBlockFile::Read64K(float *buffer, size_t start, size_t len)
|
||||
else
|
||||
{
|
||||
//return nothing - it hasn't been calculated yet
|
||||
buffer = NULL;
|
||||
return true;
|
||||
ClearSamples((samplePtr)buffer, floatSample, 0, len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,40 +507,43 @@ size_t ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
|
||||
|
||||
/// Read the summary of this alias block from disk. Since the audio data
|
||||
/// is elsewhere, this consists of reading the entire summary file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
///
|
||||
/// @param *data The buffer where the summary data will be stored. It must
|
||||
/// be at least mSummaryInfo.totalSummaryBytes long.
|
||||
bool ODPCMAliasBlockFile::ReadSummary(void *data)
|
||||
bool ODPCMAliasBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
|
||||
mFileNameMutex.Lock();
|
||||
ODLocker locker{ &mFileNameMutex };
|
||||
wxFFile summaryFile(mFileName.GetFullPath(), wxT("rb"));
|
||||
|
||||
if( !summaryFile.IsOpened() ){
|
||||
if( !summaryFile.IsOpened() ) {
|
||||
|
||||
// NEW model; we need to return valid data
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
|
||||
// we silence the logging for this operation in this object
|
||||
// after first occurrence of error; it's already reported and
|
||||
// spewing at the user will complicate the user's ability to
|
||||
// deal
|
||||
mSilentLog=TRUE;
|
||||
|
||||
mFileNameMutex.Unlock();
|
||||
return true;
|
||||
mSilentLog = TRUE;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
mSilentLog=FALSE; // worked properly, any future error is NEW
|
||||
mSilentLog = FALSE; // worked properly, any future error is NEW
|
||||
|
||||
auto read = summaryFile.Read(data, mSummaryInfo.totalSummaryBytes);
|
||||
auto read = summaryFile.Read(data.get(), mSummaryInfo.totalSummaryBytes);
|
||||
|
||||
FixSummary(data);
|
||||
if (read != mSummaryInfo.totalSummaryBytes) {
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
FixSummary(data.get());
|
||||
|
||||
mFileNameMutex.Unlock();
|
||||
return (read == mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Prevents a read on other threads.
|
||||
|
@ -121,7 +121,7 @@ class ODPCMAliasBlockFile final : public PCMAliasBlockFile
|
||||
size_t start, size_t len) const override;
|
||||
|
||||
/// Read the summary into a buffer
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
|
||||
///sets the file name the summary info will be saved in. threadsafe.
|
||||
void SetFileName(wxFileNameWrapper &&name) override;
|
||||
|
@ -24,9 +24,10 @@ SilentBlockFile::~SilentBlockFile()
|
||||
{
|
||||
}
|
||||
|
||||
bool SilentBlockFile::ReadSummary(void *data)
|
||||
bool SilentBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ class SilentBlockFile final : public BlockFile {
|
||||
// Reading
|
||||
|
||||
/// Read the summary section of the disk file
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
/// Read the data section of the disk file
|
||||
size_t ReadData(samplePtr data, sampleFormat format,
|
||||
size_t start, size_t len) const override;
|
||||
|
@ -321,9 +321,8 @@ void SimpleBlockFile::FillCache()
|
||||
}
|
||||
|
||||
// Read summary data into cache
|
||||
mCache.summaryData.reinit(mSummaryInfo.totalSummaryBytes);
|
||||
if (!ReadSummary(mCache.summaryData.get()))
|
||||
memset(mCache.summaryData.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
// Fills with zeroes in case of failure:
|
||||
ReadSummary(mCache.summaryData);
|
||||
|
||||
// Cache is active but already on disk
|
||||
mCache.active = true;
|
||||
@ -336,12 +335,12 @@ void SimpleBlockFile::FillCache()
|
||||
///
|
||||
/// @param *data The buffer to write the data to. It must be at least
|
||||
/// mSummaryinfo.totalSummaryBytes long.
|
||||
bool SimpleBlockFile::ReadSummary(void *data)
|
||||
bool SimpleBlockFile::ReadSummary(ArrayOf<char> &data)
|
||||
{
|
||||
if (mCache.active)
|
||||
{
|
||||
data.reinit( mSummaryInfo.totalSummaryBytes );
|
||||
if (mCache.active) {
|
||||
//wxLogDebug("SimpleBlockFile::ReadSummary(): Summary is already in cache.");
|
||||
memcpy(data, mCache.summaryData.get(), mSummaryInfo.totalSummaryBytes);
|
||||
memcpy(data.get(), mCache.summaryData.get(), mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -357,23 +356,24 @@ bool SimpleBlockFile::ReadSummary(void *data)
|
||||
// FIXME: TRAP_ERR no report to user of absent summary files?
|
||||
// filled with zero instead.
|
||||
if (!file.IsOpened()){
|
||||
memset(data, 0, mSummaryInfo.totalSummaryBytes);
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
mSilentLog = TRUE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mSilentLog=FALSE;
|
||||
mSilentLog = FALSE;
|
||||
|
||||
// The offset is just past the au header
|
||||
// FIXME: Seek in summary file could fail.
|
||||
if( !file.Seek(sizeof(auHeader)) )
|
||||
if( !file.Seek(sizeof(auHeader)) ||
|
||||
file.Read(data.get(), mSummaryInfo.totalSummaryBytes) !=
|
||||
mSummaryInfo.totalSummaryBytes ) {
|
||||
memset(data.get(), 0, mSummaryInfo.totalSummaryBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto read = file.Read(data, mSummaryInfo.totalSummaryBytes);
|
||||
FixSummary(data.get());
|
||||
|
||||
FixSummary(data);
|
||||
|
||||
return (read == mSummaryInfo.totalSummaryBytes);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ class PROFILE_DLL_API SimpleBlockFile /* not final */ : public BlockFile {
|
||||
// Reading
|
||||
|
||||
/// Read the summary section of the disk file
|
||||
bool ReadSummary(void *data) override;
|
||||
bool ReadSummary(ArrayOf<char> &data) override;
|
||||
/// Read the data section of the disk file
|
||||
size_t ReadData(samplePtr data, sampleFormat format,
|
||||
size_t start, size_t len) const override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user