2022-07-25 14:36:05 +08:00
|
|
|
#include <SFML/Audio/Music.hpp>
|
|
|
|
|
2023-04-16 10:50:24 +08:00
|
|
|
// Other 1st party headers
|
|
|
|
#include <SFML/System/FileInputStream.hpp>
|
|
|
|
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
|
|
|
|
|
|
#include <AudioUtil.hpp>
|
|
|
|
#include <SystemUtil.hpp>
|
|
|
|
#include <thread>
|
2022-07-25 14:36:05 +08:00
|
|
|
#include <type_traits>
|
|
|
|
|
2023-04-16 10:50:24 +08:00
|
|
|
TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
|
|
|
|
{
|
|
|
|
SECTION("Type traits")
|
|
|
|
{
|
|
|
|
STATIC_CHECK(!std::is_copy_constructible_v<sf::Music>);
|
|
|
|
STATIC_CHECK(!std::is_copy_assignable_v<sf::Music>);
|
2024-06-09 02:05:39 +08:00
|
|
|
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::Music>);
|
|
|
|
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Music>);
|
2023-04-16 10:50:24 +08:00
|
|
|
STATIC_CHECK(std::has_virtual_destructor_v<sf::Music>);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Span")
|
|
|
|
{
|
|
|
|
const sf::Music::Span<float> span;
|
|
|
|
CHECK(span.offset == 0);
|
|
|
|
CHECK(span.length == 0);
|
|
|
|
|
|
|
|
const sf::Music::TimeSpan timeSpan;
|
|
|
|
CHECK(timeSpan.offset == sf::Time::Zero);
|
|
|
|
CHECK(timeSpan.length == sf::Time::Zero);
|
|
|
|
}
|
|
|
|
|
2024-07-06 10:24:00 +08:00
|
|
|
SECTION("Constructor")
|
2024-07-06 09:38:32 +08:00
|
|
|
{
|
2024-07-06 10:24:00 +08:00
|
|
|
SECTION("Default constructor")
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
CHECK(music.getChannelCount() == 0);
|
|
|
|
CHECK(music.getSampleRate() == 0);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("File")
|
|
|
|
{
|
|
|
|
SECTION("Invalid file")
|
|
|
|
{
|
|
|
|
CHECK_THROWS_AS(sf::Music("does/not/exist.wav"), std::runtime_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Valid file")
|
|
|
|
{
|
|
|
|
const sf::Music music("Audio/ding.mp3");
|
|
|
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(1990884));
|
|
|
|
CHECK(music.getChannelCount() == 1);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Memory")
|
|
|
|
{
|
|
|
|
std::vector<std::byte> memory(10, std::byte{0xCA});
|
|
|
|
|
|
|
|
SECTION("Invalid buffer")
|
|
|
|
{
|
|
|
|
CHECK_THROWS_AS(sf::Music(memory.data(), memory.size()), std::runtime_error);
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Valid buffer")
|
|
|
|
{
|
|
|
|
memory = loadIntoMemory("Audio/ding.flac");
|
|
|
|
|
|
|
|
const sf::Music music(memory.data(), memory.size());
|
|
|
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(1990884));
|
|
|
|
CHECK(music.getChannelCount() == 1);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Stream")
|
|
|
|
{
|
|
|
|
sf::FileInputStream stream("Audio/doodle_pop.ogg");
|
|
|
|
const sf::Music music(stream);
|
|
|
|
CHECK(music.getDuration() == sf::microseconds(24002176));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(24002176));
|
|
|
|
CHECK(music.getChannelCount() == 2);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 10:24:00 +08:00
|
|
|
}
|
2024-07-06 09:38:32 +08:00
|
|
|
}
|
|
|
|
|
2023-04-16 10:50:24 +08:00
|
|
|
SECTION("openFromFile()")
|
|
|
|
{
|
2024-07-06 09:38:32 +08:00
|
|
|
sf::Music music;
|
|
|
|
|
2023-04-16 10:50:24 +08:00
|
|
|
SECTION("Invalid file")
|
|
|
|
{
|
2024-07-06 09:38:32 +08:00
|
|
|
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);
|
|
|
|
CHECK(music.getChannelCount() == 0);
|
|
|
|
CHECK(music.getSampleRate() == 0);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2023-04-16 10:50:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Valid file")
|
|
|
|
{
|
2024-07-06 09:38:32 +08:00
|
|
|
REQUIRE(music.openFromFile("Audio/ding.mp3"));
|
2023-04-16 10:50:24 +08:00
|
|
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(1990884));
|
|
|
|
CHECK(music.getChannelCount() == 1);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
2024-05-17 02:57:40 +08:00
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
2023-04-16 10:50:24 +08:00
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2023-04-16 10:50:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("openFromMemory()")
|
2024-07-06 09:38:32 +08:00
|
|
|
{
|
|
|
|
std::vector<std::byte> memory;
|
|
|
|
sf::Music music;
|
|
|
|
|
|
|
|
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);
|
|
|
|
CHECK(music.getChannelCount() == 0);
|
|
|
|
CHECK(music.getSampleRate() == 0);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 09:38:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Valid buffer")
|
|
|
|
{
|
|
|
|
memory = loadIntoMemory("Audio/ding.flac");
|
|
|
|
REQUIRE(music.openFromMemory(memory.data(), memory.size()));
|
|
|
|
CHECK(music.getDuration() == sf::microseconds(1990884));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(1990884));
|
|
|
|
CHECK(music.getChannelCount() == 1);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 09:38:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("openFromStream()")
|
|
|
|
{
|
|
|
|
sf::FileInputStream stream;
|
|
|
|
sf::Music music;
|
|
|
|
|
|
|
|
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);
|
|
|
|
CHECK(music.getChannelCount() == 0);
|
|
|
|
CHECK(music.getSampleRate() == 0);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 09:38:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("Valid stream")
|
|
|
|
{
|
|
|
|
REQUIRE(stream.open("Audio/doodle_pop.ogg"));
|
|
|
|
REQUIRE(music.openFromStream(stream));
|
|
|
|
CHECK(music.getDuration() == sf::microseconds(24002176));
|
|
|
|
const auto [offset, length] = music.getLoopPoints();
|
|
|
|
CHECK(offset == sf::Time::Zero);
|
|
|
|
CHECK(length == sf::microseconds(24002176));
|
|
|
|
CHECK(music.getChannelCount() == 2);
|
|
|
|
CHECK(music.getSampleRate() == 44100);
|
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
|
|
|
CHECK(music.getPlayingOffset() == sf::Time::Zero);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2024-07-06 09:38:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-16 10:50:24 +08:00
|
|
|
SECTION("play/pause/stop")
|
|
|
|
{
|
2024-07-06 10:24:00 +08:00
|
|
|
sf::Music music("Audio/ding.mp3");
|
2023-04-16 10:50:24 +08:00
|
|
|
|
|
|
|
// Wait for background thread to start
|
|
|
|
music.play();
|
2024-05-17 02:57:40 +08:00
|
|
|
while (music.getStatus() == sf::Music::Status::Stopped)
|
2023-04-16 10:50:24 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
2024-05-17 02:57:40 +08:00
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Playing);
|
2023-04-16 10:50:24 +08:00
|
|
|
|
|
|
|
// Wait for background thread to pause
|
|
|
|
music.pause();
|
2024-05-17 02:57:40 +08:00
|
|
|
while (music.getStatus() == sf::Music::Status::Playing)
|
2023-04-16 10:50:24 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
2024-05-17 02:57:40 +08:00
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Paused);
|
2023-04-16 10:50:24 +08:00
|
|
|
|
|
|
|
// Wait for background thread to stop
|
|
|
|
music.stop();
|
2024-05-17 02:57:40 +08:00
|
|
|
while (music.getStatus() == sf::Music::Status::Paused)
|
2023-04-16 10:50:24 +08:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
2024-05-17 02:57:40 +08:00
|
|
|
CHECK(music.getStatus() == sf::Music::Status::Stopped);
|
2023-04-16 10:50:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION("setLoopPoints()")
|
|
|
|
{
|
2024-07-06 10:24:00 +08:00
|
|
|
sf::Music music("Audio/killdeer.wav");
|
2024-05-21 09:42:43 +08:00
|
|
|
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);
|
2024-08-06 02:55:10 +08:00
|
|
|
CHECK(!music.isLooping());
|
2023-04-16 10:50:24 +08:00
|
|
|
}
|
|
|
|
}
|