202 lines
4.4 KiB
C++
202 lines
4.4 KiB
C++
#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_Chunk>(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<int>(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<float>(sdl_volume) / static_cast<float>(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<int>(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<int>(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_Music>(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);
|
|
}
|