add option for texture resize filter to sprite, add functions for finding loudest mixer channel
This commit is contained in:
parent
11c8abcc54
commit
1fff973b46
|
@ -2,6 +2,39 @@
|
|||
|
||||
using namespace sb::audio;
|
||||
|
||||
int sb::audio::loudest_channel()
|
||||
{
|
||||
int loudest_volume = 0;
|
||||
int loudest_channel = 0;
|
||||
int volume = 0;
|
||||
int count = Mix_GroupCount(-1);
|
||||
for (int channel = 0; channel < count; channel++)
|
||||
{
|
||||
volume = Mix_Volume(channel, -1);
|
||||
if (volume > loudest_volume)
|
||||
{
|
||||
loudest_volume = volume;
|
||||
loudest_channel = channel;
|
||||
}
|
||||
}
|
||||
return loudest_channel;
|
||||
}
|
||||
|
||||
float sb::audio::loudest_channel_volume()
|
||||
{
|
||||
return normalize_volume(Mix_Volume(loudest_channel(), -1));
|
||||
}
|
||||
|
||||
std::uint8_t sb::audio::convert_volume(float volume)
|
||||
{
|
||||
return std::clamp(static_cast<int>(std::round(volume * MIX_MAX_VOLUME)), 0, MIX_MAX_VOLUME);
|
||||
}
|
||||
|
||||
float sb::audio::normalize_volume(std::uint8_t volume)
|
||||
{
|
||||
return float(volume) / float(MIX_MAX_VOLUME);
|
||||
}
|
||||
|
||||
Chunk::Chunk(const fs::path& path)
|
||||
{
|
||||
load(path);
|
||||
|
@ -18,11 +51,6 @@ void Chunk::load(const fs::path& path)
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -24,9 +24,36 @@ namespace sb::audio
|
|||
{
|
||||
|
||||
/*!
|
||||
* Load audio from an OGG or WAV file and play it on multiple channels.
|
||||
* @return channel ID of the SDL mixer channel with the loudest volume setting
|
||||
*/
|
||||
int loudest_channel();
|
||||
|
||||
/*!
|
||||
* @return volume of the loudest SDL mixer channel, normalized to between 0.0 and 1.0
|
||||
*/
|
||||
float loudest_channel_volume();
|
||||
|
||||
/*!
|
||||
* Convert floating point volume between 0.0 and 1.0 to SDL 8-bit unsigned integer volume between 0 and `MIX_MAX_VOLUME`.
|
||||
*
|
||||
* @param volume Volume between 0.0 and 1.0
|
||||
* @return Same volume represented in the range 0 to `MIX_MAX_VOLUME`
|
||||
*/
|
||||
std::uint8_t convert_volume(float volume);
|
||||
|
||||
/*!
|
||||
* Convert volume between 0 and `MIX_MAX_VOLUME` to a float between 0.0 and 1.0.
|
||||
*
|
||||
* @param volume Volume between 0 and `MIX_MAX_VOLUME`
|
||||
* @return Same volume represented as a float between 0.0 and 1.0
|
||||
*/
|
||||
float normalize_volume(std::uint8_t volume);
|
||||
|
||||
/*!
|
||||
* Load audio from an OGG or WAV file and play it.
|
||||
*
|
||||
* This class interfaces with SDL mixer's API and its `Mix_Chunk` audio data struct.
|
||||
* Each instance contains an SDL `Mix_Chunk` audio data struct and automatically finds a open channel to play it on when play is requested. The chunk
|
||||
* can be playing on multiple channels simultaneously.
|
||||
*
|
||||
* There are some differences between how `Mix_Chunk` and `Mix_Music` can be used with the API, most notably that multiple chunks can be playing on
|
||||
* multiple channels simultaneously, but only one music object can be playing at a time. This is most likely because `Mix_Music` objects are streamed
|
||||
|
@ -42,13 +69,6 @@ namespace sb::audio
|
|||
/* -1 means loop forever, any other value is the number of times to loop */
|
||||
int loops = 0;
|
||||
|
||||
/*!
|
||||
* Convert floating point volume between 0.0 and 1.0 to SDL 8-bit unsigned integer volume between 0 and `MIX_MAX_VOLUME`.
|
||||
*
|
||||
* @param volume Volume between 0.0 and 1.0
|
||||
*/
|
||||
static std::uint8_t convert_volume(float volume);
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
|
|
|
@ -104,14 +104,15 @@ namespace sb
|
|||
*
|
||||
* @see sb::Texture::load()
|
||||
*
|
||||
* @param paths list of paths to images
|
||||
* @param scale amount to scale
|
||||
* @param paths List of paths to images
|
||||
* @param scale Amount to scale
|
||||
* @param filter Resize filter to use when rendering textures
|
||||
*/
|
||||
Sprite(std::initializer_list<fs::path> paths, glm::vec2 scale = glm::vec2{1.0f}) : Sprite(scale)
|
||||
Sprite(std::initializer_list<fs::path> paths, glm::vec2 scale = glm::vec2{1.0f}, std::optional<GLint> filter = std::nullopt) : Sprite(scale)
|
||||
{
|
||||
for (const fs::path& path : paths)
|
||||
{
|
||||
this->texture(path);
|
||||
this->texture(path, filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,13 +121,11 @@ namespace sb
|
|||
*
|
||||
* @see ::Sprite(std::initializer_list<fs::path>, glm::vec2)
|
||||
*
|
||||
* @param path path to an image
|
||||
* @param scale amount to scale
|
||||
* @param path Path to an image
|
||||
* @param scale Amount to scale
|
||||
* @param filter Resize filter to use when rendering textures
|
||||
*/
|
||||
Sprite(const fs::path& path, glm::vec2 scale = glm::vec2{1.0f}) : Sprite({path}, scale)
|
||||
{
|
||||
this->texture(path);
|
||||
}
|
||||
Sprite(const fs::path& path, glm::vec2 scale = glm::vec2{1.0f}, std::optional<GLint> filter = std::nullopt) : Sprite({path}, scale, filter) {};
|
||||
|
||||
/*!
|
||||
* Add a previously constructed sb::Texture to the sprite's plane object.
|
||||
|
@ -144,11 +143,16 @@ namespace sb
|
|||
* The texture is loaded into GPU memory if the GL context is active. Otherwise, the path is just attached to the texture,
|
||||
* and it must be loaded with a call to Sprite::load.
|
||||
*
|
||||
* @param path path to an image
|
||||
* @param path Path to an image
|
||||
* @param filter Resize filter to use when rendering the texture
|
||||
*/
|
||||
void texture(const fs::path& path)
|
||||
void texture(const fs::path& path, std::optional<GLint> filter = std::nullopt)
|
||||
{
|
||||
sb::Texture texture;
|
||||
if (filter.has_value())
|
||||
{
|
||||
texture.filter(filter.value());
|
||||
}
|
||||
if (SDL_GL_GetCurrentContext() != nullptr)
|
||||
{
|
||||
texture.load(path);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Model.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "Texture.hpp"
|
||||
|
||||
namespace sb
|
||||
{
|
||||
|
|
|
@ -23,12 +23,17 @@ void Texture::associate(fs::path path)
|
|||
this->path = path;
|
||||
}
|
||||
|
||||
void Texture::filter(GLint value)
|
||||
{
|
||||
_filter = value;
|
||||
}
|
||||
|
||||
void Texture::generate()
|
||||
{
|
||||
GLObject::generate(glGenTextures);
|
||||
}
|
||||
|
||||
void Texture::generate(glm::vec2 size, GLenum format, GLint filter)
|
||||
void Texture::generate(glm::vec2 size, GLenum format, std::optional<GLint> filter_value)
|
||||
{
|
||||
/* Only generate a new texture ID and reallocate memory if the current texture ID hasn't been registered by this object as having identically
|
||||
* sized memory with the same format. */
|
||||
|
@ -44,8 +49,12 @@ void Texture::generate(glm::vec2 size, GLenum format, GLint filter)
|
|||
}
|
||||
|
||||
/* Set the resizing algorithm of this texture */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
if (!filter_value.has_value())
|
||||
{
|
||||
filter_value = _filter;
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_value.value());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_value.value());
|
||||
|
||||
/* Set the texture wrap of this texture */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
|
|
|
@ -44,6 +44,10 @@ namespace sb
|
|||
std::optional<glm::vec2> _size;
|
||||
std::optional<GLenum> _format;
|
||||
|
||||
/* The filter will be applied using glTexParameter whenever Texture::generate(glm::vec2, GLenum, std::optional<GLint>) is called without a filter
|
||||
* specified. */
|
||||
GLint _filter = GL_NEAREST;
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
|
@ -66,6 +70,14 @@ namespace sb
|
|||
*/
|
||||
void associate(fs::path path);
|
||||
|
||||
/*!
|
||||
* Set the resize filter of the texture. This must be set before Texture::generate(glm::vec2, GLenum, std::optional<GLint>) is called for it
|
||||
* to be applied.
|
||||
*
|
||||
* @param value Resize filter to use (see `glTexParameter` for options)
|
||||
*/
|
||||
void filter(GLint value);
|
||||
|
||||
/*!
|
||||
* Forward the GL texture generate function to the base class
|
||||
*/
|
||||
|
@ -76,9 +88,9 @@ namespace sb
|
|||
*
|
||||
* @param size Width and height of the texture in texels
|
||||
* @param format Sized internal format to be used to store texture data (for example, `GL_RGBA8`, `GL_RGB8`)
|
||||
* @param filter Resize function to use (see `glTexParameter`)
|
||||
* @param filter Resize function to use (see `glTexParameter`). Overrides the value of Texture::filter.
|
||||
*/
|
||||
void generate(glm::vec2 size, GLenum format = GL_RGBA8, GLint filter = GL_NEAREST);
|
||||
void generate(glm::vec2 size, GLenum format = GL_RGBA8, std::optional<GLint> filter = std::nullopt);
|
||||
|
||||
/*!
|
||||
* Load a texture from the path that was previously set.
|
||||
|
|
Loading…
Reference in New Issue