(set! *warn-on-reflection* true) (defn byte-array-sound [frequency sample-rate nb-frame] (let [sample-array (make-array (. Byte TYPE) (* nb-frame 2)) sample-interval (/ (float frequency) (float sample-rate)) limit (alength sample-array)] (loop [sample-index 0 impulse-train (float 0)] (let [sample (short (* (int (Short/MAX_VALUE)) (Math/sin (* impulse-train 2.0 (Math/PI)))))] (aset-byte sample-array sample-index (byte (bit-shift-right sample 8))) (aset-byte sample-array (+ sample-index 1) (byte (bit-and (int sample) (int 255))))) (if (< (+ sample-index 2) limit) (recur (inc (inc sample-index)) (float (let [next-impl-tr (+ impulse-train sample-interval)] (if (< next-impl-tr 1) next-impl-tr (- next-impl-tr 1))))) sample-array))))
(time (byte-array-sound 44100 96000 50000)) Takes 90ms on my machine. For some reason byte doesn't inform the compiler about the bit-and op and I had to convert the args int, also I had to type-hint Short/MAX_VALUE. Perhaps Rich Hickey or someone more knowledgeable then me can shed some light on why? On Sat, May 9, 2009 at 8:30 PM, Stuart Sierra <the.stuart.sie...@gmail.com>wrote: > > 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 -~----------~----~----~----~------~----~------~--~---