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

One function for the common parts of BlockFile::ReadData overrides

This commit is contained in:
Paul Licameli 2016-12-26 08:09:32 -05:00
parent a86cc1cb3b
commit a4a9df5c03
7 changed files with 157 additions and 292 deletions

View File

@ -55,6 +55,9 @@ out.
#include "Internat.h"
#include "MemoryX.h"
#include "sndfile.h"
#include "FileFormats.h"
#include "AudacityApp.h"
// msmeyer: Define this to add debug output via printf()
//#define DEBUG_BLOCKFILE
@ -498,6 +501,135 @@ bool BlockFile::Read64K(float *buffer,
return true;
}
size_t BlockFile::CommonReadData(
const wxFileName &fileName, bool &mSilentLog,
const AliasBlockFile *pAliasFile, sampleCount origin, unsigned channel,
samplePtr data, sampleFormat format, size_t start, size_t len,
const sampleFormat *pLegacyFormat, size_t legacyLen)
{
// Third party library has its own type alias, check it before
// adding origin + size_t
static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
"Type sf_count_t is too narrow to hold a sampleCount");
SF_INFO info;
memset(&info, 0, sizeof(info));
if ( pLegacyFormat ) {
switch( *pLegacyFormat ) {
case int16Sample:
info.format =
SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU;
break;
default:
case floatSample:
info.format =
SF_FORMAT_RAW | SF_FORMAT_FLOAT | SF_ENDIAN_CPU;
break;
case int24Sample:
info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32 | SF_ENDIAN_CPU;
break;
}
info.samplerate = 44100; // Doesn't matter
info.channels = 1;
info.frames = legacyLen + origin.as_long_long();
}
wxFile f; // will be closed when it goes out of scope
SFFile sf;
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
const auto fullPath = fileName.GetFullPath();
if (wxFile::Exists(fullPath) && f.Open(fullPath)) {
// Even though there is an sf_open() that takes a filename, use the one that
// takes a file descriptor since wxWidgets can open a file with a Unicode name and
// 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);
size_t framesRead = 0;
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 */);
}
return framesRead;
}
/// Constructs an AliasBlockFile based on the given information about
/// the aliased file.
///

View File

@ -44,6 +44,7 @@ class SummaryInfo {
class BlockFile;
class AliasBlockFile;
using BlockFilePtr = std::shared_ptr<BlockFile>;
template< typename Result, typename... Args >
@ -185,6 +186,12 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
/// on a different platform
virtual void FixSummary(void *data);
static size_t CommonReadData(
const wxFileName &fileName, bool &mSilentLog,
const AliasBlockFile *pAliasFile, sampleCount origin, unsigned channel,
samplePtr data, sampleFormat format, size_t start, size_t len,
const sampleFormat *pLegacyFormat = nullptr, size_t legacyLen = 0);
private:
int mLockCount;
@ -247,7 +254,7 @@ class AliasBlockFile /* not final */ : public BlockFile
wxFileNameWrapper mAliasedFileName;
sampleCount mAliasStart;
int mAliasChannel;
const int mAliasChannel;
mutable bool mSilentAliasLog;
};

View File

