initialize audio manager only if an instance needs it

partially addressing [this request](https://rive.app/community/forums/bugs/fsLjspgTHYcR/new-web-runtime-is-trying-to-setup-audiocontext-before-user-interaction/ftnduzDdPGw9) from a user
this improves how we handle audio in web.
Now, instead of requesting an audio context for all cases, we reduce it to scenarios where an animation has an audio event.

Diffs=
328d307df initialize audio manager only if an instance needs it (#7132)

Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head
index a569826..3d7de34 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-2b2e92ca7ef815c7c60176c14bed4bd488d44d0c
+328d307dfdfcc3c4a9d7c726f783b5325bfbef43
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp
index 2365af9..ba4ae11 100644
--- a/include/rive/artboard.hpp
+++ b/include/rive/artboard.hpp
@@ -127,6 +127,7 @@
     bool isTranslucent() const;
     bool isTranslucent(const LinearAnimation*) const;
     bool isTranslucent(const LinearAnimationInstance*) const;
+    bool hasAudio() const;
 
     template <typename T = Component> T* find(const std::string& name)
     {
diff --git a/src/artboard.cpp b/src/artboard.cpp
index 0b4778d..0ddaf7b 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -4,6 +4,7 @@
 #include "rive/dependency_sorter.hpp"
 #include "rive/draw_rules.hpp"
 #include "rive/draw_target.hpp"
+#include "rive/audio_event.hpp"
 #include "rive/draw_target_placement.hpp"
 #include "rive/drawable.hpp"
 #include "rive/animation/keyed_object.hpp"
@@ -648,6 +649,25 @@
     return true;
 }
 
+bool Artboard::hasAudio() const
+{
+    for (auto object : m_Objects)
+    {
+        if (object != nullptr && object->coreType() == AudioEventBase::typeKey)
+        {
+            return true;
+        }
+    }
+    for (auto nestedArtboard : m_NestedArtboards)
+    {
+        if (nestedArtboard->artboard()->hasAudio())
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 bool Artboard::isTranslucent(const LinearAnimation* anim) const
 {
     // For now we're conservative/lazy -- if we see that any of our paints are
diff --git a/test/assets/sound2.riv b/test/assets/sound2.riv
new file mode 100644
index 0000000..4f7e9c5
--- /dev/null
+++ b/test/assets/sound2.riv
Binary files differ
diff --git a/test/audio_test.cpp b/test/audio_test.cpp
index c96e4e0..734262a 100644
--- a/test/audio_test.cpp
+++ b/test/audio_test.cpp
@@ -185,4 +185,49 @@
     REQUIRE(engine->playingSoundCount() == 0);
 }
 
+TEST_CASE("Artboard has audio", "[audio]")
+{
+    rcp<AudioEngine> engine = AudioEngine::Make(2, 44100);
+
+    auto file = ReadRiveFile("../../test/assets/sound2.riv");
+    auto artboard = file->artboardNamed("child");
+    artboard->audioEngine(engine);
+
+    REQUIRE(artboard != nullptr);
+
+    auto audioEvents = artboard->find<AudioEvent>();
+    REQUIRE(audioEvents.size() == 1);
+    REQUIRE(artboard->hasAudio() == true);
+}
+
+TEST_CASE("Artboard has audio in nested artboard", "[audio]")
+{
+    rcp<AudioEngine> engine = AudioEngine::Make(2, 44100);
+
+    auto file = ReadRiveFile("../../test/assets/sound2.riv");
+    auto artboard = file->artboardNamed("grand-parent");
+    artboard->audioEngine(engine);
+
+    REQUIRE(artboard != nullptr);
+
+    auto audioEvents = artboard->find<AudioEvent>();
+    REQUIRE(audioEvents.size() == 0);
+    REQUIRE(artboard->hasAudio() == true);
+}
+
+TEST_CASE("Artboard does not have audio", "[audio]")
+{
+    rcp<AudioEngine> engine = AudioEngine::Make(2, 44100);
+
+    auto file = ReadRiveFile("../../test/assets/sound2.riv");
+    auto artboard = file->artboardNamed("no-audio");
+    artboard->audioEngine(engine);
+
+    REQUIRE(artboard != nullptr);
+
+    auto audioEvents = artboard->find<AudioEvent>();
+    REQUIRE(audioEvents.size() == 0);
+    REQUIRE(artboard->hasAudio() == false);
+}
+
 // TODO check if sound->stop calls completed callback!!!
\ No newline at end of file