Skip to content

Commit

Permalink
feat(audio): add audioPlugin and audio sample
Browse files Browse the repository at this point in the history
Co-Authored-By: João Miguel Nogueira <[email protected]>
  • Loading branch information
diogomsmiranda and Dageus committed Nov 23, 2024
1 parent ce15432 commit d3ab458
Show file tree
Hide file tree
Showing 25 changed files with 655 additions and 3 deletions.
11 changes: 9 additions & 2 deletions core/include/cubos/core/al/audio_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ namespace cubos::core::al
/// @brief Plays the source.
virtual void play() = 0;

/// @brief Stops the source, restarting buffer to position 0.
virtual void stop() = 0;

/// @brief Pauses the source, allowing to be played from the moment it was paused.
virtual void pause() = 0;

protected:
Source() = default;
};
Expand Down Expand Up @@ -188,8 +194,9 @@ namespace cubos::core::al
/// @return Handle of the new source.
virtual std::shared_ptr<impl::Source> createSource() = 0;

/// @brief Creates a new audio listener.
/// @return Handle of the new listener.
/// @brief Gets the listener with the specific index.
/// @param index Index of the listener.
/// @return Handle of the listener.
virtual std::shared_ptr<impl::Listener> listener(size_t index) = 0;

protected:
Expand Down
27 changes: 26 additions & 1 deletion core/src/al/miniaudio_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,25 @@ class MiniaudioSource : public impl::Source
}
}

void stop() override
{
if (ma_sound_stop(&mSound) != MA_SUCCESS)
{
CUBOS_ERROR("Failed to stop sound");
return;
}
ma_sound_seek_to_pcm_frame(&mSound, 0);
}

void pause() override
{
if (ma_sound_stop(&mSound) != MA_SUCCESS)
{
CUBOS_ERROR("Failed to pause sound");
return;
}
}