@ -191,90 +191,11 @@ bool LegacyBlockFile::ReadSummary(void *data)
size_t LegacyBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
{
SF_INFO info;
memset(&info, 0, sizeof(info));
switch(mFormat) {
case int16Sample:
info.format =
SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU;
break;
default:
case floatSample:
info.format =
SF_FORMAT_RAW | SF_FORMAT_FLOAT | SF_ENDIAN_CPU;
break;
case int24Sample:
info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32 | SF_ENDIAN_CPU;
break;
}
info.samplerate = 44100; // Doesn't matter
info.channels = 1;
info.frames = mLen + (mSummaryInfo.totalSummaryBytes /
SAMPLE_SIZE(mFormat));
wxFile f; // will be closed when it goes out of scope
SFFile sf;
if (f.Open(mFileName.GetFullPath())) {
// Even though there is an sf_open() that takes a filename, use the one that
// takes a file descriptor since wxWidgets can open a file with a Unicode name and
// 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 LegacyBlockfile::ReadData.
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
if (!sf){
memset(data, 0, SAMPLE_SIZE(format)*len);
mSilentLog = TRUE;
return len;
}
}
mSilentLog=FALSE;
sf_count_t seekstart = start +
(mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));
SFCall<sf_count_t>(sf_seek, sf.get(), seekstart , SEEK_SET);
SampleBuffer buffer(len, floatSample);
size_t framesRead = 0;
// If both the src and dest formats are integer formats,
// read integers from the file (otherwise we would be
// converting to float and back, which is unneccesary)
if (format == int16Sample &&
sf_subtype_is_integer(info.format)) {
framesRead = SFCall<sf_count_t>(sf_readf_short, sf.get(), (short *)data, len);
}
else if (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 {
// Otherwise, let libsndfile handle the conversion and
// scaling, and pass us normalized data as floats. We can
// then convert to whatever format we want.
framesRead = SFCall<sf_count_t>(sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
CopySamples(buffer.ptr(), floatSample,
(samplePtr)data, format, framesRead);
}
return framesRead;
sf_count_t origin = (mSummaryInfo.totalSummaryBytes / SAMPLE_SIZE(mFormat));
return CommonReadData(
mFileName, mSilentLog, nullptr, origin, 0, data, format, start, len,
&mFormat, mLen
);
}
void LegacyBlockFile::SaveXML(XMLWriter &xmlFile)

View File

@ -185,7 +185,7 @@ class ODDecodeBlockFile final : public SimpleBlockFile
sampleFormat mFormat;
sampleCount mAliasStart;//where in the encoded audio file this block corresponds to.
int mAliasChannel;//The channel number in the encoded file..
const int mAliasChannel;//The channel number in the encoded file..
};

View File

@ -490,81 +490,18 @@ size_t ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
LockRead();
SF_INFO info;
if(!mAliasedFileName.IsOk()){ // intentionally silenced
memset(data,0,SAMPLE_SIZE(format)*len);
UnlockRead();
return len;
}
memset(&info, 0, sizeof(info));
wxString aliasPath = mAliasedFileName.GetFullPath();
wxFile f; // will be closed when it goes out of scope
SFFile sf;
if (f.Exists(aliasPath) && f.Open(aliasPath)) {
// Even though there is an sf_open() that takes a filename, use the one that
// takes a file descriptor since wxWidgets can open a file with a Unicode name and
// 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 ODPCMAliasBlockFile::ReadData.
if (!sf) {
memset(data,0,SAMPLE_SIZE(format)*len);
mSilentAliasLog = TRUE;
// Set a marker to display an error message
if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
wxGetApp().MarkAliasedFilesMissingWarning(this);
UnlockRead();
return len;
}
mSilentAliasLog=FALSE;
// Third party library has its own type alias, check it
static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
"Type sf_count_t is too narrow to hold a sampleCount");
SFCall<sf_count_t>(sf_seek, sf.get(),
( mAliasStart + start ).as_long_long(), SEEK_SET);
wxASSERT(info.channels >= 0);
SampleBuffer buffer(len * info.channels, floatSample);
size_t framesRead = 0;
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.
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())[(info.channels * i) + mAliasChannel];
}
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.
framesRead = SFCall<sf_count_t>(sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
float *bufferPtr = &((float *)buffer.ptr())[mAliasChannel];
CopySamples((samplePtr)bufferPtr, floatSample,
(samplePtr)data, format,
framesRead, true, info.channels);
}
auto result = CommonReadData(
mAliasedFileName, mSilentAliasLog, this, mAliasStart, mAliasChannel,
data, format, start, len);
UnlockRead();
return framesRead;
return result;
}
/// Read the summary of this alias block from disk. Since the audio data

View File

