Skip to content

Commit f70e625

Browse files
committed
asynchronous playback!
(it was already asynchronous, I just made it so that the Thread/sleep x length of the score is optional; the Thread/sleep is only really necessary for the `boot play` task, which needs to block so that the process doesn't exit)
1 parent 13f998d commit f70e625

File tree

3 files changed

+28
-16
lines changed

3 files changed

+28
-16
lines changed

build.boot

+4-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
(alda.sound/play! (eval (parse-input (if code code (slurp file))))
9393
{:pre-buffer (or pre-buffer 0)
9494
:post-buffer (or post-buffer 1000)
95-
:one-off? true})))
95+
:one-off? true})
96+
identity))
9697

9798
(deftask alda-repl
9899
"Starts an Alda Read-Evaluate-Play-Loop."
@@ -101,7 +102,8 @@
101102
s stock bool "Use the default MIDI soundfont of your JVM, instead of FluidR3."]
102103
(binding [alda.sound.midi/*midi-soundfont* (when-not stock (fluid-r3!))]
103104
(alda.repl/start-repl! +version+ {:pre-buffer pre-buffer
104-
:post-buffer post-buffer})))
105+
:post-buffer post-buffer
106+
:async? true})))
105107

106108
(defn -main [& args]
107109
(apply alda.core/-main args))

src/alda/now.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
new-events# (set/difference
3131
(:events new-score#)
3232
(:events old-score#))]
33-
(play-new-events! new-events#)))
33+
(play-new-events! new-events# {:async? true})))
3434

3535
(defn refresh!
3636
"Clears all events and resets the current-offset of each instrument to 0.

src/alda/sound.clj

+23-13
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,33 @@
6060

6161
; TODO: control where to start and stop playing using the start & end keys
6262
(defn play!
63-
"Plays an Alda score, optionally from given start/end marks."
63+
"Plays an Alda score, optionally from given start/end marks.
64+
65+
Returns a function that, when called mid-playback, will stop any further
66+
events from playing."
6467
[{:keys [events instruments] :as score}
65-
& [{:keys [start end pre-buffer post-buffer one-off?] :as opts}]]
66-
(let [audio-types (determine-audio-types score)]
67-
(when one-off? (set-up! audio-types score))
68-
(let [start (+ (now) (or pre-buffer 0))
69-
pool (mk-pool)]
70-
(doall (pmap (fn [{:keys [offset instrument] :as event}]
71-
(let [instrument (-> instrument instruments)]
72-
(at (+ start offset) #(play-event! event instrument) pool)))
73-
events))
68+
& [{:keys [start end pre-buffer post-buffer one-off? async?] :as opts}]]
69+
(let [audio-types (determine-audio-types score)
70+
_ (when one-off? (set-up! audio-types score))
71+
pool (mk-pool)
72+
playing? (atom true)
73+
start (+ (now) (or pre-buffer 0))]
74+
(doall (pmap (fn [{:keys [offset instrument] :as event}]
75+
(let [instrument (-> instrument instruments)]
76+
(at (+ start offset)
77+
#(when @playing?
78+
(play-event! event instrument))
79+
pool)))
80+
events))
81+
(when-not async?
82+
; block until the score is done playing
7483
(Thread/sleep (+ (score-length score) (or post-buffer 0))))
75-
(when one-off? (tear-down! audio-types score))))
84+
(when one-off? (tear-down! audio-types score))
85+
#(reset! playing? false)))
7686

7787
(defn make-wav!
78-
"Parses an input file and saves the resulting sound data as a wav file, using the
79-
specified options."
88+
"Parses an input file and saves the resulting sound data as a wav file,
89+
using the specified options."
8090
[input-file output-file {:keys [start end]}]
8191
(let [target-file (check-for output-file)]
8292
(comment "To do.")))

0 commit comments

Comments
 (0)