Files
jaildoctors_dilemma/source/core/audio/audio.cpp

183 lines
5.2 KiB
C++

#include "audio.hpp"
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_G...
#include <algorithm> // Para clamp
#include <iostream> // Para std::cout
// Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp)
// clang-format off
#undef STB_VORBIS_HEADER_ONLY
#include "external/stb_vorbis.h"
// clang-format on
#include "core/audio/jail_audio.hpp" // Para JA_FadeOutMusic, JA_Init, JA_PauseM...
#include "core/resources/resource_cache.hpp" // Para Resource
#include "game/options.hpp" // Para AudioOptions, audio, MusicOptions
// Singleton
Audio* Audio::instance = nullptr;
// Inicializa la instancia única del singleton
void Audio::init() { Audio::instance = new Audio(); }
// Libera la instancia
void Audio::destroy() { delete Audio::instance; }
// Obtiene la instancia
auto Audio::get() -> Audio* { return Audio::instance; }
// Constructor
Audio::Audio() { initSDLAudio(); }
// Destructor
Audio::~Audio() {
JA_Quit();
}
// Método principal
void Audio::update() {
JA_Update();
}
// Reproduce la música
void Audio::playMusic(const std::string& name, const int loop) {
bool new_loop = (loop != 0);
// Si ya está sonando exactamente la misma pista y mismo modo loop, no hacemos nada
if (music_.state == MusicState::PLAYING && music_.name == name && music_.loop == new_loop) {
return;
}
// Intentar obtener recurso; si falla, no tocar estado
auto* resource = Resource::Cache::get()->getMusic(name);
if (resource == nullptr) {
// manejo de error opcional
return;
}
// Si hay algo reproduciéndose, detenerlo primero (si el backend lo requiere)
if (music_.state == MusicState::PLAYING) {
JA_StopMusic(); // sustituir por la función de stop real del API si tiene otro nombre
}
// Llamada al motor para reproducir la nueva pista
JA_PlayMusic(resource, loop);
// Actualizar estado y metadatos después de iniciar con éxito
music_.name = name;
music_.loop = new_loop;
music_.state = MusicState::PLAYING;
}
// Pausa la música
void Audio::pauseMusic() {
if (music_enabled_ && music_.state == MusicState::PLAYING) {
JA_PauseMusic();
music_.state = MusicState::PAUSED;
}
}
// Continua la música pausada
void Audio::resumeMusic() {
if (music_enabled_ && music_.state == MusicState::PAUSED) {
JA_ResumeMusic();
music_.state = MusicState::PLAYING;
}
}
// Detiene la música
void Audio::stopMusic() {
if (music_enabled_) {
JA_StopMusic();
music_.state = MusicState::STOPPED;
}
}
// Reproduce un sonido por nombre
void Audio::playSound(const std::string& name, Group group) const {
if (sound_enabled_) {
JA_PlaySound(Resource::Cache::get()->getSound(name), 0, static_cast<int>(group));
}
}
// Reproduce un sonido por puntero directo
void Audio::playSound(JA_Sound_t* sound, Group group) const {
if (sound_enabled_) {
JA_PlaySound(sound, 0, static_cast<int>(group));
}
}
// Detiene todos los sonidos
void Audio::stopAllSounds() const {
if (sound_enabled_) {
JA_StopChannel(-1);
}
}
// Realiza un fundido de salida de la música
void Audio::fadeOutMusic(int milliseconds) const {
if (music_enabled_ && getRealMusicState() == MusicState::PLAYING) {
JA_FadeOutMusic(milliseconds);
}
}
// Consulta directamente el estado real de la música en jailaudio
auto Audio::getRealMusicState() -> MusicState {
JA_Music_state ja_state = JA_GetMusicState();
switch (ja_state) {
case JA_MUSIC_PLAYING:
return MusicState::PLAYING;
case JA_MUSIC_PAUSED:
return MusicState::PAUSED;
case JA_MUSIC_STOPPED:
case JA_MUSIC_INVALID:
case JA_MUSIC_DISABLED:
default:
return MusicState::STOPPED;
}
}
// Establece el volumen de los sonidos
void Audio::setSoundVolume(float sound_volume, Group group) const {
if (sound_enabled_) {
sound_volume = std::clamp(sound_volume, MIN_VOLUME, MAX_VOLUME);
const float CONVERTED_VOLUME = sound_volume * Options::audio.volume;
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
}
}
// Establece el volumen de la música
void Audio::setMusicVolume(float music_volume) const {
if (music_enabled_) {
music_volume = std::clamp(music_volume, MIN_VOLUME, MAX_VOLUME);
const float CONVERTED_VOLUME = music_volume * Options::audio.volume;
JA_SetMusicVolume(CONVERTED_VOLUME);
}
}
// Aplica la configuración
void Audio::applySettings() {
enable(Options::audio.enabled);
}
// Establecer estado general
void Audio::enable(bool value) {
enabled_ = value;
setSoundVolume(enabled_ ? Options::audio.sound.volume : MIN_VOLUME);
setMusicVolume(enabled_ ? Options::audio.music.volume : MIN_VOLUME);
}
// Inicializa SDL Audio
void Audio::initSDLAudio() {
if (!SDL_Init(SDL_INIT_AUDIO)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
} else {
JA_Init(FREQUENCY, SDL_AUDIO_S16LE, 2);
enable(Options::audio.enabled);
std::cout << "\n** AUDIO SYSTEM **\n";
std::cout << "Audio system initialized successfully\n";
}
}