private:
ma_sound mSound;
ma_engine& mEngine;
Expand All @@ -188,7 +207,7 @@ class MiniaudioSource : public impl::Source
class MiniaudioDevice : public impl::AudioDevice
{
public:
MiniaudioDevice(ma_context& context, const std::string& deviceName, ma_uint32 listenerCount)
MiniaudioDevice(ma_context& context, const std::string& specifier, ma_uint32 listenerCount)
: mContext(context)
{
ma_device_info* pPlaybackDeviceInfos;
Expand All @@ -202,6 +221,12 @@ class MiniaudioDevice : public impl::AudioDevice
return;
}

std::string deviceName{specifier};
if (deviceName == "")
{
deviceName = pPlaybackDeviceInfos[0].name;
}

ma_device_id* deviceId = nullptr;
for (ma_uint32 i = 0; i < playbackDeviceCount; i++)
{
Expand Down
9 changes: 9 additions & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ set(CUBOS_ENGINE_SOURCE
"src/utils/free_camera/plugin.cpp"
"src/utils/free_camera/controller.cpp"

"src/audio/plugin.cpp"
"src/audio/source.cpp"
"src/audio/source_impl.cpp"
"src/audio/listener.cpp"
"src/audio/listener_impl.cpp"
"src/audio/pause.cpp"
"src/audio/play.cpp"
"src/audio/stop.cpp"

"src/audio/audio.cpp"
"src/audio/bridge.cpp"

Expand Down
24 changes: 24 additions & 0 deletions engine/include/cubos/engine/audio/listener.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// @file
/// @brief Component @ref cubos::engine::AudioListener.
/// @ingroup audio-plugin

#pragma once

#include <map>

#include <cubos/core/al/audio_context.hpp>
#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>

namespace cubos::engine
{
/// @brief Component which adds an AudioListener to the entitiy
/// @ingroup audio-plugin
struct CUBOS_ENGINE_API AudioListener
{
CUBOS_REFLECT;

bool active{false};
};
} // namespace cubos::engine
22 changes: 22 additions & 0 deletions engine/include/cubos/engine/audio/pause.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// @file
/// @brief Component @ref cubos::engine::AudioPause.
/// @ingroup audio-plugin

#pragma once

#include <glm/glm.hpp>

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>
#include <cubos/engine/prelude.hpp>

namespace cubos::engine
{
/// @brief Component which adds an AudioSource to the entitiy
/// @ingroup audio-plugin
struct CUBOS_ENGINE_API AudioPause
{
CUBOS_REFLECT;
};
} // namespace cubos::engine
22 changes: 22 additions & 0 deletions engine/include/cubos/engine/audio/play.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// @file
/// @brief Component @ref cubos::engine::AudioPlay.
/// @ingroup audio-plugin

#pragma once

#include <glm/glm.hpp>

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>
#include <cubos/engine/prelude.hpp>

namespace cubos::engine
{
/// @brief Component which adds an AudioSource to the entitiy
/// @ingroup audio-plugin
struct CUBOS_ENGINE_API AudioPlay
{
CUBOS_REFLECT;
};
} // namespace cubos::engine
40 changes: 40 additions & 0 deletions engine/include/cubos/engine/audio/plugin.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/// @dir
/// @brief @ref audio-plugin plugin directory.

/// @file
/// @brief Plugin entry point.
/// @ingroup audio-plugin

#pragma once

#include <cubos/engine/audio/audio.hpp>
#include <cubos/engine/audio/listener.hpp>
#include <cubos/engine/audio/pause.hpp>
#include <cubos/engine/audio/play.hpp>
#include <cubos/engine/audio/source.hpp>
#include <cubos/engine/audio/stop.hpp>
#include <cubos/engine/prelude.hpp>

namespace cubos::engine
{
/// @defgroup audio-plugin Audio
/// @ingroup engine
/// @brief Adds audio to @b Cubos
///
/// ## Settings
/// - `audio.listener.count` - number of listeners per audio device (default: `4`).
///
/// ## Dependencies
/// - @ref settings-plugin

/// @brief Initializes the audio context (after @ref settingsTag).
CUBOS_ENGINE_API extern Tag audioInitTag;

/// @brief Initializes the audio state (after @ref audioInitTag).
CUBOS_ENGINE_API extern Tag audioStateInitTag;

/// @brief Plugin entry function.
/// @param cubos @b Cubos main class.
/// @ingroup assets-plugin
CUBOS_ENGINE_API void audioPlugin(Cubos& cubos);
} // namespace cubos::engine
41 changes: 41 additions & 0 deletions engine/include/cubos/engine/audio/source.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// @file
/// @brief Component @ref cubos::engine::AudioSource.
/// @ingroup audio-plugin

#pragma once

#include <glm/glm.hpp>

#include <cubos/core/al/audio_context.hpp>
#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>
#include <cubos/engine/audio/audio.hpp>
#include <cubos/engine/prelude.hpp>

namespace cubos::engine
{
/// @brief Component which adds an AudioSource to the entitiy
/// @ingroup audio-plugin
struct CUBOS_ENGINE_API AudioSource
{
CUBOS_REFLECT;

bool playing{false};
bool looping{false};
bool stop{false};

float gain;
float pitch;
float maxDistance;
float minDistance;

float innerConeAngle;
float outerConeAngle;
float outerConeGain;

glm::vec3 coneDirection;

Asset<Audio> sound{};
};
} // namespace cubos::engine
22 changes: 22 additions & 0 deletions engine/include/cubos/engine/audio/stop.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// @file
/// @brief Component @ref cubos::engine::AudioStop.
/// @ingroup audio-plugin

#pragma once

#include <glm/glm.hpp>

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>
#include <cubos/engine/prelude.hpp>

namespace cubos::engine
{
/// @brief Component which adds an AudioSource to the entitiy
/// @ingroup audio-plugin
struct CUBOS_ENGINE_API AudioStop
{
CUBOS_REFLECT;
};
} // namespace cubos::engine
8 changes: 8 additions & 0 deletions engine/include/cubos/engine/transform/local_to_world.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ namespace cubos::engine
/// @return Rotation quaternion in world space.
glm::quat worldRotation() const;

/// @brief Gets global forward vector of the entity.
/// @return Forward vector in world space.
glm::vec3 forward() const;

/// @brief Gets global up vector of the entity.
/// @return Up vector in world space.
glm::vec3 up() const;

/// @brief Gets global scale of the entity.
/// @return Scale value in world space.
float worldScale() const;
Expand Down
1 change: 1 addition & 0 deletions engine/samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ macro(make_sample)
endif()
endmacro()
# Add samples
make_sample(DIR "audio" ASSETS)
make_sample(DIR "hello-cubos")
make_sample(DIR "settings")
make_sample(DIR "events")
Expand Down
Binary file added engine/samples/audio/assets/bg_music.mp3
Binary file not shown.
3 changes: 3 additions & 0 deletions engine/samples/audio/assets/bg_music.mp3.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"id": "059c16e7-a439-44c7-9bdc-7f133dba0c80"
}
72 changes: 72 additions & 0 deletions engine/samples/audio/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <cubos/engine/assets/plugin.hpp>
#include <cubos/engine/audio/plugin.hpp>
#include <cubos/engine/collisions/plugin.hpp>
#include <cubos/engine/fixed_step/plugin.hpp>
#include <cubos/engine/physics/plugin.hpp>
#include <cubos/engine/render/camera/camera.hpp>
#include <cubos/engine/render/camera/draws_to.hpp>
#include <cubos/engine/render/camera/perspective.hpp>
#include <cubos/engine/render/defaults/plugin.hpp>
#include <cubos/engine/render/defaults/target.hpp>
#include <cubos/engine/settings/plugin.hpp>
#include <cubos/engine/settings/settings.hpp>
#include <cubos/engine/transform/plugin.hpp>
#include <cubos/engine/window/plugin.hpp>

using namespace cubos::engine;

/// [Get handles to assets]
static const Asset<Audio> AudioAsset = AnyAsset("059c16e7-a439-44c7-9bdc-7f133dba0c80");
/// [Get handles to assets]

int main(int argc, char** argv)
{
Cubos cubos{argc, argv};

cubos.plugin(settingsPlugin);
cubos.plugin(windowPlugin);
cubos.plugin(transformPlugin);
cubos.plugin(fixedStepPlugin);
cubos.plugin(assetsPlugin);
cubos.plugin(renderDefaultsPlugin);
cubos.plugin(collisionsPlugin);
cubos.plugin(physicsPlugin);
cubos.plugin(audioPlugin);

cubos.startupSystem("configure Assets").tagged(settingsTag).call([](Settings& settings) {
settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER);
});

cubos.startupSystem("create a camera").call([](Commands cmds) {
auto targetEnt = cmds.create().add(RenderTargetDefaults{}).entity();

cmds.create()
.relatedTo(targetEnt, DrawsTo{})
.add(Camera{.zNear = 0.1F, .zFar = 1000.0F})
.add(PerspectiveCamera{.fovY = 60.0F})
.add(Position{{0.0F, 0.0F, 0.0F}})
.add(Rotation::lookingAt({-1.0F, -1.0F, -1.0F}, glm::vec3{0.0F, 1.0F, 0.0F}))
.add(AudioListener{true});
});

cubos.startupSystem("create an audio source").after(audioStateInitTag).call([](Commands cmds) {
cmds.create()
.add(Position{{0.0F, 0.0F, 0.0F}})
.add(Velocity{.vec = {1.0F, 1.0F, 1.0F}})
.add(Rotation::lookingAt({-1.0F, -1.0F, -1.0F}, glm::vec3{0.0F, 1.0F, 0.0F}))
.add(AudioSource{});
});

cubos.system("play audio").call([](Commands cmds, Query<Entity, AudioSource&> query) {
for (auto [ent, src] : query)
{
if (src.sound.isNull())
{
src.sound = AudioAsset;
cmds.add(ent, AudioPlay{});
}
}
});

cubos.run();
}
11 changes: 11 additions & 0 deletions engine/src/audio/listener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <cubos/core/ecs/reflection.hpp>
#include <cubos/core/reflection/external/primitives.hpp>

#include <cubos/engine/audio/listener.hpp>

CUBOS_REFLECT_IMPL(cubos::engine::AudioListener)
{
return core::ecs::TypeBuilder<AudioListener>("cubos::engine::AudioListener")
.withField("active", &AudioListener::active)
.build();
}
11 changes: 11 additions & 0 deletions engine/src/audio/listener_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "listener_impl.hpp"

#include <cubos/core/ecs/reflection.hpp>
#include <cubos/core/reflection/external/primitives.hpp>

CUBOS_REFLECT_IMPL(cubos::engine::AudioListenerImpl)
{
return core::ecs::TypeBuilder<AudioListenerImpl>("cubos::engine::AudioListenerImpl")
.withField("index", &AudioListenerImpl::index)
.build();
}
Loading

0 comments on commit d3ab458

Please sign in to comment.