diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad14ec..b776fa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ set(TETRIS_SOURCES src/graphics/renderers/SyncLineRenderer.cpp src/graphics/renderers/UIRenderer.cpp src/audio/Audio.cpp + src/audio/AudioManager.cpp src/renderer/SDLRenderer.cpp src/gameplay/effects/LineEffect.cpp src/audio/SoundEffect.cpp diff --git a/src/audio/Audio.cpp b/src/audio/Audio.cpp index 582f7b5..15570b5 100644 --- a/src/audio/Audio.cpp +++ b/src/audio/Audio.cpp @@ -118,6 +118,7 @@ static bool decodeMP3(const std::string& path, std::vector& outPCM, int outCh = static_cast(clientFormat.mChannelsPerFrame); return !outPCM.empty(); } + #else static bool decodeMP3(const std::string& path, std::vector& outPCM, int& outRate, int& outCh){ (void)outPCM; (void)outRate; (void)outCh; (void)path; @@ -184,6 +185,8 @@ void Audio::skipToNextTrack(){ void Audio::toggleMute(){ muted=!muted; } void Audio::setMuted(bool m){ muted=m; } +bool Audio::isMuted() const { return muted; } + void Audio::nextTrack(){ if(tracks.empty()) { current = -1; return; } // Try every track once to find a decodable one diff --git a/src/audio/Audio.h b/src/audio/Audio.h index 35f520a..2e1a176 100644 --- a/src/audio/Audio.h +++ b/src/audio/Audio.h @@ -32,29 +32,27 @@ public: void setSoundVolume(float volume) override; bool isMusicPlaying() const override; - // Existing Audio class methods - bool init(); // initialize backend (MF on Windows) - void addTrack(const std::string& path); // decode MP3 -> PCM16 stereo 44100 - void addTrackAsync(const std::string& path); // add track for background loading - void startBackgroundLoading(); // start background thread for loading - void waitForLoadingComplete(); // wait for all tracks to finish loading - bool isLoadingComplete() const; // check if background loading is done - int getLoadedTrackCount() const; // get number of tracks loaded so far - void shuffle(); // randomize order - void start(); // begin playback - void skipToNextTrack(); // advance to the next music track - void toggleMute(); + // Additional IAudioSystem methods (forwarded to concrete implementation) + bool init() override; + void shutdown() override; + void addTrack(const std::string& path) override; + void addTrackAsync(const std::string& path) override; + void startBackgroundLoading() override; + bool isLoadingComplete() const override; + int getLoadedTrackCount() const override; + void start() override; + void skipToNextTrack() override; + void shuffle() override; + void toggleMute() override; + bool isMuted() const override; void setMuted(bool m); - bool isMuted() const { return muted; } - - // Menu music support - void setMenuTrack(const std::string& path); - void playMenuMusic(); - void playGameMusic(); - - // Queue a sound effect to mix over the music (pcm can be mono/stereo, any rate; will be converted) - void playSfx(const std::vector& pcm, int channels, int rate, float volume); - void shutdown(); + void setMenuTrack(const std::string& path) override; + void playMenuMusic() override; + void playGameMusic() override; + void playSfx(const std::vector& pcm, int channels, int rate, float volume) override; + + // Existing Audio class helper methods + void waitForLoadingComplete(); // wait for all tracks to finish loading private: Audio()=default; ~Audio()=default; Audio(const Audio&)=delete; Audio& operator=(const Audio&)=delete; static void SDLCALL streamCallback(void* userdata, SDL_AudioStream* stream, int additional, int total); diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp new file mode 100644 index 0000000..775a4d2 --- /dev/null +++ b/src/audio/AudioManager.cpp @@ -0,0 +1,15 @@ +#include "AudioManager.h" +#include "Audio.h" + +static IAudioSystem* g_audioSystem = nullptr; + +IAudioSystem* AudioManager::get() { + if (!g_audioSystem) { + g_audioSystem = &Audio::instance(); + } + return g_audioSystem; +} + +void AudioManager::set(IAudioSystem* sys) { + g_audioSystem = sys; +} diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h new file mode 100644 index 0000000..ebf078b --- /dev/null +++ b/src/audio/AudioManager.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../core/interfaces/IAudioSystem.h" + +class AudioManager { +public: + // Get the currently registered audio system (may return Audio::instance()) + static IAudioSystem* get(); + // Replace the audio system (for tests or different backends) + static void set(IAudioSystem* sys); +}; diff --git a/src/audio/SoundEffect.cpp b/src/audio/SoundEffect.cpp index ecc34ee..e48393e 100644 --- a/src/audio/SoundEffect.cpp +++ b/src/audio/SoundEffect.cpp @@ -2,6 +2,7 @@ #include "SoundEffect.h" #include #include "audio/Audio.h" +#include "audio/AudioManager.h" #include #include #include @@ -93,7 +94,9 @@ void SimpleAudioPlayer::playSound(const std::vector& pcmData, int chann return; } // Route through shared Audio mixer so SFX always play over music - Audio::instance().playSfx(pcmData, channels, sampleRate, volume); + if (auto sys = AudioManager::get()) { + sys->playSfx(pcmData, channels, sampleRate, volume); + } } bool SoundEffect::loadWAV(const std::string& filePath) { diff --git a/src/core/application/ApplicationManager.cpp b/src/core/application/ApplicationManager.cpp index 9e4da60..e7c13e2 100644 --- a/src/core/application/ApplicationManager.cpp +++ b/src/core/application/ApplicationManager.cpp @@ -7,6 +7,7 @@ #include "../interfaces/IInputHandler.h" #include #include "../../audio/Audio.h" +#include "../../audio/AudioManager.h" #include "../../audio/SoundEffect.h" #include "../../persistence/Scores.h" #include "../../states/State.h" @@ -267,7 +268,7 @@ void ApplicationManager::shutdown() { m_running = false; // Stop audio systems before tearing down SDL to avoid aborts/asserts - Audio::instance().shutdown(); + if (auto sys = ::AudioManager::get()) sys->shutdown(); SoundEffectManager::instance().shutdown(); // Cleanup in reverse order of initialization @@ -381,11 +382,11 @@ bool ApplicationManager::initializeManagers() { // M: Toggle/mute music; start playback if unmuting and not started yet if (!consume && sc == SDL_SCANCODE_M) { - Audio::instance().toggleMute(); + if (auto sys = ::AudioManager::get()) sys->toggleMute(); m_musicEnabled = !m_musicEnabled; - if (m_musicEnabled && !m_musicStarted && Audio::instance().getLoadedTrackCount() > 0) { - Audio::instance().shuffle(); - Audio::instance().start(); + if (m_musicEnabled && !m_musicStarted && ::AudioManager::get() && ::AudioManager::get()->getLoadedTrackCount() > 0) { + ::AudioManager::get()->shuffle(); + ::AudioManager::get()->start(); m_musicStarted = true; } consume = true; @@ -393,11 +394,7 @@ bool ApplicationManager::initializeManagers() { // N: Skip to next song in the playlist (or restart menu track) if (!consume && sc == SDL_SCANCODE_N) { - Audio::instance().skipToNextTrack(); - if (!m_musicStarted && Audio::instance().getLoadedTrackCount() > 0) { - m_musicStarted = true; - m_musicEnabled = true; - } + if (auto sys = ::AudioManager::get()) { sys->skipToNextTrack(); if (!m_musicStarted && sys->getLoadedTrackCount() > 0) { m_musicStarted = true; m_musicEnabled = true; } } consume = true; } @@ -515,13 +512,13 @@ void ApplicationManager::registerServices() { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registered IInputHandler service"); } - // Register Audio system singleton - auto& audioInstance = Audio::instance(); - auto audioPtr = std::shared_ptr