Audio update
This commit is contained in:
@ -57,6 +57,7 @@ set(TETRIS_SOURCES
|
|||||||
src/graphics/renderers/SyncLineRenderer.cpp
|
src/graphics/renderers/SyncLineRenderer.cpp
|
||||||
src/graphics/renderers/UIRenderer.cpp
|
src/graphics/renderers/UIRenderer.cpp
|
||||||
src/audio/Audio.cpp
|
src/audio/Audio.cpp
|
||||||
|
src/audio/AudioManager.cpp
|
||||||
src/renderer/SDLRenderer.cpp
|
src/renderer/SDLRenderer.cpp
|
||||||
src/gameplay/effects/LineEffect.cpp
|
src/gameplay/effects/LineEffect.cpp
|
||||||
src/audio/SoundEffect.cpp
|
src/audio/SoundEffect.cpp
|
||||||
|
|||||||
@ -118,6 +118,7 @@ static bool decodeMP3(const std::string& path, std::vector<int16_t>& outPCM, int
|
|||||||
outCh = static_cast<int>(clientFormat.mChannelsPerFrame);
|
outCh = static_cast<int>(clientFormat.mChannelsPerFrame);
|
||||||
return !outPCM.empty();
|
return !outPCM.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static bool decodeMP3(const std::string& path, std::vector<int16_t>& outPCM, int& outRate, int& outCh){
|
static bool decodeMP3(const std::string& path, std::vector<int16_t>& outPCM, int& outRate, int& outCh){
|
||||||
(void)outPCM; (void)outRate; (void)outCh; (void)path;
|
(void)outPCM; (void)outRate; (void)outCh; (void)path;
|
||||||
@ -184,6 +185,8 @@ void Audio::skipToNextTrack(){
|
|||||||
void Audio::toggleMute(){ muted=!muted; }
|
void Audio::toggleMute(){ muted=!muted; }
|
||||||
void Audio::setMuted(bool m){ muted=m; }
|
void Audio::setMuted(bool m){ muted=m; }
|
||||||
|
|
||||||
|
bool Audio::isMuted() const { return muted; }
|
||||||
|
|
||||||
void Audio::nextTrack(){
|
void Audio::nextTrack(){
|
||||||
if(tracks.empty()) { current = -1; return; }
|
if(tracks.empty()) { current = -1; return; }
|
||||||
// Try every track once to find a decodable one
|
// Try every track once to find a decodable one
|
||||||
|
|||||||
@ -32,29 +32,27 @@ public:
|
|||||||
void setSoundVolume(float volume) override;
|
void setSoundVolume(float volume) override;
|
||||||
bool isMusicPlaying() const override;
|
bool isMusicPlaying() const override;
|
||||||
|
|
||||||
// Existing Audio class methods
|
// Additional IAudioSystem methods (forwarded to concrete implementation)
|
||||||
bool init(); // initialize backend (MF on Windows)
|
bool init() override;
|
||||||
void addTrack(const std::string& path); // decode MP3 -> PCM16 stereo 44100
|
void shutdown() override;
|
||||||
void addTrackAsync(const std::string& path); // add track for background loading
|
void addTrack(const std::string& path) override;
|
||||||
void startBackgroundLoading(); // start background thread for loading
|
void addTrackAsync(const std::string& path) override;
|
||||||
void waitForLoadingComplete(); // wait for all tracks to finish loading
|
void startBackgroundLoading() override;
|
||||||
bool isLoadingComplete() const; // check if background loading is done
|
bool isLoadingComplete() const override;
|
||||||
int getLoadedTrackCount() const; // get number of tracks loaded so far
|
int getLoadedTrackCount() const override;
|
||||||
void shuffle(); // randomize order
|
void start() override;
|
||||||
void start(); // begin playback
|
void skipToNextTrack() override;
|
||||||
void skipToNextTrack(); // advance to the next music track
|
void shuffle() override;
|
||||||
void toggleMute();
|
void toggleMute() override;
|
||||||
|
bool isMuted() const override;
|
||||||
void setMuted(bool m);
|
void setMuted(bool m);
|
||||||
bool isMuted() const { return muted; }
|
void setMenuTrack(const std::string& path) override;
|
||||||
|
void playMenuMusic() override;
|
||||||
// Menu music support
|
void playGameMusic() override;
|
||||||
void setMenuTrack(const std::string& path);
|
void playSfx(const std::vector<int16_t>& pcm, int channels, int rate, float volume) override;
|
||||||
void playMenuMusic();
|
|
||||||
void playGameMusic();
|
// Existing Audio class helper methods
|
||||||
|
void waitForLoadingComplete(); // wait for all tracks to finish loading
|
||||||
// Queue a sound effect to mix over the music (pcm can be mono/stereo, any rate; will be converted)
|
|
||||||
void playSfx(const std::vector<int16_t>& pcm, int channels, int rate, float volume);
|
|
||||||
void shutdown();
|
|
||||||
private:
|
private:
|
||||||
Audio()=default; ~Audio()=default; Audio(const Audio&)=delete; Audio& operator=(const Audio&)=delete;
|
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);
|
static void SDLCALL streamCallback(void* userdata, SDL_AudioStream* stream, int additional, int total);
|
||||||
|
|||||||
15
src/audio/AudioManager.cpp
Normal file
15
src/audio/AudioManager.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
11
src/audio/AudioManager.h
Normal file
11
src/audio/AudioManager.h
Normal file
@ -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);
|
||||||
|
};
|
||||||
@ -2,6 +2,7 @@
|
|||||||
#include "SoundEffect.h"
|
#include "SoundEffect.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include "audio/Audio.h"
|
#include "audio/Audio.h"
|
||||||
|
#include "audio/AudioManager.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <random>
|
#include <random>
|
||||||
@ -93,7 +94,9 @@ void SimpleAudioPlayer::playSound(const std::vector<int16_t>& pcmData, int chann
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Route through shared Audio mixer so SFX always play over music
|
// 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) {
|
bool SoundEffect::loadWAV(const std::string& filePath) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "../interfaces/IInputHandler.h"
|
#include "../interfaces/IInputHandler.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "../../audio/Audio.h"
|
#include "../../audio/Audio.h"
|
||||||
|
#include "../../audio/AudioManager.h"
|
||||||
#include "../../audio/SoundEffect.h"
|
#include "../../audio/SoundEffect.h"
|
||||||
#include "../../persistence/Scores.h"
|
#include "../../persistence/Scores.h"
|
||||||
#include "../../states/State.h"
|
#include "../../states/State.h"
|
||||||
@ -267,7 +268,7 @@ void ApplicationManager::shutdown() {
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
|
|
||||||
// Stop audio systems before tearing down SDL to avoid aborts/asserts
|
// Stop audio systems before tearing down SDL to avoid aborts/asserts
|
||||||
Audio::instance().shutdown();
|
if (auto sys = ::AudioManager::get()) sys->shutdown();
|
||||||
SoundEffectManager::instance().shutdown();
|
SoundEffectManager::instance().shutdown();
|
||||||
|
|
||||||
// Cleanup in reverse order of initialization
|
// 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
|
// M: Toggle/mute music; start playback if unmuting and not started yet
|
||||||
if (!consume && sc == SDL_SCANCODE_M) {
|
if (!consume && sc == SDL_SCANCODE_M) {
|
||||||
Audio::instance().toggleMute();
|
if (auto sys = ::AudioManager::get()) sys->toggleMute();
|
||||||
m_musicEnabled = !m_musicEnabled;
|
m_musicEnabled = !m_musicEnabled;
|
||||||
if (m_musicEnabled && !m_musicStarted && Audio::instance().getLoadedTrackCount() > 0) {
|
if (m_musicEnabled && !m_musicStarted && ::AudioManager::get() && ::AudioManager::get()->getLoadedTrackCount() > 0) {
|
||||||
Audio::instance().shuffle();
|
::AudioManager::get()->shuffle();
|
||||||
Audio::instance().start();
|
::AudioManager::get()->start();
|
||||||
m_musicStarted = true;
|
m_musicStarted = true;
|
||||||
}
|
}
|
||||||
consume = true;
|
consume = true;
|
||||||
@ -393,11 +394,7 @@ bool ApplicationManager::initializeManagers() {
|
|||||||
|
|
||||||
// N: Skip to next song in the playlist (or restart menu track)
|
// N: Skip to next song in the playlist (or restart menu track)
|
||||||
if (!consume && sc == SDL_SCANCODE_N) {
|
if (!consume && sc == SDL_SCANCODE_N) {
|
||||||
Audio::instance().skipToNextTrack();
|
if (auto sys = ::AudioManager::get()) { sys->skipToNextTrack(); if (!m_musicStarted && sys->getLoadedTrackCount() > 0) { m_musicStarted = true; m_musicEnabled = true; } }
|
||||||
if (!m_musicStarted && Audio::instance().getLoadedTrackCount() > 0) {
|
|
||||||
m_musicStarted = true;
|
|
||||||
m_musicEnabled = true;
|
|
||||||
}
|
|
||||||
consume = true;
|
consume = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,13 +512,13 @@ void ApplicationManager::registerServices() {
|
|||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registered IInputHandler service");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registered IInputHandler service");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register Audio system singleton
|
// Register Audio system singleton (via AudioManager)
|
||||||
auto& audioInstance = Audio::instance();
|
IAudioSystem* audioInstance = AudioManager::get();
|
||||||
auto audioPtr = std::shared_ptr<Audio>(&audioInstance, [](Audio*) {
|
if (audioInstance) {
|
||||||
// Custom deleter that does nothing since Audio is a singleton
|
std::shared_ptr<IAudioSystem> audioPtr(audioInstance, [](IAudioSystem*){});
|
||||||
});
|
m_serviceContainer.registerSingleton<IAudioSystem>(audioPtr);
|
||||||
m_serviceContainer.registerSingleton<IAudioSystem>(audioPtr);
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registered IAudioSystem service");
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registered IAudioSystem service");
|
}
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Service registration completed successfully");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Service registration completed successfully");
|
||||||
}
|
}
|
||||||
@ -618,7 +615,7 @@ bool ApplicationManager::initializeGame() {
|
|||||||
// as lambdas that reference members here.
|
// as lambdas that reference members here.
|
||||||
|
|
||||||
// Start background music loading similar to main.cpp: Audio init + file discovery
|
// Start background music loading similar to main.cpp: Audio init + file discovery
|
||||||
Audio::instance().init();
|
if (auto sys = ::AudioManager::get()) sys->init();
|
||||||
// Discover available tracks (up to 100) and queue for background loading
|
// Discover available tracks (up to 100) and queue for background loading
|
||||||
m_totalTracks = 0;
|
m_totalTracks = 0;
|
||||||
std::vector<std::string> trackPaths;
|
std::vector<std::string> trackPaths;
|
||||||
@ -634,15 +631,15 @@ bool ApplicationManager::initializeGame() {
|
|||||||
}
|
}
|
||||||
m_totalTracks = static_cast<int>(trackPaths.size());
|
m_totalTracks = static_cast<int>(trackPaths.size());
|
||||||
for (const auto& path : trackPaths) {
|
for (const auto& path : trackPaths) {
|
||||||
Audio::instance().addTrackAsync(path);
|
if (auto sys = ::AudioManager::get()) sys->addTrackAsync(path);
|
||||||
}
|
}
|
||||||
if (m_totalTracks > 0) {
|
if (m_totalTracks > 0) {
|
||||||
Audio::instance().startBackgroundLoading();
|
if (auto sys = ::AudioManager::get()) sys->startBackgroundLoading();
|
||||||
// Kick off playback now; Audio will pick a track once decoded.
|
// Kick off playback now; Audio will pick a track once decoded.
|
||||||
// Do not mark as started yet; we'll flip the flag once a track is actually loaded.
|
// Do not mark as started yet; we'll flip the flag once a track is actually loaded.
|
||||||
if (m_musicEnabled) {
|
if (m_musicEnabled) {
|
||||||
Audio::instance().shuffle();
|
if (auto sys = ::AudioManager::get()) { sys->shuffle(); sys->start(); }
|
||||||
Audio::instance().start();
|
m_musicStarted = true;
|
||||||
}
|
}
|
||||||
m_currentTrackLoading = 1; // mark started
|
m_currentTrackLoading = 1; // mark started
|
||||||
}
|
}
|
||||||
@ -941,15 +938,15 @@ void ApplicationManager::setupStateHandlers() {
|
|||||||
// Start music as soon as at least one track has decoded (don’t wait for all)
|
// Start music as soon as at least one track has decoded (don’t wait for all)
|
||||||
// Start music as soon as at least one track has decoded (don't wait for all)
|
// Start music as soon as at least one track has decoded (don't wait for all)
|
||||||
if (m_musicEnabled && !m_musicStarted) {
|
if (m_musicEnabled && !m_musicStarted) {
|
||||||
if (Audio::instance().getLoadedTrackCount() > 0) {
|
if (auto sys = ::AudioManager::get()) {
|
||||||
Audio::instance().shuffle();
|
if (sys->getLoadedTrackCount() > 0) { sys->shuffle(); sys->start(); m_musicStarted = true; }
|
||||||
Audio::instance().start();
|
|
||||||
m_musicStarted = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Track completion status for UI
|
// Track completion status for UI
|
||||||
if (!m_musicLoaded && Audio::instance().isLoadingComplete()) {
|
if (!m_musicLoaded) {
|
||||||
m_musicLoaded = true;
|
if (auto sys = ::AudioManager::get()) {
|
||||||
|
if (sys->isLoadingComplete()) m_musicLoaded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
#include "../../graphics/ui/Font.h"
|
#include "../../graphics/ui/Font.h"
|
||||||
#include "../../audio/Audio.h"
|
#include "../../audio/Audio.h"
|
||||||
|
#include "../../audio/AudioManager.h"
|
||||||
#include "../../audio/SoundEffect.h"
|
#include "../../audio/SoundEffect.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
@ -40,7 +41,7 @@ bool AssetManager::initialize(SDL_Renderer* renderer) {
|
|||||||
m_renderer = renderer;
|
m_renderer = renderer;
|
||||||
|
|
||||||
// Get references to singleton systems
|
// Get references to singleton systems
|
||||||
m_audioSystem = &Audio::instance();
|
m_audioSystem = ::AudioManager::get();
|
||||||
m_soundSystem = &SoundEffectManager::instance();
|
m_soundSystem = &SoundEffectManager::instance();
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
|||||||
@ -7,12 +7,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "../interfaces/IAssetLoader.h"
|
#include "../interfaces/IAssetLoader.h"
|
||||||
#include "../interfaces/IAssetLoader.h"
|
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class FontAtlas;
|
class FontAtlas;
|
||||||
class Audio;
|
class Audio;
|
||||||
class SoundEffectManager;
|
class SoundEffectManager;
|
||||||
|
class IAudioSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AssetManager - Centralized resource management following SOLID principles
|
* AssetManager - Centralized resource management following SOLID principles
|
||||||
@ -121,7 +121,7 @@ private:
|
|||||||
|
|
||||||
// System references
|
// System references
|
||||||
SDL_Renderer* m_renderer;
|
SDL_Renderer* m_renderer;
|
||||||
Audio* m_audioSystem; // Pointer to singleton
|
IAudioSystem* m_audioSystem; // Pointer to audio system (IAudioSystem)
|
||||||
SoundEffectManager* m_soundSystem; // Pointer to singleton
|
SoundEffectManager* m_soundSystem; // Pointer to singleton
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Abstract interface for audio system operations
|
* @brief Abstract interface for audio system operations
|
||||||
@ -52,4 +54,28 @@ public:
|
|||||||
* @return true if music is playing, false otherwise
|
* @return true if music is playing, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool isMusicPlaying() const = 0;
|
virtual bool isMusicPlaying() const = 0;
|
||||||
|
|
||||||
|
// Extended control methods used by the application
|
||||||
|
virtual bool init() = 0;
|
||||||
|
virtual void shutdown() = 0;
|
||||||
|
|
||||||
|
virtual void addTrack(const std::string& path) = 0;
|
||||||
|
virtual void addTrackAsync(const std::string& path) = 0;
|
||||||
|
virtual void startBackgroundLoading() = 0;
|
||||||
|
virtual bool isLoadingComplete() const = 0;
|
||||||
|
virtual int getLoadedTrackCount() const = 0;
|
||||||
|
|
||||||
|
virtual void start() = 0;
|
||||||
|
virtual void skipToNextTrack() = 0;
|
||||||
|
virtual void shuffle() = 0;
|
||||||
|
|
||||||
|
virtual void toggleMute() = 0;
|
||||||
|
virtual bool isMuted() const = 0;
|
||||||
|
|
||||||
|
virtual void setMenuTrack(const std::string& path) = 0;
|
||||||
|
virtual void playMenuMusic() = 0;
|
||||||
|
virtual void playGameMusic() = 0;
|
||||||
|
|
||||||
|
// Low-level SFX path (raw PCM) used by internal SFX mixer
|
||||||
|
virtual void playSfx(const std::vector<int16_t>& pcm, int channels, int rate, float volume) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "audio/Audio.h"
|
#include "audio/Audio.h"
|
||||||
|
#include "audio/AudioManager.h"
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.14159265358979323846
|
#define M_PI 3.14159265358979323846
|
||||||
@ -266,6 +267,6 @@ void LineEffect::playLineClearSound(int lineCount) {
|
|||||||
const std::vector<int16_t>* sample = (lineCount == 4) ? &tetrisSample : &lineClearSample;
|
const std::vector<int16_t>* sample = (lineCount == 4) ? &tetrisSample : &lineClearSample;
|
||||||
if (sample && !sample->empty()) {
|
if (sample && !sample->empty()) {
|
||||||
// Mix via shared Audio device so it layers with music
|
// Mix via shared Audio device so it layers with music
|
||||||
Audio::instance().playSfx(*sample, 2, 44100, (lineCount == 4) ? 0.9f : 0.7f);
|
if (auto sys = ::AudioManager::get()) sys->playSfx(*sample, 2, 44100, (lineCount == 4) ? 0.9f : 0.7f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "audio/Audio.h"
|
#include "audio/Audio.h"
|
||||||
|
#include "audio/AudioManager.h"
|
||||||
#include "gameplay/core/Game.h"
|
#include "gameplay/core/Game.h"
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
@ -461,7 +462,7 @@ void LineEffect::playLineClearSound(int lineCount) {
|
|||||||
const std::vector<int16_t>* sample = (lineCount == 4) ? &tetrisSample : &lineClearSample;
|
const std::vector<int16_t>* sample = (lineCount == 4) ? &tetrisSample : &lineClearSample;
|
||||||
if (sample && !sample->empty()) {
|
if (sample && !sample->empty()) {
|
||||||
// Mix via shared Audio device so it layers with music
|
// Mix via shared Audio device so it layers with music
|
||||||
Audio::instance().playSfx(*sample, 2, 44100, (lineCount == 4) ? 0.9f : 0.7f);
|
if (auto sys = ::AudioManager::get()) sys->playSfx(*sample, 2, 44100, (lineCount == 4) ? 0.9f : 0.7f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "../core/Settings.h"
|
#include "../core/Settings.h"
|
||||||
#include "../core/state/StateManager.h"
|
#include "../core/state/StateManager.h"
|
||||||
#include "../audio/Audio.h"
|
#include "../audio/Audio.h"
|
||||||
|
#include "../audio/AudioManager.h"
|
||||||
#include "../audio/SoundEffect.h"
|
#include "../audio/SoundEffect.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3/SDL_render.h>
|
#include <SDL3/SDL_render.h>
|
||||||
@ -180,7 +181,7 @@ void MenuState::showCoopSetupPanel(bool show, bool resumeMusic) {
|
|||||||
coopSetupStep = CoopSetupStep::ChoosePartner;
|
coopSetupStep = CoopSetupStep::ChoosePartner;
|
||||||
// Resume menu music only when requested (ESC should pass resumeMusic=false)
|
// Resume menu music only when requested (ESC should pass resumeMusic=false)
|
||||||
if (resumeMusic && ctx.musicEnabled && *ctx.musicEnabled) {
|
if (resumeMusic && ctx.musicEnabled && *ctx.musicEnabled) {
|
||||||
Audio::instance().playMenuMusic();
|
if (auto sys = ::AudioManager::get()) sys->playMenuMusic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "../core/state/StateManager.h"
|
#include "../core/state/StateManager.h"
|
||||||
#include "../graphics/ui/Font.h"
|
#include "../graphics/ui/Font.h"
|
||||||
#include "../audio/Audio.h"
|
#include "../audio/Audio.h"
|
||||||
|
#include "../audio/AudioManager.h"
|
||||||
#include "../audio/SoundEffect.h"
|
#include "../audio/SoundEffect.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -220,7 +221,7 @@ void OptionsState::toggleFullscreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OptionsState::toggleMusic() {
|
void OptionsState::toggleMusic() {
|
||||||
Audio::instance().toggleMute();
|
if (auto sys = ::AudioManager::get()) sys->toggleMute();
|
||||||
// If muted, music is disabled. If not muted, music is enabled.
|
// If muted, music is disabled. If not muted, music is enabled.
|
||||||
// Note: Audio::instance().isMuted() returns true if muted.
|
// Note: Audio::instance().isMuted() returns true if muted.
|
||||||
// But Audio class doesn't expose isMuted directly in header usually?
|
// But Audio class doesn't expose isMuted directly in header usually?
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../video/VideoPlayer.h"
|
#include "../video/VideoPlayer.h"
|
||||||
#include "../audio/Audio.h"
|
#include "../audio/Audio.h"
|
||||||
|
#include "../audio/AudioManager.h"
|
||||||
#include "../core/state/StateManager.h"
|
#include "../core/state/StateManager.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
@ -104,7 +105,7 @@ void VideoState::startAudioIfReady() {
|
|||||||
if (m_audioPcm.empty()) return;
|
if (m_audioPcm.empty()) return;
|
||||||
|
|
||||||
// Use the existing audio output path (same device as music/SFX).
|
// Use the existing audio output path (same device as music/SFX).
|
||||||
Audio::instance().playSfx(m_audioPcm, m_audioChannels, m_audioRate, 1.0f);
|
if (auto sys = ::AudioManager::get()) sys->playSfx(m_audioPcm, m_audioChannels, m_audioRate, 1.0f);
|
||||||
m_audioStarted = true;
|
m_audioStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user