Giter Site home page Giter Site logo

Comments (35)

meshula avatar meshula commented on June 5, 2024

Hi, this is very helpful. I haven't seen this under MSVC, but maybe I can repro by running a bunch of times. I think I can see where the problem lies from your traces, so thanks for that legwork.

I'm traveling for a week, so can't dig in right now, but will take a look when I am back.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

The problem isn't always observable under MSVC, but it's still there. I found that crashes become almost guaranteed when adding some debug output to WaveShaperNode::processCurve, for example, but that's only because the buffers have already been corrupted at that point. On Linux, this is where nan values are read, causing the audio to deteriorate even before a SEGFAULT.

I don't have a proper Visual Studio setup for debugging MSVC, but if you share your suspicions I could test on Linux/macOS.

from labsound.

meshula avatar meshula commented on June 5, 2024

As a first pass, could you apply this patch? This provides better guards on accessing the array's data member, and also makes the WaveShaperNode temporary buffers member objects instead of unique_ptr objects. I haven't been able to detect a deletion of the float array from process(). Does this, as you mentioned, move the problem elsewhere?

From 488f2401c8c9a80be0bdc0c069ce97da8f634511 Mon Sep 17 00:00:00 2001
From: Nick Porcino <[email protected]>
Date: Sat, 11 Nov 2023 11:07:34 -0800
Subject: [PATCH] Don't use a unique pointer to the temp buffers in
 WaveShaperNode

---
 examples/src/ExamplesMain.cpp      |  4 +--
 include/LabSound/core/AudioArray.h | 42 +++++++++++++++++++++---------
 src/core/WaveShaperNode.cpp        | 14 +++++-----
 3 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/examples/src/ExamplesMain.cpp b/examples/src/ExamplesMain.cpp
index 7b5f1c4a..fa60af19 100755
--- a/examples/src/ExamplesMain.cpp
+++ b/examples/src/ExamplesMain.cpp
@@ -37,7 +37,7 @@ int main(int argc, char *argv[]) try
     
     Example examples[] = {
 
-        { Passing::pass, Skip::yes,  new ex_devices(context, NoInput) },
+        { Passing::pass, Skip::yes, new ex_devices(context, NoInput) },
         { Passing::pass, Skip::yes, new ex_play_file(context, NoInput) },
         { Passing::pass, Skip::yes, new ex_simple(context, NoInput) },
         { Passing::pass, Skip::yes, new ex_osc_pop(context, NoInput) },
@@ -59,7 +59,7 @@ int main(int argc, char *argv[]) try
         { Passing::pass, Skip::yes, new ex_granulation_node(context, NoInput) }, // note: node is under development
         { Passing::pass, Skip::yes, new ex_poly_blep(context, NoInput) },
         { Passing::fail, Skip::yes, new ex_split_merge(context, NoInput) },
-        { Passing::fail, Skip::no, new ex_waveshaper(context, NoInput)},
+        { Passing::fail, Skip::no,  new ex_waveshaper(context, NoInput)},
     };
 
     static constexpr int iterations = 1;
diff --git a/include/LabSound/core/AudioArray.h b/include/LabSound/core/AudioArray.h
index 92e0d3cb..c2c77abf 100644
--- a/include/LabSound/core/AudioArray.h
+++ b/include/LabSound/core/AudioArray.h
@@ -17,21 +17,27 @@ class AudioArray
     T * _allocation = nullptr;
     T * _data = nullptr;
     int _size = 0;
+    T _safety;
 
 public:
-    AudioArray() = default;
+    explicit AudioArray()
+    : _allocation(nullptr)
+    , _data(nullptr)
+    , _size(0)
+    , _safety(0) {}
+    
     explicit AudioArray(int n)
     : _allocation(nullptr)
     , _data(nullptr)
-    , _size(-1)
+    , _size(0)
+    , _safety(0)
     {
         allocate(n);
     }
 
     ~AudioArray()
     {
-        if (_allocation)
-            free(_allocation);
+        free(_allocation);
     }
 
     // allocation will realloc if necessary.
@@ -43,19 +49,18 @@ public:
         const uintptr_t mask = ~0xf;
         size_t initialSize = sizeof(T) * n + alignment;
         if (_size != n) {
-            if (_allocation)
-                free(_allocation);
+            free(_allocation);
 
-            if (n) {
+            if (n > 0) {
                 _allocation = static_cast<T*>(calloc(initialSize, 1));
                 _data = (T*)((((intptr_t)_allocation) + (alignment-1)) & mask);
+                _size = n;
             }
             else {
                 _allocation = nullptr;
                 _data = nullptr;
+                _size = 0;
             }
-
-            _size = n;
         }
     }
 
@@ -65,29 +70,40 @@ public:
     // size in samples, not bytes
     int size() const { return _size; }
 
-    T & operator[](size_t i) { return data()[i]; }
+    T & operator[](size_t i) {
+        if (_data)
+            return _data[i];
+        return _safety;
+    }
 
     void zero()
     {
-        memset(data(), 0, sizeof(T) * size());
+        if (_data)
+            memset(_data, 0, sizeof(T) * size());
     }
 
     void zeroRange(unsigned start, unsigned end)
     {
+        if (_data == nullptr || _size <= 0)
+            return;
+        
         bool isSafe = (start <= end) && (end <= (unsigned) size());
         if (!isSafe)
             return;
 
-        memset(data() + start, 0, sizeof(T) * (end - start));
+        memset(_data + start, 0, sizeof(T) * (end - start));
     }
 
     void copyToRange(const T * sourceData, unsigned start, unsigned end)
     {
+        if (_data == nullptr || _size <= 0)
+            return;
+
         bool isSafe = (start <= end) && (end <= (unsigned) size());
         if (!isSafe)
             return;
 
-        memcpy(data() + start, sourceData, sizeof(T) * (end - start));
+        memcpy(_data + start, sourceData, sizeof(T) * (end - start));
     }
 
 };
