Compare commits
22 Commits
10012b16cc
...
main
Author | SHA1 | Date | |
---|---|---|---|
64a5d19464 | |||
090317b394 | |||
4c580f4956 | |||
8b8c5310ae | |||
7c5d80cd31 | |||
ff1241fe36 | |||
57b8bfa719 | |||
640f6af291 | |||
0d2603abf0 | |||
13a21387df | |||
146bd49b36 | |||
71e4ff9317 | |||
64b5a8af29 | |||
76b53b5f71 | |||
67e423a77d | |||
a40c0665ac | |||
ee83818de2 | |||
29bcf9fbae | |||
ead1e742d1 | |||
81cef5cc8a | |||
b8cdd54888 | |||
e24e3e6637 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -47,3 +47,4 @@ CMakeUserPresets.json
|
|||||||
*.app
|
*.app
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
.cache/
|
||||||
|
@@ -3,12 +3,12 @@ cmake_minimum_required(VERSION 3.10)
|
|||||||
project(ChargeAudio VERSION 1.0)
|
project(ChargeAudio VERSION 1.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||||
set(CMAKE_MODULE_PATH "modules/" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "modules/" ${CMAKE_MODULE_PATH})
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-subobject-linkage")
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(lib/miniaudio)
|
add_subdirectory(lib/miniaudio)
|
||||||
|
|
||||||
find_package(Corrade REQUIRED Main)
|
find_package(Corrade REQUIRED Main)
|
||||||
@@ -19,8 +19,9 @@ pkg_check_modules(AVCODEC REQUIRED libavcodec)
|
|||||||
pkg_check_modules(AVUTIL REQUIRED libavutil)
|
pkg_check_modules(AVUTIL REQUIRED libavutil)
|
||||||
pkg_check_modules(SWRESAMPLE REQUIRED libswresample)
|
pkg_check_modules(SWRESAMPLE REQUIRED libswresample)
|
||||||
|
|
||||||
add_library(ChargeAudio SHARED "src/ChargeAudio.hpp" "src/Engine.cpp"
|
add_library(
|
||||||
"src/Sound.cpp")
|
ChargeAudio SHARED "src/ChargeAudio.hpp" "src/Engine.cpp" "src/Sound.cpp"
|
||||||
|
"src/Listener.cpp" "lib/miniaudio/miniaudio.c")
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
ChargeAudio
|
ChargeAudio
|
||||||
@@ -28,7 +29,9 @@ target_link_libraries(
|
|||||||
${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
${AVCODEC_LIBRARIES} ${AVUTIL_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
ChargeAudio PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
ChargeAudio
|
||||||
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
# Library
|
# Library
|
||||||
@@ -41,6 +44,7 @@ install(
|
|||||||
|
|
||||||
# include
|
# include
|
||||||
install(FILES src/ChargeAudio.hpp DESTINATION include/Charge)
|
install(FILES src/ChargeAudio.hpp DESTINATION include/Charge)
|
||||||
|
install(FILES lib/miniaudio/miniaudio.h DESTINATION include/Charge/miniaudio/)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
EXPORT ChargeAudioTargets
|
EXPORT ChargeAudioTargets
|
||||||
|
@@ -1,39 +1,118 @@
|
|||||||
#ifndef CHARGE_AUDIO_BASE_H
|
#ifndef CHARGE_AUDIO_BASE_H
|
||||||
#define CHARGE_AUDIO_BASE_H
|
#define CHARGE_AUDIO_BASE_H
|
||||||
#include "../lib/miniaudio/miniaudio.h"
|
#include "miniaudio/miniaudio.h"
|
||||||
#include <Magnum/Magnum.h>
|
|
||||||
#include <Magnum/Math/Vector.h>
|
#include <Corrade/Containers/Containers.h>
|
||||||
|
#include <Corrade/Containers/Pointer.h>
|
||||||
|
#include <Magnum/Math/Vector3.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace ChargeAudio {
|
namespace ChargeAudio {
|
||||||
|
using namespace Corrade;
|
||||||
|
|
||||||
|
typedef Containers::Pointer<class Sound> SoundContainer;
|
||||||
|
typedef Containers::Pointer<class Listener> ListenerContainer;
|
||||||
class Sound {
|
class Sound {
|
||||||
public:
|
public:
|
||||||
|
enum class SoundState { Idle, Playing, Paused, Finished };
|
||||||
|
enum class SoundType { FromFile, StreamedRawPCM, RawPCM };
|
||||||
|
// No copying
|
||||||
|
Sound(const Sound &) = delete;
|
||||||
|
Sound &operator=(const Sound &) = delete;
|
||||||
|
|
||||||
|
// No moving
|
||||||
|
Sound(Sound &&) = delete;
|
||||||
|
Sound &operator=(Sound &&) = delete;
|
||||||
|
|
||||||
~Sound();
|
~Sound();
|
||||||
void Play();
|
void Play();
|
||||||
void Pause();
|
void Pause();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
const SoundState GetState();
|
||||||
|
const SoundType GetSoundType();
|
||||||
|
|
||||||
|
const float GetPlaybackTime();
|
||||||
|
bool SetPlaybackTime(float time);
|
||||||
|
const float GetDuration();
|
||||||
void SetPosition(Magnum::Vector3 position);
|
void SetPosition(Magnum::Vector3 position);
|
||||||
Magnum::Vector3 GetPosition();
|
const Magnum::Vector3 GetPosition();
|
||||||
void SetVolume(float value);
|
void SetVolume(float value);
|
||||||
float GetVolume();
|
const float GetVolume();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Sound();
|
Sound(class Engine *engine, std::function<void(Sound *)> setupFunction,
|
||||||
|
SoundType type, std::string additionalErrorMessage = "");
|
||||||
|
static void onSoundFinish(void *customData, ma_sound *);
|
||||||
|
|
||||||
class Engine *baseEngine;
|
class Engine *baseEngine;
|
||||||
ma_sound maSound;
|
ma_sound maSound;
|
||||||
|
ma_sound_config maConfig;
|
||||||
|
ma_pcm_rb maRingBuffer;
|
||||||
|
ma_audio_buffer maAudioBuffer;
|
||||||
|
SoundState state = SoundState::Idle;
|
||||||
|
SoundType type;
|
||||||
|
|
||||||
|
friend class Engine;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Listener {
|
||||||
|
public:
|
||||||
|
// No copying, can move
|
||||||
|
Listener(const Listener &) = delete;
|
||||||
|
Listener &operator=(const Listener &) = delete;
|
||||||
|
|
||||||
|
void SetEnabled(bool isEnabled);
|
||||||
|
const bool GetEnabled();
|
||||||
|
void SetDirection(Magnum::Vector3 position);
|
||||||
|
const Magnum::Vector3 GetDirection();
|
||||||
|
void SetPosition(Magnum::Vector3 position);
|
||||||
|
const Magnum::Vector3 GetPosition();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Listener();
|
||||||
|
class Engine *baseEngine;
|
||||||
|
ma_uint32 listenerID;
|
||||||
friend class Engine;
|
friend class Engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Engine {
|
class Engine {
|
||||||
public:
|
public:
|
||||||
Engine();
|
Engine(uint32_t sampleRate = 44100, uint32_t channels = 2);
|
||||||
Sound CreateSound(std::string filepath);
|
|
||||||
|
// No copying
|
||||||
|
Engine(const Engine &) = delete;
|
||||||
|
Engine &operator=(const Engine &) = delete;
|
||||||
|
|
||||||
|
// No movement
|
||||||
|
Engine(Engine &&) = delete;
|
||||||
|
Engine &operator=(Engine &&) = delete;
|
||||||
|
|
||||||
|
~Engine();
|
||||||
|
|
||||||
|
// Creating tools
|
||||||
|
SoundContainer CreateSound(int bufferLengthInSeconds);
|
||||||
|
SoundContainer CreateSound(uint8_t *data, int length);
|
||||||
|
SoundContainer CreateSound(std::string filepath, bool streamFile = false);
|
||||||
|
ListenerContainer CreateListener();
|
||||||
|
|
||||||
void SetVolume(float value);
|
void SetVolume(float value);
|
||||||
float GetVolume();
|
const float GetVolume();
|
||||||
|
|
||||||
|
uint32_t GetSampleRate();
|
||||||
|
uint32_t GetChannelCount();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ma_engine maEngine;
|
ma_engine maEngine;
|
||||||
|
ma_engine_config maConfig;
|
||||||
ma_result maResponse;
|
ma_result maResponse;
|
||||||
|
ma_decoder maStero;
|
||||||
|
ma_uint64 listenerCounter = 0;
|
||||||
|
friend class Listener;
|
||||||
|
friend class Sound;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ChargeAudio
|
} // namespace ChargeAudio
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,37 +1,94 @@
|
|||||||
#include "ChargeAudio.hpp"
|
#include "ChargeAudio.hpp"
|
||||||
#include <Corrade/Utility/Debug.h>
|
#include "miniaudio/miniaudio.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <Corrade/Utility/Debug.h>
|
||||||
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using namespace ChargeAudio;
|
using namespace ChargeAudio;
|
||||||
using namespace Corrade;
|
using namespace Corrade;
|
||||||
|
|
||||||
Engine::Engine() {
|
Engine::Engine(uint32_t sampleRate, uint32_t channels) {
|
||||||
if ((maResponse = ma_engine_init(NULL, &maEngine)) != MA_SUCCESS) {
|
maConfig = ma_engine_config_init();
|
||||||
|
maConfig.sampleRate = sampleRate;
|
||||||
|
maConfig.channels = channels;
|
||||||
|
|
||||||
|
if ((maResponse = ma_engine_init(&maConfig, &maEngine)) != MA_SUCCESS) {
|
||||||
Utility::Error{} << "Could not init miniaudio (" << maResponse << ")";
|
Utility::Error{} << "Could not init miniaudio (" << maResponse << ")";
|
||||||
throw new std::runtime_error(
|
throw new std::runtime_error(
|
||||||
"Failed to init miniaudio engine. Check STDERR for more info.");
|
"Failed to init miniaudio engine. Check STDERR for more info.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sound Engine::CreateSound(std::string filepath) {
|
Engine::~Engine() { ma_engine_uninit(&maEngine); }
|
||||||
Sound sound;
|
|
||||||
sound.baseEngine = this;
|
|
||||||
|
|
||||||
maResponse = ma_sound_init_from_file(&maEngine, filepath.c_str(), 0, NULL,
|
uint32_t Engine::GetSampleRate() { return maEngine.sampleRate; }
|
||||||
NULL, &sound.maSound);
|
uint32_t Engine::GetChannelCount() { return ma_engine_get_channels(&maEngine); }
|
||||||
if (maResponse != MA_SUCCESS) {
|
|
||||||
Utility::Error{} << "Failed to create the sound from the file: "
|
// Use case: Stream of PCM data
|
||||||
<< filepath.c_str() << " (" << maResponse << ")";
|
SoundContainer Engine::CreateSound(int bufferLengthInSeconds) {
|
||||||
throw new std::runtime_error(
|
return SoundContainer(new Sound(
|
||||||
"Failed to create the sound from file. Check STDERR for more info.");
|
this,
|
||||||
|
[length = bufferLengthInSeconds, channels = GetChannelCount(),
|
||||||
|
sampleRate = GetSampleRate()](Sound *sound) {
|
||||||
|
ma_result result = ma_pcm_rb_init(
|
||||||
|
ma_format_s32, channels, sampleRate * channels * length, nullptr,
|
||||||
|
nullptr, &sound->maRingBuffer);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
Utility::Error{} << "Failed to create a new ring buffer!" << " ("
|
||||||
|
<< result << ")";
|
||||||
|
throw new std::runtime_error("Failed to create a new ring buffer! "
|
||||||
|
"Check STDERR for more info.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Sound::SoundType::StreamedRawPCM,
|
||||||
|
"Failed to create the sound from ring buffer: "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use case: 1 time set up and use audio
|
||||||
|
SoundContainer Engine::CreateSound(uint8_t *data, int length) {
|
||||||
|
return SoundContainer(new Sound(
|
||||||
|
this,
|
||||||
|
[data, length, channels = GetChannelCount(),
|
||||||
|
sampleRate = GetSampleRate()](Sound *sound) {
|
||||||
|
ma_audio_buffer_config config = ma_audio_buffer_config_init(
|
||||||
|
ma_format_s32, channels, length / (4 * channels), data, nullptr);
|
||||||
|
ma_result result =
|
||||||
|
ma_audio_buffer_init_copy(&config, &sound->maAudioBuffer);
|
||||||
|
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
Utility::Error{} << "Failed to create a new audio buffer!" << " ("
|
||||||
|
<< result << ")";
|
||||||
|
throw new std::runtime_error("Failed to create a new audio buffer! "
|
||||||
|
"Check STDERR for more info.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return sound;
|
sound->maConfig.pDataSource = &sound->maAudioBuffer;
|
||||||
|
},
|
||||||
|
Sound::SoundType::RawPCM,
|
||||||
|
"Failed to create the sound from the PCM data: "));
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundContainer Engine::CreateSound(const std::string filepath,
|
||||||
|
bool streamFile) {
|
||||||
|
return SoundContainer(new Sound(
|
||||||
|
this,
|
||||||
|
[filepath, streamFile](Sound *sound) {
|
||||||
|
sound->maConfig.pFilePath = filepath.c_str();
|
||||||
|
sound->maConfig.flags = (streamFile ? MA_SOUND_FLAG_STREAM : 0);
|
||||||
|
},
|
||||||
|
Sound::SoundType::FromFile,
|
||||||
|
"Failed to create the sound from the file: " + filepath));
|
||||||
|
}
|
||||||
|
|
||||||
|
ListenerContainer Engine::CreateListener() {
|
||||||
|
auto listener = ListenerContainer(new Listener());
|
||||||
|
listener->baseEngine = this;
|
||||||
|
listener->listenerID = listenerCounter++;
|
||||||
|
|
||||||
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
void Engine::SetVolume(float value) { ma_engine_set_volume(&maEngine, value); }
|
void Engine::SetVolume(float value) { ma_engine_set_volume(&maEngine, value); }
|
||||||
float Engine::GetVolume() { return ma_engine_get_volume(&maEngine); }
|
const float Engine::GetVolume() { return ma_engine_get_volume(&maEngine); }
|
||||||
|
36
src/Listener.cpp
Normal file
36
src/Listener.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "ChargeAudio.hpp"
|
||||||
|
|
||||||
|
using namespace ChargeAudio;
|
||||||
|
|
||||||
|
Listener::Listener() {}
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
void Listener::SetEnabled(bool isEnabled) {
|
||||||
|
ma_engine_listener_set_enabled(&baseEngine->maEngine, listenerID, isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool Listener::GetEnabled() {
|
||||||
|
return ma_engine_listener_is_enabled(&baseEngine->maEngine, listenerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Listener::SetDirection(Magnum::Vector3 position) {
|
||||||
|
ma_engine_listener_set_direction(&baseEngine->maEngine, listenerID,
|
||||||
|
position.x(), position.y(), position.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Magnum::Vector3 Listener::GetDirection() {
|
||||||
|
ma_vec3f dir =
|
||||||
|
ma_engine_listener_get_direction(&baseEngine->maEngine, listenerID);
|
||||||
|
return Magnum::Vector3{dir.x, dir.y, dir.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Listener::SetPosition(Magnum::Vector3 position) {
|
||||||
|
ma_engine_listener_set_position(&baseEngine->maEngine, listenerID,
|
||||||
|
position.x(), position.y(), position.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Magnum::Vector3 Listener::GetPosition() {
|
||||||
|
ma_vec3f pos =
|
||||||
|
ma_engine_listener_get_position(&baseEngine->maEngine, listenerID);
|
||||||
|
return Magnum::Vector3(pos.x, pos.y, pos.z);
|
||||||
|
}
|
@@ -1,22 +1,97 @@
|
|||||||
#include "ChargeAudio.hpp"
|
#include "ChargeAudio.hpp"
|
||||||
#include <Magnum/Magnum.h>
|
|
||||||
#include <Magnum/Math/Vector3.h>
|
#include <functional>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace ChargeAudio;
|
using namespace ChargeAudio;
|
||||||
Sound::~Sound() { ma_sound_uninit(&maSound); }
|
Sound::Sound(Engine *engine, std::function<void(Sound *)> setupFunction,
|
||||||
|
SoundType soundType, std::string additionalErrorMessage)
|
||||||
|
: baseEngine(engine) {
|
||||||
|
maConfig = ma_sound_config_init_2(&baseEngine->maEngine);
|
||||||
|
maConfig.endCallback = Sound::onSoundFinish;
|
||||||
|
maConfig.pEndCallbackUserData = this;
|
||||||
|
setupFunction(this);
|
||||||
|
ma_result maResponse =
|
||||||
|
ma_sound_init_ex(&baseEngine->maEngine, &maConfig, &maSound);
|
||||||
|
if (maResponse != MA_SUCCESS) {
|
||||||
|
Utility::Error{} << "Failed to create a new sound" << " (" << maResponse
|
||||||
|
<< ")";
|
||||||
|
throw new std::runtime_error(
|
||||||
|
"Failed to create a new sound. Check STDERR for more info.\n" +
|
||||||
|
additionalErrorMessage);
|
||||||
|
}
|
||||||
|
type = soundType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sound::~Sound() {
|
||||||
|
switch (type) {
|
||||||
|
case Sound::SoundType::RawPCM:
|
||||||
|
ma_audio_buffer_uninit_and_free(&maAudioBuffer);
|
||||||
|
break;
|
||||||
|
case Sound::SoundType::StreamedRawPCM:
|
||||||
|
ma_pcm_rb_uninit(&maRingBuffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ma_sound_uninit(&maSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sound::SoundState Sound::GetState() { return state; }
|
||||||
|
const Sound::SoundType Sound::GetSoundType() { return type; }
|
||||||
|
|
||||||
|
const float Sound::GetDuration() {
|
||||||
|
float time;
|
||||||
|
ma_sound_get_length_in_seconds(&this->maSound, &time);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float Sound::GetPlaybackTime() {
|
||||||
|
float time;
|
||||||
|
ma_sound_get_cursor_in_seconds(&this->maSound, &time);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// true or false depending on if the playback was set
|
||||||
|
bool Sound::SetPlaybackTime(float time) {
|
||||||
|
// Better to just catch it from the start
|
||||||
|
if (time < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = ma_sound_seek_to_second(&maSound, time) != MA_SUCCESS;
|
||||||
|
if (result) {
|
||||||
|
Utility::Error{} << "Failed to set playback time to " << time
|
||||||
|
<< " on a sound instance";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
void Sound::Play() { ma_sound_start(&maSound); }
|
void Sound::Play() {
|
||||||
void Sound::Pause() { ma_sound_stop(&maSound); }
|
ma_sound_start(&maSound);
|
||||||
|
state = Sound::SoundState::Playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::Pause() {
|
||||||
|
ma_sound_stop(&maSound);
|
||||||
|
state = Sound::SoundState::Paused;
|
||||||
|
}
|
||||||
|
|
||||||
void Sound::Reset() { ma_sound_seek_to_pcm_frame(&maSound, 0); }
|
void Sound::Reset() { ma_sound_seek_to_pcm_frame(&maSound, 0); }
|
||||||
|
|
||||||
void Sound::SetPosition(Magnum::Vector3 position) {
|
void Sound::SetPosition(Magnum::Vector3 position) {
|
||||||
ma_sound_set_position(&maSound, position.x(), position.y(), position.z());
|
ma_sound_set_position(&maSound, position.x(), position.y(), position.z());
|
||||||
}
|
}
|
||||||
Magnum::Vector3 Sound::GetPosition() {
|
const Magnum::Vector3 Sound::GetPosition() {
|
||||||
ma_vec3f pos = ma_sound_get_position(&maSound);
|
ma_vec3f pos = ma_sound_get_position(&maSound);
|
||||||
Magnum::Vector3 position(pos.x, pos.y, pos.z);
|
return Magnum::Vector3(pos.x, pos.y, pos.z);
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
void Sound::SetVolume(float value) { ma_sound_set_volume(&maSound, value); }
|
void Sound::SetVolume(float value) { ma_sound_set_volume(&maSound, value); }
|
||||||
float Sound::GetVolume() { return ma_sound_get_volume(&maSound); }
|
const float Sound::GetVolume() { return ma_sound_get_volume(&maSound); }
|
||||||
|
|
||||||
|
// STATICs
|
||||||
|
void Sound::onSoundFinish(void *customData, ma_sound *) {
|
||||||
|
auto sound = static_cast<Sound *>(customData);
|
||||||
|
sound->state = SoundState::Finished;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user