Files
spacetris/src/audio/Audio.h

88 lines
3.2 KiB
C++

// Audio.h - MP3 playlist playback (Windows Media Foundation backend) + SDL3 stream
#pragma once
#include <SDL3/SDL.h>
#include <vector>
#include <string>
#include <random>
#include <cstdint>
#include <thread>
#include <mutex>
#include <atomic>
#include "../core/interfaces/IAudioSystem.h"
struct AudioTrack {
std::string path;
std::vector<int16_t> pcm;
int channels = 2;
int rate = 44100;
size_t cursor = 0;
bool ok = false;
};
class Audio : public IAudioSystem {
public:
static Audio& instance();
// IAudioSystem interface implementation
void playSound(const std::string& name) override;
void playMusic(const std::string& name) override;
void stopMusic() override;
void setMasterVolume(float volume) override;
void setMusicVolume(float volume) override;
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 toggleMute();
// 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<int16_t>& pcm, int channels, int rate, float volume);
void shutdown();
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);
void feed(Uint32 bytesWanted, SDL_AudioStream* stream);
void nextTrack();
bool ensureStream();
void backgroundLoadingThread(); // background thread function
std::vector<AudioTrack> tracks;
AudioTrack menuTrack;
bool isMenuMusic = false;
int current=-1; bool playing=false; bool muted=false; std::mt19937 rng{std::random_device{}()};
SDL_AudioStream* audioStream=nullptr; SDL_AudioSpec outSpec{}; int outChannels=2; int outRate=44100; bool mfStarted=false;
// Threading support
std::vector<std::string> pendingTracks;
std::thread loadingThread;
std::mutex tracksMutex;
std::mutex pendingTracksMutex;
std::atomic<bool> loadingComplete{false};
std::atomic<bool> loadingAbort{false};
std::atomic<int> loadedCount{0};
// SFX mixing support
struct SfxPlay { std::vector<int16_t> pcm; size_t cursor=0; };
std::vector<SfxPlay> activeSfx;
std::mutex sfxMutex;
// Volume control
float m_masterVolume = 1.0f;
float m_musicVolume = 1.0f;
float m_sfxVolume = 1.0f;
};