我有一个线程循环声音剪辑:
(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)))
您可以尝试以下操作:
(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)