I use this to get the exact time of issues with audio for reporting results of proof-listening. Labels are not an option for me.
I recorded a macro:
And I assigned a keyboard shortcut (T):
If I use the macro via shortcut or macro menu, while the playhead is in the track without selection (selection start = selection end), I get this message: “Nyquist Prompt” requires one or more tracks to be selected.
If I run the nyquist command via Tools/Nyquist Prompt, I get the desired time code, which I can CTRL-A select and CTRL-C copy:
I suppose this means that macros should accept selections with length = 0.
I was able to assemble a h:mm:ss.mmm format output, working around the missing mod/floor functions in XLISP:
;version 4
;debugflags trace
; get selection start in ms
(setq ms (float 3902.3135))
; ms.math.floor() so we can use rem (replacement for mod) later
(setq sec (truncate ms))
; only the decimals of ms (3 of them)
(setq msonly (truncate (* (- ms sec) 1000)))
(setq hrs (truncate (/ sec 3600)))
(setq sec (- sec (* hrs 3600)))
(setq min (truncate (/ sec 60)))
(setq sec (- sec (* min 60)))
(format t "~a:" hrs)
(if (< min 10)
(format t "0~a:" min)
(format t "~a:" min)
)
(if (< sec 10)
(format t "0~a." sec)
(format t "~a." sec)
)
(format t "~a" msonly)
""
; get selection start in ms
(setq ms (float 3902.3135))
You appear to be actually converting from seconds rather than ms.
For general use, it’s convenient to wrap the code in a function so that you can call it any time you like without having to duplicate code.
Here’s an example which I think will be reasonable robust. Note that the “n” argument is optional and defaults to 3 decimal places:
Oh boy, I posted my testing version which doesn’t actually get the time and uses a test value. Here’s the version I actually finished with yesterday:
;version 4
;debugflags trace
; get selection start in ms
(setq ms (get '*selection*' start))
; ms.math.floor() so we can use rem (replacement for mod) later
(setq sec (truncate ms))
; only the decimals of ms (3 of them)
(setq msonly (truncate (* (- ms sec) 1000)))
(setq hrs (truncate (/ sec 3600)))
(setq sec (- sec (* hrs 3600)))
(setq min (truncate (/ sec 60)))
(setq sec (- sec (* min 60)))
(if (> hrs 0)
(format t "~a:" hrs)
)
(if (< min 10)
(format t "0~a:" min)
(format t "~a:" min)
)
(if (< sec 10)
(format t "0~a." sec)
(format t "~a." sec)
)
(format t "~a" msonly)
""
Ah, cool. I did see some comparison that claimed mod/rem are different when negative numbers are involved but of course this doesn’t matter here.
Thanks! I did see float-format during my “research” but could not for the life of me figure out how to actually use it and was too many hours into my first steps with LISP, so I was just glad I could find a simplistic approach.
You did well. Please don’t take my comments as criticisms, they are just tips from someone that has worked with Nyquist for a long time. Hopefully they will save you a lot of time and effort figuring out how to use Nyquist.
Do you really want minutes to be “00” when the selection is less than 60 seconds?
Maybe something like this:
;version 4
;debugflags trace
(defun format-time(sec &optional (n 3))
;; Return time formatted to hh:mm:ss + n decimal places.
(unless (and (numberp sec) (numberp n))
(error "format-time arguments must be numbers."))
(flet ((pad (x) (if (< x 10) (format nil "0~a" x) x)))
(let* ((hh (truncate (/ sec 3600)))
(mm (truncate (/ sec 60)))
(ss (- sec (* mm 60)))
(old-format *float-format*)
rslt)
(setf mm (- mm (* hh 60)))
(setf *float-format* (format nil "%.~af" n))
(setf rslt (format nil "~a~a~a"
(if (> hh 0)
(format nil "~a:" hh)
"")
(if (> hh 0)
(format nil "~a:" (pad mm))
(if (> mm 0)
(format nil "~a:" mm)
""))
(if (> mm 0) (pad ss) ss)))
(setf *float-format* old-format)
rslt)))
; get selection start in ms
(format t (format-time (get '*selection*' start) 3))
""
Some time ago I wrote a more complex version with a lot more formatting options. You may find it interesting. It’s here on my blog: https://audionyq.com/display-time-as-hhmmss/
One of the take-aways from this is that manipulating text is a pain in Nyquist (but of course the main purpose of Nyquist is for manipulating audio rather than text).
If you are only printing the time, it would be better to simply return the time string, and Audacity will display it in a message box (rather than using the debug output).
To do that, change:
; get selection start in ms
(format t (format-time (get '*selection*' start) 3))
""
to:
; get selection start in ms
(format nil (format-time (get '*selection*' start) 3))
(format t …) outputs to the debug window, whereas (format nil …) simply returns the string.
Note that it may not work correctly in current versions of Audacity - it was written over 9 years ago. (I should really update it when I get time).
Update:
Just tried it, and actually it does still work, though I wonder why I used (optional) positional arguments rather than keyword arguments. I’d probably have used keyword arguments if I were writing it now.
I’m using this macro for finding mistakes in long recordings to annotate the text document, so I need to instantly copy-paste the result. The text box (pictured in screenshot) content can’t be copied (Windows 10 if that plays any role).
Although, if there is a way to combine this with writing directly to the clipboard, this might be interesting. I definitely need the visual feedback that I successfully activated the macro either way.
Yes, that’s an old issue on Windows. Using the debug output is probably the best workaround.
There isn’t. Nyquist cannot access the Windows clipboard.
Nyquist can write to files, but it can’t “append” to files. If you need to append a file (write to the end of existing text), then the file has to be read into ram, appended, then written back to the file (a bit awkward, but can be done).
Another limitation for writing files is that Nyquist won’t prompt you for the file name / path, That has to be set before the code runs (either hard coded into the plug-in, or entered via a control in a GUI plug-in.
I think it would be difficult to improve on that workflow.