Newbish question. Does anyone have any example code for playing a wav sound file?

133 views
Skip to first unread message

Rayne

unread,
Jul 27, 2009, 9:00:26 PM7/27/09
to Clojure
I've googled around, and found several ways to do this in Java, but
I've not been successful in translating the less-complex examples. I'm
wondering, how would an experienced Clojurian go about doing this in
Clojure?

All I'm trying to do is play a simple .wav sound file once.

I'll appreciate any examples!

-Anthony

_hrrld

unread,
Jul 27, 2009, 10:35:04 PM7/27/09
to Clojure
On Jul 27, 7:00 pm, Rayne <disciplera...@gmail.com> wrote:
> All I'm trying to do is play a simple .wav sound file once.
>
> I'll appreciate any examples!

I'm hesitant to even share this, since I consider myself a rank
Clojure and Java neophyte, but I think it is what you're asking for:
http://github.com/harold/clj-sound/tree/master

Specifically, have a look at sound-test.clj in that project.

It plays the wav file (on my machine at least), but I'd be very
surprised if it were anything like the way someone who knew what they
were doing would do it.

In any event,
-Harold

verec

unread,
Jul 28, 2009, 12:30:15 AM7/28/09
to Clojure
Here's a simple translation of my java production code (tested on OSX/
Vista/XP, java 1.5 & 6)
The gotcha is to forget the line listener and never dispose the
resources.
When I first tried without it, it worked perfectly on OS X but
stacked sound threads upon sound threads on XP.

This very same (java) code has been tested with: .wav. .aiff, .aif.
and .au and works fine :-)

So here's my clojure attempt:

(ns sound-tests
(:import
(javax.sound.sampled AudioInputStream
AudioSystem
Clip
LineEvent
LineListener
LineUnavailableException
UnsupportedAudioFileException)
(javax.sound.sampled.LineEvent.Type)
(java.io IOException)
(java.net URL)))

(defn simple-play
[url]
(let [stream (AudioSystem/getAudioInputStream url)
clip (AudioSystem/getClip)]
(.addLineListener clip
(proxy[LineListener] []
(update [event]
(when (and event
(= (.getType event)
(. javax.sound.sampled.LineEvent$Type
STOP)))
(.close clip)
(.close stream)))))
(try
(.open clip stream)
(.start clip)
(catch Exception e nil))))

(simple-play (URL. "file:///Users/verec/Tools/workspace/BetfairV6_new/
resources/com/mac/verec/betfair/sounds/tinkalink2.wav"))
--
JFB

Michael Wood

unread,
Jul 28, 2009, 4:23:27 AM7/28/09
to clo...@googlegroups.com
2009/7/28 verec <jeanfrancoi...@googlemail.com>:

>
> Here's a simple translation of my java production code (tested on OSX/
> Vista/XP, java 1.5 & 6)
> The gotcha is to forget the line listener and never dispose the
> resources.
> When I first tried without it, it worked perfectly on OS X  but
> stacked sound threads upon sound threads on XP.
>
> This very same (java) code has been tested with: .wav. .aiff, .aif.
> and .au and works fine :-)
>
> So here's my clojure attempt:

That's a useful example :)

I removed some of the imports that aren't being used:

(ns sound-tests
(:import
(javax.sound.sampled AudioSystem LineEvent$Type LineListener)
(java.net URL)))

(defn simple-play
[url]
(let [stream (AudioSystem/getAudioInputStream url)
clip (AudioSystem/getClip)]
(.addLineListener clip
(proxy[LineListener] []
(update [event]
(when (and event
(= (.getType event)

(LineEvent$Type/STOP)))


(.close clip)
(.close stream)))))
(try
(.open clip stream)
(.start clip)
(catch Exception e nil))))

(simple-play (URL.
"file:///Developer/Examples/Java/Sound/JavaSoundDemo/audio/1-welcome.wav"))

--
Michael Wood <esio...@gmail.com>

John Harrop

unread,
Jul 27, 2009, 11:05:26 PM7/27/09
to clo...@googlegroups.com
On Mon, Jul 27, 2009 at 9:00 PM, Rayne <discip...@gmail.com> wrote:

I've googled around, and found several ways to do this in Java, but
I've not been successful in translating the less-complex examples. I'm
wondering, how would an experienced Clojurian go about doing this in
Clojure?

On my system, the following works even for mp3 files and other compressed ones, if the appropriate JavaSound plugins are installed. It should work for plain wavs with a bare-bones Java 6/Clojure install. It blocks, so you might want to invoke it in a separate thread/via an Agent in actual practice. (It might also be instructive as an example of Java interop involving things like byte buffers.)

(defn play
  "Plays an audio file. Blocks until playback is complete."
  [file]
  (let [f (if (instance? java.io.File file) file (java.io.File. file))]
    (with-open [aif (javax.sound.sampled.AudioSystem/getAudioInputStream f)
                ais (javax.sound.sampled.AudioSystem/getAudioInputStream
                      javax.sound.sampled.AudioFormat$Encoding/PCM_SIGNED aif)]
      (let [af (.getFormat ais)]
        (with-open [line (javax.sound.sampled.AudioSystem/getSourceDataLine af)]
          (.open line af)
          (let [bufsize (.getBufferSize line)
                buf (into-array Byte/TYPE (repeat bufsize (byte 0)))]
            (.start line)
            (loop []
              (let [br (.read ais buf 0 bufsize)]
                (if-not (= -1 br)
                  (do
                    (.write line buf 0 br)
                    (recur))
                  (doto line (.drain) (.stop))))))))))) 

verec

unread,
Jul 28, 2009, 8:37:03 AM7/28/09
to Clojure
Got to admit that I had a bit of a fight with the imports and
the line that reads:

(. javax.sound.sampled.LineEvent$Type STOP)

Your solution/syntax with

(LineEvent$Type/STOP)

is a clear winner! :-)

Thanks.

On Jul 28, 9:23 am, Michael Wood <esiot...@gmail.com> wrote:
> 2009/7/28 verec <jeanfrancois.brouil...@googlemail.com>:
> Michael Wood <esiot...@gmail.com>

Rayne

unread,
Jul 28, 2009, 1:04:36 PM7/28/09
to Clojure
I appreciate all the help guys! You've given me lots of examples to
ponder. :)

Thank you.
Reply all
Reply to author
Forward
0 new messages