mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-24 19:32:55 +01:00
Streaming implementation
This commit is contained in:
parent
76fc914695
commit
139034c53b
@ -20,6 +20,8 @@ set(RWENGINE_SOURCES
|
|||||||
src/audio/Sound.hpp
|
src/audio/Sound.hpp
|
||||||
src/audio/SoundBuffer.cpp
|
src/audio/SoundBuffer.cpp
|
||||||
src/audio/SoundBuffer.hpp
|
src/audio/SoundBuffer.hpp
|
||||||
|
src/audio/SoundBufferStreamed.cpp
|
||||||
|
src/audio/SoundBufferStreamed.hpp
|
||||||
src/audio/SoundManager.cpp
|
src/audio/SoundManager.cpp
|
||||||
src/audio/SoundManager.hpp
|
src/audio/SoundManager.hpp
|
||||||
src/audio/SoundSource.cpp
|
src/audio/SoundSource.cpp
|
||||||
|
@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
#include "audio/SoundBuffer.hpp"
|
#include "audio/SoundBuffer.hpp"
|
||||||
|
|
||||||
|
Sound::~Sound() {
|
||||||
|
if (buffer) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Sound::isPlaying() const {
|
bool Sound::isPlaying() const {
|
||||||
return buffer->isPlaying();
|
return buffer->isPlaying();
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ struct Sound {
|
|||||||
std::unique_ptr<SoundBuffer> buffer;
|
std::unique_ptr<SoundBuffer> buffer;
|
||||||
|
|
||||||
Sound() = default;
|
Sound() = default;
|
||||||
~Sound() = default;
|
~Sound();
|
||||||
|
|
||||||
bool isPlaying() const;
|
bool isPlaying() const;
|
||||||
|
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
#include <rw/types.hpp>
|
#include <rw/types.hpp>
|
||||||
|
|
||||||
#include "audio/alCheck.hpp"
|
|
||||||
#include "audio/SoundSource.hpp"
|
#include "audio/SoundSource.hpp"
|
||||||
|
#include "audio/alCheck.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int kNrBuffersStreaming = 4;
|
||||||
|
constexpr int kSizeOfChunk = 4;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
SoundBuffer::SoundBuffer() {
|
SoundBuffer::SoundBuffer() {
|
||||||
alCheck(alGenSources(1, &source));
|
alCheck(alGenSources(1, &source));
|
||||||
@ -29,7 +34,6 @@ bool SoundBuffer::bufferData(SoundSource& soundSource) {
|
|||||||
static_cast<ALsizei>(soundSource.data.size() * sizeof(int16_t)),
|
static_cast<ALsizei>(soundSource.data.size() * sizeof(int16_t)),
|
||||||
soundSource.sampleRate));
|
soundSource.sampleRate));
|
||||||
alCheck(alSourcei(source, AL_BUFFER, buffer));
|
alCheck(alSourcei(source, AL_BUFFER, buffer));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,12 +57,18 @@ bool SoundBuffer::isStopped() const {
|
|||||||
|
|
||||||
void SoundBuffer::play() {
|
void SoundBuffer::play() {
|
||||||
alCheck(alSourcePlay(source));
|
alCheck(alSourcePlay(source));
|
||||||
|
|
||||||
|
running = true;
|
||||||
}
|
}
|
||||||
void SoundBuffer::pause() {
|
void SoundBuffer::pause() {
|
||||||
alCheck(alSourcePause(source));
|
alCheck(alSourcePause(source));
|
||||||
|
|
||||||
|
running = false;
|
||||||
}
|
}
|
||||||
void SoundBuffer::stop() {
|
void SoundBuffer::stop() {
|
||||||
alCheck(alSourceStop(source));
|
alCheck(alSourceStop(source));
|
||||||
|
|
||||||
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundBuffer::setPosition(const glm::vec3& position) {
|
void SoundBuffer::setPosition(const glm::vec3& position) {
|
||||||
|
@ -4,20 +4,22 @@
|
|||||||
#include <al.h>
|
#include <al.h>
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class SoundSource;
|
class SoundSource;
|
||||||
|
|
||||||
/// OpenAL tool for playing
|
/// OpenAL tool for playing
|
||||||
/// sound instance.
|
/// sound instance.
|
||||||
struct SoundBuffer {
|
struct SoundBuffer {
|
||||||
SoundBuffer();
|
SoundBuffer();
|
||||||
~SoundBuffer();
|
virtual ~SoundBuffer();
|
||||||
bool bufferData(SoundSource& soundSource);
|
virtual bool bufferData(SoundSource& soundSource);
|
||||||
|
|
||||||
bool isPlaying() const;
|
bool isPlaying() const;
|
||||||
bool isPaused() const;
|
bool isPaused() const;
|
||||||
bool isStopped() const;
|
bool isStopped() const;
|
||||||
|
|
||||||
void play();
|
virtual void play();
|
||||||
void pause();
|
void pause();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
@ -28,6 +30,8 @@ struct SoundBuffer {
|
|||||||
void setMaxDistance(float maxDist);
|
void setMaxDistance(float maxDist);
|
||||||
|
|
||||||
ALuint source;
|
ALuint source;
|
||||||
|
bool running = false;
|
||||||
|
private:
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
108
rwengine/src/audio/SoundBufferStreamed.cpp
Normal file
108
rwengine/src/audio/SoundBufferStreamed.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "audio/SoundBufferStreamed.hpp"
|
||||||
|
|
||||||
|
#include <rw/types.hpp>
|
||||||
|
|
||||||
|
#include "audio/SoundSource.hpp"
|
||||||
|
#include "audio/alCheck.hpp"
|
||||||
|
|
||||||
|
SoundBufferStreamed::SoundBufferStreamed() {
|
||||||
|
alCheck(alGenSources(1, &source));
|
||||||
|
|
||||||
|
alCheck(alGenBuffers(kNrBuffersStreaming, buffers.data()));
|
||||||
|
|
||||||
|
alCheck(alSourcef(source, AL_PITCH, 1));
|
||||||
|
alCheck(alSourcef(source, AL_GAIN, 1));
|
||||||
|
alCheck(alSource3f(source, AL_POSITION, 0, 0, 0));
|
||||||
|
alCheck(alSource3f(source, AL_VELOCITY, 0, 0, 0));
|
||||||
|
alCheck(alSourcei(source, AL_LOOPING, AL_FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundBufferStreamed::~SoundBufferStreamed() {
|
||||||
|
alCheck(alDeleteBuffers(kNrBuffersStreaming, buffers.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SoundBufferStreamed::bufferData(SoundSource &soundSource) {
|
||||||
|
/* Rewind the source position and clear the buffer queue */
|
||||||
|
alSourceRewind(source);
|
||||||
|
alSourcei(source, AL_BUFFER, 0);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(soundSource.mutex);
|
||||||
|
/* Fill the buffer queue */
|
||||||
|
for (auto i = 0u; i < buffers.size() &&
|
||||||
|
streamedData * kSizeOfChunk < soundSource.data.size();
|
||||||
|
i++) {
|
||||||
|
auto sizeOfNextChunk = std::min(static_cast<size_t>(kSizeOfChunk),
|
||||||
|
soundSource.data.size());
|
||||||
|
|
||||||
|
alCheck(alBufferData(
|
||||||
|
buffers[i],
|
||||||
|
soundSource.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
|
||||||
|
&soundSource.data[streamedData * kSizeOfChunk],
|
||||||
|
static_cast<ALsizei>(sizeOfNextChunk * sizeof(int16_t)),
|
||||||
|
soundSource.sampleRate));
|
||||||
|
streamedData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
alSourceQueueBuffers(source, kNrBuffersStreaming, buffers.data());
|
||||||
|
|
||||||
|
this->soundSource = &soundSource;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundBufferStreamed::play() {
|
||||||
|
alSourcePlay(source);
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
loadingThread = std::async(std::launch::async,
|
||||||
|
&SoundBufferStreamed::updateBuffers, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundBufferStreamed::updateBuffers() {
|
||||||
|
while (running) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
ALint processed, state;
|
||||||
|
|
||||||
|
/* Get relevant source info */
|
||||||
|
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
||||||
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(soundSource->mutex);
|
||||||
|
|
||||||
|
/* Unqueue and handle each processed buffer */
|
||||||
|
while (processed > 0 &&
|
||||||
|
streamedData * kSizeOfChunk < soundSource->data.size()) {
|
||||||
|
ALuint bufid{};
|
||||||
|
auto sizeOfNextChunk =
|
||||||
|
std::min(static_cast<size_t>(kSizeOfChunk),
|
||||||
|
soundSource->data.size() -
|
||||||
|
static_cast<size_t>(kSizeOfChunk) * streamedData);
|
||||||
|
|
||||||
|
alSourceUnqueueBuffers(source, 1, &bufid);
|
||||||
|
processed--;
|
||||||
|
|
||||||
|
if (sizeOfNextChunk > 0) {
|
||||||
|
alBufferData(bufid,
|
||||||
|
soundSource->channels == 1 ? AL_FORMAT_MONO16
|
||||||
|
: AL_FORMAT_STEREO16,
|
||||||
|
&soundSource->data[streamedData * kSizeOfChunk],
|
||||||
|
sizeOfNextChunk * sizeof(int16_t),
|
||||||
|
soundSource->sampleRate);
|
||||||
|
streamedData++;
|
||||||
|
alSourceQueueBuffers(source, 1, &bufid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure the source hasn't underrun */
|
||||||
|
if (state != AL_PLAYING && state != AL_PAUSED) {
|
||||||
|
ALint queued;
|
||||||
|
|
||||||
|
/* If no buffers are queued, playback is finished */
|
||||||
|
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
||||||
|
if (queued == 0) return;
|
||||||
|
|
||||||
|
alSourcePlay(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
rwengine/src/audio/SoundBufferStreamed.hpp
Normal file
27
rwengine/src/audio/SoundBufferStreamed.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _RWENGINE_SOUND_BUFFER_STREAMED_HPP_
|
||||||
|
#define _RWENGINE_SOUND_BUFFER_STREAMED_HPP_
|
||||||
|
|
||||||
|
#include "audio/SoundBuffer.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
struct SoundBufferStreamed : public SoundBuffer {
|
||||||
|
static constexpr unsigned int kNrBuffersStreaming = 4;
|
||||||
|
static constexpr unsigned int kSizeOfChunk = 4096;
|
||||||
|
|
||||||
|
SoundBufferStreamed();
|
||||||
|
~SoundBufferStreamed() override;
|
||||||
|
bool bufferData(SoundSource& soundSource) final;
|
||||||
|
|
||||||
|
virtual void play() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SoundSource* soundSource = nullptr;
|
||||||
|
void updateBuffers();
|
||||||
|
unsigned int streamedData = 0;
|
||||||
|
std::array<ALuint, kNrBuffersStreaming> buffers;
|
||||||
|
std::future<void> loadingThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -7,10 +7,11 @@ extern "C" {
|
|||||||
#include <libavutil/avutil.h>
|
#include <libavutil/avutil.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "audio/alCheck.hpp"
|
|
||||||
#include "audio/Sound.hpp"
|
#include "audio/Sound.hpp"
|
||||||
#include "audio/SoundBuffer.hpp"
|
#include "audio/SoundBuffer.hpp"
|
||||||
|
#include "audio/SoundBufferStreamed.hpp"
|
||||||
#include "audio/SoundSource.hpp"
|
#include "audio/SoundSource.hpp"
|
||||||
|
#include "audio/alCheck.hpp"
|
||||||
#include "engine/GameData.hpp"
|
#include "engine/GameData.hpp"
|
||||||
#include "engine/GameWorld.hpp"
|
#include "engine/GameWorld.hpp"
|
||||||
#include "render/ViewCamera.hpp"
|
#include "render/ViewCamera.hpp"
|
||||||
@ -98,19 +99,19 @@ void SoundManager::deinitializeOpenAL() {
|
|||||||
|
|
||||||
// De-initialize OpenAL
|
// De-initialize OpenAL
|
||||||
if (alContext) {
|
if (alContext) {
|
||||||
alcMakeContextCurrent(nullptr);
|
alcMakeContextCurrent(nullptr);
|
||||||
alcDestroyContext(alContext);
|
alcDestroyContext(alContext);
|
||||||
}
|
}
|
||||||
alContext = nullptr;
|
alContext = nullptr;
|
||||||
|
|
||||||
if (alDevice) {
|
if (alDevice) {
|
||||||
alcCloseDevice(alDevice);
|
alcCloseDevice(alDevice);
|
||||||
}
|
}
|
||||||
alDevice = nullptr;
|
alDevice = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoundManager::loadSound(const std::string& name,
|
bool SoundManager::loadSound(const std::string& name,
|
||||||
const std::string& fileName) {
|
const std::string& fileName, bool streamed) {
|
||||||
Sound* sound = nullptr;
|
Sound* sound = nullptr;
|
||||||
auto sound_iter = sounds.find(name);
|
auto sound_iter = sounds.find(name);
|
||||||
|
|
||||||
@ -118,14 +119,14 @@ bool SoundManager::loadSound(const std::string& name,
|
|||||||
sound = &sound_iter->second;
|
sound = &sound_iter->second;
|
||||||
} else {
|
} else {
|
||||||
auto [it, emplaced] = sounds.emplace(std::piecewise_construct,
|
auto [it, emplaced] = sounds.emplace(std::piecewise_construct,
|
||||||
std::forward_as_tuple(name),
|
std::forward_as_tuple(name),
|
||||||
std::forward_as_tuple());
|
std::forward_as_tuple());
|
||||||
sound = &it->second;
|
sound = &it->second;
|
||||||
|
|
||||||
sound->source = std::make_shared<SoundSource>();
|
sound->source = std::make_shared<SoundSource>();
|
||||||
sound->buffer = std::make_unique<SoundBuffer>();
|
sound->buffer = streamed ? std::make_unique<SoundBufferStreamed>() : std::make_unique<SoundBuffer>();
|
||||||
|
|
||||||
sound->source->loadFromFile(fileName);
|
sound->source->loadFromFile(fileName, streamed);
|
||||||
sound->isLoaded = sound->buffer->bufferData(*sound->source);
|
sound->isLoaded = sound->buffer->bufferData(*sound->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ size_t SoundManager::createSfxInstance(size_t index) {
|
|||||||
Sound* sound = nullptr;
|
Sound* sound = nullptr;
|
||||||
auto soundRef = sfx.find(index);
|
auto soundRef = sfx.find(index);
|
||||||
|
|
||||||
if(soundRef == sfx.end()) {
|
if (soundRef == sfx.end()) {
|
||||||
// Sound source is not loaded yet
|
// Sound source is not loaded yet
|
||||||
loadSound(index);
|
loadSound(index);
|
||||||
soundRef = sfx.find(index);
|
soundRef = sfx.find(index);
|
||||||
@ -161,16 +162,15 @@ size_t SoundManager::createSfxInstance(size_t index) {
|
|||||||
// Let's use this buffer
|
// Let's use this buffer
|
||||||
sound.buffer = std::make_unique<SoundBuffer>();
|
sound.buffer = std::make_unique<SoundBuffer>();
|
||||||
sound.source = soundRef->second.source;
|
sound.source = soundRef->second.source;
|
||||||
sound.isLoaded =
|
sound.isLoaded = sound.buffer->bufferData(*sound.source);
|
||||||
sound.buffer->bufferData(*sound.source);
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// There's no available free buffer, so
|
// There's no available free buffer, so
|
||||||
// we should create a new one.
|
// we should create a new one.
|
||||||
auto [it, emplaced] = buffers.emplace(std::piecewise_construct,
|
auto [it, emplaced] = buffers.emplace(std::piecewise_construct,
|
||||||
std::forward_as_tuple(bufferNr),
|
std::forward_as_tuple(bufferNr),
|
||||||
std::forward_as_tuple());
|
std::forward_as_tuple());
|
||||||
sound = &it->second;
|
sound = &it->second;
|
||||||
|
|
||||||
sound->id = bufferNr;
|
sound->id = bufferNr;
|
||||||
@ -341,7 +341,6 @@ void SoundManager::setSoundPosition(const std::string& name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SoundManager::setVolume(float vol) {
|
void SoundManager::setVolume(float vol) {
|
||||||
_volume = vol;
|
_volume = vol;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
~SoundManager();
|
~SoundManager();
|
||||||
|
|
||||||
/// Load sound from file and store it with selected name
|
/// Load sound from file and store it with selected name
|
||||||
bool loadSound(const std::string& name, const std::string& fileName);
|
bool loadSound(const std::string& name, const std::string& fileName, bool streamed = true);
|
||||||
|
|
||||||
/// Load selected sfx sound
|
/// Load selected sfx sound
|
||||||
void loadSound(size_t index);
|
void loadSound(size_t index);
|
||||||
|
@ -60,7 +60,7 @@ int read_packet(void* opaque, uint8_t* buf, int buf_size) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool SoundSource::prepareFormatContextSfx(LoaderSDT& sdt, size_t index,
|
bool SoundSource::prepareFormatContextSfx(LoaderSDT& sdt, size_t index,
|
||||||
bool asWave) {
|
bool asWave) {
|
||||||
/// Now we need to prepare "custom" format context
|
/// Now we need to prepare "custom" format context
|
||||||
/// We need sdt loader for that purpose
|
/// We need sdt loader for that purpose
|
||||||
raw_sound = sdt.loadToMemory(index, asWave);
|
raw_sound = sdt.loadToMemory(index, asWave);
|
||||||
@ -288,6 +288,7 @@ void SoundSource::decodeFramesLegacy(size_t framesToDecode) {
|
|||||||
// Write samples to audio buffer
|
// Write samples to audio buffer
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i < static_cast<size_t>(frame->nb_samples); i++) {
|
i < static_cast<size_t>(frame->nb_samples); i++) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
// Interleave left/right channels
|
// Interleave left/right channels
|
||||||
for (size_t channel = 0; channel < channels;
|
for (size_t channel = 0; channel < channels;
|
||||||
channel++) {
|
channel++) {
|
||||||
@ -337,6 +338,7 @@ void SoundSource::decodeFrames(size_t framesToDecode) {
|
|||||||
|
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i < static_cast<size_t>(frame->nb_samples); i++) {
|
i < static_cast<size_t>(frame->nb_samples); i++) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
// Interleave left/right channels
|
// Interleave left/right channels
|
||||||
for (size_t channel = 0; channel < channels;
|
for (size_t channel = 0; channel < channels;
|
||||||
channel++) {
|
channel++) {
|
||||||
@ -417,6 +419,7 @@ void SoundSource::decodeAndResampleFrames(const rwfs::path& filePath,
|
|||||||
RW_ERROR("Error resampling " << filePath << '\n');
|
RW_ERROR("Error resampling " << filePath << '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i <
|
i <
|
||||||
static_cast<size_t>(resampled->nb_samples) * channels;
|
static_cast<size_t>(resampled->nb_samples) * channels;
|
||||||
@ -512,7 +515,7 @@ void SoundSource::loadFromFile(const rwfs::path& filePath, bool streaming) {
|
|||||||
decodeFramesWrap(filePath);
|
decodeFramesWrap(filePath);
|
||||||
|
|
||||||
if (streaming) {
|
if (streaming) {
|
||||||
auto loadingThread = std::async(
|
loadingThread = std::async(
|
||||||
std::launch::async,
|
std::launch::async,
|
||||||
&SoundSource::decodeRestSoundFramesAndCleanup, this, filePath);
|
&SoundSource::decodeRestSoundFramesAndCleanup, this, filePath);
|
||||||
} else {
|
} else {
|
||||||
@ -531,7 +534,7 @@ void SoundSource::loadSfx(LoaderSDT& sdt, size_t index, bool asWave,
|
|||||||
decodeFramesSfxWrap();
|
decodeFramesSfxWrap();
|
||||||
|
|
||||||
if (streaming) {
|
if (streaming) {
|
||||||
auto loadingThread =
|
loadingThread =
|
||||||
std::async(std::launch::async,
|
std::async(std::launch::async,
|
||||||
&SoundSource::decodeRestSfxFramesAndCleanup, this);
|
&SoundSource::decodeRestSfxFramesAndCleanup, this);
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,6 +10,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
/// Structure for input data
|
/// Structure for input data
|
||||||
struct InputData {
|
struct InputData {
|
||||||
@ -31,6 +32,7 @@ class LoaderSDT;
|
|||||||
class SoundSource {
|
class SoundSource {
|
||||||
friend class SoundManager;
|
friend class SoundManager;
|
||||||
friend struct SoundBuffer;
|
friend struct SoundBuffer;
|
||||||
|
friend struct SoundBufferStreamed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool allocateAudioFrame();
|
bool allocateAudioFrame();
|
||||||
@ -59,7 +61,8 @@ public:
|
|||||||
void decodeFramesWrap(const rwfs::path& filePath);
|
void decodeFramesWrap(const rwfs::path& filePath);
|
||||||
void decodeFramesSfxWrap();
|
void decodeFramesSfxWrap();
|
||||||
void decodeFrames(size_t framesToDecode);
|
void decodeFrames(size_t framesToDecode);
|
||||||
void decodeAndResampleFrames(const rwfs::path& filePath, size_t framesToDecode);
|
void decodeAndResampleFrames(const rwfs::path& filePath,
|
||||||
|
size_t framesToDecode);
|
||||||
|
|
||||||
void cleanupAfterSoundLoading();
|
void cleanupAfterSoundLoading();
|
||||||
void cleanupAfterSfxLoading();
|
void cleanupAfterSfxLoading();
|
||||||
@ -99,6 +102,9 @@ private:
|
|||||||
std::unique_ptr<char[]> raw_sound;
|
std::unique_ptr<char[]> raw_sound;
|
||||||
std::unique_ptr<uint8_t[]> inputDataStart;
|
std::unique_ptr<uint8_t[]> inputDataStart;
|
||||||
InputData input{};
|
InputData input{};
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
std::future<void> loadingThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user