Also type hinting your math ops like mad on tight loops helps:

;; ~20ms
(time (dotimes [x 1000000]
        (* (float 1.0) (* (float 2.0) (float 3.0)))))

;; ~65ms
(time (dotimes [x 1000000]
        (* 1.0 (* 2.0 3.0))))

Another 3x increase.

On May 9, 6:53 pm, Julien <julien.ma...@gmail.com> wrote:
> I'm interested to do audio synthesis and eventually audio DSP on the
> JVM using the Java sound API and I think that it could be fun to do
> that following the functional programming paradigm.
> I don't intend to build a huge library but just to try some experiment
> on my own to better understand how digital audio synthesis work.
>
> Here is a piece of code that is filling up a byte array putting into
> it audio samples calculated from the math sin function.
> I'm trying to convert this java code into clojure. While the java
> version is almost instantaneous my clojure version is way too slow. So
> I figured I must be doing something wrong.
>
> It is assuming that the audio channel is mono and sample size of 16
> bits. The sample rate is set to 44100Hz.
>
> -java code
> int EXTERNAL_BUFFER_SIZE = 128000;
> byte[]  sampleArray = new byte[EXTERNAL_BUFFER_SIZE*20];
>
> float frequency = 2000; //  Hz
> double sampleInterval = frequency/sampleRate;
> short sample;
> float impulseTrain = 0;
> for(int sampleIndex=0;sampleIndex+1<sampleArray.length;sampleIndex+=2)
> {
>         sample = (short) (Short.MAX_VALUE * Math.sin(impulseTrain * 2 *
> Math.PI));
>         sampleArray[sampleIndex] = (byte) (sample >> 8);
>         sampleArray[sampleIndex+1] = (byte) (sample & 0xFF);
>
>         impulseTrain += sampleInterval;
>         if(impulseTrain>1) impulseTrain -= 1;
>
> }
>
> -my clojure function
> (defn byte-array-sound [frequency sample-rate nb-frame]
>         (let [sample-array (make-array (. Byte TYPE) (* nb-frame 2))
>                                 sample-interval (/ frequency sample-rate)
>                                 limit (alength sample-array)]
>                 (loop [sample-index 0
>                                          impulse-train 0]
>                                 (let [sample (short (* (Short/MAX_VALUE) 
> (Math/sin (* impulse-
> train 2 (Math/PI)))))]
>                                         (aset sample-array sample-index (byte 
> (bit-shift-right sample
> 8)))
>                                         (aset sample-array (+ sample-index 1) 
> (byte (bit-and sample
> 255))))
>                                 (if (< (+ sample-index 2) limit)
>                                         (recur (inc (inc sample-index))
>                                                                  (let 
> [next-impl-tr  (+ impulse-train sample-interval)]
>                                                                          (if 
> (< next-impl-tr 1)
>                                                                               
>   next-impl-tr (- next-impl-tr 1))))
>                                         sample-array))))
>
> With a byte array of 2 560 000 bytes the java version is very fast,
> may be because of some optimizations somehow not available from
> clojure.
> I tried the clojure function with a much smaller byte array of 100 000
> bytes and it is very slow.(about 40 sec to return)
> May be clojure isn't optimize to handle primitive types as java is or
> I need to learn my clojure.
>
> I figured those functions out by myself so there might be another way
> to achieve the same thing more efficiently.
> My knowledge about audio synthesis, DSP is just growing.
>
> I'd appreciate any suggestions.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to