diff --git a/src/ChargeAudio.hpp b/src/ChargeAudio.hpp index e73a496..1dff2d0 100644 --- a/src/ChargeAudio.hpp +++ b/src/ChargeAudio.hpp @@ -17,7 +17,7 @@ typedef Containers::Pointer ListenerContainer; class Sound { public: enum class SoundState { Idle, Playing, Paused, Finished }; - enum class SoundType { FromFile, RawPCM }; + enum class SoundType { FromFile, StreamedRawPCM, RawPCM }; // No copying Sound(const Sound &) = delete; Sound &operator=(const Sound &) = delete; @@ -51,6 +51,7 @@ private: ma_sound maSound; ma_sound_config maConfig; ma_pcm_rb maRingBuffer; + ma_audio_buffer maAudioBuffer; SoundState state = SoundState::Idle; SoundType type; @@ -93,6 +94,7 @@ public: // Creating tools SoundContainer CreateSound(int bufferLengthInSeconds); + SoundContainer CreateSound(uint8_t *data, int length); SoundContainer CreateSound(std::string filepath, bool streamFile = false); ListenerContainer CreateListener(); diff --git a/src/Engine.cpp b/src/Engine.cpp index 0981963..9e240ec 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -25,6 +25,7 @@ Engine::~Engine() { ma_engine_uninit(&maEngine); } uint32_t Engine::GetSampleRate() { return maEngine.sampleRate; } uint32_t Engine::GetChannelCount() { return ma_engine_get_channels(&maEngine); } +// Use case: Stream of PCM data SoundContainer Engine::CreateSound(int bufferLengthInSeconds) { return SoundContainer(new Sound( this, @@ -40,7 +41,32 @@ SoundContainer Engine::CreateSound(int bufferLengthInSeconds) { "Check STDERR for more info."); } }, - Sound::SoundType::RawPCM, "Failed to create the sound from the data: ")); + 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."); + } + + sound->maConfig.pDataSource = &sound->maAudioBuffer; + }, + Sound::SoundType::RawPCM, + "Failed to create the sound from the PCM data: ")); } SoundContainer Engine::CreateSound(const std::string filepath, diff --git a/src/Sound.cpp b/src/Sound.cpp index c93eba8..ca6b682 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -24,7 +24,16 @@ Sound::Sound(Engine *engine, std::function setupFunction, } Sound::~Sound() { - ma_pcm_rb_uninit(&maRingBuffer); + 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); }