# findMinMax may have a bug?

**URL:** <https://forum.juce.com/t/findminmax-may-have-a-bug/40816>\
**Category:** General JUCE discussion\
**Created:** [July 20, 2020, 2:53pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816 "2020-07-20T14:53:56Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jerryuhoo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jerryuhoo/32/8844_2.png) [@Jerryuhoo](https://forum.juce.com/u/Jerryuhoo)\
**Post date:** [July 20, 2020, 2:53pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/1 "2020-07-20T14:53:56Z")

</div>

I wrote this code to calculate the magnitude of samples in buffer.

```auto
Range<float> range;
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
    for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
    {
        range = buffer.findMinMax(channel, 0, buffer.getNumSamples());
    }
    float magnitude = range.getLength() / 2.f;
}

```

I wrote that cuz I didn’t know there’s a function “getMagnitude”

```auto
sampleMaxValue = buffer.getMagnitude (0, buffer.getNumSamples());

```

So I believe this works the same as the first one and it is easier to use. But I found the first method “findMinMax” sometimes returns the magnitude = 0 even the buffer has non-zero values. I haven’t tested if it is a findMinMax() bug or getLength() bug, or maybe I did something wrong with my code.

I use MacOS Catalina 10.15.5 and Xcode 11.6. I tested this in Fl Studio.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [July 20, 2020, 4:50pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/2 "2020-07-20T16:50:23Z")

</div>

Whilst it’s certainly possible that findMinMax has a bug, the internals of it haven’t changed for a very long time and we haven’t had any other big reports.

Would it be possible to get the contents of a buffer where it’s not doing what you expect it to?

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [July 20, 2020, 5:00pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/3 "2020-07-20T17:00:58Z")

</div>

Could it be that the isClear flag is set for those buffers? From another thread, doing something like the following (getting the write pointer _before_ calling clear()), causes the isClear flag to remain set, even after changing data in the buffer:

```
auto buf = buffer.getWritePointer (0);
buffer.clear();
buf[0] = 1.f;

```

When that flag is set, findMinMax will return the range 0…0.

---

<div class="post-metadata">

**Author:** ![Jerryuhoo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jerryuhoo/32/8844_2.png) [@Jerryuhoo](https://forum.juce.com/u/Jerryuhoo)\
**Post date:** [July 21, 2020, 3:28am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/4 "2020-07-21T03:28:04Z")

</div>

I took some screenshots yesterday.  
The input was a continuous sin wave.  
This was the code I wrote originally

 ![image](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/d/d861472e516e53709af6f55239ab16ba531595cc.jpeg)  
And these were buffer values I printed when the magnitude returned 0.  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/7/736f736ee6ba8da743c472c2f41a10822dd049de.png)  
And these were magnitude (sampleMaxValue) I printed for each buffer. They were normal (around 0.23) most time, but sometimes (maybe 1%) returned 0.  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/8/80cd6d7b7e555df9860c3ba5a27d62c3c942a7a9.png)

By the way, after I changed to getMagnitude instead of findMinMax, it always returned non-zero values, which was correct.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [July 21, 2020, 6:59am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/5 "2020-07-21T06:59:57Z")

</div>

Would it be possible to narrow it down a little further? When sampleMaxType is zero could you print the number of channels in the butter, the number of samples in each channel, and the value of all the samples in each channel?

Ideally we would have a case where we could feed a single, prefilled, buffer to findMinMax and see it produce a zero.

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [July 21, 2020, 7:03am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/6 "2020-07-21T07:03:00Z")

</div>

Also you can paste code and output snippets into this forum if you surround the snippets with three backticks and it’ll be formatted nicely, so you don’t need to screenshot. This makes it searchable if anyone else if having the same problem.

```  
Paste your code here  
```

---

<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:** [July 21, 2020, 12:16pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/7 "2020-07-21T12:16:44Z")

</div>

The isClear flag is no concern here, since it is checked in findMinMax and 0 is returned if it is true.

The difference is, because two definitions of magnitude are mixed here.  
In JUCE magnitude is Us but the OP uses Uss/2 (Peak vs. Peak to peak halved)

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [July 21, 2020, 1:51pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/8 "2020-07-21T13:51:20Z")

</div>

