Audio Abstrakcija - WIP

This commit is contained in:
2026-03-13 14:28:08 +01:00
parent 8ae713ba8a
commit 52df67da09
13 changed files with 324 additions and 43 deletions

37
src/audio/audio.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include <audio/audio.hpp>
namespace Game::Audio {
Audio::~Audio() {
if (mDevice != 0) {
SDL_CloseAudioDevice(mDevice);
LOG("Audio device closed successfully");
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
LOG("SDL audio subsystem quit successfully");
}
Audio& Audio::getInstance() {
static Audio instance;
return instance;
}
bool Audio::init() {
if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) {
ERROR("Failed to initialize SDL audio subsystem: " << SDL_GetError());
} else {
LOG("SDL audio subsystem initialized successfully");
}
mAudioSpec.channels = 2; // Stereo
mAudioSpec.freq = 44100; // CD quality
mAudioSpec.format = SDL_AUDIO_F32; // 32-bit float
mDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &mAudioSpec);
if (mDevice == 0) {
ERROR("Failed to open audio device: " << SDL_GetError());
return false;
}
return true;
}
}

View File

@@ -2,26 +2,22 @@
namespace Game::AGame {
void Player::start() {
LOG("Created the Player");
mSound = Object::Sound("../resources/example.wav", Object::Format::WAV);
mSound.play();
if (mTex && mTex->getId() == "Roboto") {
LOG("Player texture is a font");
// Treat as Font and build it
std::shared_ptr<Renderer::Font> font = std::dynamic_pointer_cast<Renderer::Font>(mTex);
if (font) {
font->build({255, 255, 255, 255}, "Hello, World!");
} else {
ERROR("Failed to cast texture to font");
}
}
mTransform.x = 640.f - (mTex->getWidth() / 2.f * mTransform.scaleX); // Start in the middle of the screen
mTransform.y = 360.f - (mTex->getHeight() / 2.f * mTransform.scaleY);
mTransform.rotation = 0.f;
}
void Player::update(float deltaTime) {
if (!mIsActive) return;
//LOG("Updated Player");
mTransform.x += 1.f; // Move right at a constant speed for testing
//mTransform.x += 1.f; // Move right at a constant speed for testing
mTransform.rotation += 1.f; // Rotate clockwise for testing
//LOG(mName << " position: " << mTransform.x << ' ' << mTransform.y);
//LOG("DeltaTime: " << deltaTime);
mTransform.scaleX = 1.f + 1.f * std::sin(RUNNING_TIME() / 0.5f); // Pulsate scale for testing
//mTransform.scaleY = 1.f + 1.f * std::sin(SDL_GetTicks() / 500.f);
}
}

150
src/object/sound.cpp Normal file
View File

@@ -0,0 +1,150 @@
#include <object/sound.hpp>
namespace Game::Object {
namespace {
static SDL_AudioSpec makeFloatStereo44100() {
SDL_AudioSpec spec{};
spec.freq = 44100;
spec.channels = 2;
spec.format = SDL_AUDIO_F32;
return spec;
}
}
Sound::Sound(std::string path, Format format, int volume)
: mAudioBuffer(nullptr), mAudioLength(0), mAudioStream(nullptr), mVolume(volume) {
if (format == Format::WAV) {
SDL_AudioSpec wavSpec = makeFloatStereo44100();
if (!SDL_LoadWAV(path.c_str(), &wavSpec, &mAudioBuffer, &mAudioLength)) {
ERROR("Failed to load WAV file: " << SDL_GetError());
return;
}
LOG("WAV file loaded successfully");
SDL_AudioSpec spec = makeFloatStereo44100();
mAudioStream = SDL_OpenAudioDeviceStream(
Audio::Audio::getInstance().getAudioDevice(), &spec, nullptr, nullptr
);
if (!mAudioStream) {
ERROR("Failed to create audio stream: " << SDL_GetError());
SDL_free(mAudioBuffer);
mAudioBuffer = nullptr;
mAudioLength = 0;
}
} else {
ERROR("Unsupported audio format");
}
}
Sound::Sound(const Sound& other)
: mAudioBuffer(nullptr), mAudioLength(0), mAudioStream(nullptr), mVolume(other.mVolume) {
if (&other == this) return;
if (other.mAudioBuffer && other.mAudioLength > 0) {
Uint8* newBuffer = static_cast<Uint8*>(SDL_malloc(other.mAudioLength));
if (!newBuffer) {
ERROR("Failed to allocate memory for audio buffer copy");
return;
}
SDL_memcpy(newBuffer, other.mAudioBuffer, other.mAudioLength);
mAudioBuffer = newBuffer;
mAudioLength = other.mAudioLength;
}
SDL_AudioSpec wavSpec = makeFloatStereo44100();
mAudioStream = SDL_OpenAudioDeviceStream(
Audio::Audio::getInstance().getAudioDevice(), &wavSpec, nullptr, nullptr
);
if (!mAudioStream) {
ERROR("Failed to create audio stream for copied Sound: " << SDL_GetError());
}
}
Sound& Sound::operator=(const Sound& other) {
if (&other == this) return *this;
Uint8* newBuffer = nullptr;
Uint32 newLength = 0;
if (other.mAudioBuffer && other.mAudioLength > 0) {
newBuffer = static_cast<Uint8*>(SDL_malloc(other.mAudioLength));
if (!newBuffer) {
ERROR("Failed to allocate memory for audio buffer copy");
return *this;
}
SDL_memcpy(newBuffer, other.mAudioBuffer, other.mAudioLength);
newLength = other.mAudioLength;
}
SDL_AudioStream* newStream = nullptr;
SDL_AudioSpec wavSpec = makeFloatStereo44100();
newStream = SDL_OpenAudioDeviceStream(
Audio::Audio::getInstance().getAudioDevice(), &wavSpec, nullptr, nullptr
);
if (!newStream) {
ERROR("Failed to create audio stream for copied Sound: " << SDL_GetError());
if (newBuffer) SDL_free(newBuffer);
return *this;
}
if (mAudioBuffer) SDL_free(mAudioBuffer);
if (mAudioStream && SDL_WasInit(SDL_INIT_AUDIO)) SDL_DestroyAudioStream(mAudioStream);
mAudioBuffer = newBuffer;
mAudioLength = newLength;
mAudioStream = newStream;
mVolume = other.mVolume;
return *this;
}
Sound::Sound(Sound&& other)
: mAudioBuffer(other.mAudioBuffer),
mAudioLength(other.mAudioLength),
mAudioStream(other.mAudioStream),
mVolume(other.mVolume) {
other.mAudioBuffer = nullptr;
other.mAudioLength = 0;
other.mAudioStream = nullptr;
}
Sound& Sound::operator=(Sound&& other) {
if (this != &other) {
if (mAudioBuffer) SDL_free(mAudioBuffer);
if (mAudioStream && SDL_WasInit(SDL_INIT_AUDIO)) SDL_DestroyAudioStream(mAudioStream);
mAudioBuffer = other.mAudioBuffer;
mAudioLength = other.mAudioLength;
mAudioStream = other.mAudioStream;
mVolume = other.mVolume;
other.mAudioBuffer = nullptr;
other.mAudioLength = 0;
other.mAudioStream = nullptr;
}
return *this;
}
Sound::~Sound() {
if (mAudioBuffer) {
SDL_free(mAudioBuffer);
mAudioBuffer = nullptr;
}
if (mAudioStream) {
if (SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_DestroyAudioStream(mAudioStream);
}
mAudioStream = nullptr;
}
}
void Sound::play() {
if (mAudioStream && mAudioBuffer && mAudioLength > 0) {
if (!SDL_PutAudioStreamData(mAudioStream, mAudioBuffer, mAudioLength)) {
ERROR("Failed to queue audio data: " << SDL_GetError());
}
}
}
}

