Skip to content

[FEATURE]: Use AssetManager to load/play audio. #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
@@ -11,12 +11,12 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
build_type: [Release, RelWithDebInfo]
os: [ubuntu-latest] # , windows-latest]
build_type: [Release] # RelWithDebInfo]
include:
- os: windows-latest
cpp_compiler: cl
separator: '\\'
# - os: windows-latest
# cpp_compiler: cl
# separator: '\\'
- os: ubuntu-latest
cpp_compiler: g++
separator: "/"
19 changes: 19 additions & 0 deletions src/engine/assets/asset_manager.cpp
Original file line number Diff line number Diff line change
@@ -77,6 +77,18 @@ AssetHandle<T> AssetManager::load(const std::string &path) {
m_totalAssets--;
throw std::runtime_error(createInfo.errorMsg);
}
// Load AudioFile
} else if constexpr (std::is_same_v<T, AudioFile>) {
AudioFile::CreateInfo createInfo;
if (auto audioFile = AudioFile::createFromFile(path, createInfo)) {
auto asset = std::make_shared<AudioFile>(std::move(*audioFile));
m_assets.try_emplace(path, asset, 1);
m_loadedAssets++;
return AssetHandle<T>(asset);
} else {
m_totalAssets--;
throw std::runtime_error(createInfo.errorMsg);
}
} else {
// Asset type-specific loading logic here
throw std::runtime_error("Unsupported asset type");
@@ -143,4 +155,11 @@ AssetManager::loadAsync<Texture>(const std::string &);
template bool AssetManager::exists<Texture>(const std::string &) const;
template void AssetManager::remove<Texture>(const std::string &);

template AssetHandle<AudioFile>
AssetManager::load<AudioFile>(const std::string &);
template std::future<AssetHandle<AudioFile>>
AssetManager::loadAsync<AudioFile>(const std::string &);
template bool AssetManager::exists<AudioFile>(const std::string &) const;
template void AssetManager::remove<AudioFile>(const std::string &);

} // namespace ste
1 change: 1 addition & 0 deletions src/engine/assets/asset_manager.h
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
#include <vector>

#include "engine/async/thread_pool.h"
#include "engine/audio/audio_file.h"
#include "engine/rendering/shader.h"
#include "engine/rendering/texture.h"

60 changes: 32 additions & 28 deletions src/engine/audio/audio_engine.cpp
Original file line number Diff line number Diff line change
@@ -79,8 +79,11 @@ void AudioChannel::mix(float *buffer, size_t frames) {
m_position = static_cast<size_t>(readPosition);
}

void AudioChannel::play(std::shared_ptr<AudioFile> file, float vol) {
m_currentFile = std::move(file);
void AudioChannel::play(AudioFile *file, float vol) {
if (!file)
return;

m_currentFile = file;
m_position = 0;
m_volume = vol;
m_targetVolume = vol;
@@ -90,8 +93,10 @@ void AudioChannel::play(std::shared_ptr<AudioFile> file, float vol) {

void AudioChannel::stop() {
m_active = false;
m_currentFile.reset();
m_currentFile = nullptr;
m_position = 0;
m_currentSpeed = 1.0f;
m_targetSpeed = 1.0f;
}

void AudioChannel::setVolume(float vol) {
@@ -217,37 +222,34 @@ AudioEngine::~AudioEngine() {
stopAll();
}

void AudioEngine::playSound(const std::string &path, float m_volume) {
try {
auto file = std::make_shared<AudioFile>(path);
int channel = findFreeChannel();
if (channel != -1) {
m_commandQueue.pushPlay(file, m_volume, channel);
}
} catch (const AudioFileException &e) {
std::cerr << "Failed to load sound file: " << e.what() << std::endl;
// Handle or propagate error
// Could log error or throw depending on your error handling strategy
void AudioEngine::playSound(AssetHandle<AudioFile> sound, float volume) {
if (!sound.isValid()) {
std::cerr << "Attempted to play invalid sound asset" << std::endl;
return;
}

int channel = findFreeChannel();
if (channel != -1) {
m_commandQueue.pushPlay(sound.operator->(), volume, channel);
}
}

void AudioEngine::playMusic(const std::string &path, bool loop) {
try {
auto file = std::make_shared<AudioFile>(path);
file->setLooping(loop);
void AudioEngine::playMusic(AssetHandle<AudioFile> music, bool loop) {
if (!music.isValid()) {
std::cerr << "Attempted to play invalid music asset" << std::endl;
return;
}

// Stop any currently playing music
stopChannel(0);
// Set looping state on the audio file
music->setLooping(loop);

// Queue the new music
m_commandQueue.pushPlay(file, 1.0f, 0); // Channel 0 reserved for music
} catch (const AudioFileException &e) {
std::cerr << "Failed to load sound file: " << e.what() << std::endl;
// Stop any currently playing music
stopChannel(0);

// Handle or propagate error
}
// Queue the new music
m_commandQueue.pushPlay(music.operator->(), 1.0f,
0); // Channel 0 reserved for music
}

void AudioEngine::stopChannel(int channelId) {
if (channelId >= 0 && channelId < static_cast<int>(MAX_CHANNELS)) {
m_commandQueue.pushStop(channelId);
@@ -379,10 +381,12 @@ void AudioEngine::audioCallback(float *buffer, size_t frames) {
}
}

int AudioEngine::findFreeChannel() const {
int AudioEngine::findFreeChannel() {
// Skip channel 0 (reserved for music)
for (size_t i = 1; i < MAX_CHANNELS; ++i) {
if (!m_channels[i].isActive()) {
// Optionally force a stop to ensure clean state
m_channels[i].stop();
return static_cast<int>(i);
}
}
11 changes: 6 additions & 5 deletions src/engine/audio/audio_engine.h
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@

#include "audio_file.h"
#include "audio_queue.h"
#include "engine/assets/asset_manager.h"

namespace ste {

@@ -18,7 +19,7 @@ class AudioChannel {
// Core audio functions
void update(float deltaTime);
void mix(float *buffer, size_t frames);
void play(std::shared_ptr<AudioFile> file, float vol = 1.0f);
void play(AudioFile *file, float vol = 1.0f);
void stop();

// State control
@@ -36,7 +37,7 @@ class AudioChannel {

private:
// Audio data
std::shared_ptr<AudioFile> m_currentFile;
AudioFile *m_currentFile = nullptr;
size_t m_position = 0;

// Volume control
@@ -76,8 +77,8 @@ class AudioEngine {
AudioEngine &operator=(AudioEngine &&) = delete;

// Main interface
void playSound(const std::string &path, float volume = 1.0f);
void playMusic(const std::string &path, bool loop = true);
void playSound(AssetHandle<AudioFile> sound, float volume = 1.0f);
void playMusic(AssetHandle<AudioFile> music, bool loop = true);
void stopChannel(int channelId);
void stopAll();
void setChannelVolume(int channelId, float volume);
@@ -113,7 +114,7 @@ class AudioEngine {

void processCommands();
void mixAudio(float *buffer, size_t frames);
[[nodiscard]] int findFreeChannel() const;
[[nodiscard]] int findFreeChannel();
};

}; // namespace ste
Loading