;; neuromuse
;; Frederic Voisin, 2000 - 2003

;;connection d'un MLP au MIDI

;; ce fichier a servi a plusieurs presentations:
;;au Web-Bar en decembre 2001,
;; seminaire interne recherche et creation IRCAM, mars 2002
;;PRISMA (Anomos) Workshop at Tempo-Real, janv. 2003


;;variables diverses...
(defvar *memlost* .0)
(defvar *temp* .0)
(defvar *end* nil)
(defvar time .001)
(defvar time2 .001)

;cf http://www.neuromuse.org/lefrigo/pulse3g-learn_tutorial.html

(defvar test-score '(#(0.1 0.9 0.9 0.1) #(0.9 0.9 0.1 0.9) #(0.1 0.9 0.9 0.1) #(0.9 0.9 0.1 0.9)
                #(0.1 0.9 0.9 0.1) #(0.9 0.9 0.1 0.9) #(0.1 0.9 0.9 0.1) #(0.9 0.9 0.1 0.9))
)

(setf test-score '(#(0.9 0.9 0.9 0.1) #(0.1 0.1 0.1 0.1) #(0.1 0.1 0.1 0.1) #(0.9 0.1 0.9 0.1)
                   #(0.9 0.9 0.9 0.1) #(0.1 0.1 0.1 0.1) #(0.1 0.1 0.1 0.1) #(0.9 0.1 0.9 0.1))
)

(defun play-pulse3G ()
   (let ((r1 (list (car test-score))))
      (gc)
      (setf (recurrent-layer-activation pulse3g)  (coerce (make-list 4 :initial-element 0) 'vector) )
      (loop until *end*
               do
               (wait-for time2)
               (push (run-mlp pulse3g (car r1)
                                       :out-func #'logistic
                                       :hidden-func #'logistic
                                       :thresh 1.
                                       :temp *temp*
                                       :slope .99)
                         r1)
               (dotimes (n (length (recurrent-layer-activation pulse3G)))
                  (setf (elt (recurrent-layer-activation pulse3G) n)
                           (+ (elt (recurrent-layer-activation pulse3G) n)
                               (- (random *memlost*) (/ *memlost* 2)))))
               (dotimes (n (length (car r1)))
                  (send-ctl (1+ n) (round (scale (elt (car r1) n) .01 1. 0 127)) 0)   ;;; <- send-ctl est une fonction MIDISHARE
                  (wait-for time)
                  )
;;on peut inclure ici une boucle d'apprentissage...
               ))
   
   (format t "~%PULSE3G stop playing.")
   (values)
   )

;;; DEFINE SEPARATE LISP PROCESS to RUN

(defclass net-process (process)
    ())
 
(copy-mlpj pulse3G pulse3G-clone)

(defvar time .1)
(defvar *pulse3G-PROCESS* (make-process "pulse3G"))

(process-preset *pulse3G-PROCESS* #'play-pulse3G)
(setf time .01)
(setf time .1)
(setf time2 .1)
(process-enable *pulse3G-PROCESS*)  ; on active le process
(process-block *pulse3G-PROCESS* "run = wait !")  ; pause
(process-unblock *pulse3G-PROCESS*) ; resume
(process-disable *pulse3G-PROCESS*)  ; desactive le process



;;definir une fonction pour l'apprentissage
(defun pulse3g-learn-fct ()

(learn  pulse3g
                (butlast test-score)
                (cdr test-score)
                :temp .005
                :slope (+ .99 (random .02))
                :learn learn
                :error .001
                :stop 1 ;(- 500 (floor (* 10 k)))
                :thresh 1.0
                :input-func nil
                :out-func #'logistic
                :hidden-func #'logistic
                :method 'sequence
                :monitor nil
                :verbose nil))

;; et l'utiliser ensuite dans un process separe comme pour le run...



;;fred