diff --git a/src/ChargeAudio.hpp b/src/ChargeAudio.hpp index 7bbb31d..a67c368 100644 --- a/src/ChargeAudio.hpp +++ b/src/ChargeAudio.hpp @@ -42,6 +42,9 @@ public: void SetVolume(float value); const float GetVolume(); + // For StreamedRawPCM + void WriteToRingBuffer(uint8_t *data, uint32_t length); + private: Sound(class Engine *engine, std::function setupFunction, SoundType type, std::string additionalErrorMessage = ""); @@ -110,6 +113,8 @@ private: ma_result maResponse; ma_decoder maStero; ma_uint64 listenerCounter = 0; + ma_format PCMFormat = ma_format_f32; + ma_uint8 frameSize; friend class Listener; friend class Sound; }; diff --git a/src/Engine.cpp b/src/Engine.cpp index e3af11e..4b19f37 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -10,6 +10,7 @@ Engine::Engine(uint32_t sampleRate, uint32_t channels) { maConfig = ma_engine_config_init(); maConfig.sampleRate = sampleRate; maConfig.channels = channels; + frameSize = ma_get_bytes_per_sample(PCMFormat) * channels; ThrowOnRuntimeError("Failed to init miniaudio engine", ma_engine_init(&maConfig, &maEngine)); @@ -27,9 +28,10 @@ SoundContainer Engine::CreateSound(int bufferLengthInSeconds) { [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); + sound->baseEngine->PCMFormat, channels, sampleRate * length, + nullptr, nullptr, &sound->maRingBuffer); ThrowOnRuntimeError("Failed to create a new ring buffer!", result); + sound->maConfig.pDataSource = &sound->maRingBuffer; }, Sound::SoundType::StreamedRawPCM, "Failed to create the sound from ring buffer: ")); @@ -42,7 +44,8 @@ SoundContainer Engine::CreateSound(uint8_t *data, int length) { [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); + sound->baseEngine->PCMFormat, channels, + length / sound->baseEngine->frameSize, data, nullptr); ma_result result = ma_audio_buffer_init_copy(&config, &sound->maAudioBuffer); diff --git a/src/Sound.cpp b/src/Sound.cpp index cc640a7..2e32d01 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -1,5 +1,8 @@ #include "ChargeAudio.hpp" +#include +#include +#include #include using namespace ChargeAudio; @@ -94,6 +97,30 @@ const Magnum::Vector3 Sound::GetPosition() { void Sound::SetVolume(float value) { ma_sound_set_volume(&maSound, value); } const float Sound::GetVolume() { return ma_sound_get_volume(&maSound); } +// StreamedRawPCM +void Sound::WriteToRingBuffer(uint8_t *data, uint32_t length) { + uint8_t *dataPosition = data; + void *writePosition; + uint32_t framesToWrite = length / baseEngine->frameSize, framesWritten = 0, + framesAvailable = 0; + + while (framesWritten < framesToWrite) { + framesAvailable = framesToWrite - framesWritten; + + // Sometimes this can fail. Actually terrifying. + ThrowOnRuntimeError("PCM ring buffer could not allocate... Oh no", + ma_pcm_rb_acquire_write(&maRingBuffer, &framesAvailable, + &writePosition)); + + memcpy(writePosition, dataPosition, + (framesAvailable * baseEngine->frameSize) - 8); + ma_pcm_rb_commit_write(&maRingBuffer, framesAvailable); + + framesWritten += framesAvailable; + dataPosition += framesAvailable * baseEngine->frameSize; + } +} + // STATICs void Sound::onSoundFinish(void *customData, ma_sound *) { auto sound = static_cast(customData);