> [@daniel](#):
>
> The isClear flag is no concern here, since it is checked in findMinMax and 0 is returned if it is true.

Huh? I was responding to this:

> But I found the first method “findMinMax” sometimes returns the magnitude = 0 even the buffer has non-zero values.

The code referenced (his first example, using findMinMax) gets the range from findMinMax, which would be 0…0 if isClear is set. This would cause his call to get the magnitude to return 0. How can that not be relevant? It’s exactly what he said was happening!

---

<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:** [July 21, 2020, 4:18pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/9 "2020-07-21T16:18:46Z")

</div>

Apologies, somehow I read the problem the other way round.

---

<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:** [July 21, 2020, 5:43pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/10 "2020-07-21T17:43:45Z")

</div>

Nevertheless the more likely explanation that I pointed out is, that in the OP’s formula a buffer with a DC signal would yield 0, while the juce implementation will yield the value of the DC offset. Especially for buffers of the length for 1 sample, this will always return 0.

Reason for that is a wrong definition of magnitude. (I wonder which one is the correct?)

---

<div class="post-metadata">

**Author:** ![anthony-nicholls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/anthony-nicholls/32/1246_2.png) [@anthony-nicholls](https://forum.juce.com/u/anthony-nicholls)\
**Post date:** [July 24, 2020, 9:53pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/11 "2020-07-24T21:53:38Z")

</div>

As Daniel has pointed out the definition of “magnitude” as determined by the algorithm in the original post is not the same as the one returned by `getMagnitude` from the JUCE AudioBuffer. JUCE returns the “highest absolute sample value”. The original post returns half of the range between the highest and lowest sample values.

Take the last two values printed in the example buffer values after `start=====`. They are both `-0.197144`, the range of these is 0, divided by 2 is still 0, whereas `getMagnitude` will return `0.197144`. Maybe this is the result of buffers with very few values? (DAWs sometimes do this to improve automation accuracy) although @HowardAntares makes a good point too however it’s not clear from the examples why this would only happen occasionally.

As a side note the original post calls `buffer.findMinMax` for the entire buffer, for every sample? the `sample` variable is actually unused in the example (unless I’m missing something?).

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [July 24, 2020, 10:00pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/12 "2020-07-24T22:00:02Z")

</div>

> [@anthony-nicholls](#):
>
> As a side note the original post calls `buffer.findMinMax` for the entire buffer, for every sample?

No, the loop is over the number of channels, not over every sample. We don’t see the rest of the code for actually processing the samples in the post.

But yeah, if the buffer is short enough, that code will just grab a few adjacent values, whose range is not likely to cover the whole range of the audio over a larger time span, and could indeed lead to 0 as the range.

---

<div class="post-metadata">

**Author:** ![anthony-nicholls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/anthony-nicholls/32/1246_2.png) [@anthony-nicholls](https://forum.juce.com/u/anthony-nicholls)\
**Post date:** [July 24, 2020, 10:05pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/13 "2020-07-24T22:05:33Z")

</div>

> [@HowardAntares](#):
>
> No, the loop is over the number of channels, not over every sample. We don’t see the rest of the code for actually processing the samples in the post.

This is the code from the original post, it loops over the channels then inside that it loops over the samples but never does anything with the samples but instead calls `findMinMax` on the entire buffer (for each sample). It doesn’t really change anything in terms of outcome it just means the calculation is being performed for every sample when it only needs to be performed once.

> [@Jerryuhoo](#):
>
> ```auto
> Range<float> range;
> for (int channel = 0; channel < totalNumInputChannels; ++channel)
> {
> for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
> {
> range = buffer.findMinMax(channel, 0, buffer.getNumSamples());
> }
> float magnitude = range.getLength() / 2.f;
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [July 24, 2020, 10:22pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/14 "2020-07-24T22:22:09Z")

</div>

Oh, I guess I didn’t see that code.

---

<div class="post-metadata">

**Author:** ![Jerryuhoo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jerryuhoo/32/8844_2.png) [@Jerryuhoo](https://forum.juce.com/u/Jerryuhoo)\
**Post date:** [August 2, 2020, 2:14am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/15 "2020-08-02T02:14:04Z")

</div>

Hi, thanks for all your replies! Sorry, I was traveling for a week so I didn’t have time to test. This is the code I tested:

```auto
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
    auto* channelData = buffer.getWritePointer(channel);
    for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
    {
        DBG(channelData[sample]);
    }
    Range<float> range = buffer.findMinMax(channel, 0, buffer.getNumSamples());
    float min = range.getStart();
    float max = range.getEnd();
    if (min!=0) {
        DBG("===min max====");
        DBG(min);
        DBG(max);
        DBG("===loop start====");
    }   
}

```

This is the output: (This is only a section of the output data that has problem)

```auto
...
===loop start====
-0.622248
-0.60635
-0.58998
-0.573027
-0.555385
-0.537037
-0.517889
-0.498088
-0.477648
-0.456605
-0.435
-0.412778
-0.390139
-0.367115
-0.343757
-0.320116
-0.296135
-0.272042
-0.247869
-0.223669
-0.199496
-0.175286
-0.151284
-0.127517
-0.104031
-0.080877
-0.0579862
-0.0356034
-0.0137434
0.00755922
0.0282652
0.048454
0.0678927
0.0865863
0.104522
0.121681
0.138155
0.153737
0.168459
0.182336
0.195375
0.20768
0.219081
0.229636
0.239387
0.248364
0.256681
0.264201
0.271
0.277141
0.282666
0.28768
0.292081
0.295946
0.299339
0.302306
0.30493
0.307135
0.308985
0.310536
0.311824
0.312904
0.313723
0.314327
0.314754
0.315026
0.315168
0.315153
0.315005
0.31474
0.314366
0.313879
0.313282
0.312573
0.311748
0.310802
0.309702
0.308483
0.307118
0.305584
0.303863
0.301897
0.29975
0.297374
0.29473
0.29179
0.288474
0.28487
0.280919
0.276568
0.271786
0.266473
0.260744
0.254532
0.247783
0.240468
0.232474
0.223943
0.214811
0.205031
0.194585
0.183355
0.171513
0.159003
0.145798
0.131892
0.117176
0.101843
0.0858595
0.0692168
0.0519275
0.033892
0.0153262
-0.00378603
-0.023431
-0.0435804
-0.0641991
-0.0853688
-0.10686
-0.128668
-0.150758
-0.17309
-0.195732
-0.218456
-0.241246
-0.264057
-0.286843
-0.30966
-0.332291
-0.354712
-0.376877
-0.398737
-0.420336
-0.441481
-0.462143
-0.482278
-0.501843
-0.520868
-0.539191
-0.556785
-0.573613
-0.589636
-0.604874
-0.619203
-0.632601
-0.645039
-0.656488
-0.666955
-0.676361
-0.684689
-0.691922
-0.698042
-0.703045
-0.706897
-0.709592
-0.711121
-0.711482
-0.710657
-0.708662
-0.705499
-0.701173
-0.695692
-0.68903
-0.68125
-0.672362
-0.662384
-0.651338
-0.639188
-0.626041
-0.611918
-0.596847
-0.580862
-0.563919
-0.546167
-0.527634
-0.50836
-0.488385
-0.467662
-0.446377
-0.42456
-0.402261
-0.379527
-0.356306
-0.332812
-0.309079
-0.285159
-0.261106
-0.236859
-0.212656
-0.188527
-0.164522
-0.140695
-0.11698
-0.0936228
-0.070645
-0.0480887
-0.026
-0.004305
0.0167556
0.0371757
0.0569307
0.0759897
0.0944385
0.112056
0.128858
0.144846
0.160014
0.174459
0.187992
0.200657
0.212484
0.223491
===min max====
-0.711482
0.315168
===loop start====
0.233558
0.242771
0.251462
0.25945
0.266698
0.27332
0.27922
0.284487
0.28919
0.293373
0.297129
0.300368
0.303163
0.305574
0.307643
0.30944
===min max====
0.233558
0.30944
===loop start====
0.233697
0.243115
0.251769
0.259687
0.266897
0.27351
0.279411
0.284678
0.289378
0.293554
0.297303
0.300535
0.303323
0.305728
0.30779
0.309581
===min max====
0.233697
0.309581
===loop start====
0.311329
0.312493
0.313265
0.313882
0.31443
0.314824
0.315048
0.315113
0.31504
0.31485
0.314536
0.31411
0.313576
0.312932
0.312162
0.311282
0.310281
0.309145
0.30786
0.306384
0.304763
0.302962
0.300949
0.298699
0.296146
0.293363
0.290297
0.286902
0.283146
0.27894
0.274386
0.269418
0.263983
0.258049
0.251509
0.244492
0.236929
0.228772
0.219992
0.210475
0.200378
0.189639
0.178221
0.166109
0.153191
0.139648
0.125436
0.110535
0.0949499
0.0785737
0.0616132
0.0440419
0.0258632
0.00709764
-0.0123481
-0.0322512
-0.0526184
-0.0734276
-0.0946438
-0.116346
-0.138305
-0.160512
-0.18293
-0.205514
-0.228331
-0.251155
-0.273966
-0.296719
-0.319367
-0.341962
-0.364292
-0.386333
-0.408038
-0.42936
-0.450249
-0.470739
-0.490652
-0.509959
-0.528619
-0.546589
-0.563896
-0.580394
-0.596059
-0.610856
-0.624754
-0.637764
-0.649784
-0.660795
-0.670772
-0.679693
-0.687559
-0.694311
-0.69994
-0.704431
-0.707775
-0.70996
-0.710976
-0.710822
-0.709495
-0.706998
-0.70331
-0.698468
-0.69248
-0.685356
-0.677111
-0.667715
-0.657252
-0.645737
-0.633194
-0.61965
-0.605065
-0.589569
-0.573183
-0.555944
-0.537888
-0.51897
-0.499357
-0.479079
-0.458179
-0.436705
-0.414603
-0.392076
-0.369156
-0.345894
-0.322342
-0.298443
-0.274423
-0.250316
-0.226173
-0.202048
-0.17788
-0.153911
-0.130166
-0.106695
-0.0835477
-0.0606546
-0.0382608
-0.0163813
0.00494916
0.0256909
0.0459231
0.0654127
0.0841643
0.102165
0.119394
0.135943
0.151607
0.166414
0.180379
0.193509
0.205908
0.217404
0.228054
0.2379
0.246972
0.255382
0.262994
0.269882
0.276109
0.281716
0.28681
0.291286
0.295222
0.298682
0.301711
0.304394
0.306653
0.308552
0.31015
0.311479
0.312597
0.313451
0.314086
0.314542
0.314839
0.315004
0.31501
0.314881
0.314633
0.314275
0.313803
0.31322
0.312524
0.311713
0.31078
0.309695
0.30849
0.30714
0.305623
0.30392
0.301975
0.29985
0.297499
0.294882
0.291973
0.28869
===min max====
-0.710976
0.315113
...

```

So from that output I think findMinMax returns the correct output. However, there are two kinds of output from that result. -0.710976 and 0.315113 are the correct values for min and max. But in another situation, the loop only has around 20 values for both left and right channels, not 512. And it returns 0.233697 and 0.309581. I don’t know why @t0m

---

<div class="post-metadata">

**Author:** ![Jerryuhoo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jerryuhoo/32/8844_2.png) [@Jerryuhoo](https://forum.juce.com/u/Jerryuhoo)\
**Post date:** [August 2, 2020, 2:25am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/16 "2020-08-02T02:25:28Z")

</div>

> [@anthony-nicholls](#):
>
> Maybe this is the result of buffers with very few values? (DAWs sometimes do this to improve automation accuracy)

Yes, exactly! I posted the test result just now and found that sometimes the buffer doesn’t have 512 samples, only around 20 samples. Does every DAW do this? I tested this in fl studio, what about Ableton Live?  
@anthony-nicholls

---

<div class="post-metadata">

**Author:** ![Jerryuhoo](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jerryuhoo/32/8844_2.png) [@Jerryuhoo](https://forum.juce.com/u/Jerryuhoo)\
**Post date:** [August 2, 2020, 2:39am UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/17 "2020-08-02T02:39:25Z")

</div>

> [@anthony-nicholls](#):
>
> It doesn’t really change anything in terms of outcome it just means the calculation is being performed for every sample when it only needs to be performed once.

Yeah, I realized that should only be performed once. Thanks for pointing out that mistake cuz I am a newbie lol.

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [August 2, 2020, 2:41pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/18 "2020-08-02T14:41:33Z")

</div>

> [@Jerryuhoo](#):
>
> I posted the test result just now and found that sometimes the buffer doesn’t have 512 samples, only around 20 samples.

That’s to be expected. DAWs are free to pass fewer samples than the maximum that you specified. They can even pass 0 samples (for example, to simply send parameter changes but not audio);

---

<div class="post-metadata">

**Author:** ![anthony-nicholls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/anthony-nicholls/32/1246_2.png) [@anthony-nicholls](https://forum.juce.com/u/anthony-nicholls)\
**Post date:** [August 2, 2020, 3:08pm UTC](https://forum.juce.com/t/findminmax-may-have-a-bug/40816/19 "2020-08-02T15:08:04Z")

</div>

> [@Jerryuhoo](#):
>
> Yes, exactly! I posted the test result just now and found that sometimes the buffer doesn’t have 512 samples, only around 20 samples. Does every DAW do this? I tested this in fl studio, what about Ableton Live?

Off the top of my head I don’t know what DAWs do and don’t do this, however you’ll have to deal with it either way.

If you want to make sure you always have at least _n_ samples then you’ll need to make a buffer. Set the size of the buffer in `prepareToPlay()` and create an `int` to keep track of the number of samples you have added to the buffer, once you have filled the buffer perform the calculation on the buffer and set the number of processed samples back to 0 and repeat.
