One comment, although this has no effect on performance: you don't need to use the static class fields as functions. That is, you can write Math/PI and Short/MAX_VALUE instead of (Math/PI) and (Short/ MAX_VALUE).
-Stuart Sierra 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 -~----------~----~----~----~------~----~------~--~---