diff --git a/src/core/WaveShaperNode.cpp b/src/core/WaveShaperNode.cpp
index 066effd4..0fa90ce4 100644
--- a/src/core/WaveShaperNode.cpp
+++ b/src/core/WaveShaperNode.cpp
@@ -17,8 +17,8 @@
 namespace lab {
 struct OverSamplingArrays
 {
-    std::unique_ptr<AudioFloatArray> m_tempBuffer;
-    std::unique_ptr<AudioFloatArray> m_tempBuffer2;
+    AudioFloatArray m_tempBuffer;
+    AudioFloatArray m_tempBuffer2;
     std::unique_ptr<UpSampler> m_upSampler;
     std::unique_ptr<DownSampler> m_downSampler;
     std::unique_ptr<UpSampler> m_upSampler2;
@@ -28,8 +28,8 @@ static void* createOversamplingArrays()
 {
     struct OverSamplingArrays * osa = new struct OverSamplingArrays;
     int renderQuantumSize = 128;  // from https://www.w3.org/TR/webaudio/#render-quantum-size
-    osa->m_tempBuffer = std::make_unique<AudioFloatArray>(renderQuantumSize * 2);
-    osa->m_tempBuffer2 = std::make_unique<AudioFloatArray>(renderQuantumSize * 4);
+    osa->m_tempBuffer.allocate(renderQuantumSize * 2);
+    osa->m_tempBuffer2.allocate(renderQuantumSize * 4);
     osa->m_upSampler = std::make_unique<UpSampler>(renderQuantumSize);
     osa->m_downSampler = std::make_unique<DownSampler>(renderQuantumSize * 2);
     osa->m_upSampler2 = std::make_unique<UpSampler>(renderQuantumSize * 2);
@@ -114,7 +114,7 @@ void WaveShaperNode::processCurve(const float* source, float* destination, int f
 void WaveShaperNode::processCurve2x(const float * source, float * destination, int framesToProcess)
 {
     struct OverSamplingArrays * osa = (struct OverSamplingArrays *) m_oversamplingArrays;
-    float * tempP = osa->m_tempBuffer->data();
+    float * tempP = osa->m_tempBuffer.data();
 
     osa->m_upSampler->process(source, tempP, framesToProcess);
 
@@ -127,8 +127,8 @@ void WaveShaperNode::processCurve4x(const float * source, float * destination, i
 {
     struct OverSamplingArrays * osa = (struct OverSamplingArrays *) m_oversamplingArrays;
 
-    float * tempP = osa->m_tempBuffer->data();
-    float * tempP2 = osa->m_tempBuffer2->data();
+    float * tempP = osa->m_tempBuffer.data();
+    float * tempP2 = osa->m_tempBuffer2.data();
 
     osa->m_upSampler->process(source, tempP, framesToProcess);
     osa->m_upSampler2->process(tempP, tempP2, framesToProcess * 2);
-- 
2.39.3 (Apple Git-145)

from labsound.

meshula avatar meshula commented on June 5, 2024

And here's a further patch to mutex setting the curve.

From 9975447ab9aa87b36b94befe0a0ffef42f1619e8 Mon Sep 17 00:00:00 2001
From: Nick Porcino <[email protected]>
Date: Sat, 11 Nov 2023 11:59:14 -0800
Subject: [PATCH] Add mutex for set curve on wave shaper node

---
 include/LabSound/core/WaveShaperNode.h | 11 ++++----
 src/core/WaveShaperNode.cpp            | 37 +++++++++-----------------
 2 files changed, 18 insertions(+), 30 deletions(-)

diff --git a/include/LabSound/core/WaveShaperNode.h b/include/LabSound/core/WaveShaperNode.h
index bb2ec563..4cbb5909 100644
--- a/include/LabSound/core/WaveShaperNode.h
+++ b/include/LabSound/core/WaveShaperNode.h
@@ -6,9 +6,7 @@
 #define WaveShaperNode_h
 
 #include "LabSound/core/AudioNode.h"
-//#include <vector>
-//#include "../src/internal/UpSampler.h" //ouch..how to hide internal from calling application?
-//#include "../src/internal/DownSampler.h"
+#include <mutex>
 
 namespace lab {
 enum OverSampleType
@@ -38,15 +36,18 @@ public:
 
     // AudioNode
     virtual void process(ContextRenderLock &, int bufferSize) override;
-    virtual void reset(ContextRenderLock&) override {}
+    virtual void reset(ContextRenderLock &) override {}
 
 protected:
     void processCurve(const float * source, float * destination, int framesToProcess);
     virtual double tailTime(ContextRenderLock& r) const override { return 0.; }
     virtual double latencyTime(ContextRenderLock& r) const override { return 0.; }
 
+    std::mutex _curveMutex;
+    
     std::vector<float> m_curve;
-    std::vector<float>* m_newCurve = nullptr;
+    std::vector<float> m_newCurve;
+    bool _newCurveReady = false;
 
     // Oversampling.
     void * m_oversamplingArrays = nullptr;
diff --git a/src/core/WaveShaperNode.cpp b/src/core/WaveShaperNode.cpp
index 0fa90ce4..ccf2292f 100644
--- a/src/core/WaveShaperNode.cpp
+++ b/src/core/WaveShaperNode.cpp
@@ -9,7 +9,6 @@
 #include "internal/Assertions.h"
 #include <algorithm>
 #include <memory>
-#include <mutex>
 #include <vector>
 #include "internal/UpSampler.h" //ouch..how to hide internal from calling application?
 #include "internal/DownSampler.h"
@@ -60,26 +59,14 @@ WaveShaperNode::WaveShaperNode(AudioContext & ac, AudioNodeDescriptor const & de
 
 WaveShaperNode::~WaveShaperNode()
 {
-    if (m_newCurve)
-    {
-        // @TODO mutex
-        delete m_newCurve;
-    }
-    if (m_oversamplingArrays) delete m_oversamplingArrays;
+    delete (OverSamplingArrays*) m_oversamplingArrays;
 }
 
 void WaveShaperNode::setCurve(std::vector<float> & curve)
 {
-    std::vector<float>* new_curve = new std::vector<float>();
-    *new_curve = curve;
-    if (m_newCurve)
-    {
-        // @TODO mutex
-        std::vector<float>* x = nullptr;
-        std::swap(x, m_newCurve);
-        delete x;
-    }
-    m_newCurve = new_curve;
+    std::lock_guard<std::mutex> lock(_curveMutex);
+    m_newCurve = curve;
+    _newCurveReady = true;
 }
 
 void WaveShaperNode::processCurve(const float* source, float* destination, int framesToProcess)
@@ -113,7 +100,7 @@ void WaveShaperNode::processCurve(const float* source, float* destination, int f
 // https://github.com/WebKit/WebKit/blob/main/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp
 void WaveShaperNode::processCurve2x(const float * source, float * destination, int framesToProcess)
 {
-    struct OverSamplingArrays * osa = (struct OverSamplingArrays *) m_oversamplingArrays;
+    OverSamplingArrays * osa = (OverSamplingArrays *) m_oversamplingArrays;
     float * tempP = osa->m_tempBuffer.data();
 
     osa->m_upSampler->process(source, tempP, framesToProcess);
@@ -123,9 +110,10 @@ void WaveShaperNode::processCurve2x(const float * source, float * destination, i
 
     osa->m_downSampler->process(tempP, destination, framesToProcess * 2);
 }
+
 void WaveShaperNode::processCurve4x(const float * source, float * destination, int framesToProcess)
 {
-    struct OverSamplingArrays * osa = (struct OverSamplingArrays *) m_oversamplingArrays;
+    OverSamplingArrays * osa = (OverSamplingArrays *) m_oversamplingArrays;
 
     float * tempP = osa->m_tempBuffer.data();
     float * tempP2 = osa->m_tempBuffer2.data();
@@ -142,13 +130,12 @@ void WaveShaperNode::processCurve4x(const float * source, float * destination, i
 
 void WaveShaperNode::process(ContextRenderLock & r, int bufferSize)
 {
-    if (m_newCurve)
+    if (_newCurveReady)
     {
-        // @TODO mutex
-        std::vector<float>* x = nullptr;
-        std::swap(x, m_newCurve);
-        m_curve = *x;
-        delete x;
+        // this could cause a pop, but setting a curve should be extremely rare
+        std::lock_guard<std::mutex> lock(_curveMutex);
+        std::swap(m_curve, m_newCurve);
+        _newCurveReady = false;
     }
 
     AudioBus* destinationBus = output(0)->bus(r);
-- 
2.39.3 (Apple Git-145)

from labsound.

meshula avatar meshula commented on June 5, 2024

... I've pushed the patches to main as it makes things cleaner overall, and if you have a chance to test, could you LMK if you still get the memory corruption please?

from labsound.

phildremi avatar phildremi commented on June 5, 2024

... I've pushed the patches to main as it makes things cleaner overall, and if you have a chance to test, could you LMK if you still get the memory corruption please?

Tested with 9975447:

  • Sporadic SEGFAULTs under MSVC can still be observed
  • I also once got a failed assertion with MSVC (DownSampler.cpp:83 - isInputBlockSizeGood)
  • Using WSL, the audio is still broken, even if a SEGFAULT seems to be harder to reproduce in gdb
  • Crashes do also still happen in WSL (more rarely), but I suspect gdb can't necessarily identify the right location

Based on the above, I assume the corruption is still happening. Would need more debugging and testing on other machines to see how the problem manifests there. I also had audio drop immediately after End UpdateGraphThread - very strange...


I haven't been able to detect a deletion of the float array from process()

Maybe that was poorly explained on my part; inside process I first observed that nan was being read on Linux, which I suspect causes the garbled audio. But this is likely just a symptom of the buffer being corrupted, so I haven't investigated further yet.


More WSL logs below. Unfortunately, they may be red herrings if the corruption results from a threading-related issue:

(gdb) bt
#0  0x00005555555dede9 in lab::AudioNodeOutput::bus(lab::ContextRenderLock&) const ()
#1  0x00005555555d6c83 in lab::AudioNode::unsilenceOutputs(lab::ContextRenderLock&) ()
#2  0x00005555555d674a in lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) ()
#3  0x00005555555ded81 in lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) ()
#4  0x00005555555de02f in lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) ()
#5  0x00005555555d1fec in lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) ()
#6  0x00005555555d2416 in lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) ()
#7  0x0000555555683da7 in lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) ()
#8  0x0000555555682886 in lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) ()
#9  0x0000555555686b8c in RtApiPulse::callbackEvent() ()
#10 0x000055555568684a in pulseaudio_callback(void*) ()
#11 0x00007ffff7a9d3ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#12 0x00007ffff7b1da2c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Thread 3 "LabSoundExample" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff270d6c0 (LWP 1344)]
0x000055555563855d in lab::DownSampler::process(float const*, float*, unsigned long) ()
(gdb) bt
#0  0x000055555563855d in lab::DownSampler::process(float const*, float*, unsigned long) ()
#1  0x0000555555606892 in lab::WaveShaperNode::processCurve4x(float const*, float*, int) ()
#2  0x0000555555606c20 in lab::WaveShaperNode::process(lab::ContextRenderLock&, int) ()
#3  0x00005555555d6323 in lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) ()
#4  0x00005555555ded81 in lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) ()
#5  0x00005555555de02f in lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) ()
#6  0x00005555555d1fec in lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) ()
#7  0x00005555555d2416 in lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) ()
#8  0x0000555555683da7 in lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) ()
#9  0x0000555555682886 in lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) ()
#10 0x0000555555686b8c in RtApiPulse::callbackEvent() ()
#11 0x000055555568684a in pulseaudio_callback(void*) ()
#12 0x00007ffff7a9d3ec in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#13 0x00007ffff7b1da2c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

from labsound.

phildremi avatar phildremi commented on June 5, 2024

FWIW, running the example with -fsanitize=thread -fno-omit-frame-pointer yields some warnings.

I don't have time to look into these (or do testing on other machines) right now, but it might be worth trying tsan/usan/asan.

from labsound.

meshula avatar meshula commented on June 5, 2024

Thanks, much appreciated.

from labsound.

meshula avatar meshula commented on June 5, 2024

I notice that UpSampler has this code

    for (unsigned i = 0; i < sourceFramesToProcess; ++i)
        destP[i * 2 + 1] = oddSamplesP[i];

and the destination buffers are allocated only to sourceFramesToProcess * 2.

that maybe needs to be sourceFramesToProcess - 1...

from labsound.

phildremi avatar phildremi commented on June 5, 2024

Back to testing on native Linux now. The corruption is definitely still there. Presumably, it's the same problem. Symptoms:

  • SEGFAULT in AudioContext::currentTime() because _destinationNode is nullptr (I added an early exit as a workaround)
  • Again a failed assertion DownSampler.cpp:83 - isInputBlockSizeGood - same as the one observed under MSVC
  • In DownSampler::process, another SEGFAULT after the sourceP and m_reducedKernel have become invalid
  • SEGFAULT in AudioChannel::clearSilentFlag because this is pointing to invalid memory (?)
  • Another where m_kernel in the UpSampler has become corrupted
  • One where curveData in the WaveShaperNode points to invalid memory
  • Sometimes, the source and destination pointers in WaveShaperNode::process2x/4x are exactly the same
  • I've once observed the std::vector memory being corrupted before swapping curves in here, too

These are separate runs. Crashes are still sporadic, and audio remains garbled. I'll try running the sanitizers (with GCC) next...

from labsound.

meshula avatar meshula commented on June 5, 2024

Is the crash at the end of the demo? I just got repro due to deleting the ShaperNode while it was still processing in the audio thread.

Disconnecting the node before deleting it should prevent that:

        for (int i = -2; i < 3; i++)
        {
            // std::vector<float> curve = makeDistortionCurve(100.0f * i);
            makeDistortionCurveA(curve, n_samples, .25f * i + .5f);
            printf("A i %d curve[0] %f curve[44099] %f oversample none\n", i, curve[0], curve[44099]);
            waveshaper->setCurve(curve);
            Wait(delay_time_ms);
        }
        
        // ensure the waveshaper node is not being processed before deleting it
        ac.disconnect(ac.destinationNode());
        ac.synchronizeConnections();
    }

If this works for you, I would not consider it a fix, but a workaround. Deleting running nodes should Just Work.

from labsound.

meshula avatar meshula commented on June 5, 2024

When you say "audio is garbled" do you mean, all the time for all demos? Or sporadically, with regards to the WaveShaperNode demo?

from labsound.

phildremi avatar phildremi commented on June 5, 2024

Is the crash at the end of the demo? I just got repro due to deleting the ShaperNode while it was still processing in the audio thread.

Crashes seem to appear at "random" times, so not necessarily (or at least not exclusively) at the end of the demo.

Disconnecting the node before deleting it should prevent that:
...
If this works for you, I would not consider it a fix, but a workaround. Deleting running nodes should Just Work.

Making this change might at best reduce the frequency of SEGFAULTs, but unfortunately it doesn't eliminate them.

Afterwards, I still got a crash originating from what looks to be a synchronization issue. TSAN snapshot (last 2 warnings):

Running LabSoundExample with ThreadSanitizer enabled (excerpt)
==================
WARNING: ThreadSanitizer: data race (pid=27797)
  Write of size 8 at 0x7b640002fd00 by main thread:
    #0 free ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:740 (libtsan.so.2+0x3c7bf) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 lab::AudioArray<float>::~AudioArray() <null> (LabSoundExample+0x4e456) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 lab::WaveShaperNode::~WaveShaperNode() LabSound/src/core/WaveShaperNode.cpp:62 (LabSoundExample+0xe4fb0) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 void std::_Destroy<lab::WaveShaperNode>(lab::WaveShaperNode*) <null> (LabSoundExample+0x61e6e) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Previous write of size 4 at 0x7b640002fd00 by thread T2 (mutexes: write M0):
    #0 lab::UpSampler::process(float const*, float*, unsigned long) LabSound/src/internal/src/UpSampler.cpp:107 (LabSoundExample+0x144365) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #1 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:121 (LabSoundExample+0xe54f4) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:185 (LabSoundExample+0xe5a08) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:546 (LabSoundExample+0x9ba01) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0xa946d) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0xa7faa) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:77 (LabSoundExample+0x94eeb) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #7 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:136 (LabSoundExample+0x954b7) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #8 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:317 (LabSoundExample+0x1a1dc1) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #9 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:28 (LabSoundExample+0x19fd42) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #10 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:9420 (LabSoundExample+0x1a6d31) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #11 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:9341 (LabSoundExample+0x1a6748) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock(pthread_mutex_t*) <null> (LabSoundExample+0x31c22) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:136 (LabSoundExample+0x954b7) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:317 (LabSoundExample+0x1a1dc1) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:28 (LabSoundExample+0x19fd42) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:9420 (LabSoundExample+0x1a6d31) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:9341 (LabSoundExample+0x1a6748) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Thread T2 (tid=27805, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9806 (LabSoundExample+0x1a8f01) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:404 (LabSoundExample+0x1a5e0a) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:299 (LabSoundExample+0x1a5830) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:167 (LabSoundExample+0x1a0fde) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:188 (LabSoundExample+0x1a126f) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 main <null> (LabSoundExample+0x30730) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

SUMMARY: ThreadSanitizer: data race (LabSound/build/bin/LabSoundExample+0x4e456) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d) in lab::AudioArray<float>::~AudioArray()
==================
==================
WARNING: ThreadSanitizer: data race (pid=27797)
  Write of size 8 at 0x7b1400007808 by main thread:
    #0 operator delete(void*, unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:150 (libtsan.so.2+0x886d6) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 lab::WaveShaperNode::~WaveShaperNode() LabSound/src/core/WaveShaperNode.cpp:62 (LabSoundExample+0xe4fbd) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 void std::_Destroy<lab::WaveShaperNode>(lab::WaveShaperNode*) <null> (LabSoundExample+0x61e6e) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Previous read of size 8 at 0x7b1400007808 by thread T2 (mutexes: write M0):
    #0 lab::AudioArray<float>::data() LabSound/include/LabSound/core/AudioArray.h:67 (LabSoundExample+0x6688a) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #1 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:118 (LabSoundExample+0xe54b3) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:185 (LabSoundExample+0xe5a08) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:546 (LabSoundExample+0x9ba01) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0xa946d) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0xa7faa) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:77 (LabSoundExample+0x94eeb) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #7 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:136 (LabSoundExample+0x954b7) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #8 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:317 (LabSoundExample+0x1a1dc1) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #9 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:28 (LabSoundExample+0x19fd42) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #10 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:9420 (LabSoundExample+0x1a6d31) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #11 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:9341 (LabSoundExample+0x1a6748) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock(pthread_mutex_t*) <null> (LabSoundExample+0x31c22) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:136 (LabSoundExample+0x954b7) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:317 (LabSoundExample+0x1a1dc1) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:28 (LabSoundExample+0x19fd42) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:9420 (LabSoundExample+0x1a6d31) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:9341 (LabSoundExample+0x1a6748) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

  Thread T2 (tid=27805, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9806 (LabSoundExample+0x1a8f01) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:404 (LabSoundExample+0x1a5e0a) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:299 (LabSoundExample+0x1a5830) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:167 (LabSoundExample+0x1a0fde) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:188 (LabSoundExample+0x1a126f) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)
    #6 main <null> (LabSoundExample+0x30730) (BuildId: d4b1fbdf637e46db9d450db0abc960d37681e85d)

SUMMARY: ThreadSanitizer: data race ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:150 in operator delete(void*, unsigned long)
==================
ThreadSanitizer:DEADLYSIGNAL
==27797==ERROR: ThreadSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55801f36b133 bp 0x7fd3985fe010 sp 0x7fd3985fdfa0 T27805)
==27797==The signal is caused by a READ memory access.
==27797==Hint: address points to the zero page.

This does look like the WaveShaperNode being deleted while sampling is still in process, though. The full log (2800 lines) is here.


When you say "audio is garbled" do you mean, all the time for all demos? Or sporadically, with regards to the WaveShaperNode demo?

It's always garbled (on Linux only. Windows and macOS don't have this problem). Tested with ex_play_file, ex_waveshaper, and even a completely separate "hello world" application that reads WAV, MP3 etc. and plays it back. Might be a separate issue?

I haven't looked into this more since it may resolve itself after the crashes are gone, but there were nan in the audio buffer.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

I pulled in the latest changes (3ba7b49, previously on 9975447. SEGFAULT and garbled audio still observable. Additionally, the WaveShaperNode example now fails this assertion: LabSound/src/core/AudioNode.cpp:426 - _self->m_channelCount != 0

from labsound.

meshula avatar meshula commented on June 5, 2024

I pushed a fix for m_channelCount.

The full TSAN report you posted shows the creation of two pulse audio threads, and that they are frequently racing.

RtAudio creates two pulse Audio threads in the case that the input device and the output device have different id's.

I see this at the beginning of the log

10:20:45 INFO  LabSound/include/LabSound/core/AudioDevice.h:104: AudioHardwareDeviceNode() 
	* Sample Rate:     48000.000000 
	* Input Channels:  1 
	* Output Channels: 2  

The differing number of channels suggests to me that we are getting two threads due to this detail that two devices are involved.

To test a theory that there is a problem when launching to pulse audio threads, could you modify this line in ExamplesMain, which will prevent the second thread from being launched:

int main(int argc, char *argv[]) try
{
...    
    AudioStreamConfig _inputConfig;
    AudioStreamConfig _outputConfig;
    auto config = GetDefaultAudioDeviceConfiguration(false); // only create an output thread

from labsound.

meshula avatar meshula commented on June 5, 2024

We are using RtAudio 5.1.0. I notice the following in the 5.2.0 release notes. Perhaps we are bumping against the issues they have fixed in 5.2.0, as my current theory is that we are getting two devices when we actually only want one. I don't notice any related changes in the 6.0 release.

Release 5.2.0
see git history for complete list of changes
update to audioprobe.cpp to list devices for all APIs
miscellaneous build system updates
PulseAudio device detection fixes
various WASAPI updates (thanks to Marcus Tomlinson)

from labsound.

meshula avatar meshula commented on June 5, 2024

Pushed an update to 5.2.0, but not 6, as 6 has many API changes.

from labsound.

meshula avatar meshula commented on June 5, 2024

I'm now able to reproduce the data race locally! This should help things along :)

from labsound.

phildremi avatar phildremi commented on June 5, 2024

The good news is that the RtAudio upgrade seems to have resolved the "garbled audio" (Linux-only) issue, as far as I can tell.

Still on Linux, there are a few remaining problems that may be due to the corruption/data race:

  • Running ex_waveshaper, there appears a "buzzing" sound once reaching oversample2x (it remains for the rest of the test)
  • SEGFAULTs still appear, which is to be expected since a PulseAudio issue shouldn't cause crashes on MSVC/macOS
  • Occasionally, the audio drops out completely at the start of the test - can't say why exactly yet as there's no crash or error

Finally, I noticed that the debug output seems to suggest that the same thread is playing back the AudioNode twice:

(I added std::this_thread::get_id() to see if multiple threads were accessing the same node)

Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
B i -2 curve[0] -1.000000 curve[44099] 0.999955 oversample none
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
Thread ID: 139853194852096 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
B i -1 curve[0] -1.000000 curve[44099] 0.999973 oversample none
B i 0 curve[0] -1.000000 curve[44099] 0.999985 oversample none
B i 1 curve[0] -1.000000 curve[44099] 0.999994 oversample none
... 

This strikes me as rather peculiar to say the least. It's also visible in the other logs. Might be intentional, though?

from labsound.

meshula avatar meshula commented on June 5, 2024

i don't hear the buzzing. The -1 I introduced in the "odd samples" write could be the cause...

I'm working on the race first, the new info is also interesting, thanks

from labsound.

meshula avatar meshula commented on June 5, 2024

It's a relief and reassuring that it was possible to deduce a possible RtAudio initialization issue, and upgrading an RtAudio that included Pulse Audio initialization fixes resolved the garbled audio.

from labsound.

meshula avatar meshula commented on June 5, 2024

There is an unfortunate race in the RtAudio code, even the new one. I've corrected it using a std::atomic flag so that the RtAudio callback doesn't attempt to do processing before the RtAudio set up is complete. The upshot of this is that the temporary RtAudio context created to enumerate devices can conflict with the RtAudio device created to play back audio. Although I corrected the race, I also changed the RtAudio object itself to be a global singleton, since clearly RtAudio was not written with the idea that there might be more than one RtAudio object instantiated.

I corrected all the runtime races I encountered in device set up, and in the WaveShaperNode.

There is still a race when the WaveShaperNode is deleted, my workaround doesn't work, so I will continue looking at that.

This much, I hope, will fix all the non-shutdown related tsan issues you are encountering, and also I hope, it will resolve the "playing twice" issue you noticed. Playing twice would definitely cause garbling or crackling in many nodes that expect that they will not be invoked twice per render quantum.

Fixes to this point (not including a Shaper node deletion fix) are now pushed.

from labsound.

meshula avatar meshula commented on June 5, 2024

If the fix to RtAudio improves things for you, I will send a pull request upstream to the RtAudio project (or rather, I will check if it has been fixed in RtAudio 6, and take it from there).

from labsound.

meshula avatar meshula commented on June 5, 2024

pushed fix for race on wave shaper node deletion.

down to one race when the destination audio node is deleted on demo shutdown, and the rtaudio callback is still running.

from labsound.

meshula avatar meshula commented on June 5, 2024

pushed fix to RtAudio shutdown races, and all the ones in LabSound I could find.

Next step is to investigate if RtAudio 6 has corrected the races.

from labsound.

meshula avatar meshula commented on June 5, 2024

RtAudio 6 has introduced mutexes on mac which is more heavy-handed than my fixes. RtAudio 6 hasn't got all the races fixed. Not going to upgrade to 6 unless someone points to an urgent need, since I'd rather not spend time fixing 6...

from labsound.

phildremi avatar phildremi commented on June 5, 2024

Thanks for your effort! It seems there are significantly fewer data races, though some must still exist. Remaining issues:

  • Oversampling introduces the "buzzing sound" still, as previously mentioned
  • Playback seems to sometimes start before UpdateGraphThread finished, causing audio to drop out (see logs below)
  • I got one crash with pure virtual method called and terminate called without an active exception = another race?
  • The output still shows Scheduler: fade in and Scheduler: playing twice, from the same thread... same as before

Here's some more logs that might help (all while on 565cfde):

Firstly, this is one run where the audio dropped for the entire test
New Thread 0x7ffff31d3700 (LWP 57295)]
[New Thread 0x7ffff29d2700 (LWP 57296)]
[New Thread 0x7ffff21d1700 (LWP 57297)]
08:39:10 TRACE LabSound/src/core/AudioContext.cpp:534: Begin UpdateGraphThread
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
B i -2 curve[0] -1.000000 curve[44099] 0.999955 oversample none
08:39:10 TRACE LabSound/src/core/AudioContext.cpp:583: End UpdateGraphThread
// Short "bleeping" sound here, then audio is dead (and remains dead for the entirety of the run)
[Thread 0x7ffff21d1700 (LWP 57297) exited]
B i -1 curve[0] -1.000000 curve[44099] 0.999973 oversample none
B i 0 curve[0] -1.000000 curve[44099] 0.999985 oversample none
B i 1 curve[0] -1.000000 curve[44099] 0.999994 oversample none
B i 2 curve[0] -1.000000 curve[44099] 1.000000 oversample none
For comparison, this is a "normal" run where audio playback works as expected
New Thread 0x7ffff31d3700 (LWP 57555)]
[New Thread 0x7ffff29d2700 (LWP 57556)]
[New Thread 0x7ffff21d1700 (LWP 57557)]
11:44:39 TRACE LabSound/src/core/AudioContext.cpp:534: Begin UpdateGraphThread
B i -2 curve[0] -1.000000 curve[44099] 0.999955 oversample none
11:44:39 TRACE LabSound/src/core/AudioContext.cpp:583: End UpdateGraphThread
[Thread 0x7ffff21d1700 (LWP 57557) exited]
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:160
Scheduler: fade in
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
Thread ID: 140737263773440 - File: LabSound/src/core/AudioNode.cpp:183
Scheduler: playing
B i -1 curve[0] -1.000000 curve[44099] 0.999973 oversample none
B i 0 curve[0] -1.000000 curve[44099] 0.999985 oversample none
B i 1 curve[0] -1.000000 curve[44099] 0.999994 oversample none

Lastly, here are the full TSAN logs for dropout/no dropout/the virtual method crash: f34e1fede723dc9565cf382783544775


If the fix to RtAudio improves things for you, I will send a pull request upstream to the RtAudio project (or rather, I will check if it has been fixed in RtAudio 6, and take it from there).

It's a bit difficult to determine whether things improved as the crashes have been sporadic:

  • I'm running stress tests to find them, which sometimes do SEGFAULT (or otherwise crash) still
  • When manually running in gdb, I can't seem to get any though - so no additional backtraces, for now
  • The most common problem is audio dropouts, followed by the occasional crash while running the test script

I'd say it definitely feels like there's a lot less actual crashing now. However, clearly there are still some concurrency issues left.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

Just observed another crash, this time with MSVC:

A i 0 curve[0] -0.342995 curve[44099] 0.342989 oversample none
A i 1 curve[0] -0.344421 curve[44099] 0.344417 oversample none
A i 2 curve[0] -0.345305 curve[44099] 0.345301 oversample none
15:33:06 TRACE LabSound__LabSound\src\core\AudioContext.cpp:170: Begin AudioContext::~AudioContext()
15:33:06 TRACE LabSound__LabSound\src\core\AudioContext.cpp:262: AudioContext::uninitialize()
15:33:06 INFO  LabSound__LabSound\src\core\AudioContext.cpp:195: Finish AudioContext::~AudioContext()
D:\a\_work\1\s\src\vctools\crt\github\stl\src\mutex.cpp(61): mutex destroyed while busy

This happened after the example completed, with the same duplicate playback/buzzing problem as on Linux.

from labsound.

meshula avatar meshula commented on June 5, 2024

Thanks for the update.

Since you mention having an issue with an MSVC build, that gives me an avenue to see if I can get the buzzing repro'd. I have a bunch of windows machines here.

I'm running stress tests to find them, which sometimes do SEGFAULT (or otherwise crash) still

How are you doing this? If you have a command line or script to share, I can start doing the same thing here.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

How are you doing this? If you have a command line or script to share, I can start doing the same thing here.

Just running the program in a loop. The current script is here - but beware, the windows versions are completely untested.

The last few SEGFAULTs appeared after 52 and 66 iterations, so it can take quite a while. Still seems to be the same problem:

23:16:11 INFO  LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:59: using rtaudio api linux_pulse
23:16:11 INFO  LabSound/include/LabSound/core/AudioDevice.h:104: AudioHardwareDeviceNode() 
	* Sample Rate:     48000.000000 
	* Input Channels:  0 
	* Output Channels: 2   
23:16:11 INFO  LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:128: using output device idx: 0
23:16:11 INFO  LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:130: using output device name: Family 17h (Models 10h-1fh) HD Audio Controller Analog Stereo
23:16:11 INFO  LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:135: using input device idx: -1
23:16:11 TRACE LabSound/src/core/AudioContext.cpp:534: Begin UpdateGraphThread
23:16:11 TRACE LabSound/src/core/AudioContext.cpp:583: End UpdateGraphThread
23:16:27 TRACE LabSound/src/core/AudioContext.cpp:170: corrupted double-linked list
Begin AudioContext::~AudioContext()
// Crashed here, although there may be buffered output that wasn't flushed

from labsound.

meshula avatar meshula commented on June 5, 2024

Cool. ExamplesMain also has an iteration count for this purpose (

static constexpr int iterations = 1;
) If bumping the iterations there to a 100 results in a crash it might make it easier to get tsan logs.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

Huh... I actually didn't see that, but it wouldn't catch crashes in the setup/teardown part of the example program. Speaking of which, the remaining SEGFAULTs might be due to the "deleted node is still playing" problem you mentioned earlier. TSAN log:

Use-after-free when deleting the WaveShaperNode while it's still playing
WARNING: ThreadSanitizer: heap-use-after-free (pid=21829)
  Write of size 8 at 0x7b7400030c00 by thread T2 (mutexes: write M0):
    #0 memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:899 (libtsan.so.2+0x42769) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:891 (libtsan.so.2+0x42769)
    #2 memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34 (LabSoundExample+0x15c874) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 lab::DirectConvolver::process(lab::AudioArray<float>*, float const*, float*, unsigned long) LabSound/src/internal/src/DirectConvolver.cpp:350 (LabSoundExample+0x15c874)
    #4 lab::UpSampler::process(float const*, float*, unsigned long) LabSound/src/internal/src/UpSampler.cpp:111 (LabSoundExample+0x126d16) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:131 (LabSoundExample+0xcfaf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:188 (LabSoundExample+0xd0791) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:547 (LabSoundExample+0x8cda6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0x96d0c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0x95ba6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #10 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:71 (LabSoundExample+0x882a0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #11 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #12 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #13 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #14 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #15 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Previous write of size 8 at 0x7b7400030c00 by main thread:
    #0 free ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:740 (libtsan.so.2+0x3c7bf) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 lab::AudioArray<float>::~AudioArray() LabSound/include/LabSound/core/AudioArray.h:40 (LabSoundExample+0xd1a07) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 lab::DirectConvolver::~DirectConvolver() LabSound/src/internal/DirectConvolver.h:39 (LabSoundExample+0xd1a07)
    #3 lab::UpSampler::~UpSampler() LabSound/src/internal/UpSampler.h:41 (LabSoundExample+0xd1a07)
    #4 void std::_Destroy<lab::UpSampler>(lab::UpSampler*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0xd1a07)
    #5 void std::allocator_traits<std::allocator<void> >::destroy<lab::UpSampler>(std::allocator<void>&, lab::UpSampler*) /usr/include/c++/13/bits/alloc_traits.h:674 (LabSoundExample+0xd1a07)
    #6 std::_Sp_counted_ptr_inplace<lab::UpSampler, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/13/bits/shared_ptr_base.h:613 (LabSoundExample+0xd1a07)
    #7 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:175 (LabSoundExample+0xceb9f) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0xceb9f)
    #9 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0xceb9f)
    #10 std::__shared_ptr<lab::UpSampler, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0xceb9f)
    #11 std::shared_ptr<lab::UpSampler>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0xceb9f)
    #12 lab::OverSamplingArrays::~OverSamplingArrays() LabSound/src/core/WaveShaperNode.cpp:17 (LabSoundExample+0xceb9f)
    #13 lab::WaveShaperNode::~WaveShaperNode() LabSound/src/core/WaveShaperNode.cpp:62 (LabSoundExample+0xceb9f)
    #14 void std::_Destroy<lab::WaveShaperNode>(lab::WaveShaperNode*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x3fd23) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #15 void std::allocator_traits<std::allocator<void> >::destroy<lab::WaveShaperNode>(std::allocator<void>&, lab::WaveShaperNode*) /usr/include/c++/13/bits/alloc_traits.h:674 (LabSoundExample+0x3fd23)
    #16 std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/13/bits/shared_ptr_base.h:613 (LabSoundExample+0x3fd23)
    #17 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:175 (LabSoundExample+0x459dc) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #18 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0x459dc)
    #19 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0x459dc)
    #20 std::__shared_ptr<lab::AudioNode, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0x459dc)
    #21 std::shared_ptr<lab::AudioNode>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0x459dc)
    #22 void std::_Destroy<std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x459dc)
    #23 void std::_Destroy_aux<false>::__destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:163 (LabSoundExample+0x459dc)
    #24 void std::_Destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:196 (LabSoundExample+0x459dc)
    #25 void std::_Destroy<std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*, std::allocator<std::shared_ptr<lab::AudioNode> >&) /usr/include/c++/13/bits/alloc_traits.h:947 (LabSoundExample+0x459dc)
    #26 std::vector<std::shared_ptr<lab::AudioNode>, std::allocator<std::shared_ptr<lab::AudioNode> > >::~vector() /usr/include/c++/13/bits/stl_vector.h:732 (LabSoundExample+0x459dc)
    #27 labsound_example::~labsound_example() LabSound/examples/src/ExamplesCommon.h:85 (LabSoundExample+0x459dc)
    #28 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #29 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7)
    #30 main LabSound/examples/src/ExamplesMain.cpp:75 (LabSoundExample+0x3b26b) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (LabSoundExample+0x87fca) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::mutex::lock() /usr/include/c++/13/bits/std_mutex.h:113 (LabSoundExample+0x87fca)
    #3 lab::ContextRenderLock::ContextRenderLock(lab::AudioContext*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) LabSound/include/LabSound/extended/AudioContextLock.h:70 (LabSoundExample+0x87fca)
    #4 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:41 (LabSoundExample+0x87fca)
    #5 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Thread T2 (tid=21832, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9304 (LabSoundExample+0x1708fb) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:387 (LabSoundExample+0x1694ef) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:292 (LabSoundExample+0x1698a3) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:175 (LabSoundExample+0x162206) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:196 (LabSoundExample+0x1628e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 main LabSound/examples/src/ExamplesMain.cpp:29 (LabSoundExample+0x3a426) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

SUMMARY: ThreadSanitizer: heap-use-after-free /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34 in memcpy
==================
==================
WARNING: ThreadSanitizer: heap-use-after-free (pid=21829)
  Write of size 8 at 0x7b7400031600 by thread T2 (mutexes: write M0):
    #0 memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:899 (libtsan.so.2+0x42769) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:891 (libtsan.so.2+0x42769)
    #2 memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34 (LabSoundExample+0x126d7c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 lab::UpSampler::process(float const*, float*, unsigned long) LabSound/src/internal/src/UpSampler.cpp:117 (LabSoundExample+0x126d7c)
    #4 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:131 (LabSoundExample+0xcfaf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:188 (LabSoundExample+0xd0791) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:547 (LabSoundExample+0x8cda6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0x96d0c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0x95ba6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:71 (LabSoundExample+0x882a0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #10 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #11 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #12 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #13 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #14 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Previous write of size 8 at 0x7b7400031600 by main thread:
    #0 free ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:740 (libtsan.so.2+0x3c7bf) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 lab::AudioArray<float>::~AudioArray() LabSound/include/LabSound/core/AudioArray.h:40 (LabSoundExample+0xd19e3) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 lab::UpSampler::~UpSampler() LabSound/src/internal/UpSampler.h:41 (LabSoundExample+0xd19e3)
    #3 void std::_Destroy<lab::UpSampler>(lab::UpSampler*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0xd19e3)
    #4 void std::allocator_traits<std::allocator<void> >::destroy<lab::UpSampler>(std::allocator<void>&, lab::UpSampler*) /usr/include/c++/13/bits/alloc_traits.h:674 (LabSoundExample+0xd19e3)
    #5 std::_Sp_counted_ptr_inplace<lab::UpSampler, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/13/bits/shared_ptr_base.h:613 (LabSoundExample+0xd19e3)
    #6 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:175 (LabSoundExample+0xceb9f) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0xceb9f)
    #8 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0xceb9f)
    #9 std::__shared_ptr<lab::UpSampler, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0xceb9f)
    #10 std::shared_ptr<lab::UpSampler>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0xceb9f)
    #11 lab::OverSamplingArrays::~OverSamplingArrays() LabSound/src/core/WaveShaperNode.cpp:17 (LabSoundExample+0xceb9f)
    #12 lab::WaveShaperNode::~WaveShaperNode() LabSound/src/core/WaveShaperNode.cpp:62 (LabSoundExample+0xceb9f)
    #13 void std::_Destroy<lab::WaveShaperNode>(lab::WaveShaperNode*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x3fd23) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #14 void std::allocator_traits<std::allocator<void> >::destroy<lab::WaveShaperNode>(std::allocator<void>&, lab::WaveShaperNode*) /usr/include/c++/13/bits/alloc_traits.h:674 (LabSoundExample+0x3fd23)
    #15 std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c++/13/bits/shared_ptr_base.h:613 (LabSoundExample+0x3fd23)
    #16 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:175 (LabSoundExample+0x459dc) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #17 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0x459dc)
    #18 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0x459dc)
    #19 std::__shared_ptr<lab::AudioNode, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0x459dc)
    #20 std::shared_ptr<lab::AudioNode>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0x459dc)
    #21 void std::_Destroy<std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x459dc)
    #22 void std::_Destroy_aux<false>::__destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:163 (LabSoundExample+0x459dc)
    #23 void std::_Destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:196 (LabSoundExample+0x459dc)
    #24 void std::_Destroy<std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*, std::allocator<std::shared_ptr<lab::AudioNode> >&) /usr/include/c++/13/bits/alloc_traits.h:947 (LabSoundExample+0x459dc)
    #25 std::vector<std::shared_ptr<lab::AudioNode>, std::allocator<std::shared_ptr<lab::AudioNode> > >::~vector() /usr/include/c++/13/bits/stl_vector.h:732 (LabSoundExample+0x459dc)
    #26 labsound_example::~labsound_example() LabSound/examples/src/ExamplesCommon.h:85 (LabSoundExample+0x459dc)
    #27 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #28 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7)
    #29 main LabSound/examples/src/ExamplesMain.cpp:75 (LabSoundExample+0x3b26b) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (LabSoundExample+0x87fca) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::mutex::lock() /usr/include/c++/13/bits/std_mutex.h:113 (LabSoundExample+0x87fca)
    #3 lab::ContextRenderLock::ContextRenderLock(lab::AudioContext*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) LabSound/include/LabSound/extended/AudioContextLock.h:70 (LabSoundExample+0x87fca)
    #4 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:41 (LabSoundExample+0x87fca)
    #5 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Thread T2 (tid=21832, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9304 (LabSoundExample+0x1708fb) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:387 (LabSoundExample+0x1694ef) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:292 (LabSoundExample+0x1698a3) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:175 (LabSoundExample+0x162206) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:196 (LabSoundExample+0x1628e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 main LabSound/examples/src/ExamplesMain.cpp:29 (LabSoundExample+0x3a426) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

SUMMARY: ThreadSanitizer: heap-use-after-free /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34 in memcpy
==================
==================
WARNING: ThreadSanitizer: heap-use-after-free (pid=21829)
  Read of size 8 at 0x7b2800000550 by thread T2 (mutexes: write M0):
    #0 std::vector<float, std::allocator<float> >::data() /usr/include/c++/13/bits/stl_vector.h:1258 (LabSoundExample+0xcf4c0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #1 lab::WaveShaperNode::processCurve(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:74 (LabSoundExample+0xcf4c0)
    #2 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:134 (LabSoundExample+0xcfb10) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:188 (LabSoundExample+0xd0791) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:547 (LabSoundExample+0x8cda6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0x96d0c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0x95ba6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:71 (LabSoundExample+0x882a0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #10 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #11 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #12 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Previous write of size 8 at 0x7b2800000550 by main thread:
    #0 operator delete(void*, unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:150 (libtsan.so.2+0x886d6) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 std::__new_allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::deallocate(std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/include/c++/13/bits/new_allocator.h:168 (LabSoundExample+0x412ce) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::deallocate(std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&, std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:516 (LabSoundExample+0x412ce)
    #3 std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::~__allocated_ptr() /usr/include/c++/13/bits/allocated_ptr.h:74 (LabSoundExample+0x412ce)
    #4 std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_destroy() /usr/include/c++/13/bits/shared_ptr_base.h:623 (LabSoundExample+0x412ce)
    #5 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:191 (LabSoundExample+0x45a30) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:172 (LabSoundExample+0x45a30)
    #7 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0x45a30)
    #8 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0x45a30)
    #9 std::__shared_ptr<lab::AudioNode, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0x45a30)
    #10 std::shared_ptr<lab::AudioNode>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0x45a30)
    #11 void std::_Destroy<std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x45a30)
    #12 void std::_Destroy_aux<false>::__destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:163 (LabSoundExample+0x45a30)
    #13 void std::_Destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:196 (LabSoundExample+0x45a30)
    #14 void std::_Destroy<std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*, std::allocator<std::shared_ptr<lab::AudioNode> >&) /usr/include/c++/13/bits/alloc_traits.h:947 (LabSoundExample+0x45a30)
    #15 std::vector<std::shared_ptr<lab::AudioNode>, std::allocator<std::shared_ptr<lab::AudioNode> > >::~vector() /usr/include/c++/13/bits/stl_vector.h:732 (LabSoundExample+0x45a30)
    #16 labsound_example::~labsound_example() LabSound/examples/src/ExamplesCommon.h:85 (LabSoundExample+0x45a30)
    #17 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #18 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7)
    #19 main LabSound/examples/src/ExamplesMain.cpp:75 (LabSoundExample+0x3b26b) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (LabSoundExample+0x87fca) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::mutex::lock() /usr/include/c++/13/bits/std_mutex.h:113 (LabSoundExample+0x87fca)
    #3 lab::ContextRenderLock::ContextRenderLock(lab::AudioContext*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) LabSound/include/LabSound/extended/AudioContextLock.h:70 (LabSoundExample+0x87fca)
    #4 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:41 (LabSoundExample+0x87fca)
    #5 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Thread T2 (tid=21832, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9304 (LabSoundExample+0x1708fb) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:387 (LabSoundExample+0x1694ef) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:292 (LabSoundExample+0x1698a3) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:175 (LabSoundExample+0x162206) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:196 (LabSoundExample+0x1628e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 main LabSound/examples/src/ExamplesMain.cpp:29 (LabSoundExample+0x3a426) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

SUMMARY: ThreadSanitizer: heap-use-after-free /usr/include/c++/13/bits/stl_vector.h:1258 in std::vector<float, std::allocator<float> >::data()
==================
==================
WARNING: ThreadSanitizer: heap-use-after-free (pid=21829)
  Read of size 8 at 0x7b2800000558 by thread T2 (mutexes: write M0):
    #0 std::vector<float, std::allocator<float> >::size() const /usr/include/c++/13/bits/stl_vector.h:990 (LabSoundExample+0xcf4cd) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #1 lab::WaveShaperNode::processCurve(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:75 (LabSoundExample+0xcf4cd)
    #2 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:134 (LabSoundExample+0xcfb10) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:188 (LabSoundExample+0xd0791) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:547 (LabSoundExample+0x8cda6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0x96d0c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0x95ba6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:71 (LabSoundExample+0x882a0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #10 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #11 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #12 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Previous write of size 8 at 0x7b2800000558 by main thread:
    #0 operator delete(void*, unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:150 (libtsan.so.2+0x886d6) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 std::__new_allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::deallocate(std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/include/c++/13/bits/new_allocator.h:168 (LabSoundExample+0x412ce) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::deallocate(std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&, std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/include/c++/13/bits/alloc_traits.h:516 (LabSoundExample+0x412ce)
    #3 std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::~__allocated_ptr() /usr/include/c++/13/bits/allocated_ptr.h:74 (LabSoundExample+0x412ce)
    #4 std::_Sp_counted_ptr_inplace<lab::WaveShaperNode, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_destroy() /usr/include/c++/13/bits/shared_ptr_base.h:623 (LabSoundExample+0x412ce)
    #5 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:191 (LabSoundExample+0x45a30) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release_last_use() /usr/include/c++/13/bits/shared_ptr_base.h:172 (LabSoundExample+0x45a30)
    #7 std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c++/13/bits/shared_ptr_base.h:361 (LabSoundExample+0x45a30)
    #8 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c++/13/bits/shared_ptr_base.h:1071 (LabSoundExample+0x45a30)
    #9 std::__shared_ptr<lab::AudioNode, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c++/13/bits/shared_ptr_base.h:1524 (LabSoundExample+0x45a30)
    #10 std::shared_ptr<lab::AudioNode>::~shared_ptr() /usr/include/c++/13/bits/shared_ptr.h:175 (LabSoundExample+0x45a30)
    #11 void std::_Destroy<std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:151 (LabSoundExample+0x45a30)
    #12 void std::_Destroy_aux<false>::__destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:163 (LabSoundExample+0x45a30)
    #13 void std::_Destroy<std::shared_ptr<lab::AudioNode>*>(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*) /usr/include/c++/13/bits/stl_construct.h:196 (LabSoundExample+0x45a30)
    #14 void std::_Destroy<std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode> >(std::shared_ptr<lab::AudioNode>*, std::shared_ptr<lab::AudioNode>*, std::allocator<std::shared_ptr<lab::AudioNode> >&) /usr/include/c++/13/bits/alloc_traits.h:947 (LabSoundExample+0x45a30)
    #15 std::vector<std::shared_ptr<lab::AudioNode>, std::allocator<std::shared_ptr<lab::AudioNode> > >::~vector() /usr/include/c++/13/bits/stl_vector.h:732 (LabSoundExample+0x45a30)
    #16 labsound_example::~labsound_example() LabSound/examples/src/ExamplesCommon.h:85 (LabSoundExample+0x45a30)
    #17 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #18 ex_waveshaper::~ex_waveshaper() LabSound/examples/src/Examples.hpp:1686 (LabSoundExample+0x45bf7)
    #19 main LabSound/examples/src/ExamplesMain.cpp:75 (LabSoundExample+0x3b26b) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Mutex M0 (0x7b50000004b0) created at:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4481 (libtsan.so.2+0x4ea9f) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/13/bits/gthr-default.h:749 (LabSoundExample+0x87fca) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 std::mutex::lock() /usr/include/c++/13/bits/std_mutex.h:113 (LabSoundExample+0x87fca)
    #3 lab::ContextRenderLock::ContextRenderLock(lab::AudioContext*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) LabSound/include/LabSound/extended/AudioContextLock.h:70 (LabSoundExample+0x87fca)
    #4 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:41 (LabSoundExample+0x87fca)
    #5 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

  Thread T2 (tid=21832, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1036 (libtsan.so.2+0x3d179) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #1 RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*) LabSound/src/backends/RtAudio/RtAudio.cpp:9304 (LabSoundExample+0x1708fb) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 RtApi::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:387 (LabSoundExample+0x1694ef) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 RtAudio::openStream(RtAudio::StreamParameters*, RtAudio::StreamParameters*, unsigned long, unsigned int, unsigned int*, int (*)(void*, void*, unsigned int, double, unsigned int, void*), void*, RtAudio::StreamOptions*, void (*)(RtAudioError::Type, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) LabSound/src/backends/RtAudio/RtAudio.cpp:292 (LabSoundExample+0x1698a3) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioDevice_RtAudio::createContext() LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:175 (LabSoundExample+0x162206) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioDevice_RtAudio::AudioDevice_RtAudio(lab::AudioStreamConfig const&, lab::AudioStreamConfig const&) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:196 (LabSoundExample+0x1628e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 main LabSound/examples/src/ExamplesMain.cpp:29 (LabSoundExample+0x3a426) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)

SUMMARY: ThreadSanitizer: heap-use-after-free /usr/include/c++/13/bits/stl_vector.h:990 in std::vector<float, std::allocator<float> >::size() const
==================
ThreadSanitizer:DEADLYSIGNAL
==21829==ERROR: ThreadSanitizer: SEGV on unknown address 0x7f54b282d0ec (pc 0x55e0a052654d bp 0x00000000ac43 sp 0x7f54c53fdfe0 T21832)
==21829==The signal is caused by a READ memory access.
    #0 lab::WaveShaperNode::processCurve(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:97 (LabSoundExample+0xcf54d) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #1 lab::WaveShaperNode::processCurve4x(float const*, float*, int) LabSound/src/core/WaveShaperNode.cpp:134 (LabSoundExample+0xcfb10) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #2 lab::WaveShaperNode::process(lab::ContextRenderLock&, int) LabSound/src/core/WaveShaperNode.cpp:188 (LabSoundExample+0xd0791) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #3 lab::AudioNode::processIfNecessary(lab::ContextRenderLock&, int) LabSound/src/core/AudioNode.cpp:547 (LabSoundExample+0x8cda6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #4 lab::AudioNodeOutput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeOutput.cpp:122 (LabSoundExample+0x96d0c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #5 lab::AudioNodeInput::pull(lab::ContextRenderLock&, lab::AudioBus*, int) LabSound/src/core/AudioNodeInput.cpp:153 (LabSoundExample+0x95ba6) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #6 lab::pull_graph(lab::AudioContext*, lab::AudioNodeInput*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&, lab::AudioSourceProvider*) LabSound/src/core/AudioDevice.cpp:71 (LabSoundExample+0x882a0) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #7 lab::AudioDestinationNode::render(lab::AudioSourceProvider*, lab::AudioBus*, lab::AudioBus*, int, lab::SamplingInfo const&) LabSound/src/core/AudioDevice.cpp:131 (LabSoundExample+0x885e2) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #8 lab::AudioDevice_RtAudio::render(lab::AudioSourceProvider*, int, void*, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:331 (LabSoundExample+0x161951) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #9 lab::rt_audio_callback(void*, void*, unsigned int, double, unsigned int, void*) LabSound/src/backends/RtAudio/AudioDevice_RtAudio.cpp:32 (LabSoundExample+0x161c9c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #10 RtApiPulse::callbackEvent() LabSound/src/backends/RtAudio/RtAudio.cpp:8886 (LabSoundExample+0x16cdac) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #11 pulseaudio_callback LabSound/src/backends/RtAudio/RtAudio.cpp:8815 (LabSoundExample+0x16da2c) (BuildId: 22b165cfb8a4c940174fe156aad98fe5140a40f0)
    #12 __tsan_thread_start_func ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1026 (libtsan.so.2+0x373e9) (BuildId: 5e847b809f54bed9069b4ad5e6285626c3e4f0ef)
    #13 start_thread /build/glibc-BHL3KM/glibc-2.31/nptl/pthread_create.c:477 (libpthread.so.0+0x8608) (BuildId: f5b7b9b3efe01ef7aec691dc8f4e272c518f8cdf)
    #14 __clone <null> (libc.so.6+0x11f132) (BuildId: e678fe54a5d2c2092f8e47eb0b33105e380f7340)

ThreadSanitizer can not provide additional info.
SUMMARY: ThreadSanitizer: SEGV LabSound/src/core/WaveShaperNode.cpp:97 in lab::WaveShaperNode::processCurve(float const*, float*, int)
==21829==ABORTING

As far as I can tell, this would explain the crashes at the end (but not the dropped audio, which warrants further investigation).

Deleting running nodes should Just Work

What should a proper fix look like? I mean one that works for every case, not the "hack". Can they just be stopped/disconnected?

from labsound.

meshula avatar meshula commented on June 5, 2024

Stopped/disconnected should fix it yes.

Looking at it more deeply:

Every AudioNode has the structural pattern:

public interfaces
    get/set connect/disconnect
data for processing

The public interfaces have to live as long as the C++ object the developer is holding onto in their code
The data for processing has to live as long as the last audio buffer relying on it

Trying to synchronize those lifespans is how I've been trying to solve concurrency.

The fundamental problem is that the public interfaces are conflated with the data for processing. In other words, one can set a value, but processing has to reach into the Param or Setting to get the value.

I think what has to happen, structurally, across the board, is that the public interfaces need to queue operations to the processor, and the data for processing should be separably held, presumably in an object held by a shared pointer, so that the data itself is deleted when processing is over, and there is not synchronization required with the holding Node object.

from labsound.

phildremi avatar phildremi commented on June 5, 2024

That sounds like a major rework, so unfortunately a bit above what I would be able to contribute with my limited knowledge. If you want to sketch out a prototype/demo I can probably get a better understanding of the challenges involved, but no problem if there isn't time. I'm investigating the "dropped audio" bug, which I suspect could be related to this issue, based on my observations:

  • The TSAN logs display the exact same warning right before a dropout happens
  • As far as I understand, PulseAudio failing to send/receive would explain why there's no audio whatsoever
  • ... as well as why I can't seem to reproduce it on Windows (MSVC), PulseAudio not being a thing here

I still want to do more testing, especially on macOS, to see if it's happening there. But maybe I'm on the wrong path completely.

from labsound.

meshula avatar meshula commented on June 5, 2024

tsan is looking clean on mac, at least :)

Interesting note on pulse from the SDL report.

from labsound.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.