command to find loudest sample in selection, possible?

Hello everyone,

I could really benefit from a plugin that would allow me to find the loudest (highest) sample of a selection (like the peak of a single wave cycle), so that I can erase everything before of after it without having to zoom a thousand times in both vertical and horizontal direction.

Can anyone help me creating a Nyquist command for this? it would make my day : )

How about we use existing commands?

Select the whole performance by clicking just above MUTE.

Effect > Amplify: OK.

That should snug the whole show up against “0” as much as possible without actual overload or damage.

View > Show Clipping. That should produce one red band in the timeline and that will be the one point closest to overload and/or loudest.

There are no laws saying you can’t get two or more. That’s the luck of the draw.

Koz

Audacity will not let you “back out” of the effects, but you can duplicate the show and only use the top show as the indicator. After you find the point, work on the bottom show and delete the top one.

If you think Zooming is time consuming, maybe you’re using the wrong tools. I only ever use three Zooms.

Drag-select something and zoom into it with Control-E
Zoom out a little bit Control-3
Zoom out full Control-F.

Shift-ScrollWheel will push the timeline left and right.

Change the timeline so it doesn’t change position by itself (this can be maddening). Edit > Preferences > Tracks > [_] Update… (de-select).

Koz

If it is a very short selection that you need to analyze, the following code will do the job (run it in the “Nyquist Prompt” effect).
This requires a very recent version of Audacity, preferably the current Audacity 2.1.1.
Note that this code is only suitable for mono tracks of less than a few minutes.
It places a label at the position of the greatest amplitude.

(setq maxval 0.0)
(setf num 0)
(do ((count 0 (1+ count))
     (val (snd-fetch *track*)(snd-fetch *track*)))
    ((not val) (list (list (/ num *sound-srate*) "")))
  (when (> (abs val) maxval)
    (setf maxval (abs val))
    (setf num count)))

It places a label at the position of the greatest amplitude.

And if it hits more than one?

Koz

Same code snippet with lots of comments to describe how it works.
See also:
http://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference
http://www.cs.cmu.edu/~rbd/doc/nyquist/
http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-index.htm
http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/xlisp/xlisp-ref/xlisp-ref-index.htm

;initialize "maximum found sample"
(setq maxval 0.0)

;initialize "sample number"
(setf num 0)

;start loop
(do

    ;initialize "count" to 0, and increment on each loop
    ((count 0 (1+ count)) 

     ;initialize "val", fetch first sample from *track*
     ;and fetch another sample on each loop
     (val (snd-fetch *track*)(snd-fetch *track*)))
 
    ;loop until run out of samples
    ((not val) 

     ;return a list of lists.
     ;this is a special format that tells Audacity to
     ;create a label.
     ;See: http://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference#Return_Values
     ;(/ num *sound-srate*) gives us the time in seconds of sample number "num".
     (list (list (/ num *sound-srate*) "")))

  ;Start of loop body.
  ;Is the absolute value (ignoring +/- sign) of "val" greater than "maxval"?
  (when (> (abs val) maxval)

    ;when above test is true, set "maxval" to the absolute
    ;value of "val" and set "num" equal to "count".
    ;we have stored the sample number so that we know where
    ;to put the label.
    (setf maxval (abs val))
    (setf num count)))

As described in my previous post, the code is looking at each sample value and comparing it with the previously found maximum value. If the current sample value is greater, then that becomes the new “maxval”. The code will therefore return just one label.

If we want a label for each sample that has the maximum value (which is only likely to occur if the audio is clipped) then we could save a list of maximum values rather than just one maximum value, then on completion we would convert that list into labels.

The code that i posted was intended as a starting point in response to N871’s question. Where to take it from here depends on what N871 wants to do.

Like this:

(setf maxval 0.0)
(setf labels ())
(do ((count 0 (1+ count))
     (val (snd-fetch *track*)(snd-fetch *track*)))
    ((not val))
  (cond
    ((> (abs val) maxval)
      (setf maxval (abs val))
      (setf peaklist (list count)))
    ((= (abs val) maxval)
      (push count peaklist))))
