Nyquist Reference in a nut shell

I am glad to present a new plug-in, especially designed for developers and those who want to start out with Nyquist.
LittleHelper.zip (123 KB)
The plug-in provides a method for a fast look up of Nyquist and Xlisp functions and primitives.
If properly installed, the helper tool will appear under the generate menu.

Current features of this version are:

  • 358 Nyquist high and low level functions
  • High level functions are ordered alphabetically and can easily be reached by typing the first letter.
  • Low level functions are proceeded by a space and are directly under their counter part.
  • Those L-L functions which have no association can be found under “Snd-…”.
  • You can choose if only the argument list (i.e. the Lisp syntax) or the entire source code (high level only) shall be presented.
  • The category, under which the function can be found on the web page is provided.
  • Also the name of the library file is shown.
  • It is followed by the description (same as on the web page of the CMU)
  • Some functions have a snippet that can directly be copied and pasted to the Nyquist prompt.
  • An Audio preview is also available in some cases (mostly the snippet from the debug screen)
  • 296 XLISP primitives (those which work under Audacity) can be displayed as well.
  • They return the syntax, description and examples in the nearly same format as on the web page.
  • The program recognizes which function is newly chosen (Nyquist or Xlisp)
  • New plug-in calls will display the two categories alternatively (Nyq. and Xlisp) if no changes are made.

Ensure that you install all files from the zip archive into the plug-in folder i.e. little-helper.ny and little-helper.dir (folder). The plug-in must have (read only) access to the two data files in the mentioned folder. The path selection routine is not tested on all systems, maybe you’ll have to specify the path manually if you encounter any problems.

As usual, feed back, suggestions and corrections are appreciated. Feel free to send me your favorite (sounding) Snippets if you want them to be included in the next release or post them directly here.

I use a Excel file as a template for all the given information. A direct manipulation of the data files is not recommended.
I hope my little helper tool (actually the largest Nyquist plug-in you can come across so far) is of some use for you.
Thank you very much for downloading and testing.

My Thanks go furthermore to Roger B. Dannenberg and all those who have contributed to Nyquist. Thanks also to David Betz (author of Xlisp), Edgar Franke (who created the web pages from other sources) and Steve Daulton for re-formatting the code.

“What’s your confession?” - “I am a Nyquistian”

Unfortunately I’m having difficulty with it.

The debug window shows:

error: bad argument type - NIL
Function: #<Subr-NTH: #94df878>
Arguments:
  2
  NIL
Function: #<FSubr-SETQ: #94df8e4>
Arguments:
  FUN-NAME
  (CAR (NTH NYQFN NYQ-TABLE))
Function: #<Closure-NYQ-DISPLAY: #9408584>
Function: #<FSubr-COND: #94ddae4>
Arguments:
  ((AND (NOT-EQL (PROP "nyquist") NYQFN) (NOT-EQL (PROP "xlisp") XLISPFN)) (NYQ-DISPLAY) (PROP "nyquist" NYQFN) (FORMAT T "~%     ----------------~%") (XLISP-DISPLAY) (PROP "xlisp" XLISPFN) (PROP "last" 0))
  ((NOT-EQL (PROP "nyquist") NYQFN) (NYQ-DISPLAY) (PROP "nyquist" NYQFN) (PROP "last" 0))
  ((NOT-EQL (PROP "xlisp") XLISPFN) (XLISP-DISPLAY) (PROP "xlisp" XLISPFN) (PROP "last" 1))
  (T (CASE (PROP "last") (0 (NYQ-DISPLAY) (PROP "nyquist" NYQFN) (PROP "last" 1)) (1 (XLISP-DISPLAY) (PROP "xlisp" XLISPFN) (PROP "last" 0))))
1> "Please see debug-window for results"
1>

It seems that the Nyquist-reference data file is not loaded. I guess you work on Linux.
Try to specify the storage location of the files manually.
The path specification is in the lines 38 to 41 (notepad++ without automatic line breaks).
You are much more familiar with the file management and you are therefore the very man to solve the problem.
Hopefully you’ll find a solution. Thanks in advance.

