(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
<[email protected]>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 <[email protected]> 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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---