(dotimes (i (length peaklist) labels)
  (setf time (/ (nth i peaklist) *sound-srate*))
  (push (list time "") labels))

I’d like to thank everyone for replying to my post.

Steve, your code is very nice, but because I’m cutting samples (working in a project with hundreds of tracks) it’s not practical to use the labels. would it be possible to make it work like this:

you make a selection, use the code, and the result is a new selection that starts with the loudest (highest) sample and ends with the last sample that was originally selected.

Or the other way around if easier: The new selection starts with the first sample that was originally selected and ends with the loudest sample of the original selection.

Unfortunately Nyquist plug-ins are not able to change the selection times.
However, Nyquist plug-ins can delete part of the selection. Would that be any help?
It would certainly help us if you could paint a picture in words to describe what the job is - what exactly are you trying to do, and why?

Yes! that would be perfect in fact.

if it can delete everything in the selection before or after (could use both codes) the highest sample, that would be great.

I’m designing digital oscillators starting from chromatic sampled recordings. The process takes a while to explain, but I need
to cut the samples so that they can not only be looped but also crossfaded with each other, they need to be cut at exactly the same place
before I speed-shift them to exactly the same length (and pitch). I did first cut all the samples at a same zero crossing point, but I now discovered that it will be better to cut at the peak.

If you can make 2 codes like explained above that would be awesome…

Additional to my explanation on the previous page, here are some pictures of before and after the effect I need:

before: a selection

after: the beginning of the selection is cut until the sample right before the highest sample (the highest sample is not cut).

I could also use the opposite: the highest sample or peak is cut until the end of the selection (this time the highest sample is also cut)
AFTER.png
BEFORE.png

Something like this perhaps:

(setq maxval 0.0)
(setf num 0)

(defun get-peak (sig)
  (do ((count 0 (1+ count))
       (val (snd-fetch sig)(snd-fetch sig)))
      ((not val) (/ num *sound-srate*))
    (when (> (abs val) maxval)
      (setf maxval (abs val))
      (setf num count))))

(extract-abs (get-peak (snd-copy *track*)) (get-duration 1) *track*)

Steve, thank you so much, this helps a lot!!

few last questions if I may:

(-)possible to do the same without splitting the track?
-if I change all maxval’s into minvals it will work for the lowest peak?..stupid question, will try it out myself
-possible to make a version… that does the opposite: the highest sample or peak is cut until the end of the selection (this time the highest sample is also cut)

thank you again for your time and expertise!

The split line is a behaviour implemented by Audacity on effects that change the length of the selection. However there is a plug-in header command that overrides the behaviour:

;mergeclips 1

“maxval” is not a command, it is just the name of a variable. You could change “maxval” to “archaeopteryx” and the code would still behave in exactly the same way.
Look at the code, in particular the code in which I added lots of code comments. See how we are comparing the previous maximum value with the absolute value of the current sample (see: XLISP abs)

If you just want the maximum positive peak, then you need to compare with the signed value rather than the absolute value.

(when (> (abs val) maxval)



(when (> val maxval)

Similarly if you want the maximum negative peak, but looking for “smaller than” rather than “grater than”.

Ok I see, the instances where I would like to cut starting from a negative peak, I can use the same code because in these instances the negative peak will always be bigger than the positive peaks that might be included in the same selection. Thanks.

Just possible to help me with a code for the opposite? => the loudest sample or peak (abs again) is cut, as is what comes afterwards in the selection (this time the loudest sample is also cut) This is my very last request : )

some pictures to clarify:
AFTER 2.png
BEFORE 2.png

Have a look at “extract-abs” in the Nyquist manual - I think you should be able to work that one out :wink:
http://www.cs.cmu.edu/~rbd/doc/nyquist/part8.html#index566

I was somehow expecting this reply : ) my fear became reality hehe.
I promise I will take a look at it, but please don’t kill me if if I return to the forum.
The cutting of this endless amount of samples didn’t make me very …flexible : )

If you get stuck, feel free to ask, but do read through what I’ve already posted - most of the information is already there, and if you can work out how to use it then you will be in a much better position to make your own tools when you need them (rather than relying on me :wink:)