Numbered Label

Share your Audacity/Nyquist plug-ins here, or test drive the latest plug-ins submitted by Audacity users.

After testing a plug-in from this forum, please post feedback for the plug-in author.
jozefh
Posts: 79
Joined: Wed Nov 27, 2019 10:06 am
Operating System: Windows 10 / 11

Numbered Label

Post by jozefh » Wed Sep 21, 2022 2:03 pm

Hello,

here is a plugin that creates a new label and it sets the number as a label text. The number is increased by 1 for every new label.
The label is created on the same track as the build-in feature Add Label at Selection would do.

Feel free to share any feedback.

Thank you.
Numbered Label.ny
(2.27 KiB) Downloaded 17 times
(v1; 2022/09/21)

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Wed Sep 21, 2022 4:56 pm

Congratulations. It works nicely.

I don't have time to study the code in detail, but a few general comments:

1. Spaces not tabs.
Unless the person reading the code has the same tab settings as the person writing the code, the indentation will be messed up by tabs (and indentation is very important for reading LISP languages).

2. Try to avoid very long lines (for readability)
Example:

Code: Select all

(setf msg (format nil "~a- Label n ~a(~a); maxnum=~a; New label ID=~a~%" msg number_of_labels lval maxnum label_ID)))
might be better as:

Code: Select all

(setf msg (format nil "~a- Label n ~a(~a); maxnum=~a; New label ID=~a~%"
                  msg number_of_labels lval maxnum label_ID)))
3. Look to see if some of those global variables can be made local to functions. Global variables aren't bad per se, but they are a common cause of bugs, and anyone reading the code has to jump around to follow the flow.

4. Try to avoid long functions.
Again for readability and to simplify debugging, small functions with clear purpose are easier to read and verify.
Example, the comment "; get ID of the focused audio track" would be unnecessary if that loop was moved out into a separate function:
Instead of:

Code: Select all

