mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-24 13:44:58 +00:00
refactor: Implement SDL audio initialization, playback, and cleanup in SdlAudioService
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include "sdl_audio_service.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
namespace sdl3cpp::services::impl {
|
||||
|
||||
@@ -19,9 +21,33 @@ void SdlAudioService::Initialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Initialize SDL audio subsystem
|
||||
logger_->Info("Audio service initialized (stub implementation)");
|
||||
// Initialize SDL audio
|
||||
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
|
||||
throw std::runtime_error("Failed to initialize SDL audio: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
// Set up desired audio spec
|
||||
SDL_AudioSpec desiredSpec;
|
||||
SDL_zero(desiredSpec);
|
||||
desiredSpec.freq = 44100;
|
||||
desiredSpec.format = SDL_AUDIO_S16;
|
||||
desiredSpec.channels = 2;
|
||||
desiredSpec.samples = 4096;
|
||||
desiredSpec.callback = AudioCallback;
|
||||
desiredSpec.userdata = this;
|
||||
|
||||
// Open audio device
|
||||
audioDevice_ = SDL_OpenAudioDevice(nullptr, 0, &desiredSpec, &audioSpec_, 0);
|
||||
if (audioDevice_ == 0) {
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
throw std::runtime_error("Failed to open audio device: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
// Start audio playback
|
||||
SDL_PlayAudioDevice(audioDevice_);
|
||||
|
||||
initialized_ = true;
|
||||
logger_->Info("SDL audio service initialized successfully");
|
||||
}
|
||||
|
||||
void SdlAudioService::Shutdown() noexcept {
|
||||
@@ -31,9 +57,24 @@ void SdlAudioService::Shutdown() noexcept {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Shutdown SDL audio subsystem
|
||||
// Stop and cleanup audio
|
||||
if (audioDevice_ != 0) {
|
||||
SDL_PauseAudioDevice(audioDevice_, 1); // Pause
|
||||
SDL_CloseAudioDevice(audioDevice_);
|
||||
audioDevice_ = 0;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(audioMutex_);
|
||||
if (backgroundAudio_) {
|
||||
CleanupAudioData(*backgroundAudio_);
|
||||
backgroundAudio_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
initialized_ = false;
|
||||
logger_->Info("Audio service shutdown (stub implementation)");
|
||||
logger_->Info("SDL audio service shutdown");
|
||||
}
|
||||
|
||||
void SdlAudioService::PlayBackground(const std::filesystem::path& path, bool loop) {
|
||||
@@ -43,8 +84,25 @@ void SdlAudioService::PlayBackground(const std::filesystem::path& path, bool loo
|
||||
throw std::runtime_error("Audio service not initialized");
|
||||
}
|
||||
|
||||
// TODO: Implement background music playback using SDL_mixer or similar
|
||||
logger_->Info("Playing background audio: " + path.string() + " (loop: " + std::to_string(loop) + ") - STUB");
|
||||
std::lock_guard<std::mutex> lock(audioMutex_);
|
||||
|
||||
// Stop current background audio
|
||||
if (backgroundAudio_) {
|
||||
CleanupAudioData(*backgroundAudio_);
|
||||
backgroundAudio_.reset();
|
||||
}
|
||||
|
||||
// Load new audio file
|
||||
backgroundAudio_ = std::make_unique<AudioData>();
|
||||
if (!LoadAudioFile(path, *backgroundAudio_)) {
|
||||
backgroundAudio_.reset();
|
||||
throw std::runtime_error("Failed to load audio file: " + path.string());
|
||||
}
|
||||
|
||||
backgroundAudio_->loop = loop;
|
||||
backgroundAudio_->position = 0;
|
||||
|
||||
logger_->Info("Playing background audio: " + path.string() + " (loop: " + std::to_string(loop) + ")");
|
||||
}
|
||||
|
||||
void SdlAudioService::PlayEffect(const std::filesystem::path& path, bool loop) {
|
||||
@@ -54,8 +112,8 @@ void SdlAudioService::PlayEffect(const std::filesystem::path& path, bool loop) {
|
||||
throw std::runtime_error("Audio service not initialized");
|
||||
}
|
||||
|
||||
// TODO: Implement sound effect playback
|
||||
logger_->Info("Playing effect audio: " + path.string() + " (loop: " + std::to_string(loop) + ") - STUB");
|
||||
// For now, effects are not implemented - could be added later
|
||||
logger_->Info("Playing effect audio: " + path.string() + " (loop: " + std::to_string(loop) + ") - NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
void SdlAudioService::StopBackground() {
|
||||
@@ -65,25 +123,26 @@ void SdlAudioService::StopBackground() {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Stop background music
|
||||
logger_->Info("Stopping background audio - STUB");
|
||||
std::lock_guard<std::mutex> lock(audioMutex_);
|
||||
if (backgroundAudio_) {
|
||||
CleanupAudioData(*backgroundAudio_);
|
||||
backgroundAudio_.reset();
|
||||
}
|
||||
|
||||
logger_->Info("Stopped background audio");
|
||||
}
|
||||
|
||||
void SdlAudioService::StopAll() {
|
||||
logger_->TraceFunction(__func__);
|
||||
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Stop all audio
|
||||
logger_->Info("Stopping all audio - STUB");
|
||||
StopBackground();
|
||||
// Effects would be stopped here too
|
||||
logger_->Info("Stopped all audio");
|
||||
}
|
||||
|
||||
void SdlAudioService::SetVolume(float volume) {
|
||||
volume_ = std::clamp(volume, 0.0f, 1.0f);
|
||||
// Note: AudioPlayer doesn't expose volume control,
|
||||
// this would need to be added to AudioPlayer implementation
|
||||
logger_->TraceVariable("volume", volume_);
|
||||
}
|
||||
|
||||
float SdlAudioService::GetVolume() const {
|
||||
@@ -91,8 +150,74 @@ float SdlAudioService::GetVolume() const {
|
||||
}
|
||||
|
||||
bool SdlAudioService::IsBackgroundPlaying() const {
|
||||
// TODO: Check if background music is currently playing
|
||||
return false; // Stub implementation
|
||||
std::lock_guard<std::mutex> lock(audioMutex_);
|
||||
return backgroundAudio_ != nullptr;
|
||||
}
|
||||
|
||||
void SdlAudioService::AudioCallback(void* userdata, Uint8* stream, int len) {
|
||||
auto* service = static_cast<SdlAudioService*>(userdata);
|
||||
service->MixAudio(stream, len);
|
||||
}
|
||||
|
||||
void SdlAudioService::MixAudio(Uint8* stream, int len) {
|
||||
std::lock_guard<std::mutex> lock(audioMutex_);
|
||||
|
||||
// Clear the stream
|
||||
SDL_memset(stream, 0, len);
|
||||
|
||||
if (!backgroundAudio_ || !backgroundAudio_->isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read audio data from vorbis file
|
||||
char buffer[4096];
|
||||
int bytesRead = 0;
|
||||
int totalBytesRead = 0;
|
||||
|
||||
while (totalBytesRead < len) {
|
||||
bytesRead = ov_read(&backgroundAudio_->vorbisFile, buffer, std::min(4096, len - totalBytesRead), 0, 2, 1, nullptr);
|
||||
if (bytesRead <= 0) {
|
||||
// End of file
|
||||
if (backgroundAudio_->loop) {
|
||||
// Loop back to beginning
|
||||
ov_pcm_seek(&backgroundAudio_->vorbisFile, 0);
|
||||
continue;
|
||||
} else {
|
||||
// Stop playback
|
||||
CleanupAudioData(*backgroundAudio_);
|
||||
backgroundAudio_.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mix audio data (simple copy for now, could add volume mixing)
|
||||
SDL_MixAudio(stream + totalBytesRead, reinterpret_cast<Uint8*>(buffer), bytesRead, SDL_MIX_MAXVOLUME);
|
||||
totalBytesRead += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
bool SdlAudioService::LoadAudioFile(const std::filesystem::path& path, AudioData& audioData) {
|
||||
FILE* file = fopen(path.c_str(), "rb");
|
||||
if (!file) {
|
||||
logger_->Error("Failed to open audio file: " + path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ov_open(file, &audioData.vorbisFile, nullptr, 0) < 0) {
|
||||
fclose(file);
|
||||
logger_->Error("Failed to open vorbis file: " + path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
audioData.isOpen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SdlAudioService::CleanupAudioData(AudioData& audioData) {
|
||||
if (audioData.isOpen) {
|
||||
ov_clear(&audioData.vorbisFile);
|
||||
audioData.isOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sdl3cpp::services::impl
|
||||
|
||||
Reference in New Issue
Block a user