在Clojure中停止一个线程声音循环

时间:2012-08-21 14:41:59

标签: clojure javax.sound.sampled

我有一个线程循环声音片段:

(def f
  (future
    (let [sound-file (java.io.File. "/path/to/file.wav")
          sound-in (javax.sound.sampled.AudioSystem/getAudioInputStream sound-file)
          format (.getFormat sound-in)
          info (javax.sound.sampled.DataLine$Info. javax.sound.sampled.Clip format)
          clip (javax.sound.sampled.AudioSystem/getLine info)]
      (.open clip sound-in)
      (.loop clip javax.sound.sampled.Clip/LOOP_CONTINUOUSLY))))

问题是当我试图杀死线程时:

(future-cancel f)

它不会停止播放,播放永远。我发现阻止它的唯一方法是明确地调用(.stop clip)。我的问题:这样做的最佳/惯用方法是什么?我对Clojure很陌生,所以到目前为止我只尝试future,但是agent可能更适合这种情况吗?

更新:鉴于.loop函数是非阻塞的(如下所述),我通过删除初始future简化了我的设计:

(defn play-loop [wav-fn]
    (let [sound-file (java.io.File. wav-fn)
          sound-in (javax.sound.sampled.AudioSystem/getAudioInputStream sound-file)
          format (.getFormat sound-in)
          info (javax.sound.sampled.DataLine$Info. javax.sound.sampled.Clip format)
          clip (javax.sound.sampled.AudioSystem/getLine info)]
      (.open clip sound-in)
      (.loop clip javax.sound.sampled.Clip/LOOP_CONTINUOUSLY)
      clip))

以及控件atom

(def ^:dynamic *clip* (atom nil))

我开始循环:

(when (nil? @*clip*)
  (reset! *clip* (play-loop "/path/to/file.wav")))

并停止它:

(when @*clip*
  (future (.stop @*clip*) ; to avoid a slight delay caused by .stop
          (reset! *clip* nil)))

1 个答案:

答案 0 :(得分:4)

您可以尝试这样的事情:

(def f
  (future
    (let [sound-file (java.io.File. "/path/to/file.wav")
          sound-in (javax.sound.sampled.AudioSystem/getAudioInputStream sound-file)
          format (.getFormat sound-in)
          info (javax.sound.sampled.DataLine$Info. javax.sound.sampled.Clip format)
          clip (javax.sound.sampled.AudioSystem/getLine info)
          stop (fn [] (.stop clip))]
      (.open clip sound-in)
      (.loop clip javax.sound.sampled.Clip/LOOP_CONTINUOUSLY)
       stop)))

(def stop-loop @f)
(stop-loop)