#include "Audio.hpp" using namespace sb::audio; Chunk::Chunk(const fs::path& path) { load(path); } void Chunk::load(const fs::path& path) { chunk = std::shared_ptr(Mix_LoadWAV(path.string().c_str()), Mix_FreeChunk); if (chunk.get() == nullptr) { std::ostringstream message; message << "Unable to load audio chunk at " << path << "."; Log::sdl_error(message.str(), Log::Level::WARN); } } std::uint8_t Chunk::convert_volume(float volume) { return std::clamp(static_cast(std::round(volume * MIX_MAX_VOLUME)), 0, MIX_MAX_VOLUME); } float Chunk::volume() const { if (Mix_QuerySpec(nullptr, nullptr, nullptr) != 0) { std::uint8_t sdl_volume = Mix_VolumeChunk(chunk.get(), -1); return static_cast(sdl_volume) / static_cast(MIX_MAX_VOLUME); } else { Log::log("Cannot check volume. Audio device is not open.", Log::WARN); return 0.0f; } } void Chunk::volume(float level) { if (Mix_QuerySpec(nullptr, nullptr, nullptr) != 0) { Mix_VolumeChunk(chunk.get(), convert_volume(level)); } else { Log::log("Cannot set volume. Audio device is not open.", Log::WARN); } } void Chunk::channel_volume(float volume) { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get()) { Mix_Volume(channel, convert_volume(volume)); } } } void Chunk::loop() { loops = -1; } void Chunk::loop(int count) { loops = count; } int Chunk::play(float fade, int channel) { /* Play the audio with a fade in time if any was specified. */ int assignment; if (fade <= 0.0f) { assignment = Mix_PlayChannel(channel, chunk.get(), loops); } else { int milliseconds = static_cast(std::round(fade * 1000.0f)); assignment = Mix_FadeInChannel(channel, chunk.get(), loops, milliseconds); } /* Check if the audio is paused on other channels. If so, stop the audio on those channels. */ int count = Mix_GroupCount(-1); for (int index = 0; index < count; index++) { if (index != assignment && Mix_GetChunk(index) == chunk.get() && Mix_Paused(index)) { Mix_HaltChannel(index); } } return assignment; } void Chunk::stop(float fade) { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get()) { if (fade <= 0.0f) { Mix_HaltChannel(channel); } else { int milliseconds = static_cast(std::round(fade * 1000.0f)); Mix_FadeOutChannel(channel, milliseconds); } } } } void Chunk::pause() { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get()) { Mix_Pause(channel); } } } void Chunk::resume() { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get()) { Mix_Resume(channel); } } } bool Chunk::playing() const { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get() && Mix_Playing(channel)) { return true; } } return false; } bool Chunk::paused() const { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get() && Mix_Paused(channel)) { return true; } } return false; } bool Chunk::fading() const { int count = Mix_GroupCount(-1); for (int channel = 0; channel < count; channel++) { if (Mix_GetChunk(channel) == chunk.get() && Mix_FadingChannel(channel)) { return true; } } return false; } Music::Music(const fs::path& path) { load(path); } void Music::load(const fs::path& path) { music = std::shared_ptr(Mix_LoadMUS(path.string().c_str()), Mix_FreeMusic); if (music.get() == nullptr) { Log::sdl_error(); } } void Music::play(int loops) { Mix_PlayMusic(music.get(), loops); }