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