@ -77,79 +77,14 @@ PCMAliasBlockFile::~PCMAliasBlockFile()
size_t PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
size_t start, size_t len) const
{
SF_INFO info;
if(!mAliasedFileName.IsOk()){ // intentionally silenced
memset(data,0,SAMPLE_SIZE(format)*len);
memset(data, 0, SAMPLE_SIZE(format) * len);
return len;
}
wxFile f; // will be closed when it goes out of scope
SFFile sf;
{
Maybe<wxLogNull> silence{};
if (mSilentAliasLog)
silence.create();
memset(&info, 0, sizeof(info));
if (f.Exists(mAliasedFileName.GetFullPath())) { // Don't use Open if file does not exits
if (f.Open(mAliasedFileName.GetFullPath())) {
// Even though there is an sf_open() that takes a filename, use the one that
// takes a file descriptor since wxWidgets can open a file with a Unicode name and
// 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 PCMAliasBlockFile::ReadData.
}
if (!sf) {
memset(data, 0, SAMPLE_SIZE(format)*len);
silence.reset();
mSilentAliasLog = TRUE;
// Set a marker to display an error message for the silence
if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
wxGetApp().MarkAliasedFilesMissingWarning(this);
return len;
}
}
mSilentAliasLog=FALSE;
// Third party library has its own type alias, check it
static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
"Type sf_count_t is too narrow to hold a sampleCount");
SFCall<sf_count_t>(sf_seek, sf.get(),
( mAliasStart + start ).as_long_long(), SEEK_SET);
wxASSERT(info.channels >= 0);
SampleBuffer buffer(len * info.channels, floatSample);
size_t framesRead = 0;
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.
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())[(info.channels * i) + mAliasChannel];
}
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.
framesRead = SFCall<sf_count_t>(sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
float *bufferPtr = &((float *)buffer.ptr())[mAliasChannel];
CopySamples((samplePtr)bufferPtr, floatSample,
(samplePtr)data, format,
framesRead, true, info.channels);
}
return framesRead;
return CommonReadData(
mAliasedFileName, mSilentAliasLog, this, mAliasStart, mAliasChannel,
data, format, start, len);
}
/// Construct a NEW PCMAliasBlockFile based on this one, but writing

View File

@ -402,76 +402,9 @@ size_t SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
mCache.format, data, format, len);
return len;
}
else {
//wxLogDebug("SimpleBlockFile::ReadData(): Reading data from disk.");
SF_INFO info;
wxFile f; // will be closed when it goes out of scope
SFFile sf;
{
Maybe<wxLogNull> silence{};
if (mSilentLog)
silence.create();
memset(&info, 0, sizeof(info));
if (f.Open(mFileName.GetFullPath())) {
// Even though there is an sf_open() that takes a filename, use the one that
// takes a file descriptor since wxWidgets can open a file with a Unicode name and
// 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 SimpleBlockFile::ReadData.
// FIXME: Too much cut and paste code between the different block file types.
if (!sf) {
memset(data, 0, SAMPLE_SIZE(format)*len);
mSilentLog = TRUE;
return len;
}
}
mSilentLog=FALSE;
SFCall<sf_count_t>(sf_seek, sf.get(), start, SEEK_SET);
SampleBuffer buffer(len, floatSample);
size_t framesRead = 0;
// If both the src and dest formats are integer formats,
// read integers from the file (otherwise we would be
// converting to float and back, which is unneccesary)
if (format == int16Sample &&
sf_subtype_is_integer(info.format)) {
framesRead = SFCall<sf_count_t>(sf_readf_short, sf.get(), (short *)data, len);
}
else
if (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 {
// Otherwise, let libsndfile handle the conversion and
// scaling, and pass us normalized data as floats. We can
// then convert to whatever format we want.
framesRead = SFCall<sf_count_t>(sf_readf_float, sf.get(), (float *)buffer.ptr(), len);
CopySamples(buffer.ptr(), floatSample,
(samplePtr)data, format, framesRead);
}
return framesRead;
}
else
return CommonReadData(
mFileName, mSilentLog, nullptr, 0, 0, data, format, start, len);
}
void SimpleBlockFile::SaveXML(XMLWriter &xmlFile)