mirror of
https://github.com/SFML/SFML.git
synced 2025-01-19 15:55:13 +08:00
Modernize memory management of FLAC pointers
This commit is contained in:
parent
f3341359eb
commit
95465a3359
@ -184,6 +184,14 @@ void streamError(const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, voi
|
|||||||
|
|
||||||
namespace sf::priv
|
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)
|
bool SoundFileReaderFlac::check(InputStream& stream)
|
||||||
{
|
{
|
||||||
@ -218,18 +226,11 @@ bool SoundFileReaderFlac::check(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
SoundFileReaderFlac::~SoundFileReaderFlac()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
|
bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
|
||||||
{
|
{
|
||||||
// Create the decoder
|
// Create the decoder
|
||||||
m_decoder = FLAC__stream_decoder_new();
|
m_decoder.reset(FLAC__stream_decoder_new());
|
||||||
if (!m_decoder)
|
if (!m_decoder)
|
||||||
{
|
{
|
||||||
err() << "Failed to open FLAC file (failed to allocate the decoder)" << std::endl;
|
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
|
// Initialize the decoder with our callbacks
|
||||||
m_clientData.stream = &stream;
|
m_clientData.stream = &stream;
|
||||||
FLAC__stream_decoder_init_stream(m_decoder,
|
FLAC__stream_decoder_init_stream(m_decoder.get(),
|
||||||
&streamRead,
|
&streamRead,
|
||||||
&streamSeek,
|
&streamSeek,
|
||||||
&streamTell,
|
&streamTell,
|
||||||
@ -250,9 +251,9 @@ bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
|
|||||||
&m_clientData);
|
&m_clientData);
|
||||||
|
|
||||||
// Read the header
|
// 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;
|
err() << "Failed to open FLAC file (failed to read metadata)" << std::endl;
|
||||||
return false;
|
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
|
// 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
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// FLAC decoder can't skip straight to EOF, so we short-seek by one sample and skip the rest
|
// 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_seek_absolute(m_decoder.get(),
|
||||||
FLAC__stream_decoder_skip_single_frame(m_decoder);
|
(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
|
// This was re-populated during the seek, but we're skipping everything in this, so we need it emptied
|
||||||
m_clientData.leftovers.clear();
|
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
|
// Everything happens in the "write" callback
|
||||||
// This will break on any fatal error (does not include EOF)
|
// 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;
|
||||||
|
|
||||||
// Break on EOF
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxCount - m_clientData.remaining;
|
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
|
} // namespace sf::priv
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <SFML/Audio/SoundFileReader.hpp>
|
#include <SFML/Audio/SoundFileReader.hpp>
|
||||||
|
|
||||||
#include <FLAC/stream_decoder.h>
|
#include <FLAC/stream_decoder.h>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
@ -52,12 +53,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] static bool check(InputStream& stream);
|
[[nodiscard]] static bool check(InputStream& stream);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Default constructor
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
~SoundFileReaderFlac() override;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open a sound file for reading
|
/// \brief Open a sound file for reading
|
||||||
///
|
///
|
||||||
@ -108,17 +103,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Close the open FLAC file
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void close();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
FLAC__StreamDecoder* m_decoder{}; //!< FLAC decoder
|
struct FlacStreamDecoderDeleter
|
||||||
ClientData m_clientData; //!< Structure passed to the decoder callbacks
|
{
|
||||||
|
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
|
} // namespace sf::priv
|
||||||
|
@ -39,6 +39,14 @@
|
|||||||
|
|
||||||
namespace sf::priv
|
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)
|
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)
|
bool SoundFileWriterFlac::open(const std::filesystem::path& filename, unsigned int sampleRate, unsigned int channelCount)
|
||||||
{
|
{
|
||||||
// Create the encoder
|
// Create the encoder
|
||||||
m_encoder = FLAC__stream_encoder_new();
|
m_encoder.reset(FLAC__stream_encoder_new());
|
||||||
if (!m_encoder)
|
if (!m_encoder)
|
||||||
{
|
{
|
||||||
err() << "Failed to write flac file (failed to allocate encoder)\n"
|
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
|
// Setup the encoder
|
||||||
FLAC__stream_encoder_set_channels(m_encoder, channelCount);
|
FLAC__stream_encoder_set_channels(m_encoder.get(), channelCount);
|
||||||
FLAC__stream_encoder_set_bits_per_sample(m_encoder, 16);
|
FLAC__stream_encoder_set_bits_per_sample(m_encoder.get(), 16);
|
||||||
FLAC__stream_encoder_set_sample_rate(m_encoder, sampleRate);
|
FLAC__stream_encoder_set_sample_rate(m_encoder.get(), sampleRate);
|
||||||
|
|
||||||
// Initialize the output stream
|
// 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)
|
FLAC__STREAM_ENCODER_INIT_STATUS_OK)
|
||||||
{
|
{
|
||||||
err() << "Failed to write flac file (failed to open the file)\n" << formatDebugPathInfo(filename) << std::endl;
|
err() << "Failed to write flac file (failed to open the file)\n" << formatDebugPathInfo(filename) << std::endl;
|
||||||
close();
|
m_encoder.reset();
|
||||||
return false;
|
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);
|
m_samples32.assign(samples, samples + frames * m_channelCount);
|
||||||
|
|
||||||
// Write them to the FLAC stream
|
// 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
|
// Next chunk
|
||||||
count -= m_samples32.size();
|
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
|
} // namespace sf::priv
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <FLAC/stream_encoder.h>
|
#include <FLAC/stream_encoder.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
@ -53,12 +54,6 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
[[nodiscard]] static bool check(const std::filesystem::path& filename);
|
[[nodiscard]] static bool check(const std::filesystem::path& filename);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Destructor
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
~SoundFileWriterFlac() override;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Open a sound file for writing
|
/// \brief Open a sound file for writing
|
||||||
///
|
///
|
||||||
@ -81,18 +76,16 @@ public:
|
|||||||
void write(const std::int16_t* samples, std::uint64_t count) override;
|
void write(const std::int16_t* samples, std::uint64_t count) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Close the file
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void close();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
FLAC__StreamEncoder* m_encoder{}; //!< FLAC stream encoder
|
struct FlacStreamEncoderDeleter
|
||||||
unsigned int m_channelCount{}; //!< Number of channels
|
{
|
||||||
std::vector<std::int32_t> m_samples32; //!< Conversion buffer
|
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
|
} // namespace sf::priv
|
||||||
|
Loading…
Reference in New Issue
Block a user