mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Remove default empty state of sf::SoundBuffer
This commit is contained in:
parent
1a40f01957
commit
add6422e6b
@ -13,9 +13,7 @@
|
||||
void playSound()
|
||||
{
|
||||
// Load a sound buffer from a wav file
|
||||
sf::SoundBuffer buffer;
|
||||
if (!buffer.loadFromFile("resources/killdeer.wav"))
|
||||
return;
|
||||
const auto buffer = sf::SoundBuffer::loadFromFile("resources/killdeer.wav").value();
|
||||
|
||||
// Display sound information
|
||||
std::cout << "killdeer.wav:" << '\n'
|
||||
|
@ -49,9 +49,7 @@ int main()
|
||||
window.setVerticalSyncEnabled(true);
|
||||
|
||||
// Load the sounds used in the game
|
||||
sf::SoundBuffer ballSoundBuffer;
|
||||
if (!ballSoundBuffer.loadFromFile(resourcesDir() / "ball.wav"))
|
||||
return EXIT_FAILURE;
|
||||
const auto ballSoundBuffer = sf::SoundBuffer::loadFromFile(resourcesDir() / "ball.wav").value();
|
||||
sf::Sound ballSound(ballSoundBuffer);
|
||||
|
||||
// Create the SFML logo texture:
|
||||
|
@ -274,12 +274,7 @@ private:
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// sf::SoundBuffer buffer;
|
||||
/// if (!buffer.loadFromFile("sound.wav"))
|
||||
/// {
|
||||
/// // Handle error...
|
||||
/// }
|
||||
///
|
||||
/// const auto buffer = sf::SoundBuffer::loadFromFile("sound.wav").value();
|
||||
/// sf::Sound sound(buffer);
|
||||
/// sound.play();
|
||||
/// \endcode
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <SFML/System/Time.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
@ -54,12 +55,6 @@ class InputStream;
|
||||
class SFML_AUDIO_API SoundBuffer
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer() = default;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Copy constructor
|
||||
///
|
||||
@ -82,12 +77,12 @@ public:
|
||||
///
|
||||
/// \param filename Path of the sound file to load
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
||||
///
|
||||
/// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename);
|
||||
[[nodiscard]] static std::optional<SoundBuffer> loadFromFile(const std::filesystem::path& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load the sound buffer from a file in memory
|
||||
@ -98,12 +93,12 @@ public:
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param sizeInBytes Size of the data to load, in bytes
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
||||
///
|
||||
/// \see loadFromFile, loadFromStream, loadFromSamples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t sizeInBytes);
|
||||
[[nodiscard]] static std::optional<SoundBuffer> loadFromMemory(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load the sound buffer from a custom stream
|
||||
@ -113,12 +108,12 @@ public:
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
||||
///
|
||||
/// \see loadFromFile, loadFromMemory, loadFromSamples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] bool loadFromStream(InputStream& stream);
|
||||
[[nodiscard]] static std::optional<SoundBuffer> loadFromStream(InputStream& stream);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load the sound buffer from an array of audio samples
|
||||
@ -131,12 +126,13 @@ public:
|
||||
/// \param sampleRate Sample rate (number of samples to play per second)
|
||||
/// \param channelMap Map of position in sample frame to sound channel
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
/// \return Sound buffer if loading succeeded, `std::nullopt` if it failed
|
||||
///
|
||||
/// \see loadFromFile, loadFromMemory, saveToFile
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] bool loadFromSamples(const std::int16_t* samples,
|
||||
[[nodiscard]] static std::optional<SoundBuffer> loadFromSamples(
|
||||
const std::int16_t* samples,
|
||||
std::uint64_t sampleCount,
|
||||
unsigned int channelCount,
|
||||
unsigned int sampleRate,
|
||||
@ -247,6 +243,12 @@ public:
|
||||
private:
|
||||
friend class Sound;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct from vector of samples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit SoundBuffer(std::vector<std::int16_t>&& samples);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Initialize the internal state after loading a new sound
|
||||
///
|
||||
@ -255,7 +257,7 @@ private:
|
||||
/// \return True on successful initialization, false on failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] bool initialize(InputSoundFile& file);
|
||||
[[nodiscard]] static std::optional<SoundBuffer> initialize(InputSoundFile& file);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Update the internal buffer with the cached audio samples
|
||||
@ -341,14 +343,8 @@ private:
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Declare a new sound buffer
|
||||
/// sf::SoundBuffer buffer;
|
||||
///
|
||||
/// // Load it from a file
|
||||
/// if (!buffer.loadFromFile("sound.wav"))
|
||||
/// {
|
||||
/// // error...
|
||||
/// }
|
||||
/// // Load a new sound buffer from a file
|
||||
/// const auto buffer = sf::SoundBuffer::loadFromFile("sound.wav").value();
|
||||
///
|
||||
/// // Create a sound source bound to the buffer
|
||||
/// sf::Sound sound1(buffer);
|
||||
|
@ -98,7 +98,7 @@ private:
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<std::int16_t> m_samples; //!< Temporary sample buffer to hold the recorded data
|
||||
SoundBuffer m_buffer; //!< Sound buffer that will contain the recorded data
|
||||
std::optional<SoundBuffer> m_buffer; //!< Sound buffer that will contain the recorded data
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -68,40 +68,41 @@ SoundBuffer::~SoundBuffer()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromFile(const std::filesystem::path& filename)
|
||||
std::optional<SoundBuffer> SoundBuffer::loadFromFile(const std::filesystem::path& filename)
|
||||
{
|
||||
InputSoundFile file;
|
||||
if (file.openFromFile(filename))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
std::optional<SoundBuffer> SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
InputSoundFile file;
|
||||
if (file.openFromMemory(data, sizeInBytes))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromStream(InputStream& stream)
|
||||
std::optional<SoundBuffer> SoundBuffer::loadFromStream(InputStream& stream)
|
||||
{
|
||||
InputSoundFile file;
|
||||
if (file.openFromStream(stream))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
||||
std::optional<SoundBuffer> SoundBuffer::loadFromSamples(
|
||||
const std::int16_t* samples,
|
||||
std::uint64_t sampleCount,
|
||||
unsigned int channelCount,
|
||||
unsigned int sampleRate,
|
||||
@ -110,10 +111,12 @@ bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
||||
if (samples && sampleCount && channelCount && sampleRate && !channelMap.empty())
|
||||
{
|
||||
// Copy the new audio samples
|
||||
m_samples.assign(samples, samples + sampleCount);
|
||||
SoundBuffer soundBuffer(std::vector<std::int16_t>(samples, samples + sampleCount));
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
return update(channelCount, sampleRate, channelMap);
|
||||
if (!soundBuffer.update(channelCount, sampleRate, channelMap))
|
||||
return std::nullopt;
|
||||
return soundBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -124,7 +127,7 @@ bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
|
||||
<< "channels: " << channelCount << ", "
|
||||
<< "samplerate: " << sampleRate << ")" << std::endl;
|
||||
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,21 +209,30 @@ SoundBuffer& SoundBuffer::operator=(const SoundBuffer& right)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::initialize(InputSoundFile& file)
|
||||
SoundBuffer::SoundBuffer(std::vector<std::int16_t>&& samples) : m_samples(std::move(samples))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::optional<SoundBuffer> SoundBuffer::initialize(InputSoundFile& file)
|
||||
{
|
||||
// Retrieve the sound parameters
|
||||
const std::uint64_t sampleCount = file.getSampleCount();
|
||||
|
||||
// Read the samples from the provided file
|
||||
m_samples.resize(static_cast<std::size_t>(sampleCount));
|
||||
if (file.read(m_samples.data(), sampleCount) == sampleCount)
|
||||
std::vector<std::int16_t> samples(static_cast<std::size_t>(sampleCount));
|
||||
if (file.read(samples.data(), sampleCount) == sampleCount)
|
||||
{
|
||||
// Update the internal buffer with the new samples
|
||||
return update(file.getChannelCount(), file.getSampleRate(), file.getChannelMap());
|
||||
SoundBuffer soundBuffer(std::move(samples));
|
||||
if (!soundBuffer.update(file.getChannelCount(), file.getSampleRate(), file.getChannelMap()))
|
||||
return std::nullopt;
|
||||
return soundBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ SoundBufferRecorder::~SoundBufferRecorder()
|
||||
bool SoundBufferRecorder::onStart()
|
||||
{
|
||||
m_samples.clear();
|
||||
m_buffer = SoundBuffer();
|
||||
m_buffer.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -69,7 +69,12 @@ void SoundBufferRecorder::onStop()
|
||||
if (m_samples.empty())
|
||||
return;
|
||||
|
||||
if (!m_buffer.loadFromSamples(m_samples.data(), m_samples.size(), getChannelCount(), getSampleRate(), getChannelMap()))
|
||||
m_buffer = sf::SoundBuffer::loadFromSamples(m_samples.data(),
|
||||
m_samples.size(),
|
||||
getChannelCount(),
|
||||
getSampleRate(),
|
||||
getChannelMap());
|
||||
if (!m_buffer)
|
||||
err() << "Failed to stop capturing audio data" << std::endl;
|
||||
}
|
||||
|
||||
@ -77,7 +82,8 @@ void SoundBufferRecorder::onStop()
|
||||
////////////////////////////////////////////////////////////
|
||||
const SoundBuffer& SoundBufferRecorder::getBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
assert(m_buffer && "SoundBufferRecorder::getBuffer() Cannot return reference to null buffer");
|
||||
return *m_buffer;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
@ -25,8 +25,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
||||
STATIC_CHECK(std::has_virtual_destructor_v<sf::Sound>);
|
||||
}
|
||||
|
||||
sf::SoundBuffer soundBuffer;
|
||||
REQUIRE(soundBuffer.loadFromFile("Audio/ding.flac"));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
|
||||
SECTION("Construction")
|
||||
{
|
||||
@ -52,8 +51,8 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
||||
|
||||
SECTION("Assignment")
|
||||
{
|
||||
const sf::SoundBuffer emptySoundBuffer;
|
||||
sf::Sound soundCopy(emptySoundBuffer);
|
||||
const sf::SoundBuffer otherSoundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
sf::Sound soundCopy(otherSoundBuffer);
|
||||
soundCopy = sound;
|
||||
CHECK(&soundCopy.getBuffer() == &soundBuffer);
|
||||
CHECK(!soundCopy.getLoop());
|
||||
@ -64,7 +63,7 @@ TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
|
||||
|
||||
SECTION("Set/get buffer")
|
||||
{
|
||||
const sf::SoundBuffer otherSoundBuffer;
|
||||
const sf::SoundBuffer otherSoundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
sf::Sound sound(soundBuffer);
|
||||
sound.setBuffer(otherSoundBuffer);
|
||||
CHECK(&sound.getBuffer() == &otherSoundBuffer);
|
||||
|
@ -14,6 +14,7 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
{
|
||||
SECTION("Type traits")
|
||||
{
|
||||
STATIC_CHECK(!std::is_default_constructible_v<sf::SoundBuffer>);
|
||||
STATIC_CHECK(std::is_copy_constructible_v<sf::SoundBuffer>);
|
||||
STATIC_CHECK(std::is_copy_assignable_v<sf::SoundBuffer>);
|
||||
STATIC_CHECK(std::is_move_constructible_v<sf::SoundBuffer>);
|
||||
@ -22,20 +23,9 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
STATIC_CHECK(!std::is_nothrow_move_assignable_v<sf::SoundBuffer>);
|
||||
}
|
||||
|
||||
SECTION("Construction")
|
||||
{
|
||||
const sf::SoundBuffer soundBuffer;
|
||||
CHECK(soundBuffer.getSamples() == nullptr);
|
||||
CHECK(soundBuffer.getSampleCount() == 0);
|
||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||
CHECK(soundBuffer.getChannelCount() == 1);
|
||||
CHECK(soundBuffer.getDuration() == sf::Time::Zero);
|
||||
}
|
||||
|
||||
SECTION("Copy semantics")
|
||||
{
|
||||
sf::SoundBuffer soundBuffer;
|
||||
REQUIRE(soundBuffer.loadFromFile("Audio/ding.flac"));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
|
||||
SECTION("Construction")
|
||||
{
|
||||
@ -49,7 +39,7 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
|
||||
SECTION("Assignment")
|
||||
{
|
||||
sf::SoundBuffer soundBufferCopy;
|
||||
sf::SoundBuffer soundBufferCopy = sf::SoundBuffer::loadFromFile("Audio/doodle_pop.ogg").value();
|
||||
soundBufferCopy = soundBuffer;
|
||||
CHECK(soundBufferCopy.getSamples() != nullptr);
|
||||
CHECK(soundBufferCopy.getSampleCount() == 87798);
|
||||
@ -61,16 +51,14 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
|
||||
SECTION("loadFromFile()")
|
||||
{
|
||||
sf::SoundBuffer soundBuffer;
|
||||
|
||||
SECTION("Invalid filename")
|
||||
{
|
||||
CHECK(!soundBuffer.loadFromFile("does/not/exist.wav"));
|
||||
CHECK(!sf::SoundBuffer::loadFromFile("does/not/exist.wav"));
|
||||
}
|
||||
|
||||
SECTION("Valid file")
|
||||
{
|
||||
REQUIRE(soundBuffer.loadFromFile("Audio/ding.flac"));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
CHECK(soundBuffer.getSamples() != nullptr);
|
||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||
@ -81,19 +69,17 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
|
||||
SECTION("loadFromMemory()")
|
||||
{
|
||||
sf::SoundBuffer soundBuffer;
|
||||
|
||||
SECTION("Invalid memory")
|
||||
{
|
||||
CHECK(!soundBuffer.loadFromMemory(nullptr, 0));
|
||||
CHECK(!sf::SoundBuffer::loadFromMemory(nullptr, 0));
|
||||
constexpr std::array<std::byte, 5> memory{};
|
||||
CHECK(!soundBuffer.loadFromMemory(memory.data(), memory.size()));
|
||||
CHECK(!sf::SoundBuffer::loadFromMemory(memory.data(), memory.size()));
|
||||
}
|
||||
|
||||
SECTION("Valid memory")
|
||||
{
|
||||
const auto memory = loadIntoMemory("Audio/ding.flac");
|
||||
REQUIRE(soundBuffer.loadFromMemory(memory.data(), memory.size()));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromMemory(memory.data(), memory.size()).value();
|
||||
CHECK(soundBuffer.getSamples() != nullptr);
|
||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||
@ -105,17 +91,16 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
SECTION("loadFromStream()")
|
||||
{
|
||||
sf::FileInputStream stream;
|
||||
sf::SoundBuffer soundBuffer;
|
||||
|
||||
SECTION("Invalid stream")
|
||||
{
|
||||
CHECK(!soundBuffer.loadFromStream(stream));
|
||||
CHECK(!sf::SoundBuffer::loadFromStream(stream));
|
||||
}
|
||||
|
||||
SECTION("Valid stream")
|
||||
{
|
||||
REQUIRE(stream.open("Audio/ding.flac"));
|
||||
REQUIRE(soundBuffer.loadFromStream(stream));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromStream(stream).value();
|
||||
CHECK(soundBuffer.getSamples() != nullptr);
|
||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||
@ -129,13 +114,11 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
|
||||
const auto filename = std::filesystem::temp_directory_path() / "ding.flac";
|
||||
|
||||
{
|
||||
sf::SoundBuffer soundBuffer;
|
||||
REQUIRE(soundBuffer.loadFromFile("Audio/ding.flac"));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromFile("Audio/ding.flac").value();
|
||||
REQUIRE(soundBuffer.saveToFile(filename));
|
||||
}
|
||||
|
||||
sf::SoundBuffer soundBuffer;
|
||||
REQUIRE(soundBuffer.loadFromFile(filename));
|
||||
const auto soundBuffer = sf::SoundBuffer::loadFromFile(filename).value();
|
||||
CHECK(soundBuffer.getSamples() != nullptr);
|
||||
CHECK(soundBuffer.getSampleCount() == 87798);
|
||||
CHECK(soundBuffer.getSampleRate() == 44100);
|
||||
|
Loading…
Reference in New Issue
Block a user