Skip to content

Commit

Permalink
Remove default empty state of sf::SoundBuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisThrasher committed May 19, 2024
1 parent 1a40f01 commit add6422
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 100 deletions.
4 changes: 1 addition & 3 deletions examples/sound/Sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
6 changes: 2 additions & 4 deletions examples/tennis/Tennis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ int main()
window.setVerticalSyncEnabled(true);

// Load the sounds used in the game
sf::SoundBuffer ballSoundBuffer;
if (!ballSoundBuffer.loadFromFile(resourcesDir() / "ball.wav"))
return EXIT_FAILURE;
sf::Sound ballSound(ballSoundBuffer);
const auto ballSoundBuffer = sf::SoundBuffer::loadFromFile(resourcesDir() / "ball.wav").value();
sf::Sound ballSound(ballSoundBuffer);

// Create the SFML logo texture:
sf::Texture sfmlLogoTexture;
Expand Down
7 changes: 1 addition & 6 deletions include/SFML/Audio/Sound.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,7 @@ class SFML_AUDIO_API Sound : public SoundSource
///
/// 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
Expand Down
50 changes: 23 additions & 27 deletions include/SFML/Audio/SoundBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <SFML/System/Time.hpp>

#include <filesystem>
#include <optional>
#include <unordered_set>
#include <vector>

Expand All @@ -54,12 +55,6 @@ class InputStream;
class SFML_AUDIO_API SoundBuffer
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SoundBuffer() = default;

////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
Expand All @@ -82,12 +77,12 @@ class SFML_AUDIO_API SoundBuffer
///
/// \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
Expand All @@ -98,12 +93,12 @@ class SFML_AUDIO_API SoundBuffer
/// \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
Expand All @@ -113,12 +108,12 @@ class SFML_AUDIO_API SoundBuffer
///
/// \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
Expand All @@ -131,16 +126,17 @@ class SFML_AUDIO_API SoundBuffer
/// \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,
std::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap);
[[nodiscard]] static std::optional<SoundBuffer> loadFromSamples(
const std::int16_t* samples,
std::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap);

////////////////////////////////////////////////////////////
/// \brief Save the sound buffer to an audio file
Expand Down Expand Up @@ -247,6 +243,12 @@ class SFML_AUDIO_API SoundBuffer
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
///
Expand All @@ -255,7 +257,7 @@ class SFML_AUDIO_API SoundBuffer
/// \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
Expand Down Expand Up @@ -341,14 +343,8 @@ class SFML_AUDIO_API SoundBuffer
///
/// 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);
Expand Down
4 changes: 2 additions & 2 deletions include/SFML/Audio/SoundBufferRecorder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class SFML_AUDIO_API SoundBufferRecorder : public SoundRecorder
////////////////////////////////////////////////////////////
// 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::vector<std::int16_t> m_samples; //!< Temporary sample buffer to hold the recorded data
std::optional<SoundBuffer> m_buffer; //!< Sound buffer that will contain the recorded data
};

} // namespace sf
Expand Down
50 changes: 31 additions & 19 deletions src/SFML/Audio/SoundBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,52 +68,55 @@ 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::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap)
std::optional<SoundBuffer> SoundBuffer::loadFromSamples(
const std::int16_t* samples,
std::uint64_t sampleCount,
unsigned int channelCount,
unsigned int sampleRate,
const std::vector<SoundChannel>& channelMap)
{
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
{
Expand All @@ -124,7 +127,7 @@ bool SoundBuffer::loadFromSamples(const std::int16_t* samples,
<< "channels: " << channelCount << ", "
<< "samplerate: " << sampleRate << ")" << std::endl;

return false;
return std::nullopt;
}
}

Expand Down Expand Up @@ -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;
}
}

Expand Down
12 changes: 9 additions & 3 deletions src/SFML/Audio/SoundBufferRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ SoundBufferRecorder::~SoundBufferRecorder()
bool SoundBufferRecorder::onStart()
{
m_samples.clear();
m_buffer = SoundBuffer();
m_buffer.reset();

return true;
}
Expand All @@ -69,15 +69,21 @@ 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;
}


////////////////////////////////////////////////////////////
const SoundBuffer& SoundBufferRecorder::getBuffer() const
{
return m_buffer;
assert(m_buffer && "SoundBufferRecorder::getBuffer() Cannot return reference to null buffer");
return *m_buffer;
}

} // namespace sf
9 changes: 4 additions & 5 deletions test/Audio/Sound.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")
{
Expand All @@ -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());
Expand All @@ -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);
Expand Down

0 comments on commit add6422

Please sign in to comment.