(defun get_new_label_ID_and_value ()
  (let ((labels (aud-get-info "Labels"))
				(tracks (aud-get-info "Tracks"))
				(cursor_time (get '*selection* 'start))
				lval
				(track_id -1))
		(dolist (t tracks) ; get ID of the focused audio track
			(setf track_id (1+ track_id))
			(when (and (= (second (second t)) 1) (= focused_track_ID 0))
				(setf focused_track_ID track_id)))
				...
you could write something like:

Code: Select all

(defun get_new_label_ID_and_value ()
  (let ((labels (aud-get-info "Labels"))
        (tracks (aud-get-info "Tracks"))
        (cursor_time (get '*selection* 'start))
        lval
        (track_id -1))
  (get-focus-track-id track)
		...
Learn more about Nyquist programming at audionyq.com

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Wed Sep 21, 2022 7:39 pm

I think the code could be greatly simplified, but I'm not sure about some of your intentions. For example, if you have 3 labels:

Tracks000.png
Tracks000.png (14.55 KiB) Viewed 194 times
What do you want the next label number to be?
Learn more about Nyquist programming at audionyq.com

jozefh
Posts: 79
Joined: Wed Nov 27, 2019 10:06 am
Operating System: Windows 10 / 11

Re: Numbered Label

Post by jozefh » Thu Sep 22, 2022 2:32 pm

steve wrote:
Wed Sep 21, 2022 7:39 pm
What do you want the next label number to be?
In this specific case, when the existing labels are A, 7 and c, then the new numbered label would be 8. Of course, this specific example does not highlight the advantage of the Numbered Label plugin.

Imagine you are preparing the list of the labels that tag the audio parts like paragraphs, boxes, etc. This list then can be converted to the JSON file that can be used on the website, so the reader of article can playback any of the article part by clicking on it. Usually web article paragraphs have incremental numbered IDs for the reference.

Another advantage is that this provides a quick identification. Imagine that you want to label some parts of audio when you do checking. Then you want to write into the printed script that identification. Just with one hotkey, you place a label and then you note down the number of the label into the printed script.
steve wrote:
Wed Sep 21, 2022 7:39 pm
the code could be greatly simplified, but I'm not sure about some of your intentions.
The complexity of the code is increased by:
  • the possibility to have multiple label tracks
  • the possibility to have multiple audio tracks with multiple label tracks (multiple web-articles in one project)
  • it is not possible to create easily a label and set its text on the existing label track by nyquist plugin
Spaces not tabs.
OK, I will do my best to stick to this standard. But I have this problem: I am using Notepad++ and when I select Enter key, the next row will be intended by tab(s) according to the previous row, although the previous row has spaces at the beginning. So for me to stick to the mentioned standard requires extra "manual work". Every time I hit the Enter I need to remember to check the beginning of the row and most of the time I have to delete tabs and replace them with the spaces. Or in my last project, I used tabs as usually and when I finished, I replaced all tabs with double space.

Of course, I will implement later all your precious suggestions from the first message.

Thank you.

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Thu Sep 22, 2022 2:55 pm

jozefh wrote:
Thu Sep 22, 2022 2:32 pm
I am using Notepad++
When I was on Windows, I always used NotePad++ for writing Nyquist code, and I still recommend it :)
I've not used it so much in recent years (I'm usually on Linux and use another app that, like NotePad++, is based on Scintilla, called "Scite"). I'm pretty sure that NotePad++ has an option to always use spaces for indentation, though I don't recall where that option is.
Learn more about Nyquist programming at audionyq.com

jozefh
Posts: 79
Joined: Wed Nov 27, 2019 10:06 am
Operating System: Windows 10 / 11

Re: Numbered Label

Post by jozefh » Thu Sep 22, 2022 3:03 pm

Thanks for the tip!

So after quick googling, I found it and this is the right settings for Nyquist programming convention:
2022-09-22 17_00_26-Preferences.png
2022-09-22 17_00_26-Preferences.png (25.87 KiB) Viewed 148 times
Finally!! :D

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Thu Sep 22, 2022 3:42 pm

I'll post a series of short comments relating to this plug-in that you may find useful.
Here's the first:

There's a (undocumented?) function in the Nyquist source code (file name: "sal-parse.lsp") called string-to-number.
This is the function definition:

Code: Select all

(defun string-to-number (s)
  (read (make-string-input-stream s)))
There's also a higher level function defined in "aud-do-support.lsp" called number-string-p. This is described as:
"like digit-char-p for strings"
If a string starts with a number (positive or negative, integer or float), then the number is returned, else NIL.
Note that for floats, the decimal separator must be a dot (not a comma).

Thus you can extract a number from a string (or start of a string) with:
(number-string-p string) ; returns number or NIL
Learn more about Nyquist programming at audionyq.com

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Thu Sep 22, 2022 4:53 pm

Say you have a list like this:

Code: Select all

((name "Audio Track") (focused 0) (selected 1) (kind "wave") (start 0) (end 30) (pan 0) (gain 1) (channels 1) (solo 0) (mute 0) (VZoomMin -1) (VZoomMax 1))
and you want to get the value of "focused".
One way to get the value is from its position:

Code: Select all

(second (second my-list))
A downside of this is "readability". Unless the reader knows the precise form of "my-list", they are reliant on comments to know what "(second (second my-list))" refers to.

Alternatively, you can use ASSOC to look up the required value:

Code: Select all

(second (assoc "focused" my-list))
Even without knowing the precise form of "my-list", the reader can immediately see that it is retrieving the value of "focused".
Learn more about Nyquist programming at audionyq.com

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Fri Sep 23, 2022 6:51 pm

Sorry for the delay, I've had a lot on.

There's a minor issue that may or may not be important. It's easiest to explain with an example:

1. Generate a tone
2. Add a few numbered labels in a label track below the audio track
3. Make a selection in the audio track before the final label
4. Press "down cursor" (focus is now on the label track)
5. Apply "Numbered Label.ny"

A label is created, but it is not numbered.

Around line 29 you have:

Code: Select all

    (dolist (ltrack labels) ; loop through all label tracks
      (when (and (> (first ltrack) focused_track_ID) (= label_track_ID -1))
          (setf label_track_ID	(first ltrack)))
I think the issue can be fixed by changing

Code: Select all

(> (first ltrack) focused_track_ID)
to

Code: Select all

(>= (first ltrack) focused_track_ID)
Alternatively, you could throw a meaningful error if no audio track has focus.
Learn more about Nyquist programming at audionyq.com

steve
Site Admin
Posts: 85412
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Numbered Label

Post by steve » Sat Sep 24, 2022 6:11 pm

There's another bug, and this one isn't so easy to fix.
If the selection start is at exactly the same time as a label in the target track, then there's no reliable way to determine the new label ID, because the label times returned by GetInfo: are not sufficiently precise.

Example:
If there's an existing label that starts at: 3.494601 seconds,
then GetInfo : returns a start time of 3.4946 seconds (rounded to 4 decimal places).

Similarly, if there's an existing label that starts at: 3.4945999 seconds
then GetInfo : returns a start time of 3.4946 seconds (rounded to 4 decimal places).

If the selection start time is exactly 3.494600 seconds, then both of these labels will appear to have the same start time as the selection, when in fact one is before and the other is after.

I'm not sure of the best way to fix this. I'll think about it and get back to you.
Learn more about Nyquist programming at audionyq.com

Post Reply