Skip to content

Commit

Permalink
Fixing audio runtimes.
Browse files Browse the repository at this point in the history
Race condition when completing in the audio completed callback thread!

Want to add a test here but ran out of time!

Diffs=
8ecc99130 Fixing audio runtimes. (#7007)

Co-authored-by: Luigi Rosso <[email protected]>
  • Loading branch information
luigi-rosso and luigi-rosso committed Apr 9, 2024
1 parent 097c1fe commit 195548a
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0bc446fad2a568a7088fdaa122af0de2de1dc940
8ecc99130db737d49ce0889501c421bd53b58f9e
3 changes: 2 additions & 1 deletion include/rive/animation/state_machine_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class StateMachineInstance : public Scene

template <typename SMType, typename InstType>
InstType* getNamedInput(const std::string& name) const;
void notifyEventListeners(std::vector<EventReport> events, NestedArtboard* source);
void notifyEventListeners(const std::vector<EventReport>& events, NestedArtboard* source);
void sortHitComponents();

public:
Expand Down Expand Up @@ -120,6 +120,7 @@ class StateMachineInstance : public Scene

/// Gets a reported event at an index < reportedEventCount().
const EventReport reportedEventAt(std::size_t index) const;
bool playsAudio() override { return true; }

private:
std::vector<EventReport> m_reportedEvents;
Expand Down
4 changes: 4 additions & 0 deletions include/rive/audio/audio_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <vector>
#include <stdio.h>
#include <cstdint>
#include <mutex>

typedef struct ma_engine ma_engine;
typedef struct ma_sound ma_sound;
Expand Down Expand Up @@ -60,6 +61,9 @@ class AudioEngine : public RefCnt<AudioEngine>
AudioEngine(ma_engine* engine);
ma_device* m_device;
ma_engine* m_engine;
std::mutex m_mutex;

void soundCompleted(rcp<AudioSound> sound);

std::vector<rcp<AudioSound>> m_completedSounds;
rcp<AudioSound> m_playingSoundsHead;
Expand Down
1 change: 1 addition & 0 deletions include/rive/audio_event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class AudioEvent : public AudioEventBase, public FileAssetReferencer
void setAsset(FileAsset* asset) override;
uint32_t assetId() override;
void trigger(const CallbackData& value) override;
void play();

#ifdef TESTING
AudioAsset* asset() const { return (AudioAsset*)m_fileAsset; }
Expand Down
1 change: 1 addition & 0 deletions include/rive/core/field_types/core_callback_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class CallbackContext
public:
virtual ~CallbackContext() {}
virtual void reportEvent(Event* event, float secondsDelay = 0.0f) {}
virtual bool playsAudio() { return false; }
};

class CallbackData
Expand Down
5 changes: 5 additions & 0 deletions include/rive/relative_local_asset_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class RelativeLocalAssetLoader : public FileAssetLoader
{
std::string filename = m_Path + asset.uniqueFilename();
FILE* fp = fopen(filename.c_str(), "rb");
if (fp == nullptr)
{
fprintf(stderr, "Failed to find file at %s\n", filename.c_str());
return false;
}

fseek(fp, 0, SEEK_END);
const size_t length = ftell(fp);
Expand Down
12 changes: 11 additions & 1 deletion src/animation/state_machine_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "rive/nested_artboard.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/math/math_types.hpp"
#include "rive/audio_event.hpp"
#include <unordered_map>

using namespace rive;
Expand Down Expand Up @@ -782,7 +783,7 @@ const EventReport StateMachineInstance::reportedEventAt(std::size_t index) const
return m_reportedEvents[index];
}

void StateMachineInstance::notifyEventListeners(std::vector<EventReport> events,
void StateMachineInstance::notifyEventListeners(const std::vector<EventReport>& events,
NestedArtboard* source)
{
if (events.size() > 0)
Expand Down Expand Up @@ -826,5 +827,14 @@ void StateMachineInstance::notifyEventListeners(std::vector<EventReport> events,
{
m_parentStateMachineInstance->notifyEventListeners(events, m_parentNestedArtboard);
}

for (auto report : events)
{
auto event = report.event();
if (event->is<AudioEvent>())
{
event->as<AudioEvent>()->play();
}
}
}
}
24 changes: 15 additions & 9 deletions src/audio/audio_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@ using namespace rive;
void AudioEngine::SoundCompleted(void* pUserData, ma_sound* pSound)
{
AudioSound* audioSound = (AudioSound*)pUserData;
auto engine = audioSound->m_engine;
engine->soundCompleted(ref_rcp(audioSound));
}

auto next = audioSound->m_nextPlaying;
auto prev = audioSound->m_prevPlaying;
void AudioEngine::soundCompleted(rcp<AudioSound> sound)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_completedSounds.push_back(sound);

auto next = sound->m_nextPlaying;
auto prev = sound->m_prevPlaying;
if (next != nullptr)
{
next->m_prevPlaying = prev;
Expand All @@ -37,16 +45,13 @@ void AudioEngine::SoundCompleted(void* pUserData, ma_sound* pSound)
prev->m_nextPlaying = next;
}

auto engine = audioSound->m_engine;
if (engine->m_playingSoundsHead.get() == audioSound)
if (m_playingSoundsHead == sound)
{
engine->m_playingSoundsHead = next;
m_playingSoundsHead = next;
}

// Unlink audio sound.
engine->m_completedSounds.push_back(ref_rcp(audioSound));
audioSound->m_nextPlaying = nullptr;
audioSound->m_prevPlaying = nullptr;
sound->m_nextPlaying = nullptr;
sound->m_prevPlaying = nullptr;
}

#ifdef WITH_RIVE_AUDIO_TOOLS
Expand Down Expand Up @@ -182,6 +187,7 @@ rcp<AudioSound> AudioEngine::play(rcp<AudioSource> source,
uint64_t endTime,
uint64_t soundStartTime)
{
std::unique_lock<std::mutex> lock(m_mutex);
// We have to dispose completed sounds out of the completed callback. So we
// do it on next play or at destruct.
for (auto sound : m_completedSounds)
Expand Down
14 changes: 11 additions & 3 deletions src/audio_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

using namespace rive;

void AudioEvent::trigger(const CallbackData& value)
void AudioEvent::play()
{
Super::trigger(value);

#ifdef WITH_RIVE_AUDIO
auto audioAsset = (AudioAsset*)m_fileAsset;
if (audioAsset == nullptr)
Expand All @@ -36,6 +34,16 @@ void AudioEvent::trigger(const CallbackData& value)
#endif
}

void AudioEvent::trigger(const CallbackData& value)
{
Super::trigger(value);
if (!value.context()->playsAudio())
{
// Context won't play audio, we'll do it ourselves.
play();
}
}

StatusCode AudioEvent::import(ImportStack& importStack)
{
auto result = registerReferencer(importStack);
Expand Down

0 comments on commit 195548a

Please sign in to comment.