DSP-DEBUG is an utility to debug a definition of a DSP. The syntax is the same of DSP! but DSP-DEBUG returns a function to call with the arguments of the DSP. The result of the evaluation of that function is the code generated by DSP!. Here is an example:

SCRATCH> (dsp-debug foo (freq amp pos)
           (foreach-channel
             (cout (pan2 (osc *sine-table* freq amp 0 :linear) pos))))
#<FUNCTION (LAMBDA (FREQ AMP POS &OPTIONAL ...)) {10085C184B}>
SCRATCH> (funcall * 440 .3 .5)
(LAMBDA (INCUDINE.VUG::%DSP-NODE%)
  (DECLARE (OPTIMIZE SPEED (SAFETY 0))
           (TYPE NODE INCUDINE.VUG::%DSP-NODE%))
  (LET* ((#:DSP-CONS18 (INCUDINE.VUG::DSP-INST-POOL-POP-CONS))
         (#:DSP19 (CAR #:DSP-CONS18))
         (#:CONTROL-TABLE2 (INCUDINE.VUG::DSP-CONTROLS #:DSP19))
         (#:FUNCTION-OBJECT22 (SYMBOL-FUNCTION 'FOO))
         (#:FREE-HOOK21
          (LIST
           (LAMBDA (#:NODE20)
             (DECLARE (IGNORE #:NODE20)
                      (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
             (IF (EQ #:FUNCTION-OBJECT22 (SYMBOL-FUNCTION 'FOO))
                 (INCUDINE.VUG::STORE-DSP-INSTANCE 'FOO #:DSP-CONS18)
                 (INCUDINE.VUG::FREE-DSP-CONS #:DSP-CONS18)))))
         (#:C-ARRAY-SAMPLE-WRAP3 (INCUDINE.VUG::MAKE-FOREIGN-SAMPLE-ARRAY 13))
         (#:C-ARRAY-SAMPLE8
          (INCUDINE.VUG::FOREIGN-SAMPLE-ARRAY-DATA #:C-ARRAY-SAMPLE-WRAP3)))
    (DECLARE (TYPE CONS #:DSP-CONS18 #:FREE-HOOK21)
             (TYPE INCUDINE.VUG::DSP #:DSP19)
             (TYPE HASH-TABLE #:CONTROL-TABLE2))
    (INCUDINE.VUG::WITH-FOREIGN-SYMBOLS (#:FREQ880 #:AMP881 #:POS882 #:FREQ883
                                         #:AMP884 #:POS885 #:%FREQ179887
                                         #:%AMP180888 #:FRAC187893
                                         #:LODIV189894 #:IN897 #:POS898
                                         #:ALPHA899)
        #:C-ARRAY-SAMPLE8
        'SAMPLE
      (INCUDINE.VUG::WITH-FOREIGN-VARIABLES (NIL #:C-ARRAY-FLOAT9 NIL
                                             #:C-ARRAY-DOUBLE10 NIL
                                             #:C-ARRAY-INT3211 NIL
                                             #:C-ARRAY-INT6412)
        (SETF #:FREQ883 440.0d0)
        (SETF #:AMP884 0.30000001192092896d0)
        (SETF #:POS885 0.5d0)
        (LET* ((#:%BUFFER178886 *SINE-TABLE*))
          (DECLARE (TYPE BUFFER #:%BUFFER178886))
          (SETF #:%FREQ179887 #:FREQ883)
          (SETF #:%AMP180888 #:AMP884)
          (LET* ((#:FREQ-INC181889
                  (SAMPLE->FIXNUM (* #:%FREQ179887 *CPS2INC*)))
                 (#:PHS182890 0)
                 (#:MINUS-LOBITS183891 (- (BUFFER-LOBITS #:%BUFFER178886)))
                 (#:DATA184892 (BUFFER-DATA #:%BUFFER178886)))
            (DECLARE (TYPE FIXNUM #:FREQ-INC181889))
            (DECLARE (TYPE FIXNUM #:PHS182890))
            (DECLARE (TYPE (INTEGER -24 0) #:MINUS-LOBITS183891))
            (DECLARE (TYPE FOREIGN-POINTER #:DATA184892))
            (SETF #:FRAC187893 0.0d0)
            (SETF #:LODIV189894 (BUFFER-LODIV #:%BUFFER178886))
            (LET* ((#:LOMASK190895 (BUFFER-LOMASK #:%BUFFER178886))
                   (#:MASK188896 (BUFFER-MASK #:%BUFFER178886)))
              (DECLARE (TYPE NON-NEGATIVE-FIXNUM #:LOMASK190895))
              (DECLARE (TYPE NON-NEGATIVE-FIXNUM #:MASK188896))
              (SETF #:POS898 #:POS885)
              (SETF #:ALPHA899 (* +HALF-PI+ #:POS898))
              (PROGN
               (SETF (GETHASH "FREQ" #:CONTROL-TABLE2)
                       (CONS
                        (LAMBDA (#:VALUE911)
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          (INCUDINE.VUG::%WITH-SET-CONTROL (NIL #:FREQ880
                                                            #:VALUE911 SAMPLE)
                            (PROGN
                             (SETF #:FREQ883 #:FREQ880)
                             (SETF #:%FREQ179887 #:FREQ883)
                             (SETF #:FREQ-INC181889
                                     (SAMPLE->FIXNUM
                                      (* #:%FREQ179887 *CPS2INC*)))
                             (VALUES))))
                        (LAMBDA ()
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          #:FREQ883)))
               (SETF (GETHASH "AMP" #:CONTROL-TABLE2)
                       (CONS
                        (LAMBDA (#:VALUE911)
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          (INCUDINE.VUG::%WITH-SET-CONTROL (NIL #:AMP881
                                                            #:VALUE911 SAMPLE)
                            (PROGN
                             (SETF #:AMP884 #:AMP881)
                             (SETF #:%AMP180888 #:AMP884)
                             (VALUES))))
                        (LAMBDA ()
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          #:AMP884)))
               (SETF (GETHASH "POS" #:CONTROL-TABLE2)
                       (CONS
                        (LAMBDA (#:VALUE911)
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          (INCUDINE.VUG::%WITH-SET-CONTROL (NIL #:POS882
                                                            #:VALUE911 SAMPLE)
                            (PROGN
                             (SETF #:POS885 #:POS882)
                             (SETF #:POS898 #:POS885)
                             (SETF #:ALPHA899 (* +HALF-PI+ #:POS898))
                             (VALUES))))
                        (LAMBDA ()
                          (DECLARE
                           (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                          #:POS885)))
               (SETF (GETHASH (LIST :POINTER "FREQ") #:CONTROL-TABLE2)
                       (LOCALLY
                        (DECLARE
                         (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                        (CONS (GET-POINTER #:FREQ880)
                              (LAMBDA ()
                                (DECLARE
                                 (SB-EXT:MUFFLE-CONDITIONS
                                  SB-EXT:COMPILER-NOTE))
                                (PROGN
                                 (SETF #:FREQ883 #:FREQ880)
                                 (SETF #:%FREQ179887 #:FREQ883)
                                 (SETF #:FREQ-INC181889
                                         (SAMPLE->FIXNUM
                                          (* #:%FREQ179887 *CPS2INC*)))
                                 (VALUES))))))
               (SETF (GETHASH (LIST :POINTER "AMP") #:CONTROL-TABLE2)
                       (LOCALLY
                        (DECLARE
                         (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                        (CONS (GET-POINTER #:AMP881)
                              (LAMBDA ()
                                (DECLARE
                                 (SB-EXT:MUFFLE-CONDITIONS
                                  SB-EXT:COMPILER-NOTE))
                                (PROGN
                                 (SETF #:AMP884 #:AMP881)
                                 (SETF #:%AMP180888 #:AMP884)
                                 (VALUES))))))
               (SETF (GETHASH (LIST :POINTER "POS") #:CONTROL-TABLE2)
                       (LOCALLY
                        (DECLARE
                         (SB-EXT:MUFFLE-CONDITIONS SB-EXT:COMPILER-NOTE))
                        (CONS (GET-POINTER #:POS882)
                              (LAMBDA ()
                                (DECLARE
                                 (SB-EXT:MUFFLE-CONDITIONS
                                  SB-EXT:COMPILER-NOTE))
                                (PROGN
                                 (SETF #:POS885 #:POS882)
                                 (SETF #:POS898 #:POS885)
                                 (SETF #:ALPHA899 (* +HALF-PI+ #:POS898))
                                 (VALUES))))))
               (SETF (GETHASH "%CONTROL-LIST%" #:CONTROL-TABLE2)
                       (CONS NIL
                             (LAMBDA ()
                               (DECLARE
                                (SB-EXT:MUFFLE-CONDITIONS
                                 SB-EXT:COMPILER-NOTE))
                               (LIST #:FREQ883 #:AMP884 #:POS885))))
               (SETF (GETHASH "%CONTROL-NAMES%" #:CONTROL-TABLE2)
                       (CONS NIL (LAMBDA () '(FREQ AMP POS)))))
              (PROGN
               (SETF (INCUDINE.VUG::DSP-NAME #:DSP19) 'FOO)
               (SETF (INCUDINE::NODE-CONTROLS INCUDINE.VUG::%DSP-NODE%)
                       #:CONTROL-TABLE2)
               (INCUDINE.VUG::UPDATE-FREE-HOOK INCUDINE.VUG::%DSP-NODE%
                                               #:FREE-HOOK21)
               (INCUDINE.VUG::REORDER-INITIALIZATION-CODE)
               (LET ((CURRENT-CHANNEL 0))
                 (DECLARE (TYPE CHANNEL-NUMBER CURRENT-CHANNEL)
                          (IGNORABLE CURRENT-CHANNEL))
                 (VALUES))
               (INCUDINE.VUG::SET-DSP-OBJECT #:DSP19 :INIT-FUNCTION
                                             (LAMBDA (#:NODE20 FREQ AMP POS)
                                               (DECLARE
                                                (SB-EXT:MUFFLE-CONDITIONS
                                                 SB-EXT:COMPILER-NOTE))
                                               (SETF (INCUDINE::NODE-CONTROLS
                                                      #:NODE20)
                                                       (INCUDINE.VUG::DSP-CONTROLS
                                                        #:DSP19))
                                               (SETF INCUDINE.VUG::%DSP-NODE%
                                                       #:NODE20)
                                               (PROGN
                                                (SETF #:FREQ883 FREQ)
                                                (SETF #:AMP884 AMP)
                                                (SETF #:POS885 POS)
                                                (SETF #:%BUFFER178886
                                                        *SINE-TABLE*)
                                                (SETF #:%FREQ179887 #:FREQ883)
                                                (SETF #:%AMP180888 #:AMP884)
                                                (SETF #:FREQ-INC181889
                                                        (SAMPLE->FIXNUM
                                                         (* #:%FREQ179887
                                                            *CPS2INC*)))
                                                (SETF #:PHS182890 0)
                                                (SETF #:MINUS-LOBITS183891
                                                        (-
                                                         (BUFFER-LOBITS
                                                          #:%BUFFER178886)))
                                                (SETF #:DATA184892
                                                        (BUFFER-DATA
                                                         #:%BUFFER178886))
                                                (SETF #:FRAC187893 0.0d0)
                                                (SETF #:LODIV189894
                                                        (BUFFER-LODIV
                                                         #:%BUFFER178886))
                                                (SETF #:LOMASK190895
                                                        (BUFFER-LOMASK
                                                         #:%BUFFER178886))
                                                (SETF #:MASK188896
                                                        (BUFFER-MASK
                                                         #:%BUFFER178886))
                                                (SETF #:POS898 #:POS885)
                                                (SETF #:ALPHA899
                                                        (* +HALF-PI+
                                                           #:POS898)))
                                               (INCUDINE.VUG::UPDATE-FREE-HOOK
                                                #:NODE20 #:FREE-HOOK21)
                                               (LET ((CURRENT-CHANNEL 0))
                                                 (DECLARE
                                                  (TYPE CHANNEL-NUMBER
                                                   CURRENT-CHANNEL)
                                                  (IGNORABLE CURRENT-CHANNEL))
                                                 (VALUES))
                                               #:NODE20)
                                             :FREE-FUNCTION
                                             (LAMBDA ()
                                               (INCUDINE.VUG::FREE-FOREIGN-SAMPLE-ARRAY
                                                #:C-ARRAY-SAMPLE-WRAP3))
                                             :PERF-FUNCTION
                                             (LAMBDA ()
                                               (LET ((CURRENT-CHANNEL 0))
                                                 (DECLARE
                                                  (TYPE CHANNEL-NUMBER
                                                   CURRENT-CHANNEL)
                                                  (IGNORABLE CURRENT-CHANNEL))
                                                 (BLOCK NIL
                                                   (LET ((#:I172 0))
                                                     (DECLARE
                                                      (TYPE CHANNEL-NUMBER
                                                       #:I172))
                                                     (TAGBODY
                                                       (GO #:G174)
                                                      #:G173
                                                       (TAGBODY
                                                         (LET ((CURRENT-CHANNEL
                                                                #:I172))
                                                           (DECLARE
                                                            (TYPE
                                                             CHANNEL-NUMBER
                                                             CURRENT-CHANNEL)
                                                            (IGNORABLE
                                                             CURRENT-CHANNEL))
                                                           (PROGN
                                                            NIL
                                                            (LET* ((#:CURRENT-CHANNEL176
                                                                    CURRENT-CHANNEL)
                                                                   (#:G177
                                                                    (SAMPLE
                                                                     (IF (ZEROP
                                                                          CURRENT-CHANNEL)
                                                                         (*
                                                                          (COS
                                                                           #:ALPHA899)
                                                                          (SETF #:IN897
                                                                                  (PROGN
                                                                                   (VALUES)
                                                                                   (LET ((#:INDEX185
                                                                                          (THE
                                                                                           FIXNUM
                                                                                           (INCUDINE.VUG::ASH
                                                                                            #:PHS182890
                                                                                            #:MINUS-LOBITS183891))))
                                                                                     (LET ((#:G186
                                                                                            (*
                                                                                             #:%AMP180888
                                                                                             (PROGN
                                                                                              (SETQ #:FRAC187893
                                                                                                      (*
                                                                                                       #:LODIV189894
                                                                                                       (LOGAND
                                                                                                        #:PHS182890
                                                                                                        #:LOMASK190895)))
                                                                                              (LINEAR-INTERP
                                                                                               #:FRAC187893
                                                                                               (SMP-REF
                                                                                                #:DATA184892
                                                                                                #:INDEX185)
                                                                                               (SMP-REF
                                                                                                #:DATA184892
                                                                                                (LOGAND
                                                                                                 (THE
                                                                                                  FIXNUM
                                                                                                  (1+
                                                                                                   #:INDEX185))
                                                                                                 #:MASK188896)))))))
                                                                                       (SETQ #:PHS182890
                                                                                               (LOGAND
                                                                                                (THE
                                                                                                 FIXNUM
                                                                                                 (+
                                                                                                  #:PHS182890
                                                                                                  #:FREQ-INC181889))
                                                                                                +PHASE-MASK+))
                                                                                       #:G186)))))
                                                                         (IF (<
                                                                              CURRENT-CHANNEL
                                                                              2)
                                                                             (*
                                                                              (SIN
                                                                               #:ALPHA899)
                                                                              #:IN897)
                                                                             (THE
                                                                              T
                                                                              +SAMPLE-ZERO+)))))
                                                                   (#:NEW175
                                                                    (+
                                                                     (AUDIO-OUT
                                                                      #:CURRENT-CHANNEL176)
                                                                     #:G177)))
                                                              (INCUDINE::SET-AUDIO-OUT
                                                               #:CURRENT-CHANNEL176
                                                               #:NEW175)))))
                                                       (LET* ()
                                                         (LET ((#:NEW191
                                                                (1+ #:I172)))
                                                           (PROGN
                                                            (SETQ #:I172
                                                                    #:NEW191)
                                                            NIL)))
                                                      #:G174
                                                       (IF (>= #:I172
                                                               *NUMBER-OF-OUTPUT-BUS-CHANNELS*)
                                                           NIL
                                                           (GO #:G173))
                                                       (RETURN-FROM NIL NIL))))
                                                 (VALUES))))))))))))

The generated code is divided in the follow parts:

The FREE-DSP-INSTANCES function is useful to free the memory pool for the instances of one or all DSPs.

SCRATCH> (free-dsp-instances)
SCRATCH> (get-foreign-sample-free-size)
67102464
SCRATCH> (get-rt-memory-free-size)
67102464

GET-FOREIGN-SAMPLE-FREE-SIZE returns the free available memory for the allocations of SAMPLE type used inside the code generated by DSP!. We can set the size of the relative memory pool by changing the value of *FOREIGN-SAMPLE-POOL-SIZE* in $HOME/.incudinerc (the default is 64MB).

GET-RT-MEMORY-FREE-SIZE returns the free available memory allocable in realtime on the C heap, without considering the allocations of SAMPLE type counted by GET-FOREIGN-SAMPLE-FREE-SIZE. We can set the size of the relative memory pool by changing the value of *FOREIGN-RT-MEMORY-POOL-SIZE* in $HOME/.incudinerc (the default is 64MB).

DESTROY-DSP is useful to completely remove a DSP and all the associated memory.

ALL-DSP-NAMES returns all the defined DSPs. We can use the combination of DESTROY-DSP and ALL-DSP-NAMES to remove all the defined DSP:

SCRATCH> (mapc #'destroy-dsp (all-dsp-names))
SCRATCH> (all-dsp-names)
NIL

Incudine has some facilities for diagnostics. There are four levels for the logger:

Every level in the list enables the previous levels. It means that if LOGGER-LEVEL is :DEBUG, all the levels are enabled. If LOGGER-LEVEL is :ERROR, only the error messages are enabled. The default is :WARN.

*LOGGER-STREAM* is *STANDARD-OUTPUT* and *LOGGER-FORCE-OUTPUT* is T by default.

Some examples:

SCRATCH> (logger-level)
:WARN
SCRATCH> (msg error "wrong direction")
ERROR: wrong direction
NIL
SCRATCH> (msg warn "the DSP can explode")
WARN: the DSP can explode
NIL
SCRATCH> (msg info "new group ~A" (1+ (random 100)))
NIL
SCRATCH> (setf (logger-level) :info)
:INFO
SCRATCH> (msg info "new group ~A" (1+ (random 100)))
new group 42
NIL
SCRATCH> (msg debug "the value of FREQ is ~,2F" (random 1000.0))
NIL
SCRATCH> (setf (logger-level) :debug)
:DEBUG
SCRATCH> (msg debug "the value of FREQ is ~,2F" (random 1000.0))
DEBUG: the value of FREQ is 826.75
NIL
SCRATCH> (msg info "free all nodes")
free all nodes
NIL
SCRATCH> (setf (logger-level) :error)
:ERROR
SCRATCH> (msg warn "a wolf!")
NIL
SCRATCH> (setf (logger-level) :warn)
:WARN
SCRATCH> (msg warn "a wolf!")
WARN: a wolf!
NIL
SCRATCH> (msg error "unknown device")
ERROR: unknown device
NIL

LOGGER-TIME is useful to show the time of the message. The possible values for LOGGER-TIME are :SEC (seconds) and :SAMP (samples)

SCRATCH> (logger-time)
NIL
SCRATCH> (setf (logger-time) :sec)
:SEC
SCRATCH> (msg warn "too late")
13878.763 WARN: too late
NIL
SCRATCH> (setf (logger-time) :samp)
:SAMP
SCRATCH> (msg warn "too late")
667113472.0 WARN: too late
NIL
SCRATCH> (setf (logger-time-function)
               (lambda ()
                 (let ((seconds-p (eq (logger-time) :sec)))
                   (format *logger-stream* "[~:[~,1F~;~,3F~]] " seconds-p
                           (* (now) (if seconds-p *sample-duration* 1))))))
SCRATCH> (msg warn "LOGGER-TIME-FUNCTION redefined")
[675466240.0] WARN: LOGGER-TIME-FUNCTION redefined
NIL
SCRATCH> (setf (logger-time-function) nil)
#<FUNCTION INCUDINE.UTIL::DEFAULT-LOGGER-TIME-FUNCTION>
SCRATCH> (setf (logger-time) nil)
NIL

We have to use NRT-MSG instead of MSG for the messages in the realtime thread. For example:

SCRATCH> (rt-eval () (msg warn "Don't use MSG in the rt thread!")) ; wrong
WARN: Don't use MSG in the rt thread!
NIL
SCRATCH> (setf (logger-level) :info)
:INFO
SCRATCH> (rt-eval () (nrt-msg info "Ok, NRT-MSG is good in the rt thread"))
Ok, NRT-MSG is good in the rt thread
NIL
SCRATCH> (setf (logger-level) :warn)
:WARN
SCRATCH> (msg warn "~A" (map 'string #'code-char '(84 72 69 32 69 78 68)))
WARN: THE END

Sourceforge project page