 (defn extract-spectrum
   "Extract frequency domain spectrum from time domain signal"
   ([windowed-data block-size sample-ratio spectrum-type]
-   (extract-spectrum windowed-data block-size sample-ratio spectrum-type 0.0 0.0))
+   (extract-spectrum windowed-data block-size sample-ratio spectrum-type 0.0 1.0))
   ([windowed-data block-size sample-ratio spectrum-type db-component normalised]
 
-   (let [spectrum (c-double block-size)]
-     (raise-errors
-      (xtract/xtract_spectrum windowed-data
-                              block-size (xtract-args sample-ratio
-                                                      spectrum-type
-                                                      db-component
-                                                      normalised)
-                              spectrum))
-     spectrum)))
+   (raise-errors
+    (xtract/xtract_spectrum windowed-data
+                            block-size (xtract-args sample-ratio
+                                                    spectrum-type
+                                                    db-component
+                                                    normalised)
+                            spectrum-buffer))
+   spectrum-buffer))
 
 (defn extract-fft-spectrum [wave-data block-size sample-rate full-window]
-  (let [windowed (c-double block-size)]
-    ;;NOTE: I'm not convienced the full-window parameter is being used.
+  ;;NOTE: I'm not convienced the full-window parameter is being used.
+  (raise-errors
+   (xtract/xtract_windowed wave-data block-size (xtract/doublea_to_voidp full-window) windowed-buffer))
+  (raise-errors
+   (xtract/xtract_init_fft block-size xtract-spectrum))
+  (let [spectrum-buffer (extract-spectrum windowed-buffer block-size (/ sample-rate block-size) xtract-spectrum-magnitude)]
     (raise-errors
-     (xtract/xtract_windowed wave-data block-size (xtract/doublea_to_voidp full-window) windowed))
-    (raise-errors
-     (xtract/xtract_init_fft block-size xtract-spectrum))
-    (let [spectrum (extract-spectrum windowed block-size (/ sample-rate block-size) xtract-spectrum-magnitude)]
-      (raise-errors
-       (xtract/xtract_free_fft))
-      (raise-errors
-       (xtract/delete_double_array windowed))
-      spectrum)))
+     (xtract/xtract_free_fft))
+    spectrum-buffer))
 
 (defn extract-peaks
   "Extract the amplitude and frequency of spectral peaks from a magnitude spectrum"
   [coefficients block-size sample-ratio peak-threshold]
-  (let [peaks (c-double block-size)]
-    (raise-errors
-     (xtract/xtract_peak_spectrum coefficients
-                                  (/ block-size 2)
-                                  (xtract-args sample-ratio peak-threshold)
-                                  peaks))
-    peaks))
+  (raise-errors
+   (xtract/xtract_peak_spectrum coefficients
+                                (/ block-size 2)
+                                (xtract-args sample-ratio peak-threshold)
+                                peaks-buffer))
+  peaks-buffer)
 
 (defn extract-rms-amp
   "Extract the RMS amplitude of an input vector"

        sub (features-from-subframes [1 2 4 8 10 12 14 16]
                                     (/ 8 2)
                                     xtract-hann)]

    (println (str "Mean:" m))
    (println (str "Var:" v))
    (println (str "Spectrum: " (pr-str spec)))

        f0-frames (remove (fn [frame] (let [stats (first (vals frame))]
                                        (= (:f0 stats) 0.0)
                                       )) frame-stats)
        n-f0s     (count f0-frames)
        f0-totals (reduce (global-stats-reduce fields) {} f0-frames)]

    (if (> n 0)
      (let [means
            (-> {}
                (assoc :rms-amplitude          (/ (:rms-amplitude totals) n))
                (assoc :spectral-centroid      (/ (:spectral-centroid totals) n))
                (assoc :spectral-irregularity  (/ (:spectral-irregularity totals) n))
                (assoc :spectral-kurtosis      (/ (:spectral-kurtosis totals) n))
                (assoc :spectral-skewness      (/ (:spectral-skewness totals) n)))


                ;;Only over non 0 frequencies

            non-0-means
            (if (> n-f0s 0)
              (-> {}
                  (assoc :spectral-inharmonicity (/ (:spectral-inharmonicity f0-totals) n-f0s))
                  (assoc :midi (/ (:midi f0-totals) n-f0s))
                  (assoc :f0   (/ (:f0 f0-totals) n-f0s)))
              {})

            means (merge means non-0-means)

            mins {:spectral-inharmonicity (min-for :spectral-inharmonicity f0-frames)
                  :midi (min-for :midi f0-frames)
                  :f0   (min-for :f0  f0-frames)}

            maxs {:rms-amplitude         (max-for :rms-amplitude frame-stats)
                  :spectral-centroid     (max-for :spectral-centroid frame-stats)
                  :spectral-irregularity (max-for :spectral-irregularity frame-stats)
                  :spectral-kurtosis      (max-for :spectral-kurtosis frame-stats)
                  :spectral-skewness      (max-for :spectral-skewness frame-stats)

                  :spectral-inharmonicity (max-for :spectral-inharmonicity frame-stats)
                  :midi (max-for :midi frame-stats)
                  :f0   (max-for :f0  frame-stats)}]
        {:mean means
         :max maxs
         :min mins})
      {:means {} :max {}})))

(comment

  (do
    (def all-wavs (filter #(.endsWith (.getName %) ".wav") (file-seq (io/file "/Users/josephwilk/Workspace/music/samples"))))

    (spit "sop.json" "")

    (doseq [w
            all-wavs
            ;;          ["/Users/josephwilk/Workspace/music/samples/CHILLSTEP/DCS_WAV_LOOPS/DCS_MUSIC_LOOPS/DCS_70_C_Cloud.wav"]
            ]
      (try
        (let [wav (.getPath w) ;; "test/fixtures/test.wav" ;;(.getPath wav)
              _ (println wav)
              b-stats (block-stats wav 512)
              g-stats (global-stats b-stats)
              ]

          (spit "sop.json" {:file wav :stats g-stats} :append true)
          (spit "sop.json" "\n" :append true)
          )

        (catch Exception e (println e))
        )))

  (dotimes [i 1]
    (let [block-stats (block-stats "test/fixtures/test.wav")]
