# Processing Audio: Sample by Sample or Buffer by Buffer?

**URL:** <https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306>\
**Category:** General JUCE discussion\
**Created:** [March 12, 2017, 10:42am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306 "2017-03-12T10:42:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![fefanto](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/fefanto/32/1518_2.png) [@fefanto](https://forum.juce.com/u/fefanto)\
**Post date:** [March 12, 2017, 10:42am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/1 "2017-03-12T10:42:09Z")

</div>

Good Sunday Jucers!

I am refactoring my audio engine, and I am in the process of deciding whether to favour sample by sample processing vs. whole buffer processing, and/or if have an hybrid approach between the two.  
i.e  
`inline float output = myEngineBlock->audio(float input)`  
vs  
`myEngineBlock->processChannel(float* buffer, long bufferSize)`

Below a list of the pros of the two approaches coming off the top of my head: what I would like to do here is to start a discussion to clarify whether some of my points are totally wrong or of little importance, or if I am totally missing other important aspects of the conversation. _Please please_ send me any of your 2 cents (or your million dollar 🙂 ).

### Sample By Sample approach

- Parameter modulation come out easier and better, since internal parameters are re-evaluated every sample
- With this approach you give more room for optimisation to the compiler and CPU cache (this is totally empiric , but I suspect there’s a reason why for example the guys at Cycling74 came out with gen~ working on a sample by sample basis )

### Buffer by Buffer approach

- Enables using optimised operations (FloatVectorOperations, IPP etc) for simpler interconnecting stuff (e.g. mixing output of two internal processing blocks)
- Makes “Block Switching” easier, since _if_ conditions or virtual function calls can be acceptable on a buffer by buffer basis (not so much on a sample by sample basis)

Thanks for reading!  
Michelangelo

---

<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:** [March 12, 2017, 3:43pm UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/2 "2017-03-12T15:43:06Z")

</div>

I just refactored my plugin a few weeks ago from sample based to buffer based and wow, what a performance difference! For me, I saw a 285% performance gain. That was all I needed to see.

---

<div class="post-metadata">

**Author:** ![pmbk](https://avatars.discourse-cdn.com/v4/letter/p/dec6dc/32.png) [@pmbk](https://forum.juce.com/u/pmbk)\
**Post date:** [March 13, 2017, 8:36pm UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/3 "2017-03-13T20:36:55Z")

</div>

With Max, the reason has more to do with simplicity for the user. It’s much simpler to write sample-by-sample code if you are newer to writing DSP code, which many gen~ users are.

The rest of the audio engine for Max is definitely block-based and that’s unlikely to change any time soon, for the same efficiency reasons as noted above. There was an interesting talk at ADC by Ian Hobbs that is worth a look. He showed a very different way of doing single-sample processing through variadic templating.

---

<div class="post-metadata">

**Author:** ![jonathonracz](https://avatars.discourse-cdn.com/v4/letter/j/da6949/32.png) [@jonathonracz](https://forum.juce.com/u/jonathonracz)\
**Post date:** [March 13, 2017, 10:48pm UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/4 "2017-03-13T22:48:09Z")

</div>

ALWAYS use buffer by buffer for JUCE’s `AudioBuffer<>` classes (unless you don’t care about performance). If your data is interleaved (which is common in image processing) then ALWAYS use sample by sample.

[Why? Spacial locality.](https://en.wikipedia.org/wiki/Locality_of_reference)

tl;dr The CPU can process elements way faster when they’re being processed in a straight line (in simple terms) vs hopping all over in memory.

---

<div class="post-metadata">

**Author:** ![fefanto](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/fefanto/32/1518_2.png) [@fefanto](https://forum.juce.com/u/fefanto)\
**Post date:** [March 14, 2017, 7:22am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/5 "2017-03-14T07:22:20Z")

</div>

Thanks for all the answers! I see just a tiny tiny preference for buffer by buffer approach 🙂  
In this case though, how do You manage a smooth parameter modulation, since all internal block parameters get dereferenced only once per buffer?

P.S  
One doubt I have (take a look at the code below): If all the tick() methods are “forced inline” then the approach below is apparently “sample by sample”, but there is no difference from “buffer by buffer” , since all the code is inlined in a big “buffer by buffer” block working on the root AudioSampleBuffer.  
Do you think this assumption is correct? If so, then the approach below is far cleaner and flexible in my opinion, as long as one does not allocate/deallocate, lock etc. inside the blocks.

`processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)`  
`{`  
`int frames = buffer.getNumSamples();`  
`float* pL = buffer.getWritePointer(0);`  
`float valueIn = 0.0f, valueOut=0.0f;`  
``  
`while (frames—)`  
`{`  
`valueIn = *pL;`  
`valueOut = myBlock1->tick(valueIn);// all tick() are forcedinline`  
`valueOut = myBlock1->tick(valueOut);`  
`// some more blocks`  
`valueOut = myBlockN->tick(valueOut);`  
`*pL++ = valueOut;`  
`}`  
`}`

Thanks again!!

---

<div class="post-metadata">

**Author:** ![chrisboy2000](https://avatars.discourse-cdn.com/v4/letter/c/a3d4f5/32.png) [@chrisboy2000](https://forum.juce.com/u/chrisboy2000)\
**Post date:** [March 14, 2017, 8:57am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/6 "2017-03-14T08:57:19Z")

</div>

But if you are jumping around the blocks in the most inner loop you may loose the “spacial locality” that Jonathan described.

---

<div class="post-metadata">

**Author:** ![chrisboy2000](https://avatars.discourse-cdn.com/v4/letter/c/a3d4f5/32.png) [@chrisboy2000](https://forum.juce.com/u/chrisboy2000)\
**Post date:** [March 14, 2017, 8:59am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/7 "2017-03-14T08:59:37Z")

</div>

Also if tick() is a virtual method (which is most likely the case unless you do variadic template stuff), the performance overhead for the vtable is not trivial.

---

<div class="post-metadata">

**Author:** ![fefanto](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/fefanto/32/1518_2.png) [@fefanto](https://forum.juce.com/u/fefanto)\
**Post date:** [March 14, 2017, 9:13am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/8 "2017-03-14T09:13:31Z")

</div>

Ok - I’m starting to get the spacial locality thing - I wonder if there’s a profiler feature or data aggregation in Xcode or visual studio that lets you check how bad is your code in that respect.

As for the virtual table topic, My assumption is that a dsp block that needs to process a single sample has a _float tick(float)_ method (or _float tick(void)_ for synths) that is not virtual and is inlined , following the STK coding style ([https://ccrma.stanford.edu/software/stk/](https://ccrma.stanford.edu/software/stk/))

---

<div class="post-metadata">

**Author:** ![chrisboy2000](https://avatars.discourse-cdn.com/v4/letter/c/a3d4f5/32.png) [@chrisboy2000](https://forum.juce.com/u/chrisboy2000)\
**Post date:** [March 15, 2017, 9:10am UTC](https://forum.juce.com/t/processing-audio-sample-by-sample-or-buffer-by-buffer/21306/9 "2017-03-15T09:10:52Z")

</div>

Last time I checked, STK does use a virtual tick() - the tick() in eg. stk::filter is virtual and the subclasses override it (they just don’t specify the override keyword).

I think this is why there are also block based methods in stk and the single tick() is left in there if performance is not an issue.

If its not virtual, you can’t use polymorphism which is key to write a generic engine unless you do the magical stuff Ian was presenting at ADC.
