// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Audio module" // For conditions of distribution and use, see copyright notice in Export.hpp #include #include #include #include #include #include #include #include #include namespace Nz { /*! * \ingroup audio * \class Nz::SoundBuffer * \brief Audio class that represents a buffer for sound * * \remark Module Audio needs to be initialized to use this class */ /*! * \brief Checks whether the parameters for the buffer' sound are correct * \return true If parameters are valid */ bool SoundBufferParams::IsValid() const { return true; } bool Serialize(SerializationContext& context, SoundBufferParams& params, TypeTag) { Serialize(context, params, TypeTag()); Serialize(context, "forceMono", params.forceMono); return true; } bool Unserialize(SerializationContext& context, SoundBufferParams* params, TypeTag) { Unserialize(context, params, TypeTag()); Unserialize(context, "forceMono", ¶ms->forceMono); return params->IsValid(); } /*! * \brief Constructs a SoundBuffer object * * \param format Format for the audio * \param sampleCount Number of samples * \param sampleRate Rate of samples * \param samples Samples raw data */ SoundBuffer::SoundBuffer(AudioFormat format, UInt64 sampleCount, UInt32 sampleRate, const Int16* samples) { NazaraAssert(sampleCount > 0, "sample count must be different from zero"); NazaraAssert(sampleRate > 0, "sample rate must be different from zero"); NazaraAssert(samples, "invalid samples"); m_duration = Time::Microseconds((1'000'000LL * sampleCount / (GetChannelCount(format) * sampleRate))); m_format = format; m_sampleCount = sampleCount; m_sampleRate = sampleRate; m_samples = std::make_unique(sampleCount); std::memcpy(&m_samples[0], samples, sampleCount * sizeof(Int16)); } const std::shared_ptr& SoundBuffer::GetAudioBuffer(AudioDevice* device) { NazaraAssert(device, "invalid device"); auto it = m_audioBufferByDevice.find(device); if (it == m_audioBufferByDevice.end()) { // Try to find an existing compatible buffer std::shared_ptr audioBuffer; for (it = m_audioBufferByDevice.begin(); it != m_audioBufferByDevice.end(); ++it) { const auto& entry = it->second; if (entry.audioBuffer->IsCompatibleWith(*device)) { audioBuffer = entry.audioBuffer; break; } } if (!audioBuffer) { // Create a new buffer audioBuffer = device->CreateBuffer(); if (!audioBuffer->Reset(m_format, m_sampleCount, m_sampleRate, m_samples.get())) throw std::runtime_error("failed to initialize audio buffer"); } it = m_audioBufferByDevice.emplace(device, AudioDeviceEntry{}).first; AudioDeviceEntry& entry = it->second; entry.audioBuffer = std::move(audioBuffer); entry.audioDeviceReleaseSlot.Connect(device->OnAudioDeviceRelease, [this](AudioDevice* device) { m_audioBufferByDevice.erase(device); }); } return it->second.audioBuffer; } /*! * \brief Loads the sound buffer from file * \return true if loading is successful * * \param filePath Path to the file * \param params Parameters for the sound buffer */ std::shared_ptr SoundBuffer::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params) { Audio* audio = Audio::Instance(); NazaraAssert(audio, "Audio module has not been initialized"); return audio->GetSoundBufferLoader().LoadFromFile(filePath, params); } /*! * \brief Loads the sound buffer from memory * \return true if loading is successful * * \param data Raw memory * \param size Size of the memory * \param params Parameters for the sound buffer */ std::shared_ptr SoundBuffer::LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params) { Audio* audio = Audio::Instance(); NazaraAssert(audio, "Audio module has not been initialized"); return audio->GetSoundBufferLoader().LoadFromMemory(data, size, params); } /*! * \brief Loads the sound buffer from stream * \return true if loading is successful * * \param stream Stream to the sound buffer * \param params Parameters for the sound buffer */ std::shared_ptr SoundBuffer::LoadFromStream(Stream& stream, const SoundBufferParams& params) { Audio* audio = Audio::Instance(); NazaraAssert(audio, "Audio module has not been initialized"); return audio->GetSoundBufferLoader().LoadFromStream(stream, params); } }