Kelsidavis-WoWee/include/audio/audio_engine.hpp
Pavel Okhlopkov 97106bd6ae fix(render): code quality cleanup
Magic number elimination:
- Create protocol_constants.hpp, warden_constants.hpp,
  render_constants.hpp, ui_constants.hpp
- Replace ~55 magic numbers across game_handler, warden_handler,
  m2_renderer_render

Reduce nesting depth:
- Extract 5 parseEffect* methods from handleSpellLogExecute
  (max indent 52 → 16 cols)
- Extract resolveSpellSchool/playSpellCastSound/playSpellImpactSound
  from 3× duplicate audio blocks in handleSpellGo
- Flatten SMSG_INVENTORY_CHANGE_FAILURE with early-return guards
- Extract drawScreenEdgeVignette() for 3 duplicate vignette blocks

DRY extract patterns:
- Replace 12 compound expansion checks with isPreWotlk() across
  movement_handler (9), chat_handler (1), social_handler (1)

const to constexpr:
- Promote 23+ static const arrays/scalars to static constexpr across
  12 source files

Error handling:
- Convert PIN auth from exceptions to std::optional<PinProof>
- Add [[nodiscard]] to 15+ initialize/parse methods
- Wrap ~20 unchecked initialize() calls with LOG_WARNING/LOG_ERROR

Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-06 22:43:13 +03:00

102 lines
3.6 KiB
C++

#pragma once
#include <glm/glm.hpp>
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
// Forward declare miniaudio types to avoid exposing implementation in header
struct ma_engine;
struct ma_sound;
namespace wowee {
namespace pipeline { class AssetManager; }
namespace audio {
/**
* AudioEngine: Singleton managing miniaudio device and playback.
* Replaces process-spawning audio system with proper non-blocking library.
*/
class AudioEngine {
public:
static AudioEngine& instance();
~AudioEngine();
// Initialization
[[nodiscard]] bool initialize();
void shutdown();
bool isInitialized() const { return initialized_; }
// Master volume (0.0 = silent, 1.0 = full)
void setMasterVolume(float volume);
float getMasterVolume() const { return masterVolume_; }
// Asset manager (enables sound loading by MPQ path)
void setAssetManager(pipeline::AssetManager* am) { assetManager_ = am; }
// 3D listener position (for positional audio)
void setListenerPosition(const glm::vec3& position);
void setListenerOrientation(const glm::vec3& forward, const glm::vec3& up);
const glm::vec3& getListenerPosition() const { return listenerPosition_; }
// Simple 2D sound playback (non-blocking)
bool playSound2D(const std::vector<uint8_t>& wavData, float volume = 1.0f, float pitch = 1.0f);
bool playSound2D(const std::string& mpqPath, float volume = 1.0f, float pitch = 1.0f);
// Stoppable 2D sound — returns a non-zero handle, or 0 on failure
uint32_t playSound2DStoppable(const std::vector<uint8_t>& wavData, float volume = 1.0f);
// Stop a sound started with playSound2DStoppable (no-op if already finished)
void stopSound(uint32_t id);
// 3D positional sound playback
bool playSound3D(const std::vector<uint8_t>& wavData, const glm::vec3& position,
float volume = 1.0f, float pitch = 1.0f, float maxDistance = 100.0f);
bool playSound3D(const std::string& mpqPath, const glm::vec3& position,
float volume = 1.0f, float pitch = 1.0f, float maxDistance = 100.0f);
// Music streaming (for background music)
bool playMusic(const std::vector<uint8_t>& musicData, float volume = 1.0f, bool loop = true);
void stopMusic();
bool isMusicPlaying() const;
void setMusicVolume(float volume);
// Update (call once per frame for cleanup/position sync)
void update(float deltaTime);
private:
AudioEngine();
AudioEngine(const AudioEngine&) = delete;
AudioEngine& operator=(const AudioEngine&) = delete;
// Track active one-shot sounds for cleanup
struct ActiveSound {
ma_sound* sound;
void* buffer; // ma_audio_buffer* - Keep audio buffer alive
std::shared_ptr<const std::vector<uint8_t>> pcmDataRef; // Keep decoded PCM alive
uint32_t id = 0; // 0 = anonymous (not stoppable)
};
std::vector<ActiveSound> activeSounds_;
uint32_t nextSoundId_ = 1;
// Music track state
ma_sound* musicSound_ = nullptr;
void* musicDecoder_ = nullptr; // ma_decoder* - Keep decoder alive for streaming
std::vector<uint8_t> musicData_; // Keep encoded music data alive
float musicVolume_ = 1.0f;
bool initialized_ = false;
float masterVolume_ = 1.0f;
glm::vec3 listenerPosition_{0.0f, 0.0f, 0.0f};
glm::vec3 listenerForward_{0.0f, 0.0f, -1.0f};
glm::vec3 listenerUp_{0.0f, 1.0f, 0.0f};
pipeline::AssetManager* assetManager_ = nullptr;
// miniaudio engine (opaque pointer)
ma_engine* engine_ = nullptr;
};
} // namespace audio
} // namespace wowee