(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
-~----------~----~----~----~------~----~------~--~---

Reply via email to