Yes I’m on Linux.
I had already edited the path to match my system.
I’ve found the problem now - you forgot about case sensitive file systems.
Your code has:

(setf nyq-table (get-fn-table "Nyqref.dat"))

where “Nyqref.dat” has an upper-case “N”, but the actual file name has a lower-case “n”.

I’ve change the case of the file name to match your code.

[Update: Similar problem with Xlispref.dat so I’ve change the code there to title case to match the file.
Both files (in my version) now begin with one upper-case letter followed by lower-case.]

You have clearly put a huge amount of work into this. Thanks for sharing.
Unfortunately there are some fairly major usability issues with it on Linux and I’m not sure how practical it is to try and fix them.

The main issue is that Linux does not automatically scroll to the first letter of the word. On Linux it is more usual to have a menu hierarchy, but the Nyquist plug-in interface does not support that.

The other main issue applies to sighted users - the debug screen is very small which makes reading the text difficult. Is there a specific reason why you are outputting to the debug window rather than the more usual message dialogue?

Thanks Steve.
For the most functions it is inpractical to send the Output to the standard Output scrreen, because the 50 chars 25 lines rule is nearly always violated. Furthermore, the results can’t neither be scrolled nor copied.
It’s a pity that the font sizes can’t be changed for the different outputs (ljust ike it is done for numbers by float-format for example).
For screen readers, the font size could be 1 Pica, it just doesn’t matter.
We could of course send the Syntax string solely to the standard output as well. However, you can’t copy it (without mouse) and nearly the same can be achieved with the (args 'searched-function) command (high level only) in the Nyquist prompt.
I really don’t see any solution for Linux users. Maybe after a little nap…

I’ve done some reformatting to the LittleHelper.ny code.

Some questions and comments about the code:

I notice that you often put a comment at the end of a function to say that it is the end of the function.
Do you want me to leave those in?
For sighted user they are not necessary because it is usually clearly evident from the indentation. Also, I think that Notepad++ can indicate “fold” positions that can collapse a function down to the first line, or expand it back, but I don’t know if that feature is accessible.

In a “DO” loop structure, it is not necessary to specify “nil” as the “result” expression. The “result” is optional and if omitted the loop returns nil. It is usual to omit the result expression unless a returned value is required.

Your function “prop” would probably be a lot cleaner and easier to follow if you used “cond” rather than nested “IF” statements.
It’s also got the rather strange expression:

(format nil "~a" (strcat " 'rjh-nyqref-" property))

which I think would work just the same as:

(format nil "~a ~a"  "'rjh-nyqref-" property)

Here’s the formatted version. It’s probably not formatted as nicely as an expert LISPer would do it, but I think that it is more readable now.

;nyquist plug-in
;version 3
;type generate
;categories http://lv2plug.in/ns/lv2core/#Function"
;name "Nyquist Reference..."
;action "Searching  for Function..."
;info "by Robert J. HaengginReleased under terms of the GNU General Public License version 2.nnShows a detailed Description of a Nyquist-function.nSearch the desired Function with the key corresponding tonthe first letter or use one of the direction keys.nnPlease press the Debug button instead of the OK-button.n" 

;; Released under terms of the GNU General Public License version 2:
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html .
;; Minimum Audacity version: 1.3.13
;;
;; Nyquist and XLISP Reference
;; Plug-in Version 1.0, October 2012
;; Thanks to Roger B. Dannenberg and all contributors to Nyquist
;; Thanks to Edgar Franke and others for the provided XLISP Reference.
;;
;; Do not insert spaces between commas and names. 
;; Otherwise, the functions can not be reached by their first letter.

;control nyqfn "Nyquist-function to show" choice "abs-env,allpass2,alpass, snd-alpass, snd-alpasscv, snd-alpassvv, snd-alpasscv, snd-alpassvv,amosc, snd-amosc,areson, snd-areson, snd-aresoncv, snd-aresonvc, snd-aresonvv,args,at,at-abs,autonorm,autonorm-off,autonorm-on,autonorm-update,bandpass2,biquad, snd-biquad,biquad-m,bkoff,bkon,bowed, snd-bowed,bowed-freq, snd-bowed-freq,breakpoints-convert,breakpoints-log,breakpoints-relative,build-harmonic,buzz,>snd-buzz,clarinet, snd-clarinet,clarinet-all, snd-clarinet-all,clarinet-freq, snd-clarinet-freq,clip, snd-clip,comb,comb-delay-from-hz,comb-feedback,compare,compute-default-sound-file,congen, snd-congen,const, snd-const,continuous-control-warp,continuous-sound-warp,control,control-srate-abs,control-warp,convolve, snd-convolve,cue,cue-file,cue-sound,current-path,db-to-linear,decf,diff,display-macro,env,envdepth,eq-band,eq-highshelf,eq-lowshelf,eval-multiseq-behavior,eval-seq-behavior,event-has-attr,expand-and-eval-expr,exp-dec,expr-set-attr,extract,extract-abs,feedback-delay, snd-delay, snd-delaycv,flute, snd-flute,flute-all, snd-flute-all,flute-freq, snd-flute-freq,fmfb, snd-fmfb, snd-fmfbv,fmlfo,fmosc, snd-fmosc,follow, snd-follow,force-srate,force-srates,full-name-p,gate,gate, snd-gate,get-duration,get-loud,get-slider-value,get-srates,get-sustain,get-tempo,get-transpose,get-warp,grindef,highpass2,highpass4,highpass6,highpass8,hp, snd-atone, snd-atonev,hzosc,hz-to-step,incf,instr-parameter,integrate,is-file-separator,jcrev,lfo,linear-to-db,list-set-attr-value,local-to-global,loud,loud-abs,lowpass2,lowpass4,lowpass6,lowpass8,lp, snd-tone, snd-tonev,maketable,mandolin, snd-mandolin,modalbar, snd-modalbar,mult,multichan-expand,multichannel-max,multiseq-iterate,must-be-sound,myosd,noise, snd-white,noise-gate,notch2,np,nrev,ny:fmfbv,ny:gc-hook,nyq:add2,nyq:add-2-sounds,nyq:coerce-to,nyq:environment-init,nyq:max-2-sounds,nyq:max-of-arrays,nyq:min-2-sounds,nyq:min-of-arrays,nyq:prod2,nyq:prod-2-sounds,nyq:prod-of-arrays,nyq:sound,nyq:sound-of-array,nyq:sound-to-array,osc, snd-osc,osc-note,osc-pulse,osc-saw,osc-tri,pan,partial, snd-partial,peak, snd-max,pitshift, snd-stkpitshift,play,play-file,pluck, snd-pluck,pop,power,prcrev,prod, snd-prod,push,pwe,pwe-list,pwer,pwer-list,pwev,pwev-list,pwevr,pwevr-list,pwl, snd-pwl,pwl-list,pwlr,pwlr-list,pwlv,pwlv-list,pwlvr,pwlvr-list,quantize, snd-quantize,r,ramp,real-random,recip, snd-recip,relative-path-p,resample, snd-resample, snd-resamplev,reson, snd-reson, snd-resoncv, snd-resonvc, snd-resonvv,rms,round,s-abs, snd-abs,s-add-to,sampler,sax, snd-sax,sax-all, snd-sax-all,sax-freq, snd-sax-freq,scale, snd-scale,scale-db,scale-srate,select-implementation-1-1,select-implementation-1-2,seq, snd-seq,seq-iterate,seqrep,set-control-srate,set-logical-stop,set-logical-stop-abs,setp,set-pitch-names,set-sound-srate,s-exp, snd-exp,sf-info,shape, snd-shape,shift-time,sim,sim-list,simrep,sine, snd-sine,sinh,siosc, snd-siosc,siosc-breakpoints,sitar, snd-sitar,s-log, snd-log,slope,s-max, snd-maxv,s-min, snd-minv,snd-add,snd-avg,snd-bandedwg,snd-chase,snd-compose,snd-copy,snd-coterm,snd-display,snd-down,snd-extent,snd-from-array ,snd-inverse,snd-multiseq,snd-normalize,snd-offset,snd-oneshot,snd-slider,snd-stkrev,snd-up,snd-xform,snd-zero,sound,soundfilename,sound-off,sound-on,sound-srate-abs,sound-warp,s-overwrite, snd-overwrite,s-plot,snd-print-tree,square,s-read, snd-read,s-read-byte-offset,s-read-dur,s-read-srate,s-read-swap,sref,s-rest,s-save, snd-save,s-save-autonorm,s-sqrt, snd-sqrt,step-to-hz,stk-breath-env,stkchorus, snd-stkchorus,stretch,stretch-abs,sum,sum-of-arrays,sustain,sustain-abs,tapf, snd-tapf,tapv, snd-tapv,tempo,timed-seq,transpose,transpose-abs,trigger, snd-trigger,warp,warp-abs,wg-glass-harm,wg-tibetan-bowl,wg-tuned-bar,wg-uniform-bar,while,with%environment,yin, snd-yin" 0

;control verbflag "Verbosity level" choice "Arguments,Source code" 0
;control previewflag "Snippets for Nyquist:" choice "Do not play,Play if possible" 0
;control xlispfn "XLISP-Primitive to show" choice "*,*,**,***,+,+,++,+++,-,-,/,/=,1+,1-,<,<=,=,>,>=,abs,alloc,and,:answer,append,apply,*applyhook*,aref,arrayp,assoc,atan,atom,&aux,backquote,baktrace,block,both-case-p,boundp,break,*breakenable*,car,caar cadr,caaar...caddr,caaaar...cadddr,case,catch,cdr,cdar cddr,cdaar...cdddr,cdaaar...cddddr,cerror,char,char/=,char<,char<=,char=,char>,char>=,characterp,char-code,char-downcase,char-equal,char-greaterp,char-int,char-lessp,char-not-equal,char-not-greaterp,char-not-lessp,char-upcase,class,:class,clean-up,close,code-char,comma,comma-at,cond,cons,consp,:constituent,continue,cos,*debug-io*,defmacro,defun,delete,delete-if,delete-if-not,digit-char,digit-char-p,do,do*,dolist,dotimes,dribble,endp,eq,eql,equal,error,*error-output*,errset,eval,evalhook,*evalhook*,evenp,exit,exp,expand,expt,fboundp,first,flatc,flatsize,flet,float,*float-format*,floatp,format,fourth,funcall,function,gc,gcd,*gc-flag*,*gc-hook*,gensym,get,get-key,get-lambda-expression,get-output-stream-list,get-output-stream-string,go,hash,if,int-char,*integer-format*,integerp,intern,:isnew,&key,labels,lambda,last,length,let,let*,list,listp,load,logand,logior,lognot,logxor,loop,lower-case-p,macroexpand,macroexpand-1,macrolet,make-array,make-string-input-stream,make-string-output-stream,make-symbol,mapc,mapcar,mapl,maplist,max,member,:mescape,min,minusp,nconc,:new,nil,:nmacro,not,nstring-downcase,nstring-upcase,nth,nthcdr,null,numberp,*obarray*,object,objectp,oddp,open,&optional,or,peek-char,plusp,pprint,prin1,princ,print,*print-case*,prog,prog*,prog1,prog2,progn,progv,psetq,putprop,quote,random,read,read-byte,read-char,read-line,*readtable*,rem,remove,remove-if,remove-if-not,remprop,rest,&rest,restore,return,return-from,reverse,room,rplaca,rplacd,save,second,self,send,send-super,:sescape,set,setf,setq,:show,sin,sort,sqrt,*standard-input*,*standard-output*,strcat,streamp,string,string/=,string<,string<=,string=,string>,string>=,stringp,string-downcase,string-equal,string-greaterp,string-left-trim,string-lessp,string-not-equal,string-not-greaterp,string-not-lessp,string-right-trim,string-trim,string-upcase,sublis,subseq,subst,symbol-function,symbol-name,symbol-plist,symbol-value,symbolp,system,t,tagbody,tan,terpri,third,throw,:tmacro,top-level,trace,*tracelimit*,*tracelist*,*tracenable*,*trace-output*,truncate,type-of,*unbound*,unless,untrace,upper-case-p,unwind-protect,vector,when,:white-space,write-byte,write-char,zerop" 0

;; simplify the handling of the global survivor *scratch*
(defun prop (property &optional val &key add rem)
  (setf arg (eval (read (make-string-input-stream 
    (format nil "~a ~a"  "'rjh-nyqref-" property)))))
  (if rem
      (remprop '*scratch* arg) 
      (if val
          (if add
              (setf (get '*scratch* arg) (+ (get '*scratch* arg) val))
              (setf (get '*scratch* arg) val))
          (get '*scratch* arg))))

;; Loads one of two available Tables
(defun get-fn-table (ftcatch)
  (psetq slash (Format nil "~a" *File-separator*) dat-table nil)
  (setq file-path 
    (format nil "~A~a~a~a~a~a~a" 
      *default-sf-dir* slash "plug-ins" slash "LITTLE HELPER" slash ftcatch))
  ;; Read all Lists
  (do* ((dat-file (open file-path :direction :input))
        (fun-lis  (read dat-file) (read dat-file)))
       ((null fun-lis))
    (setf dat-table (cons fun-lis dat-table)))
  (reverse (nconc dat-table)))

;; execute the snippet and play over DAC
(defun pre-listen (soundy &aux (s s))
  (progv '(out *standard-output*) `(,(make-string-output-stream) nil)
    (format out "~a" soundy)
    (do ((expr (read out) (read out)))
        ((null expr))
      (eval expr))))

;; List the Information for the Nyquist-function
(defun nyq-display ()
  (setf nyq-table (get-fn-table "Nyqref.dat"))
  (setq fun-name (car  (nth nyqfn nyq-table)))
  (setq defined-as 
    (nth (second (nth nyqfn nyq-table))
      `("Function"  "Macro" ,(type-of (symbol-function  fun-name)))))
  (case verbflag
        (0 (setq msg "LISP-syntax for this ~a (~a/~a):~%~a")
           (Setf cmd 'second))
        (t (setq msg "Source-code for this ~a (~a/~a):~%~a")
           (setf cmd 'cdr)))
  (format t msg defined-as 
    (1+ nyqfn)
    (length nyq-table)
    (if (not (string-equal (nth 4 (nth nyqfn nyq-table)) "Low Level"))
        (cons fun-name 
          (funcall cmd 
            (get-lambda-expression (symbol-function fun-name))))
        (nth 9 (nth nyqfn nyq-table))))
  (format t "~%Category: ~a, as found in :  ~a" 
    (third (nth nyqfn nyq-table))
    (nth 4 (nth nyqfn nyq-table)))
  (format t "~%~%Description:~%~a" 
    (fourth (nth nyqfn nyq-table)))
  (when (nth 5 (nth nyqfn nyq-table))  
    (format t "~%~%Notes: ~%~a"
      (nth 5 (nth nyqfn nyq-table))))
  (when (nth 6 (nth nyqfn nyq-table))  
    (format t "~%~%Snippet for Nyquist-prompt:~%~a"
      (nth 6  (nth nyqfn nyq-table))))
  (when (= previewflag 1)
    (if (nth 6 (nth nyqfn nyq-table)) 
        (if (nth 7 (nth nyqfn nyq-table)) 
            (pre-listen (nth 7 (nth nyqfn nyq-table))) 
            (pre-listen (nth 6 (nth nyqfn nyq-table))))
        (format t "~%No example to play")))
  (when (nth 8 (nth nyqfn nyq-table))
    (format t "~%~%Further examples under:~%~a"
      (nth 8  (nth nyqfn  nyq-table)))))

;; The same from above for XLISP primitives
(defun xlisp-display ()
  (setf xlisp-table (get-fn-table "Xlispref.dat"))
  (format t "~a (~a/~a)~%" 
    (first (nth xlispfn xlisp-table)) 
    xlispfn 
    (length xlisp-table))
  (format t "Syntax for this ~a~a~%"
    (second (nth xlispfn xlisp-table))
    (third (nth xlispfn xlisp-table)))
  (format t "Description: ~%~a~%" 
    (fourth  (nth xlispfn xlisp-table)))
  (format t "Examples: ~%~a~%" 
    (nth 4  (nth xlispfn xlisp-table))))

;; Start of the main-code
(if (equal (prop "last") nil)
    (progn 
      (prop "nyquist" 0)
      (prop "xlisp" 0)
      (prop "last" 0)
      nil))
(cond
  ((and (not-eql (prop "nyquist") nyqfn) (not-eql (prop "xlisp") xlispfn))
    (nyq-display)
    (prop "nyquist" nyqfn)
    (format t "~%     ----------------~%")
    (xlisp-display)
    (prop "xlisp" xlispfn)
    (prop "last" 0))
  ((not-eql (prop "nyquist") nyqfn)
    (nyq-display)
    (prop "nyquist" nyqfn)
    (prop "last" 0))
  ((not-eql (prop "xlisp") xlispfn)
    (xlisp-display)
    (prop "xlisp" xlispfn)
    (prop "last" 1))
  (t 
    (case (prop "last")
          (0 (nyq-display)
             (prop "nyquist" nyqfn)
             (prop "last" 1))
          (1 (xlisp-display)
             (prop "xlisp" xlispfn)
             (prop "last" 0)))))

(format nil "Please see debug-window for results")

Great Job, Steve
(Uploaded as version 1.1 in the first post)

You know, this plug-in project was startet some months ago, when I not even knew the differences between “Set”, “Setq” and “Setf”. It is a typical example for the method “learning by doing”. All techniques are gathered together, coarse to elegant and begginner to highly advanced.
Most features in Notepad++ are not accessible, such as highlighting syntax tabs in the different settings dialogs etc. I personally like to have the last two parenthesis (from “defun” and “let”) to be indicated by a comment. But much more important are the empty lines between the functions. Those allow the navigation in paragraphs -were there only ";"s, you’d jump from the beginning to the end of the program.
It’s nice to have a readable version now. However, the strings after the multi choice controls are always automatically created for each new version of the plug-in, thus their layout will be destroyed again.
Can you put this version into the first post or shall I copy your code and load it up myself?

If you are anticipating further changes in the near future I’d suggest that you just keep a copy of this for now and use it in the next version.
If you’re not planning any immediate changes, then I’d suggest that you “repackage” the ZIP file with this version and replace the previous ZIP file.
These are just suggestions - it’s your plug-in so it’s up to you what you want to do :smiley:


I don’t think that scrolling is supported on any platform, but copying is supported on Linux. It may just be Windows that does not support copying.

I’ve looked at a few more of the screens, and some of them are just too big for a non-scrolling window.

Ok, I’ll put it up soon. (Done, version 1.1)
There are some new releases planned, but not for the nearest future. I hope that some snippets and feature requests will be posted here.

Some possible features for the new versions are:

  • Selecting a specific Snippet.
  • sending a list of all snippets where the currently selected function is used to the debug window.
  • A search box for text that is contained within a function name (e.g. list of all functions with “snd-”).
  • Inclusion of a short speech and a short music sample to demonstrate the usage of some functions.
  • Some synthesised words for the preview e.g. “before”, “after”, Numbers etc.
  • Possibility to send the result from the snippet directly into the Audio track.
  • And many more…

There is also your interesting discussion about the storage location of data files of which the outcome may influence the next version.