 (ns overtone.gui.scope
-  (:import 
+  (:import
     (java.awt Graphics Dimension Color BasicStroke)
     (java.awt.geom Rectangle2D$Float Path2D$Float)
-     (javax.swing JFrame JPanel) 
+     (javax.swing JFrame JPanel)
     (com.sun.scenario.scenegraph JSGPanel SGText SGShape SGGroup SGTransform SGComponent
                                  SGAbstractShape$Mode)
      (com.sun.scenario.scenegraph.event SGMouseAdapter))
-  (:use 
+  (:use
      [overtone.core event sc synth ugen util time-utils]
     clojure.set
     clojure.stacktrace)


(defn test-scope []
  (if (not (connected?))
    (do 
      (boot)
      (on :examples-ready go-go-scope))
    (go-go-scope))

  (defsynth scoper-outer [buf 0]
    (scope-out (sin-osc 200) buf))

;		// linear
;	SynthDef("freqScope0", { arg in=0, fftbufnum=0, scopebufnum=1, rate=4, phase=1, dbFactor = 0.02;
;		var signal, chain, result, phasor, numSamples, mul, add;
;		mul = 0.00285;
;		numSamples = (BufSamples.kr(fftbufnum) - 2) * 0.5; // 1023 (bufsize=2048)
;		signal = In.ar(in);
;		chain = FFT(fftbufnum, signal, hop: 0.75, wintype:1);
;		chain = PV_MagSmear(chain, 1);
;		// -1023 to 1023, 0 to 2046, 2 to 2048 (skip first 2 elements DC and Nyquist)
;		phasor = LFSaw.ar(rate/BufDur.kr(fftbufnum), phase, numSamples, numSamples + 2);
;		phasor = phasor.round(2); // the evens are magnitude
;		ScopeOut.ar( ((BufRd.ar(1, fftbufnum, phasor, 1, 1) * mul).ampdb * dbFactor) + 1, scopebufnum);
;	}).send(server);

  (defsynth freq-scope-zero [in-bus 0 fft-buf 0 scope-buf 1
                             rate 4 phase 1 db-factor 0.02]
    (let [n-samples (* 0.5 (- (buf-samples fft-buf) 2))
          signal (in in-bus)
          chain  (pv-mag-smear (fft fft-buf signal 0.75 :hann) 1)
          phasor (+ (+ n-samples 2)
                    (* n-samples
                       (lf-saw (/ rate (buf-dur fft-buf)) phase)))
          phasor (round phasor 2)]
      (scope-out (* db-factor (ampdb (* 0.00285 (buf-rd 1 fft-buf phasor 1 1))))
                 scope-buf))))

;	// logarithmic
;	SynthDef("freqScope1", { arg in=0, fftbufnum=0, scopebufnum=1, rate=4, phase=1, dbFactor = 0.02;
;		var signal, chain, result, phasor, halfSamples, mul, add;
;		mul = 0.00285;
;		halfSamples = BufSamples.kr(fftbufnum) * 0.5;
;		signal = In.ar(in);
;		chain = FFT(fftbufnum, signal, hop: 0.75, wintype:1);
;		chain = PV_MagSmear(chain, 1);
;		phasor = halfSamples.pow(LFSaw.ar(rate/BufDur.kr(fftbufnum), phase, 0.5, 0.5)) * 2; // 2 to bufsize
;		phasor = phasor.round(2); // the evens are magnitude
;		ScopeOut.ar( ((BufRd.ar(1, fftbufnum, phasor, 1, 1) * mul).ampdb * dbFactor) + 1, scopebufnum);
;	}).send(server);
;
;(def scope-buf (buffer 2048))

;(defsynth mellow [out-bus 20 freq 440 len 20]
;  (out out-bus
;  (* (x-line:kr 0.8 0.01 len :free) 0.1
;    (+ (sin-osc (/ freq 2))
;       (rlpf (saw (+ freq (* (sin-osc 6) 6))) 440 0.2)))))
;

(if (connected?)
  (define-synths)
  (on :connected define-synths))

(defonce x-array (int-array (:width @scope*)))
(defonce _x-init (dotimes [i (:width @scope*)]
                   (aset x-array i i)))

(defonce y-array (int-array (:width @scope*)))
(defonce _y-init (dotimes [i (:width @scope*)]
                   (aset y-array i (/ (:height @scope*) 2))))

(def X-PADDING 5)
(def Y-PADDING 10)

(defn- update-scope []
  (let [{:keys [buf buf-size width height panel]} @scope*
        frames (buffer-data (:buf @scope*))
        step (int (/ buf-size width))
        y-scale (/ (- height (* 2 Y-PADDING)) 2)
        y-shift (+ (/ height 2) Y-PADDING)]
    (dotimes [x width]
      (aset #^ints y-array x
            (int (+ y-shift 
                    (* y-scale 
                       (aget #^floats frames (unchecked-multiply x step))))))))
  (.repaint (:panel @scope*)))

(defn- paint-scope [g]
  (let [{:keys [background width height color]} @scope*]
    (.setColor #^Graphics g #^Color background)
    (.fillRect #^Graphics g 0 0 width height)
    (.setColor #^Graphics g #^Color (Color. 100 100 100))
    (.drawRect #^Graphics g 0 0 width height)

    (.setColor #^Graphics g #^Color color)
    (.drawPolyline #^Graphics g #^ints x-array #^ints y-array width)))

(defn- clean-scope []
  (dosync
