Capture Maximum of a Signal?

Hello!

I’m trying to capture the maximum amplitude of a signal like this at the moment:

(
{
	var lastMax = 0; 
	var in = LFNoise2.ar(2).unipolar;
	lastMax = Latch.ar(in, in > lastMax);
	[in, lastMax]
}.scope
)

However, this only seems to only work for the first few seconds - If you turn the scope to overlay mode, it is apparent that some maximums of the signal are not tracked.
Does anybody have any tips? I’ve seen Max.ar in the sc3plugins, this however only seems to work for a duration of samples, which is not ideal in my usecase.

Thank you for reading!

All best,
moritz

How about approaching it this way?
(Although it may not be exactly what you’re looking for…)

// using RunningMax
(
{
	var lastMax = 0;
	var trigFreq = 10;
	var in = LFNoise2.ar(2).unipolar;
	lastMax = RunningMax.ar(in, Impulse.ar(trigFreq)).lag;
	[in, lastMax]
}.scope
)

Could you provide a bit more context?

1 Like

So you’ve made a bit of a (fairly common) misunderstanding in your synthdef.

The issue is that you can’t use the ‘value’ of lastMax recursively/in a loop. UGens are not the values on the server, they are the unit generators and represent something like an oscillator or effect processor — not the signal itself.

For this reason, it is often a good idea to avoid reassigning variables, as you can’t make this mistake when you do (or at least it is a lot harder).

This is equivalent and I think makes it clear why your code doesn’t run.

(
{
	var lastMax = 0; 
	var in = LFNoise2.ar(2).unipolar;
	var max = Latch.ar(in, in > lastMax);
	[in, max]
}.scope
)

Essentially, you cannot ‘store’ a server side value (signal) in a variable, you need to use a buffer if you want to do that.

(
{
	var p = LocalIn.ar(1);
	var in = LFNoise2.ar(4).unipolar;
	var thisMax = Select.ar(in > p, [p, in]);
	LocalOut.ar(thisMax);
	[in, thisMax]
}.scope
)

Edit: @schmolmo fixed my borked code.

3 Likes

Thank you both for the replies, @jordan and @prko!
I just found Peak.ar, which solves my case wonderfully:

(
{
	var in = LFNoise2.ar(4).unipolar;
	[in, Peak.ar(in)]
}.scope
)

(RunningMax would also work!)

And thank you very much for the clarification jordan, I think this is somehthing I’ve stumbled across many times before! Here’s the working version of your example, using LocalBuf and LocalOut:

(
{
	var p = LocalIn.ar(1);
	var in = LFNoise2.ar(4).unipolar;
	var thisMax = Select.ar(in > p, [p, in]);
	LocalOut.ar(thisMax);
	[in, thisMax]
}.scope
)


(
{
	var p = LocalBuf(1);
	var in = LFNoise2.ar(4);
	var old_p = BufRd.ar(1, p, DC.ar(0));
    // in > old_p returns '1' if true and '0' if false
	var new_p = Select.ar(in > old_p, [old_p, in]);
	BufWr.ar(new_p, p, DC.ar(0));
	[in, new_p]
}.scope
)

All best!
moritz

1 Like