Modernize memory management of FLAC pointers

This commit is contained in:
Chris Thrasher 2023-11-26 17:35:27 -07:00
parent f3341359eb
commit 95465a3359
4 changed files with 48 additions and 86 deletions

View File

@ -184,6 +184,14 @@ void streamError(const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, voi
namespace sf::priv
{
////////////////////////////////////////////////////////////
void SoundFileReaderFlac::FlacStreamDecoderDeleter::operator()(FLAC__StreamDecoder* decoder) const
{
FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
}
////////////////////////////////////////////////////////////
bool SoundFileReaderFlac::check(InputStream& stream)
{
@ -218,18 +226,11 @@ bool SoundFileReaderFlac::check(InputStream& stream)
}
////////////////////////////////////////////////////////////
SoundFileReaderFlac::~SoundFileReaderFlac()
{
close();
}
////////////////////////////////////////////////////////////
bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
{
// Create the decoder
m_decoder = FLAC__stream_decoder_new();
m_decoder.reset(FLAC__stream_decoder_new());
if (!m_decoder)
{
err() << "Failed to open FLAC file (failed to allocate the decoder)" << std::endl;
@ -238,7 +239,7 @@ bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
// Initialize the decoder with our callbacks
m_clientData.stream = &stream;
FLAC__stream_decoder_init_stream(m_decoder,
FLAC__stream_decoder_init_stream(m_decoder.get(),
&streamRead,
&streamSeek,
&streamTell,
@ -250,9 +251,9 @@ bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
&m_clientData);
// Read the header
if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder))
if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder.get()))
{
close();
m_decoder.reset();
err() << "Failed to open FLAC file (failed to read metadata)" << std::endl;
return false;
}
@ -279,13 +280,14 @@ void SoundFileReaderFlac::seek(std::uint64_t sampleOffset)
{
// The "write" callback will populate the leftovers buffer with the first batch of samples from the
// seek destination, and since we want that data in this typical case, we don't re-clear it afterward
FLAC__stream_decoder_seek_absolute(m_decoder, sampleOffset / m_clientData.info.channelCount);
FLAC__stream_decoder_seek_absolute(m_decoder.get(), sampleOffset / m_clientData.info.channelCount);
}
else
{
// FLAC decoder can't skip straight to EOF, so we short-seek by one sample and skip the rest
FLAC__stream_decoder_seek_absolute(m_decoder, (m_clientData.info.sampleCount / m_clientData.info.channelCount) - 1);
FLAC__stream_decoder_skip_single_frame(m_decoder);
FLAC__stream_decoder_seek_absolute(m_decoder.get(),
(m_clientData.info.sampleCount / m_clientData.info.channelCount) - 1);
FLAC__stream_decoder_skip_single_frame(m_decoder.get());
// This was re-populated during the seek, but we're skipping everything in this, so we need it emptied
m_clientData.leftovers.clear();
@ -331,27 +333,15 @@ std::uint64_t SoundFileReaderFlac::read(std::int16_t* samples, std::uint64_t max
{
// Everything happens in the "write" callback
// This will break on any fatal error (does not include EOF)
if (!FLAC__stream_decoder_process_single(m_decoder))
if (!FLAC__stream_decoder_process_single(m_decoder.get()))
break;
// Break on EOF
if (FLAC__stream_decoder_get_state(m_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
if (FLAC__stream_decoder_get_state(m_decoder.get()) == FLAC__STREAM_DECODER_END_OF_STREAM)
break;
}
return maxCount - m_clientData.remaining;
}
////////////////////////////////////////////////////////////
void SoundFileReaderFlac::close()
{
if (m_decoder)
{
FLAC__stream_decoder_finish(m_decoder);
FLAC__stream_decoder_delete(m_decoder);
m_decoder = nullptr;
}
}
} // namespace sf::priv

View File

@ -30,6 +30,7 @@
#include <SFML/Audio/SoundFileReader.hpp>
#include <FLAC/stream_decoder.h>
#include <memory>
#include <vector>
@ -52,12 +53,6 @@ public:
////////////////////////////////////////////////////////////
[[nodiscard]] static bool check(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
~SoundFileReaderFlac() override;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for reading
///
@ -108,17 +103,15 @@ public:
};
private:
////////////////////////////////////////////////////////////
/// \brief Close the open FLAC file
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FLAC__StreamDecoder* m_decoder{}; //!< FLAC decoder
ClientData m_clientData; //!< Structure passed to the decoder callbacks
struct FlacStreamDecoderDeleter
{
void operator()(FLAC__StreamDecoder* decoder) const;
};
std::unique_ptr<FLAC__StreamDecoder, FlacStreamDecoderDeleter> m_decoder; //!< FLAC decoder
ClientData m_clientData; //!< Structure passed to the decoder callbacks
};
} // namespace sf::priv

View File

@ -39,6 +39,14 @@
namespace sf::priv
{
////////////////////////////////////////////////////////////
void SoundFileWriterFlac::FlacStreamEncoderDeleter::operator()(FLAC__StreamEncoder* encoder) const
{
FLAC__stream_encoder_finish(encoder);
FLAC__stream_encoder_delete(encoder);
}
////////////////////////////////////////////////////////////
bool SoundFileWriterFlac::check(const std::filesystem::path& filename)
{
@ -46,18 +54,11 @@ bool SoundFileWriterFlac::check(const std::filesystem::path& filename)
}
////////////////////////////////////////////////////////////
SoundFileWriterFlac::~SoundFileWriterFlac()
{
close();
}
////////////////////////////////////////////////////////////
bool SoundFileWriterFlac::open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
{
// Create the encoder
m_encoder = FLAC__stream_encoder_new();
m_encoder.reset(FLAC__stream_encoder_new());
if (!m_encoder)
{
err() << "Failed to write flac file (failed to allocate encoder)\n"
@ -66,16 +67,16 @@ bool SoundFileWriterFlac::open(const std::filesystem::path& filename, unsigned i
}
// Setup the encoder
FLAC__stream_encoder_set_channels(m_encoder, channelCount);
FLAC__stream_encoder_set_bits_per_sample(m_encoder, 16);
FLAC__stream_encoder_set_sample_rate(m_encoder, sampleRate);
FLAC__stream_encoder_set_channels(m_encoder.get(), channelCount);
FLAC__stream_encoder_set_bits_per_sample(m_encoder.get(), 16);
FLAC__stream_encoder_set_sample_rate(m_encoder.get(), sampleRate);
// Initialize the output stream
if (FLAC__stream_encoder_init_file(m_encoder, filename.string().c_str(), nullptr, nullptr) !=
if (FLAC__stream_encoder_init_file(m_encoder.get(), filename.string().c_str(), nullptr, nullptr) !=
FLAC__STREAM_ENCODER_INIT_STATUS_OK)
{
err() << "Failed to write flac file (failed to open the file)\n" << formatDebugPathInfo(filename) << std::endl;
close();
m_encoder.reset();
return false;
}
@ -98,7 +99,7 @@ void SoundFileWriterFlac::write(const std::int16_t* samples, std::uint64_t count
m_samples32.assign(samples, samples + frames * m_channelCount);
// Write them to the FLAC stream
FLAC__stream_encoder_process_interleaved(m_encoder, m_samples32.data(), frames);
FLAC__stream_encoder_process_interleaved(m_encoder.get(), m_samples32.data(), frames);
// Next chunk
count -= m_samples32.size();
@ -106,19 +107,4 @@ void SoundFileWriterFlac::write(const std::int16_t* samples, std::uint64_t count
}
}
////////////////////////////////////////////////////////////
void SoundFileWriterFlac::close()
{
if (m_encoder)
{
// Close the output stream
FLAC__stream_encoder_finish(m_encoder);
// Destroy the encoder
FLAC__stream_encoder_delete(m_encoder);
m_encoder = nullptr;
}
}
} // namespace sf::priv

View File

@ -31,6 +31,7 @@
#include <FLAC/stream_encoder.h>
#include <filesystem>
#include <memory>
#include <vector>
@ -53,12 +54,6 @@ public:
////////////////////////////////////////////////////////////
[[nodiscard]] static bool check(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundFileWriterFlac() override;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for writing
///
@ -81,18 +76,16 @@ public:
void write(const std::int16_t* samples, std::uint64_t count) override;
private:
////////////////////////////////////////////////////////////
/// \brief Close the file
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FLAC__StreamEncoder* m_encoder{}; //!< FLAC stream encoder
unsigned int m_channelCount{}; //!< Number of channels
std::vector<std::int32_t> m_samples32; //!< Conversion buffer
struct FlacStreamEncoderDeleter
{
void operator()(FLAC__StreamEncoder* encoder) const;
};
std::unique_ptr<FLAC__StreamEncoder, FlacStreamEncoderDeleter> m_encoder; //!< FLAC stream encoder
unsigned int m_channelCount{}; //!< Number of channels
std::vector<std::int32_t> m_samples32; //!< Conversion buffer
};
} // namespace sf::priv