Beats Per Minute

Using Nyquist scripts in Audacity.
Post and download new plug-ins.
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
vedshree
Posts: 20
Joined: Wed Feb 26, 2014 6:26 am
Operating System: Please select

Re: Beats Per Minute

Post by vedshree » Thu Mar 06, 2014 4:53 pm

hi,
Following is the code that we tried for retrieving the time.

Code: Select all

;nyquist plug-in
;version 1
;type analyze
;categories "http://audacityteam.org/namespace#OnsetDetector"
;name "Beat Per Minute"
;action "BPM..."
;; Released under terms of the GNU General Public License version 2:
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 
;control thresval "Threshold Percentage" int "" 65 5 100
(setf s1 (if (arrayp s) (snd-add (aref s 0) (aref s 1)) s))
(defun signal () (force-srate 1000 (lp (snd-follow (lp s1 50) 0.001 0.01 0.1 512) 10)))
(setq max (peak (signal) NY:ALL))
(setq thres (* (/ thresval 100.0) max))
(setq s2 (signal))
(do ((time 0.0) (listB NIL) (checkval 1) (belowThres T) (val (snd-fetch s2))) ((not val) listB)
 (if (and(and belowThres(> val thres)) (= checkval 1))
      (progn
	     (setq listB (cons (list time "B") listB))
	(setf sampv1 (if (arrayp val) (snd-add (aref val 0) (aref val 1)) val))
(snd-srate sampv1)
(snd-t0 sampv1)
	     (setq checkval 0)     
      )
 )
 (if (and belowThres (< val thres)) 
	(setq checkval 1) 
 )
(setq belowThres (< val thres))
(setq time (+ time 0.001))
(setq val (snd-fetch s2)) 
)
We are getting the following error:
error: bad argument type - 0.469504
Function: #<Subr-SND-SRATE: #aa82998>
Arguments:
0.469504
Function: #<FSubr-PROGN: #aa7d750>
Arguments:
(SETQ LISTB (CONS (LIST TIME "B") LISTB))
(SETF SAMPV1 (IF (ARRAYP VAL) (SND-ADD (AREF VAL 0) (AREF VAL 1)) VAL))
(SND-SRATE SAMPV1)
(SND-T0 SAMPV1)
(SETQ CHECKVAL 0)
Function: #<FSubr-IF: #aa7d840>
Arguments:
(AND (AND BELOWTHRES (> VAL THRES)) (= CHECKVAL 1))
(PROGN (SETQ LISTB (CONS (LIST TIME "B") LISTB)) (SETF SAMPV1 (IF (ARRAYP VAL) (SND-ADD (AREF VAL 0) (AREF VAL 1)) VAL)) (SND-SRATE SAMPV1) (SND-T0 SAMPV1) (SETQ CHECKVAL 0))
Function: #<FSubr-DO: #aa7d6c0>
Arguments:
((TIME 0) (LISTB NIL) (CHECKVAL 1) (BELOWTHRES T) (VAL (SND-FETCH S2)))
((NOT VAL) LISTB)
(IF (AND (AND BELOWTHRES (> VAL THRES)) (= CHECKVAL 1)) (PROGN (SETQ LISTB (CONS (LIST TIME "B") LISTB)) (SETF SAMPV1 (IF (ARRAYP VAL) (SND-ADD (AREF VAL 0) (AREF VAL 1)) VAL)) (SND-SRATE SAMPV1) (SND-T0 SAMPV1) (SETQ CHECKVAL 0)))
(IF (AND BELOWTHRES (< VAL THRES)) (SETQ CHECKVAL 1))
(SETQ BELOWTHRES (< VAL THRES))
(SETQ TIME (+ TIME 0.001))
(SETQ VAL (SND-FETCH S2))
1>

The bad argument type that we are getting, is that something related to time? coz, in the code we have taken a new sound variable sampv1 for which we want the start time. When sound s2 goes above the threshold, the sound at that instance is intended to be stored in sampv1. Have we done it correctly?

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

Re: Beats Per Minute

Post by steve » Thu Mar 06, 2014 6:08 pm

I'd highly recommend using a text editor that has parentheses matching, then you won't need to count the parentheses "( )" or leave them trailing in mid air.
If you're on Windows I'd recommend NotePad++ (free). It also has Syntax highlighting for Lisp, which is close enough to Nyquist to be useful.

The idea of indenting Lisp code is so that you can see which arguments belong to which functions. Note that in your DO loop you have a list of local variables assigned to values. It is much easier to "read" these if they are a list one below the other. Have another look at that page that I sent the link for about indenting code. If the code is written clearly it is much easier to spot errors.

I've added some comments to your code indicating the main problems.

Code: Select all

;nyquist plug-in
;version 1
;type analyze
;categories "http://audacityteam.org/namespace#OnsetDetector"
;name "Beat Per Minute"
;action "BPM..."
;; Released under terms of the GNU General Public License version 2:
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
;control thresval "Threshold Percentage" int "" 65 5 100

(setf s1
  (if (arrayp s)
      (snd-add (aref s 0) (aref s 1))
      s))

(defun signal ()
  (force-srate 1000
    (lp (snd-follow (lp s1 50) 0.001 0.01 0.1 512)
        10)))

(setq max-sig (peak (signal) NY:ALL))
(setq thres (* (/ thresval 100.0) max-sig))
(setq s2 (signal))

(do ((time 0.0)
     (listB ())
     (checkval 1)
     (belowThres T)
     (val (snd-fetch s2)))  ; snd-fetch only works on sounds, not arrays
    ((not val) listB)
  (if (and (and belowThres (> val thres))
           (= checkval 1))
      (progn
        (setf listB (cons (list time "B") listB))
        ;; What is SAMPV1 for?
        (setf sampv1
          ; val cannot be an array. It is a number [float]
          (if (arrayp val)
              (snd-add (aref val 0) (aref val 1))
              val))
        ;; sampv1 is not a sound. it is a number.
        ;(snd-srate sampv1)
        ;(snd-t0 sampv1)
        (setq checkval 0)))
  (if (and belowThres (< val thres))
      (setq checkval 1))
  (setq belowThres (< val thres))
  (setq time (+ time 0.001))
  (setq val (snd-fetch s2)))

9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

Post Reply