1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-02-07 12:12:23 +01: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.
///