diff --git a/src/SFML/Audio/SoundFileReaderFlac.cpp b/src/SFML/Audio/SoundFileReaderFlac.cpp index aa2a15a63..d632cf45b 100644 --- a/src/SFML/Audio/SoundFileReaderFlac.cpp +++ b/src/SFML/Audio/SoundFileReaderFlac.cpp @@ -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 diff --git a/src/SFML/Audio/SoundFileReaderFlac.hpp b/src/SFML/Audio/SoundFileReaderFlac.hpp index 3ae761e5e..86b2efa19 100644 --- a/src/SFML/Audio/SoundFileReaderFlac.hpp +++ b/src/SFML/Audio/SoundFileReaderFlac.hpp @@ -30,6 +30,7 @@ #include #include +#include #include @@ -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 m_decoder; //!< FLAC decoder + ClientData m_clientData; //!< Structure passed to the decoder callbacks }; } // namespace sf::priv diff --git a/src/SFML/Audio/SoundFileWriterFlac.cpp b/src/SFML/Audio/SoundFileWriterFlac.cpp index 3f8a95cf6..dd9dd55ab 100644 --- a/src/SFML/Audio/SoundFileWriterFlac.cpp +++ b/src/SFML/Audio/SoundFileWriterFlac.cpp @@ -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 diff --git a/src/SFML/Audio/SoundFileWriterFlac.hpp b/src/SFML/Audio/SoundFileWriterFlac.hpp index d8969916f..c988fcc9c 100644 --- a/src/SFML/Audio/SoundFileWriterFlac.hpp +++ b/src/SFML/Audio/SoundFileWriterFlac.hpp @@ -31,6 +31,7 @@ #include #include +#include #include @@ -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 m_samples32; //!< Conversion buffer + struct FlacStreamEncoderDeleter + { + void operator()(FLAC__StreamEncoder* encoder) const; + }; + std::unique_ptr m_encoder; //!< FLAC stream encoder + unsigned int m_channelCount{}; //!< Number of channels + std::vector m_samples32; //!< Conversion buffer }; } // namespace sf::priv