1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-06 07:09:39 +02:00

BlockFile::ReadData overrides: on failure, pad with 0s or throw...

... as the mayThrow argument directs.
This commit is contained in:
Paul Licameli 2016-12-25 08:42:44 -05:00
parent 70d9e4bdc7
commit 98d1468a01
14 changed files with 113 additions and 84 deletions

View File

@ -376,7 +376,8 @@ auto BlockFile::GetMinMaxRMS(size_t start, size_t len, bool mayThrow)
{
// TODO: actually use summaries
SampleBuffer blockData(len, floatSample);
this->ReadData(blockData.ptr(), floatSample, start, len);
this->ReadData(blockData.ptr(), floatSample, start, len, mayThrow);
float min = FLT_MAX;
float max = -FLT_MAX;
@ -485,6 +486,7 @@ bool BlockFile::Read64K(float *buffer,
}
size_t BlockFile::CommonReadData(
bool mayThrow,
const wxFileName &fileName, bool &mSilentLog,
const AliasBlockFile *pAliasFile, sampleCount origin, unsigned channel,
samplePtr data, sampleFormat format, size_t start, size_t len,
@ -534,80 +536,89 @@ size_t BlockFile::CommonReadData(
// libsndfile can't (under Windows).
sf.reset(SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE));
}
// FIXME: TRAP_ERR failure of wxFile open incompletely handled in BlockFile::CommonReadData.
if (!sf) {
memset(data, 0, SAMPLE_SIZE(format)*len);
mSilentLog = TRUE;
if (pAliasFile) {
// Set a marker to display an error message for the silence
if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
wxGetApp().MarkAliasedFilesMissingWarning(pAliasFile);
}
return len;
}
}
mSilentLog=FALSE;
SFCall<sf_count_t>(
sf_seek, sf.get(), ( origin + start ).as_long_long(), SEEK_SET);
auto channels = info.channels;
wxASSERT(channels >= 1);
wxASSERT(channel < channels);
mSilentLog = !sf;
size_t framesRead = 0;
if (sf) {
auto seek_result = SFCall<sf_count_t>(
sf_seek, sf.get(), ( origin + start ).as_long_long(), SEEK_SET);
if (channels == 1 &&
format == int16Sample &&
sf_subtype_is_integer(info.format)) {
// If both the src and dest formats are integer formats,
// read integers directly from the file, comversions not needed
framesRead = SFCall<sf_count_t>(
sf_readf_short, sf.get(), (short *)data, len);
}
else if (channels == 1 &&
format == int24Sample &&
sf_subtype_is_integer(info.format)) {
framesRead = SFCall<sf_count_t>(sf_readf_int, sf.get(), (int *)data, len);
if (seek_result < 0)
// error
;
else {
auto channels = info.channels;
wxASSERT(channels >= 1);
wxASSERT(channel < channels);
// libsndfile gave us the 3 byte sample in the 3 most
// significant bytes -- we want it in the 3 least
// significant bytes.
int *intPtr = (int *)data;
for( int i = 0; i < framesRead; i++ )
intPtr[i] = intPtr[i] >> 8;
if (channels == 1 &&
format == int16Sample &&
sf_subtype_is_integer(info.format)) {
// If both the src and dest formats are integer formats,
// read integers directly from the file, comversions not needed
framesRead = SFCall<sf_count_t>(
sf_readf_short, sf.get(), (short *)data, len);
}
else if (channels == 1 &&
format == int24Sample &&
sf_subtype_is_integer(info.format)) {
framesRead = SFCall<sf_count_t>(
sf_readf_int, sf.get(), (int *)data, len);
// libsndfile gave us the 3 byte sample in the 3 most
// significant bytes -- we want it in the 3 least
// significant bytes.
int *intPtr = (int *)data;
for( int i = 0; i < framesRead; i++ )
intPtr[i] = intPtr[i] >> 8;
}
else if (format == int16Sample &&
!sf_subtype_more_than_16_bits(info.format)) {
// Special case: if the file is in 16-bit (or less) format,
// and the calling method wants 16-bit data, go ahead and
// read 16-bit data directly. This is a pretty common
// case, as most audio files are 16-bit.
SampleBuffer buffer(len * channels, int16Sample);
framesRead = SFCall<sf_count_t>(
sf_readf_short, sf.get(), (short *)buffer.ptr(), len);
for (int i = 0; i < framesRead; i++)
((short *)data)[i] =
((short *)buffer.ptr())[(channels * i) + channel];
}
else {
// Otherwise, let libsndfile handle the conversion and
// scaling, and pass us normalized data as floats. We can
// then convert to whatever format we want.
SampleBuffer buffer(len * channels, floatSample);
framesRead = SFCall<sf_count_t>(
sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
auto bufferPtr = (samplePtr)((float *)buffer.ptr() + channel);
CopySamples(bufferPtr, floatSample,
(samplePtr)data, format,
framesRead,
true /* high quality by default */,
channels /* source stride */);
}
}
}
else if (format == int16Sample &&
!sf_subtype_more_than_16_bits(info.format)) {
// Special case: if the file is in 16-bit (or less) format,
// and the calling method wants 16-bit data, go ahead and
// read 16-bit data directly. This is a pretty common
// case, as most audio files are 16-bit.
SampleBuffer buffer(len * channels, int16Sample);
framesRead = SFCall<sf_count_t>(
sf_readf_short, sf.get(), (short *)buffer.ptr(), len);
for (int i = 0; i < framesRead; i++)
((short *)data)[i] =
((short *)buffer.ptr())[(channels * i) + channel];
}
else {
// Otherwise, let libsndfile handle the conversion and
// scaling, and pass us normalized data as floats. We can
// then convert to whatever format we want.
SampleBuffer buffer(len * channels, floatSample);
framesRead = SFCall<sf_count_t>(
sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
auto bufferPtr = (samplePtr)((float *)buffer.ptr() + channel);
CopySamples(bufferPtr, floatSample,
(samplePtr)data, format,
framesRead,
true /* high quality by default */,
channels /* source stride */);
if ( framesRead < len ) {
if (mayThrow)
//throw FileException{ FileException::Cause::Read, fileName }
;
ClearSamples(data, format, framesRead, len - framesRead);
}
return framesRead;

View File

@ -67,8 +67,12 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
// Reading
/// Retrieves audio data from this BlockFile
/// Returns the number of samples really read, not more than len
/// If fewer can be read than len, throws an exception if mayThrow is true,
/// otherwise fills the remainder of data with zeroes.
virtual size_t ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const = 0;
size_t start, size_t len, bool mayThrow = true)
const = 0;
// Other Properties
@ -223,6 +227,7 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
virtual void FixSummary(void *data);
static size_t CommonReadData(
bool mayThrow,
const wxFileName &fileName, bool &mSilentLog,
const AliasBlockFile *pAliasFile, sampleCount origin, unsigned channel,
samplePtr data, sampleFormat format, size_t start, size_t len,

View File

@ -194,10 +194,10 @@ bool LegacyBlockFile::ReadSummary(ArrayOf<char> &data)
/// @param start The offset in this block file
/// @param len The number of samples to read
size_t LegacyBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
size_t start, size_t len, bool mayThrow) const
{
sf_count_t origin = (mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));
return CommonReadData(
return CommonReadData( mayThrow,
mFileName, mSilentLog, nullptr, origin, 0, data, format, start, len,
&mFormat, mLen
);

View File

@ -51,7 +51,7 @@ class LegacyBlockFile final : public BlockFile {
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;
size_t start, size_t len, bool mayThrow) const override;
/// Create a NEW block file identical to this one
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;

View File

@ -438,20 +438,22 @@ void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len,
/// @param start The offset within the block to begin reading
/// @param len The number of samples to read
size_t ODDecodeBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
size_t start, size_t len, bool mayThrow) const
{
size_t ret;
auto locker = LockForRead();
if(IsSummaryAvailable())
ret = SimpleBlockFile::ReadData(data,format,start,len);
return SimpleBlockFile::ReadData(data, format, start, len, mayThrow);
else
{
if (mayThrow)
//throw NotYetAvailableException{ mFileName }
;
//we should do an ODRequest to start processing the data here, and wait till it finishes. and just do a SimpleBlockFile
//ReadData.
ClearSamples(data, format, 0, len);
ret = len;
return 0;
}
return ret;
}
/// Read the summary of this alias block from disk. Since the audio data

View File

@ -109,7 +109,7 @@ class ODDecodeBlockFile final : public SimpleBlockFile
/// Reads the specified data from the aliased file using libsndfile
size_t ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const override;
size_t start, size_t len, bool mayThrow) const override;
/// Read the summary into a buffer
bool ReadSummary(ArrayOf<char> &data) override;

View File

@ -414,7 +414,7 @@ void ODPCMAliasBlockFile::WriteSummary()
// To build the summary data, call ReadData (implemented by the
// derived classes) to get the sample data
SampleBuffer sampleData(mLen, floatSample);
this->ReadData(sampleData.ptr(), floatSample, 0, mLen);
this->ReadData(sampleData.ptr(), floatSample, 0, mLen, true);
ArrayOf<char> cleanup;
void *summaryData = CalcSummary(sampleData.ptr(), mLen,
@ -495,7 +495,7 @@ void *ODPCMAliasBlockFile::CalcSummary(samplePtr buffer, size_t len,
/// @param start The offset within the block to begin reading
/// @param len The number of samples to read
size_t ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
size_t start, size_t len, bool mayThrow) const
{
auto locker = LockForRead();
@ -505,7 +505,7 @@ size_t ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
return len;
}
return CommonReadData(
return CommonReadData( mayThrow,
mAliasedFileName, mSilentAliasLog, this, mAliasStart, mAliasChannel,
data, format, start, len);
}

View File

@ -118,7 +118,7 @@ class ODPCMAliasBlockFile final : public PCMAliasBlockFile
/// Reads the specified data from the aliased file using libsndfile
size_t ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const override;
size_t start, size_t len, bool mayThrow) const override;
/// Read the summary into a buffer
bool ReadSummary(ArrayOf<char> &data) override;

View File

@ -75,14 +75,14 @@ PCMAliasBlockFile::~PCMAliasBlockFile()
/// @param start The offset within the block to begin reading
/// @param len The number of samples to read
size_t PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
size_t start, size_t len, bool mayThrow) const
{
if(!mAliasedFileName.IsOk()){ // intentionally silenced
memset(data, 0, SAMPLE_SIZE(format) * len);
return len;
}
return CommonReadData(
return CommonReadData( mayThrow,
mAliasedFileName, mSilentAliasLog, this, mAliasStart, mAliasChannel,
data, format, start, len);
}

View File

@ -38,7 +38,7 @@ class PCMAliasBlockFile /* not final */ : public AliasBlockFile
/// Reads the specified data from the aliased file using libsndfile
size_t ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const override;
size_t start, size_t len, bool mayThrow) const override;
void SaveXML(XMLWriter &xmlFile) override;
BlockFilePtr Copy(wxFileNameWrapper &&fileName) override;

View File

@ -32,7 +32,7 @@ bool SilentBlockFile::ReadSummary(ArrayOf<char> &data)
}
size_t SilentBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t WXUNUSED(start), size_t len) const
size_t WXUNUSED(start), size_t len, bool) const
{
ClearSamples(data, format, 0, len);

View File

@ -36,7 +36,7 @@ class SilentBlockFile final : public BlockFile {
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;
size_t start, size_t len, bool mayThrow) const override;
/// Create a NEW block file identical to this one
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;

View File

@ -315,7 +315,9 @@ void SimpleBlockFile::FillCache()
// Read samples into cache
mCache.sampleData.reinit(mLen * SAMPLE_SIZE(mCache.format));
if (ReadData(mCache.sampleData.get(), mCache.format, 0, mLen) != mLen)
if (ReadData(mCache.sampleData.get(), mCache.format, 0, mLen,
// no exceptions!
false) != mLen)
{
// Could not read all samples
mCache.sampleData.reset();
@ -387,21 +389,30 @@ bool SimpleBlockFile::ReadSummary(ArrayOf<char> &data)
/// @param start The offset in this block file
/// @param len The number of samples to read
size_t SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
size_t start, size_t len, bool mayThrow) const
{
if (mCache.active)
{
//wxLogDebug("SimpleBlockFile::ReadData(): Data are already in cache.");
len = std::min(len, std::max(start, mLen) - start);
auto framesRead = std::min(len, std::max(start, mLen) - start);
CopySamples(
(samplePtr)(mCache.sampleData.get() +
start * SAMPLE_SIZE(mCache.format)),
mCache.format, data, format, len);
return len;
mCache.format, data, format, framesRead);
if ( framesRead < len ) {
if (mayThrow)
// Not the best exception class?
//throw FileException{ FileException::Cause::Read, mFileName }
;
ClearSamples(data, format, framesRead, len - framesRead);
}
return framesRead;
}
else
return CommonReadData(
return CommonReadData( mayThrow,
mFileName, mSilentLog, nullptr, 0, 0, data, format, start, len);
}

View File

@ -66,7 +66,7 @@ class PROFILE_DLL_API SimpleBlockFile /* not final */ : public BlockFile {
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;
size_t start, size_t len, bool mayThrow) const override;
/// Create a NEW block file identical to this one
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;