# AudioBuffer\<\> and its clear flag

**URL:** <https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190>\
**Category:** General JUCE discussion\
**Created:** [June 18, 2020, 6:00am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190 "2020-06-18T06:00:30Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 13, 2021, 10:27am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/42 "2021-08-13T10:27:02Z")

</div>

> [@daniel](#):
>
> My hunch is with @jrlanglois that it doesn’t play a role, since it is per block level, so it will likely be called once in a virtual function (e.g. processBlock()), so the optimisers options are already limited.

How many times you call it really depends on context.  
For example, if you have a synth with 64 voices, each calling a chain of processors and not a single function, you’ll interact with that atomic quite a lot.

That atomic is accessed in every single AudioBuffer function, like `applyGain()`, `getArrayOfWritePointers()`, `addFrom()`, etc. And even functions that are meant to be called per sample like `setSample()`.

I agree that in many cases the impact on your speed would be minimal, but there are other cases I ran into, like a long chain of nested processes, where it’s not.

---

<div class="post-metadata">

**Author:** ![kamedin](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kamedin/32/11711_2.png) [@kamedin](https://forum.juce.com/u/kamedin)\
**Post date:** [August 13, 2021, 10:28am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/43 "2021-08-13T10:28:12Z")

</div>

> [@daniel](#):
>
> My hunch is with @jrlanglois that it doesn’t play a role, since it is per block level, so it will likely be called once in a virtual function (e.g. processBlock()), so the optimisers options are already limited.

That’s ok if you just use the buffer to take pointers, otherwise the flag is loaded and stored everywhere: in applyGain[Ramp], in add/setSample, in addFrom, copyFrom, findMindMax, getMagnitude… pretty much everywhere. I don’t think it’s fair to dismiss this with a generic “go profile and come back” -the impact would be completely different for each case. The question is whether the atomic is necessary or not.

---

<div class="post-metadata">

**Author:** ![chkn](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/chkn/32/3862_2.png) [@chkn](https://forum.juce.com/u/chkn)\
**Post date:** [August 13, 2021, 10:28am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/44 "2021-08-13T10:28:43Z")

</div>

I know (I have also written above), but this was not I was after 😉

---

<div class="post-metadata">

**Author:** ![juan1979](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@juan1979](https://forum.juce.com/u/juan1979)\
**Post date:** [August 13, 2021, 10:31am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/45 "2021-08-13T10:31:35Z")

</div>

If you write in different T\*\* positions from different threads, there shouldn’t be any problems (but there will if you write in the same positions!). The only thing they have in common is the isClear flag, that’s the reason it’s atomic I think

However I don’t see many of us writting in this from multiple threads, that why I’m using an AudioBuffer copy named LightAudioBuffer, replacing its atomic flag by a normal boolean. But this would be better if I could specify with a template parameter if I want an atomic flag or an simple bool.

The same with ValueTree… but its another story. I would prefer it uses [SingleThreadedReferenceCountedObject](https://docs.juce.com/master/classSingleThreadedReferenceCountedObject.html) instead [ReferenceCountedObject](https://docs.juce.com/master/classReferenceCountedObject.html), but that’s another story

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 13, 2021, 10:47am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/46 "2021-08-13T10:47:20Z")

</div>

> [@juan1979](#):
>
> If you write in different T\*\* positions from different threads, there shouldn’t be any problems (but there will if you write in the same positions!).

If you do that, and pass a reference to that AudioBuffer to different threads, you’ll run into more complicated data races with that atomic. I don’t think it solves that problem. The only problem it solves is TSAN getting angry at you for sharing AudioBuffers, and it was angry for a good reason!

> [@juan1979](#):
>
> But this would be better if I could specify with a template parameter if I want an atomic flag or a simple bool.

Template parameter implies that’s a feature you’d want. I think it’s not a feature you should ever want. Instead, you should use a better mechanism to share AudioBuffers, like FIFOs, or passing a T\*\* when you know you’ll write to different sections, etc.

> [@juan1979](#):
>
> The same with ValueTree… but its another story. I would prefer it uses [SingleThreadedReferenceCountedObject](https://docs.juce.com/master/classSingleThreadedReferenceCountedObject.html) instead [ReferenceCountedObject](https://docs.juce.com/master/classReferenceCountedObject.html), but that’s another story

Not sure I understand you correctly, but I agree with you that limiting ValueTree to access from the message thread only, by default, would be great and eliminate a bunch of bugs.

---

<div class="post-metadata">

**Author:** ![kamedin](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kamedin/32/11711_2.png) [@kamedin](https://forum.juce.com/u/kamedin)\
**Post date:** [August 13, 2021, 10:48am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/47 "2021-08-13T10:48:50Z")

</div>

btw, the previous commit may provide some context

> <https://github.com/juce-framework/JUCE/commit/fb5cfcd60611cd0d9c7e885e749880189d87a481>

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 13, 2021, 10:50am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/48 "2021-08-13T10:50:55Z")

</div>

> [@kamedin](#):
>
> btw, the previous commit may provide some context

Yeah, that’s what I suspected. TSan got angry at this example for a good reason. I think it would have been better to rewrite the example and use proper syncing instead of locking + touching all kinds of shared state from different threads.

---

<div class="post-metadata">

**Author:** ![juan1979](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@juan1979](https://forum.juce.com/u/juan1979)\
**Post date:** [August 13, 2021, 10:54am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/49 "2021-08-13T10:54:15Z")

</div>

I understand you. I would never share an AudioBuffer betweens threads. But that atomic is there for that reason. That’s why I would replace it with a simple bool. But my guess is that someone are filling the different channels from different threads (ie, from track1 thread → channel 0,1 / from track 2 thread → channel 2,3… and so on).

ValueTree uses a ReferenceCountedObject, which increases a decreases an atomic value. If the purpose of the ValueTree is being used in the Message thread, I don’t see why should we have an atomic there. Using the light version of SingleThreadedReferenceCountedObject should increase performance without sacrifying anything. I’m not sure if ValueTree continue using an atomic - I’ll check

---

<div class="post-metadata">

**Author:** ![kamedin](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kamedin/32/11711_2.png) [@kamedin](https://forum.juce.com/u/kamedin)\
**Post date:** [August 13, 2021, 10:55am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/50 "2021-08-13T10:55:43Z")

</div>

It may be that some usage pattern of ResamplingAudioSource involves this -I wouldn’t know, never used that class.

---

<div class="post-metadata">

**Author:** ![juan1979](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@juan1979](https://forum.juce.com/u/juan1979)\
**Post date:** [August 13, 2021, 10:59am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/51 "2021-08-13T10:59:50Z")

</div>

I confirm ValueTree continues using atomic (cst!) operations too:

`class ValueTree::SharedObject : public ReferenceCountedObject`

My proposal would be this one:

`class ValueTree::SharedObject : public SingleThreadedReferenceCountedObject`

(sorry by the offtopic on my own thread)

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 13, 2021, 11:02am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/52 "2021-08-13T11:02:35Z")

</div>

> [@juan1979](#):
>
> But my guess is that someone are filling the different channels from different threads (ie, from track1 thread → channel 0,1 / from track 2 thread → channel 2,3… and so on).

Yeah, so if I was that person, I think I’d make it clear that in this case you have to pass the internal T\*\* and manage the chunks at your own risk, as calling high level AudioBuffer functions will create data races even with the atomic…  
Imagine this:

```auto
//Thread 1:
    void setSample (int destChannel, int destSample, Type newValue) noexcept
    {
        *(channels[destChannel] + destSample) = newValue;
        //Thread 2 calls clear() here, thinking it's already clear, does nothing instead
        isClear = false;
        //Buffer will never be cleared unless we add yet another explicit call to clear()
    }

```

> [@juan1979](#):
>
> If the purpose of the ValueTree is being used in the Message thread, I don’t see why should we have an atomic there

That’s true, but this is also not meant to be used for anything performance related, and it’s possible I might pass the refcount to a different thread as a messaging system for example. So I can see the use cases for an atomic (where I can’t with AudioBuffer).

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [August 13, 2021, 12:07pm UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/53 "2021-08-13T12:07:58Z")

</div>

N.B. a very simple workaround: Use dsp::AudioBlock.  
It will once call getArrayOfWritePointers().  
After that no isClear contention at all…

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 13, 2021, 12:21pm UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/54 "2021-08-13T12:21:26Z")

</div>

Yes, I agree that using something like AudioBlock that just wraps the direct T\*\* for all future calls will indeed be much faster and will solve the problem for a local function.

But unfortunately there’s so much existing code in the library that already uses AudioBuffer, which that atomic is a negative impact on.

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [August 16, 2021, 5:09pm UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/55 "2021-08-16T17:09:28Z")

</div>

Apologies for taking a while to respond to this, I wanted to get the rest of the team’s input before making any changes.

The original forum thread that lead to this change was here:

> [@Thread Sanitizer detects a data race in AudioThumbnail](https://forum.juce.com/t/thread-sanitizer-detects-a-data-race-in-audiothumbnail/32470):
>
> In latest develop (c96bf71488a), running the JUCE demo’s audio player demo with Thread Sanitizer (“Xcode/Edit Scheme/Run/Diagnostics/Thread Sanitizer”), when opening an audio file - A data race is detected at AudioThumbnail::setLevels where it updates totalSamples. (my env: Xcode 10.1, macOS 10.14.3) This may be benign (am not familiar with the code) but I think that it’s good practice to either solve the race or mark it as benign, so people could use the invaluable Thread Sanitizer without t…

and the “fix” that I pushed was to make the `AudioBuffer::isClear` flag atomic which silenced tsan but clearly had some unintended side effects.

Given that `AudioBuffer` makes no guarantees about thread safety and contains no other synchronisation I don’t think it should be the responsibility of the class to be thread safe. Making `isClear` atomic also doesn’t make it thread safe since some higher level synchronisation would be required to actually guard the clearing and filling of the audio data, it just makes tsan happy.

I’ve reverted that change and made `isClear` a plain old `bool` here:

> <https://github.com/juce-framework/JUCE/commit/832deb9ad7dcf4f44858233b2a3d4f05a69f4d18>

and I’ve pushed a fix for the actual problem in `BufferingAudioSource` here:

> <https://github.com/juce-framework/JUCE/commit/80602649a2d3c86de7e85b335f7b6290700c4bc0>

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [August 16, 2021, 7:22pm UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/56 "2021-08-16T19:22:57Z")

</div>

Thank you so much for fixing it @ed95!

---

<div class="post-metadata">

**Author:** ![juan1979](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@juan1979](https://forum.juce.com/u/juan1979)\
**Post date:** [August 17, 2021, 9:37pm UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/57 "2021-08-17T21:37:10Z")

</div>

Thanks, much better, I will use it as soon it appears on a stable Juce version

---

<div class="post-metadata">

**Author:** ![pizzafilms](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pizzafilms/32/562_2.png) [@pizzafilms](https://forum.juce.com/u/pizzafilms)\
**Post date:** [August 18, 2021, 6:17am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/58 "2021-08-18T06:17:38Z")

</div>

My issue remains. If the name of the function is `clear()`, then it should just clear…and not depend on the state some of some flag that’s not documented. This function currently assumes that the programmer is using `setSample()` or similar. What if someone isn’t using `setSample()` and instead is getting writePointers and using them (very common), and wants to clear the buffer? It doesn’t work because of this flag.

I’d even venture to say more programmers use `getWritePointer()` and access samples that way rather than `setSample()`, but I could be wrong.

Maybe add a `clear(bool force = false)` so it can overlook the flag?

At the very least, add something to the documentation. I know I’ve spent more than a few minutes several times wondering why a damn buffer wouldn’t clear.

---

<div class="post-metadata">

**Author:** ![juan1979](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@juan1979](https://forum.juce.com/u/juan1979)\
**Post date:** [August 18, 2021, 6:38am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/59 "2021-08-18T06:38:23Z")

</div>

Well, when I stated the problem I wasn’t using the `setSample()` at all. Instead I was taking sections from the buffer using `getWritePointer` and `getArrayOfWritePointers()` and wrapping them inside an AudioBlock or writting directly in it. But takings hundreds of sections from dozens of `AudioBuffer` was expensive.

And to be honest, I didn’t understand your problem, could you explain it further? When you take an audio section using `getWritePointer()`, the flag automatically becomes true, even if you don’t write nothing. So as soon as you call `clear()`, the flag will set off, and the buffer will be actually cleared.

---

<div class="post-metadata">

**Author:** ![pizzafilms](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pizzafilms/32/562_2.png) [@pizzafilms](https://forum.juce.com/u/pizzafilms)\
**Post date:** [August 18, 2021, 7:17am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/60 "2021-08-18T07:17:31Z")

</div>

But if you only get the write pointer in prepareToPlay() and not every processBlock(), the flag was only set that one time and not on subsequent calls.

This flag makes an assumption on how the buffer is used, but it’s an odd assumption and again…it’s not documented.

To me, it’s fairly normal to create a buffer, resize it and get the writePointers only during prepareToPlay() and keep the pointers for use in processBlock(). They haven’t changed (except in prepareToPlay) so why get them again? And who knows when I may want to clear a buffer? That’s up to me.

HeapBlock::clear() doesn’t check a flag. Nor does FloatVectorOperations::clear(), or MidiBuffer::clear().

Again, if it’s called `clear()`, it should just clear and not check anything.

---

<div class="post-metadata">

**Author:** ![pizzafilms](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pizzafilms/32/562_2.png) [@pizzafilms](https://forum.juce.com/u/pizzafilms)\
**Post date:** [August 18, 2021, 7:21am UTC](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190/61 "2021-08-18T07:21:49Z")

</div>

Let me rephrase that…

clear() makes an assumption that the buffer is _dirty_, but there are other ways for the buffer to actually be dirty that the flag misses.

[Previous page](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190.md?page=2)

[Next page](https://forum.juce.com/t/audiobuffer-and-its-clear-flag/40190.md?page=4)