View File

@@ -1,42 +1,58 @@
#include <renderer/texture.hpp>
#include <utility>
Game::Renderer::Texture::Texture(std::string id)
: mTex(nullptr), mId(std::move(id)) {}
namespace Game::Renderer {
Texture::Texture(std::string id)
: mTex(nullptr), mId(std::move(id)) {}
Game::Renderer::Texture::Texture(const std::string& path, SDL_Renderer* renderer, std::string id)
: mTex(nullptr), mId(id) {
SDL_Surface* surf = IMG_Load(path.c_str());
if (!surf) {
ERROR("Failed to load image at " << path);
return;
Texture::Texture(const std::string& path, SDL_Renderer* renderer, std::string id)
: mTex(nullptr), mId(id) {
SDL_Surface* surf = IMG_Load(path.c_str());
if (!surf) {
ERROR("Failed to load image at " << path);
return;
}
mTex = SDL_CreateTextureFromSurface(renderer, surf);
SDL_DestroySurface(surf);
}
mTex = SDL_CreateTextureFromSurface(renderer, surf);
SDL_DestroySurface(surf);
}
Texture::Texture(const Texture& other) {
// Copy the references, since copying memory would require re-initing a bunch of things - for now
this->mTex = other.mTex;
}
Game::Renderer::Texture::Texture(const Texture& other) {
// Copy the references, since copying memory would require re-initing a bunch of things - for now
this->mTex = other.mTex;
}
Texture& Texture::operator=(const Texture& other) {
// Same reasoning
this->mTex = other.mTex;
return *this;
}
Game::Renderer::Texture& Game::Renderer::Texture::operator=(const Texture& other) {
// Same reasoning
this->mTex = other.mTex;
return *this;
}
Texture::~Texture() {
if (mTex)
SDL_DestroyTexture(mTex);
LOG("Destroyed texture '" << mId << "'")
}
Game::Renderer::Texture::~Texture() {
if (mTex)
SDL_DestroyTexture(mTex);
LOG("Destroyed texture '" << mId << "'")
}
SDL_Texture* Texture::getSDLTexture() {
return mTex;
}
SDL_Texture* Game::Renderer::Texture::getSDLTexture() {
return mTex;
}
std::string Texture::getId() {
return mId;
}
std::string Game::Renderer::Texture::getId() {
return mId;
float Texture::getWidth() {
if (!mTex) return 0.f;
float width;
SDL_GetTextureSize(mTex, &width, nullptr);
return width;
}
float Texture::getHeight() {
if (!mTex) return 0.f;
float height;
SDL_GetTextureSize(mTex, nullptr, &height);
return height;
}
}

View File

@@ -33,6 +33,8 @@ namespace Game::Window {
return false;
}
Audio::Audio::getInstance().init();
mWindow = SDL_CreateWindow(title.c_str(), width, height, SDL_WINDOW_RESIZABLE);
if (!mWindow) {
ERROR("Failed to create window: " << SDL_GetError());