// audio_cache.cpp - Implementació del caché de sons i música // © 2025 Port a C++20 amb SDL3 #include "core/audio/audio_cache.hpp" #include #include "core/resources/resource_helper.hpp" // Inicialització de variables estàtiques std::unordered_map AudioCache::sounds_; std::unordered_map AudioCache::musics_; std::string AudioCache::sounds_base_path_ = "data/sounds/"; std::string AudioCache::music_base_path_ = "data/music/"; JA_Sound_t* AudioCache::getSound(const std::string& name) { // Cache hit auto it = sounds_.find(name); if (it != sounds_.end()) { std::cout << "[AudioCache] Sound cache hit: " << name << std::endl; return it->second; } // Normalize path: "laser_shoot.wav" → "sounds/laser_shoot.wav" std::string normalized = name; if (normalized.find("sounds/") != 0) { normalized = "sounds/" + normalized; } // Load from resource system std::vector data = Resource::Helper::loadFile(normalized); if (data.empty()) { std::cerr << "[AudioCache] Error: no s'ha pogut load " << normalized << std::endl; return nullptr; } // Load sound from memory JA_Sound_t* sound = JA_LoadSound(data.data(), static_cast(data.size())); if (sound == nullptr) { std::cerr << "[AudioCache] Error: no s'ha pogut decodificar " << normalized << std::endl; return nullptr; } std::cout << "[AudioCache] Sound loaded: " << normalized << std::endl; sounds_[name] = sound; return sound; } JA_Music_t* AudioCache::getMusic(const std::string& name) { // Cache hit auto it = musics_.find(name); if (it != musics_.end()) { std::cout << "[AudioCache] Music cache hit: " << name << std::endl; return it->second; } // Normalize path: "title.ogg" → "music/title.ogg" std::string normalized = name; if (normalized.find("music/") != 0) { normalized = "music/" + normalized; } // Load from resource system std::vector data = Resource::Helper::loadFile(normalized); if (data.empty()) { std::cerr << "[AudioCache] Error: no s'ha pogut load " << normalized << std::endl; return nullptr; } // Load music from memory JA_Music_t* music = JA_LoadMusic(data.data(), static_cast(data.size())); if (music == nullptr) { std::cerr << "[AudioCache] Error: no s'ha pogut decodificar " << normalized << std::endl; return nullptr; } std::cout << "[AudioCache] Music loaded: " << normalized << std::endl; musics_[name] = music; return music; } void AudioCache::clear() { std::cout << "[AudioCache] Clearing cache (" << sounds_.size() << " sounds, " << musics_.size() << " music)" << std::endl; // Liberar memoria de sonidos for (auto& [name, sound] : sounds_) { if (sound && sound->buffer) { SDL_free(sound->buffer); } delete sound; } sounds_.clear(); // Liberar memoria de música for (auto& [name, music] : musics_) { if (music && music->buffer) { SDL_free(music->buffer); } if (music && music->filename) { free(music->filename); } delete music; } musics_.clear(); } size_t AudioCache::getSoundCacheSize() { return sounds_.size(); } size_t AudioCache::getMusicCacheSize() { return musics_.size(); } std::string AudioCache::resolveSoundPath(const std::string& name) { // Si es un path absoluto (comienza con '/'), usarlo directamente if (!name.empty() && name[0] == '/') { return name; } // Si ya contiene el prefix base_path, usarlo directamente if (name.find(sounds_base_path_) == 0) { return name; } // Caso contrario, añadir base_path return sounds_base_path_ + name; } std::string AudioCache::resolveMusicPath(const std::string& name) { // Si es un path absoluto (comienza con '/'), usarlo directamente if (!name.empty() && name[0] == '/') { return name; } // Si ya contiene el prefix base_path, usarlo directamente if (name.find(music_base_path_) == 0) { return name; } // Caso contrario, añadir base_path return music_base_path_ + name; }