diff --git a/include/SFML/Audio/InputSoundFile.hpp b/include/SFML/Audio/InputSoundFile.hpp index 4de7de847..effeed492 100644 --- a/include/SFML/Audio/InputSoundFile.hpp +++ b/include/SFML/Audio/InputSoundFile.hpp @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -64,10 +65,10 @@ public: /// /// \param filename Path of the sound file to load /// - /// \return True if the file was successfully opened + /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); + [[nodiscard]] static std::optional openFromFile(const std::filesystem::path& filename); //////////////////////////////////////////////////////////// /// \brief Open a sound file in memory for reading @@ -78,10 +79,10 @@ public: /// \param data Pointer to the file data in memory /// \param sizeInBytes Size of the data to load, in bytes /// - /// \return True if the file was successfully opened + /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); + [[nodiscard]] static std::optional openFromMemory(const void* data, std::size_t sizeInBytes); //////////////////////////////////////////////////////////// /// \brief Open a sound file from a custom stream for reading @@ -91,10 +92,10 @@ public: /// /// \param stream Source stream to read from /// - /// \return True if the file was successfully opened + /// \return Input sound file if the file was successfully opened, otherwise `std::nullopt` /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromStream(InputStream& stream); + [[nodiscard]] static std::optional openFromStream(InputStream& stream); //////////////////////////////////////////////////////////// /// \brief Get the total number of audio samples in the file @@ -211,6 +212,14 @@ public: void close(); private: + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Useful for implementing close() + /// + //////////////////////////////////////////////////////////// + InputSoundFile() = default; + //////////////////////////////////////////////////////////// /// \brief Deleter for input streams that only conditionally deletes /// @@ -228,6 +237,16 @@ private: bool owned{true}; }; + //////////////////////////////////////////////////////////// + /// \brief Constructor from reader, stream, and attributes + /// + //////////////////////////////////////////////////////////// + InputSoundFile(std::unique_ptr&& reader, + std::unique_ptr&& stream, + std::uint64_t sampleCount, + unsigned int sampleRate, + std::vector&& channelMap); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp index 3cbec84fb..b3ec7020c 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -248,10 +248,10 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - InputSoundFile m_file; //!< The streamed music file - std::vector m_samples; //!< Temporary buffer of samples - std::recursive_mutex m_mutex; //!< Mutex protecting the data - Span m_loopSpan; //!< Loop Range Specifier + std::optional m_file; //!< The streamed music file + std::vector m_samples; //!< Temporary buffer of samples + std::recursive_mutex m_mutex; //!< Mutex protecting the data + Span m_loopSpan; //!< Loop Range Specifier }; } // namespace sf diff --git a/include/SFML/Audio/OutputSoundFile.hpp b/include/SFML/Audio/OutputSoundFile.hpp index 4505b8dd7..e21ad58e7 100644 --- a/include/SFML/Audio/OutputSoundFile.hpp +++ b/include/SFML/Audio/OutputSoundFile.hpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -58,13 +59,14 @@ public: /// \param channelCount Number of channels in the sound /// \param channelMap Map of position in sample frame to sound channel /// - /// \return True if the file was successfully opened + /// \return Output sound file if the file was successfully opened /// //////////////////////////////////////////////////////////// - [[nodiscard]] bool openFromFile(const std::filesystem::path& filename, - unsigned int sampleRate, - unsigned int channelCount, - const std::vector& channelMap); + [[nodiscard]] static std::optional openFromFile( + const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& channelMap); //////////////////////////////////////////////////////////// /// \brief Write audio samples to the file @@ -82,6 +84,12 @@ public: void close(); private: + //////////////////////////////////////////////////////////// + /// \brief Constructor from writer + /// + //////////////////////////////////////////////////////////// + explicit OutputSoundFile(std::unique_ptr&& writer); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// diff --git a/src/SFML/Audio/InputSoundFile.cpp b/src/SFML/Audio/InputSoundFile.cpp index d6beb8075..cc0fb3203 100644 --- a/src/SFML/Audio/InputSoundFile.cpp +++ b/src/SFML/Audio/InputSoundFile.cpp @@ -65,51 +65,36 @@ void InputSoundFile::StreamDeleter::operator()(InputStream* ptr) const //////////////////////////////////////////////////////////// -bool InputSoundFile::openFromFile(const std::filesystem::path& filename) +std::optional InputSoundFile::openFromFile(const std::filesystem::path& filename) { - // If the file is already open, first close it - close(); - // Find a suitable reader for the file type auto reader = SoundFileFactory::createReaderFromFilename(filename); if (!reader) - return false; + return std::nullopt; // Wrap the file into a stream auto file = std::make_unique(); // Open it if (!file->open(filename)) - return false; + return std::nullopt; // Pass the stream to the reader - const auto info = reader->open(*file); + auto info = reader->open(*file); if (!info) - return false; + return std::nullopt; - // Take ownership of successfully opened reader and stream - m_reader = std::move(reader); - m_stream = std::move(file); - - // Retrieve the attributes of the open sound file - m_sampleCount = info->sampleCount; - m_sampleRate = info->sampleRate; - m_channelMap = info->channelMap; - - return true; + return InputSoundFile(std::move(reader), std::move(file), info->sampleCount, info->sampleRate, std::move(info->channelMap)); } //////////////////////////////////////////////////////////// -bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes) +std::optional InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes) { - // If the file is already open, first close it - close(); - // Find a suitable reader for the file type auto reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes); if (!reader) - return false; + return std::nullopt; // Wrap the memory file into a stream auto memory = std::make_unique(); @@ -118,56 +103,35 @@ bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes) memory->open(data, sizeInBytes); // Pass the stream to the reader - const auto info = reader->open(*memory); + auto info = reader->open(*memory); if (!info) - return false; + return std::nullopt; - // Take ownership of successfully opened reader and stream - m_reader = std::move(reader); - m_stream = std::move(memory); - - // Retrieve the attributes of the open sound file - m_sampleCount = info->sampleCount; - m_sampleRate = info->sampleRate; - m_channelMap = info->channelMap; - - return true; + return InputSoundFile(std::move(reader), std::move(memory), info->sampleCount, info->sampleRate, std::move(info->channelMap)); } //////////////////////////////////////////////////////////// -bool InputSoundFile::openFromStream(InputStream& stream) +std::optional InputSoundFile::openFromStream(InputStream& stream) { - // If the file is already open, first close it - close(); - // Find a suitable reader for the file type auto reader = SoundFileFactory::createReaderFromStream(stream); if (!reader) - return false; + return std::nullopt; // Don't forget to reset the stream to its beginning before re-opening it if (stream.seek(0) != 0) { err() << "Failed to open sound file from stream (cannot restart stream)" << std::endl; - return false; + return std::nullopt; } // Pass the stream to the reader - const auto info = reader->open(stream); + auto info = reader->open(stream); if (!info) - return false; + return std::nullopt; - // Take ownership of reader and store a reference to the stream without taking ownership - m_reader = std::move(reader); - m_stream = {&stream, false}; - - // Retrieve the attributes of the open sound file - m_sampleCount = info->sampleCount; - m_sampleRate = info->sampleRate; - m_channelMap = info->channelMap; - - return true; + return InputSoundFile(std::move(reader), {&stream, false}, info->sampleCount, info->sampleRate, std::move(info->channelMap)); } @@ -268,4 +232,19 @@ void InputSoundFile::close() m_channelMap.clear(); } + +//////////////////////////////////////////////////////////// +InputSoundFile::InputSoundFile(std::unique_ptr&& reader, + std::unique_ptr&& stream, + std::uint64_t sampleCount, + unsigned int sampleRate, + std::vector&& channelMap) : +m_reader(std::move(reader)), +m_stream(std::move(stream)), +m_sampleCount(sampleCount), +m_sampleRate(sampleRate), +m_channelMap(std::move(channelMap)) +{ +} + } // namespace sf diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp index 9ed7ff665..25bdd636f 100644 --- a/src/SFML/Audio/Music.cpp +++ b/src/SFML/Audio/Music.cpp @@ -34,6 +34,8 @@ #include #include +#include + namespace sf { @@ -52,7 +54,8 @@ bool Music::openFromFile(const std::filesystem::path& filename) stop(); // Open the underlying sound file - if (!m_file.openFromFile(filename)) + m_file = sf::InputSoundFile::openFromFile(filename); + if (!m_file) return false; // Perform common initializations @@ -69,7 +72,8 @@ bool Music::openFromMemory(const void* data, std::size_t sizeInBytes) stop(); // Open the underlying sound file - if (!m_file.openFromMemory(data, sizeInBytes)) + m_file = sf::InputSoundFile::openFromMemory(data, sizeInBytes); + if (!m_file) return false; // Perform common initializations @@ -86,7 +90,8 @@ bool Music::openFromStream(InputStream& stream) stop(); // Open the underlying sound file - if (!m_file.openFromStream(stream)) + m_file = sf::InputSoundFile::openFromStream(stream); + if (!m_file) return false; // Perform common initializations @@ -99,7 +104,8 @@ bool Music::openFromStream(InputStream& stream) //////////////////////////////////////////////////////////// Time Music::getDuration() const { - return m_file.getDuration(); + assert(m_file && "Music::getDuration() Cannot get duration until music is opened"); + return m_file->getDuration(); } @@ -116,7 +122,8 @@ void Music::setLoopPoints(TimeSpan timePoints) Span samplePoints{timeToSamples(timePoints.offset), timeToSamples(timePoints.length)}; // Check our state. This averts a divide-by-zero. GetChannelCount() is cheap enough to use often - if (getChannelCount() == 0 || m_file.getSampleCount() == 0) + assert(m_file && "Music::setLoopPoints() Cannot set loop points unit music is opened"); + if (getChannelCount() == 0 || m_file->getSampleCount() == 0) { err() << "Music is not in a valid state to assign Loop Points." << std::endl; return; @@ -129,7 +136,7 @@ void Music::setLoopPoints(TimeSpan timePoints) samplePoints.length -= (samplePoints.length % getChannelCount()); // Validate - if (samplePoints.offset >= m_file.getSampleCount()) + if (samplePoints.offset >= m_file->getSampleCount()) { err() << "LoopPoints offset val must be in range [0, Duration)." << std::endl; return; @@ -141,7 +148,7 @@ void Music::setLoopPoints(TimeSpan timePoints) } // Clamp End Point - samplePoints.length = std::min(samplePoints.length, m_file.getSampleCount() - samplePoints.offset); + samplePoints.length = std::min(samplePoints.length, m_file->getSampleCount() - samplePoints.offset); // If this change has no effect, we can return without touching anything if (samplePoints.offset == m_loopSpan.offset && samplePoints.length == m_loopSpan.length) @@ -172,10 +179,12 @@ void Music::setLoopPoints(TimeSpan timePoints) //////////////////////////////////////////////////////////// bool Music::onGetData(SoundStream::Chunk& data) { + assert(m_file && "Music::onGetData() Cannot perform operation until music is opened"); + const std::lock_guard lock(m_mutex); std::size_t toFill = m_samples.size(); - std::uint64_t currentOffset = m_file.getSampleOffset(); + std::uint64_t currentOffset = m_file->getSampleOffset(); const std::uint64_t loopEnd = m_loopSpan.offset + m_loopSpan.length; // If the loop end is enabled and imminent, request less data. @@ -186,11 +195,11 @@ bool Music::onGetData(SoundStream::Chunk& data) // Fill the chunk parameters data.samples = m_samples.data(); - data.sampleCount = static_cast(m_file.read(m_samples.data(), toFill)); + data.sampleCount = static_cast(m_file->read(m_samples.data(), toFill)); currentOffset += data.sampleCount; // Check if we have stopped obtaining samples or reached either the EOF or the loop end point - return (data.sampleCount != 0) && (currentOffset < m_file.getSampleCount()) && + return (data.sampleCount != 0) && (currentOffset < m_file->getSampleCount()) && (currentOffset != loopEnd || m_loopSpan.length == 0); } @@ -198,28 +207,32 @@ bool Music::onGetData(SoundStream::Chunk& data) //////////////////////////////////////////////////////////// void Music::onSeek(Time timeOffset) { + assert(m_file && "Music::onSeek() Cannot perform operation until music is opened"); + const std::lock_guard lock(m_mutex); - m_file.seek(timeOffset); + m_file->seek(timeOffset); } //////////////////////////////////////////////////////////// std::optional Music::onLoop() { + assert(m_file && "Music::onLoop() Cannot perform operation until music is opened"); + // Called by underlying SoundStream so we can determine where to loop. const std::lock_guard lock(m_mutex); - const std::uint64_t currentOffset = m_file.getSampleOffset(); + const std::uint64_t currentOffset = m_file->getSampleOffset(); if (getLoop() && (m_loopSpan.length != 0) && (currentOffset == m_loopSpan.offset + m_loopSpan.length)) { // Looping is enabled, and either we're at the loop end, or we're at the EOF // when it's equivalent to the loop end (loop end takes priority). Send us to loop begin - m_file.seek(m_loopSpan.offset); - return static_cast(m_file.getSampleOffset()); + m_file->seek(m_loopSpan.offset); + return static_cast(m_file->getSampleOffset()); } - else if (getLoop() && (currentOffset >= m_file.getSampleCount())) + else if (getLoop() && (currentOffset >= m_file->getSampleCount())) { // If we're at the EOF, reset to 0 - m_file.seek(0); + m_file->seek(0); return 0; } return std::nullopt; @@ -231,13 +244,13 @@ void Music::initialize() { // Compute the music positions m_loopSpan.offset = 0; - m_loopSpan.length = m_file.getSampleCount(); + m_loopSpan.length = m_file->getSampleCount(); // Resize the internal buffer so that it can contain 1 second of audio samples - m_samples.resize(m_file.getSampleRate() * m_file.getChannelCount()); + m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount()); // Initialize the stream - SoundStream::initialize(m_file.getChannelCount(), m_file.getSampleRate(), m_file.getChannelMap()); + SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate(), m_file->getChannelMap()); } //////////////////////////////////////////////////////////// diff --git a/src/SFML/Audio/OutputSoundFile.cpp b/src/SFML/Audio/OutputSoundFile.cpp index f6b018b05..b5982a50d 100644 --- a/src/SFML/Audio/OutputSoundFile.cpp +++ b/src/SFML/Audio/OutputSoundFile.cpp @@ -33,27 +33,24 @@ namespace sf { //////////////////////////////////////////////////////////// -bool OutputSoundFile::openFromFile(const std::filesystem::path& filename, - unsigned int sampleRate, - unsigned int channelCount, - const std::vector& channelMap) +std::optional OutputSoundFile::openFromFile( + const std::filesystem::path& filename, + unsigned int sampleRate, + unsigned int channelCount, + const std::vector& channelMap) { - // If the file is already open, first close it - close(); - // Find a suitable writer for the file type - m_writer = SoundFileFactory::createWriterFromFilename(filename); - if (!m_writer) - return false; + auto writer = SoundFileFactory::createWriterFromFilename(filename); + if (!writer) + return std::nullopt; // Pass the stream to the reader - if (!m_writer->open(filename, sampleRate, channelCount, channelMap)) + if (!writer->open(filename, sampleRate, channelCount, channelMap)) { - close(); - return false; + return std::nullopt; } - return true; + return OutputSoundFile(std::move(writer)); } @@ -72,4 +69,10 @@ void OutputSoundFile::close() m_writer.reset(); } + +//////////////////////////////////////////////////////////// +OutputSoundFile::OutputSoundFile(std::unique_ptr&& writer) : m_writer(std::move(writer)) +{ +} + } // namespace sf diff --git a/src/SFML/Audio/SoundBuffer.cpp b/src/SFML/Audio/SoundBuffer.cpp index 073257773..8431e2d5b 100644 --- a/src/SFML/Audio/SoundBuffer.cpp +++ b/src/SFML/Audio/SoundBuffer.cpp @@ -70,9 +70,8 @@ SoundBuffer::~SoundBuffer() //////////////////////////////////////////////////////////// std::optional SoundBuffer::loadFromFile(const std::filesystem::path& filename) { - InputSoundFile file; - if (file.openFromFile(filename)) - return initialize(file); + if (auto file = InputSoundFile::openFromFile(filename)) + return initialize(*file); else return std::nullopt; } @@ -81,9 +80,8 @@ std::optional SoundBuffer::loadFromFile(const std::filesystem::path //////////////////////////////////////////////////////////// std::optional SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes) { - InputSoundFile file; - if (file.openFromMemory(data, sizeInBytes)) - return initialize(file); + if (auto file = InputSoundFile::openFromMemory(data, sizeInBytes)) + return initialize(*file); else return std::nullopt; } @@ -92,9 +90,8 @@ std::optional SoundBuffer::loadFromMemory(const void* data, std::si //////////////////////////////////////////////////////////// std::optional SoundBuffer::loadFromStream(InputStream& stream) { - InputSoundFile file; - if (file.openFromStream(stream)) - return initialize(file); + if (auto file = InputSoundFile::openFromStream(stream)) + return initialize(*file); else return std::nullopt; } @@ -136,11 +133,10 @@ std::optional SoundBuffer::loadFromSamples( bool SoundBuffer::saveToFile(const std::filesystem::path& filename) const { // Create the sound file in write mode - OutputSoundFile file; - if (file.openFromFile(filename, getSampleRate(), getChannelCount(), getChannelMap())) + if (auto file = OutputSoundFile::openFromFile(filename, getSampleRate(), getChannelCount(), getChannelMap())) { // Write the samples to the opened file - file.write(m_samples.data(), m_samples.size()); + file->write(m_samples.data(), m_samples.size()); return true; } diff --git a/test/Audio/InputSoundFile.test.cpp b/test/Audio/InputSoundFile.test.cpp index 0737ae7e9..5ecc90b99 100644 --- a/test/Audio/InputSoundFile.test.cpp +++ b/test/Audio/InputSoundFile.test.cpp @@ -15,37 +15,25 @@ TEST_CASE("[Audio] sf::InputSoundFile") { SECTION("Type traits") { + STATIC_CHECK(!std::is_default_constructible_v); STATIC_CHECK(!std::is_copy_constructible_v); STATIC_CHECK(!std::is_copy_assignable_v); STATIC_CHECK(std::is_nothrow_move_constructible_v); STATIC_CHECK(std::is_nothrow_move_assignable_v); } - SECTION("Construction") - { - const sf::InputSoundFile inputSoundFile; - CHECK(inputSoundFile.getSampleCount() == 0); - CHECK(inputSoundFile.getChannelCount() == 0); - CHECK(inputSoundFile.getSampleRate() == 0); - CHECK(inputSoundFile.getDuration() == sf::Time::Zero); - CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); - CHECK(inputSoundFile.getSampleOffset() == 0); - } - SECTION("openFromFile()") { - sf::InputSoundFile inputSoundFile; - SECTION("Invalid file") { - CHECK(!inputSoundFile.openFromFile("does/not/exist.wav")); + CHECK(!sf::InputSoundFile::openFromFile("does/not/exist.wav")); } SECTION("Valid file") { SECTION("flac") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + const auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -56,7 +44,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.mp3")); + const auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.mp3").value(); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -67,7 +55,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - REQUIRE(inputSoundFile.openFromFile("Audio/doodle_pop.ogg")); + const auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/doodle_pop.ogg").value(); CHECK(inputSoundFile.getSampleCount() == 2'116'992); CHECK(inputSoundFile.getChannelCount() == 2); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -78,7 +66,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - REQUIRE(inputSoundFile.openFromFile("Audio/killdeer.wav")); + const auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/killdeer.wav").value(); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -91,9 +79,8 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("openFromMemory()") { - const auto memory = loadIntoMemory("Audio/killdeer.wav"); - sf::InputSoundFile inputSoundFile; - REQUIRE(inputSoundFile.openFromMemory(memory.data(), memory.size())); + const auto memory = loadIntoMemory("Audio/killdeer.wav"); + const auto inputSoundFile = sf::InputSoundFile::openFromMemory(memory.data(), memory.size()).value(); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -104,12 +91,11 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("openFromStream()") { - sf::InputSoundFile inputSoundFile; sf::FileInputStream stream; SECTION("Invalid stream") { - CHECK(!inputSoundFile.openFromStream(stream)); + CHECK(!sf::InputSoundFile::openFromStream(stream)); } SECTION("Valid stream") @@ -117,7 +103,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("flac") { REQUIRE(stream.open("Audio/ding.flac")); - REQUIRE(inputSoundFile.openFromStream(stream)); + const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -129,7 +115,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { REQUIRE(stream.open("Audio/ding.mp3")); - REQUIRE(inputSoundFile.openFromStream(stream)); + const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -141,7 +127,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { REQUIRE(stream.open("Audio/doodle_pop.ogg")); - REQUIRE(inputSoundFile.openFromStream(stream)); + const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); CHECK(inputSoundFile.getSampleCount() == 2'116'992); CHECK(inputSoundFile.getChannelCount() == 2); CHECK(inputSoundFile.getSampleRate() == 44'100); @@ -153,7 +139,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { REQUIRE(stream.open("Audio/killdeer.wav")); - REQUIRE(inputSoundFile.openFromStream(stream)); + const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); CHECK(inputSoundFile.getSampleCount() == 112'941); CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getSampleRate() == 22'050); @@ -166,11 +152,9 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("seek(std::uint64_t)") { - sf::InputSoundFile inputSoundFile; - SECTION("flac") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -178,7 +162,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.mp3")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.mp3").value(); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(22'675)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -186,7 +170,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - REQUIRE(inputSoundFile.openFromFile("Audio/doodle_pop.ogg")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/doodle_pop.ogg").value(); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(11'337)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -194,7 +178,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("wav") { - REQUIRE(inputSoundFile.openFromFile("Audio/killdeer.wav")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/killdeer.wav").value(); inputSoundFile.seek(1'000); CHECK(inputSoundFile.getTimeOffset() == sf::microseconds(45'351)); CHECK(inputSoundFile.getSampleOffset() == 1'000); @@ -203,8 +187,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("seek(Time)") { - sf::InputSoundFile inputSoundFile; - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); inputSoundFile.seek(sf::milliseconds(100)); CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getChannelCount() == 1); @@ -216,21 +199,15 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("read()") { - sf::InputSoundFile inputSoundFile; - std::array samples{}; - - SECTION("Unloaded file") - { - CHECK(inputSoundFile.read(samples.data(), samples.size()) == 0); - } - - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); SECTION("Null address") { CHECK(inputSoundFile.read(nullptr, 10) == 0); } + std::array samples{}; + SECTION("Zero count") { CHECK(inputSoundFile.read(samples.data(), 0) == 0); @@ -240,7 +217,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") { SECTION("flac") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); CHECK(samples == std::array{0, 1, -1, 4}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -249,7 +226,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("mp3") { - REQUIRE(inputSoundFile.openFromFile("Audio/ding.mp3")); + inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.mp3").value(); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); CHECK(samples == std::array{0, -2, 0, 2}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -258,7 +235,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("ogg") { - REQUIRE(inputSoundFile.openFromFile("Audio/doodle_pop.ogg")); + inputSoundFile = sf::InputSoundFile::openFromFile("Audio/doodle_pop.ogg").value(); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); CHECK(samples == std::array{-827, -985, -1168, -1319}); CHECK(inputSoundFile.read(samples.data(), samples.size()) == 4); @@ -274,8 +251,7 @@ TEST_CASE("[Audio] sf::InputSoundFile") SECTION("close()") { - sf::InputSoundFile inputSoundFile; - REQUIRE(inputSoundFile.openFromFile("Audio/ding.flac")); + auto inputSoundFile = sf::InputSoundFile::openFromFile("Audio/ding.flac").value(); inputSoundFile.close(); CHECK(inputSoundFile.getSampleCount() == 0); CHECK(inputSoundFile.getChannelCount() == 0); diff --git a/test/Audio/Music.test.cpp b/test/Audio/Music.test.cpp index 68bd03a4d..2219cf2a6 100644 --- a/test/Audio/Music.test.cpp +++ b/test/Audio/Music.test.cpp @@ -37,7 +37,6 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) SECTION("Construction") { const sf::Music music; - CHECK(music.getDuration() == sf::Time::Zero); const auto [offset, length] = music.getLoopPoints(); CHECK(offset == sf::Time::Zero); CHECK(length == sf::Time::Zero); @@ -55,7 +54,6 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) SECTION("Invalid file") { REQUIRE(!music.openFromFile("does/not/exist.wav")); - CHECK(music.getDuration() == sf::Time::Zero); const auto [offset, length] = music.getLoopPoints(); CHECK(offset == sf::Time::Zero); CHECK(length == sf::Time::Zero); @@ -89,7 +87,6 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) SECTION("Invalid buffer") { REQUIRE(!music.openFromMemory(memory.data(), memory.size())); - CHECK(music.getDuration() == sf::Time::Zero); const auto [offset, length] = music.getLoopPoints(); CHECK(offset == sf::Time::Zero); CHECK(length == sf::Time::Zero); @@ -124,7 +121,6 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) SECTION("Invalid stream") { CHECK(!music.openFromStream(stream)); - CHECK(music.getDuration() == sf::Time::Zero); const auto [offset, length] = music.getLoopPoints(); CHECK(offset == sf::Time::Zero); CHECK(length == sf::Time::Zero); @@ -178,32 +174,15 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests()) SECTION("setLoopPoints()") { sf::Music music; - - SECTION("No file") - { - music.setLoopPoints({sf::Time::Zero, sf::Time::Zero}); - const auto [offset, length] = music.getLoopPoints(); - CHECK(offset == sf::Time::Zero); - CHECK(length == sf::Time::Zero); - CHECK(music.getChannelCount() == 0); - CHECK(music.getSampleRate() == 0); - CHECK(music.getStatus() == sf::Music::Status::Stopped); - CHECK(music.getPlayingOffset() == sf::Time::Zero); - CHECK(!music.getLoop()); - } - - SECTION("Loaded file") - { - REQUIRE(music.openFromFile("Audio/killdeer.wav")); - music.setLoopPoints({sf::seconds(1), sf::seconds(2)}); - const auto [offset, length] = music.getLoopPoints(); - CHECK(offset == sf::seconds(1)); - CHECK(length == sf::seconds(2)); - CHECK(music.getChannelCount() == 1); - CHECK(music.getSampleRate() == 22050); - CHECK(music.getStatus() == sf::Music::Status::Stopped); - CHECK(music.getPlayingOffset() == sf::Time::Zero); - CHECK(!music.getLoop()); - } + REQUIRE(music.openFromFile("Audio/killdeer.wav")); + music.setLoopPoints({sf::seconds(1), sf::seconds(2)}); + const auto [offset, length] = music.getLoopPoints(); + CHECK(offset == sf::seconds(1)); + CHECK(length == sf::seconds(2)); + CHECK(music.getChannelCount() == 1); + CHECK(music.getSampleRate() == 22050); + CHECK(music.getStatus() == sf::Music::Status::Stopped); + CHECK(music.getPlayingOffset() == sf::Time::Zero); + CHECK(!music.getLoop()); } } diff --git a/test/Audio/OutputSoundFile.test.cpp b/test/Audio/OutputSoundFile.test.cpp index 765e79ddd..7f44c5851 100644 --- a/test/Audio/OutputSoundFile.test.cpp +++ b/test/Audio/OutputSoundFile.test.cpp @@ -2,6 +2,7 @@ #include +static_assert(!std::is_default_constructible_v); static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); static_assert(std::is_nothrow_move_constructible_v); diff --git a/test/install/Install.cpp b/test/install/Install.cpp index 8cca0b751..6027cf7e3 100644 --- a/test/install/Install.cpp +++ b/test/install/Install.cpp @@ -8,7 +8,6 @@ int main() { // Audio - [[maybe_unused]] const sf::InputSoundFile inputSoundFile; [[maybe_unused]] const sf::SoundBufferRecorder soundBufferRecorder; [[maybe_unused]] const sf::Music music;