Fase 3: import del subsistema de audio desde AEEA
Reemplaza el audio antiguo de orni_attack (singleton con new/delete
raw, sin efectos, sin crossfade) por el subsistema moderno de AEEA
(unique_ptr, RAII, crossfade nativo, echo/reverb, pitch-shift,
callbacks de fin de pista, getMusicDurationMs para timelines
deterministas).
Eliminados:
- source/core/audio/audio_cache.{hpp,cpp} (1 cache por subsistema)
- source/core/audio/jail_audio.hpp viejo (motor inline globals)
- source/external/stb_vorbis.h (v1.20)
Añadidos (copiados de AEEA, traducidos comentarios al castellano):
- source/core/audio/audio.{hpp,cpp} — singleton con Audio::Config inyectada
- source/core/audio/audio_adapter.{hpp,cpp} — adapter para getMusic/getSound
- source/core/audio/audio_effects.{hpp,cpp} — Schroeder reverb + echo DSP
- source/core/audio/jail_audio.{hpp,cpp} — Ja::Engine class-based, streaming
- source/core/audio/sound_effects_config.{hpp,cpp} — presets YAML (opcional)
- source/external/stb_vorbis.c (v1.22) — OGG decoder, versión más reciente
- source/external/stb_vorbis_impl.cpp — TU aislada para evitar clang-tidy
Adaptaciones:
- audio_adapter.cpp implementado a medida para orni: usa
Resource::Helper::loadFile (no Resource::Cache de AEEA que orni no
tiene). Cache local con unique_ptr<Ja::Music> / unique_ptr<Ja::Sound>.
- Includes: utils/defaults.hpp -> core/defaults.hpp, utils/log.hpp
reemplazado por iostream con std::cerr/std::cout.
API breaking changes (callsites migrados):
- Audio::init() -> Audio::init(Config); el Director construye la Config
desde Defaults::Audio::* (ENABLED, VOLUME, MUSIC_*, SOUND_*).
- Audio::get()->getMusicState() -> Audio::getMusicState() (ahora static).
- AudioCache::getMusic/getSound -> AudioResource::getMusic/getSound.
Defaults::Audio consolidado: ahora aglutina las constantes que antes
estaban repartidas entre namespace Audio (VOLUME, ENABLED), namespace
Music (VOLUME, ENABLED), namespace Sound (VOLUME, ENABLED). Las pistas
y rutas de efectos siguen en Music::* / Sound::*. Añadidas FREQUENCY,
FORMAT, CHANNELS, CROSSFADE_MS, VOLUME_STEP para el motor.
Beneficios para fases siguientes:
- Crossfade en transiciones de escena (uso: playMusic(name, -1, 1500)).
- Pitch-shift para variaciones de SFX (Audio::playSound(name, group, 0.95)).
- Echo/reverb DSP via playSoundWithEcho/Reverb (sounds.yaml presets).
- Callbacks setOnMusicEnded para sincronizar eventos con el fin de pista.
Compila y enlaza. Pendiente: test runtime del usuario.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
// audio_adapter.cpp - Implementación de AudioResource para orni_attack
|
||||
// © 2025 Orni Attack
|
||||
//
|
||||
// Implementa AudioResource::getMusic / getSound delegando a
|
||||
// Resource::Helper::loadFile (que abstrae el resources.pack y el fallback
|
||||
// a filesystem). Cache local de Ja::Music* / Ja::Sound* con lazy load:
|
||||
// cada recurso se carga la primera vez que se pide y se mantiene vivo
|
||||
// hasta el shutdown.
|
||||
|
||||
#include "core/audio/audio_adapter.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/audio/jail_audio.hpp"
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Cachés locales: indexados por nombre lógico ("title.ogg", "effects/laser_shoot.wav", etc.)
|
||||
// Mantienen ownership con unique_ptr; se liberan al salir del programa.
|
||||
std::unordered_map<std::string, std::unique_ptr<Ja::Music>>& musicCache() {
|
||||
static std::unordered_map<std::string, std::unique_ptr<Ja::Music>> cache;
|
||||
return cache;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<Ja::Sound>>& soundCache() {
|
||||
static std::unordered_map<std::string, std::unique_ptr<Ja::Sound>> cache;
|
||||
return cache;
|
||||
}
|
||||
|
||||
// Normaliza el nombre añadiendo la subcarpeta correspondiente si no la trae:
|
||||
// "title.ogg" -> "music/title.ogg"
|
||||
// "music/title.ogg" -> "music/title.ogg"
|
||||
// "effects/laser.wav" -> "sounds/effects/laser.wav"
|
||||
std::string normalizeMusicPath(const std::string& name) {
|
||||
return (name.rfind("music/", 0) == 0) ? name : "music/" + name;
|
||||
}
|
||||
|
||||
std::string normalizeSoundPath(const std::string& name) {
|
||||
return (name.rfind("sounds/", 0) == 0) ? name : "sounds/" + name;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace AudioResource {
|
||||
|
||||
auto getMusic(const std::string& name) -> Ja::Music* {
|
||||
auto& cache = musicCache();
|
||||
if (auto it = cache.find(name); it != cache.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
const std::string path = normalizeMusicPath(name);
|
||||
auto bytes = Resource::Helper::loadFile(path);
|
||||
if (bytes.empty()) {
|
||||
std::cerr << "[AudioResource] no se ha podido cargar música: " << path << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ja::Music* raw = Ja::loadMusic(bytes.data(), static_cast<std::uint32_t>(bytes.size()), name.c_str());
|
||||
if (raw == nullptr) {
|
||||
std::cerr << "[AudioResource] decodificación de música falló: " << path << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cache.emplace(name, std::unique_ptr<Ja::Music>(raw));
|
||||
std::cout << "[AudioResource] música cargada: " << path << "\n";
|
||||
return raw;
|
||||
}
|
||||
|
||||
auto getSound(const std::string& name) -> Ja::Sound* {
|
||||
auto& cache = soundCache();
|
||||
if (auto it = cache.find(name); it != cache.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
const std::string path = normalizeSoundPath(name);
|
||||
auto bytes = Resource::Helper::loadFile(path);
|
||||
if (bytes.empty()) {
|
||||
std::cerr << "[AudioResource] no se ha podido cargar sonido: " << path << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ja::Sound* raw = Ja::loadSound(bytes.data(), static_cast<std::uint32_t>(bytes.size()));
|
||||
if (raw == nullptr) {
|
||||
std::cerr << "[AudioResource] decodificación de sonido falló: " << path << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cache.emplace(name, std::unique_ptr<Ja::Sound>(raw));
|
||||
std::cout << "[AudioResource] sonido cargado: " << path << "\n";
|
||||
return raw;
|
||||
}
|
||||
|
||||
} // namespace AudioResource
|
||||
Reference in New Issue
Block a user