Skip to content

Commit 60f220c

Browse files
committed
Rename processor
1 parent 4b98759 commit 60f220c

1 file changed

Lines changed: 13 additions & 98 deletions

File tree

src/simulflow/transport.clj

Lines changed: 13 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -188,79 +188,6 @@
188188

189189
:transform async-in-transform})))
190190

191-
(def realtime-speakers-out-describe
192-
{:ins {:in "Channel for audio output frames "
193-
:sys-in "Channel for system messages"}
194-
:outs {:out "Channel for bot speech status frames"}
195-
:params {:audio.out/sample-rate "Sample rate of the output audio"
196-
:audio.out/sample-size-bits "Size in bits for each sample"
197-
:audio.out/channels "Number of channels. 1 or 2 (mono or stereo audio)"
198-
:audio.out/duration-ms "Duration in ms of each chunk that will be streamed to output"}})
199-
200-
(defn realtime-speakers-out-transition
201-
[{::flow/keys [in-ports out-ports] :as state} transition]
202-
(when (= transition ::flow/stop)
203-
(when-let [line (::speaker-line state)]
204-
(sound/stop! line)
205-
(sampled/flush! line)
206-
(close! line))
207-
(doseq [port (concat (vals in-ports) (vals out-ports))]
208-
(a/close! port))))
209-
210-
(defn realtime-speakers-out-init!
211-
[{:audio.out/keys [duration-ms sample-rate sample-size-bits channels]
212-
:or {sample-rate 16000
213-
channels 1
214-
sample-size-bits 16}}]
215-
216-
(let [;; send every 10ms to account for network
217-
duration (or duration-ms 20)
218-
sending-interval (/ duration 2)
219-
next-send-time (atom (u/mono-time))
220-
221-
;; Track bot speaking state
222-
speaking? (atom false)
223-
last-audio-time (atom 0)
224-
225-
line (open-line! :source (sampled/audio-format sample-rate sample-size-bits channels))
226-
audio-write-c (a/chan 1024)
227-
events-chan (a/chan 1024)
228-
229-
realtime-loop #(loop []
230-
(when-let [msg (a/<!! audio-write-c)]
231-
(assert (frame/audio-output-raw? msg) "Only audio-output-raw frames can be played to speakers.")
232-
(let [now (u/mono-time)]
233-
(reset! last-audio-time now)
234-
235-
;; Check if we need to emit bot started speaking
236-
(when (not @speaking?)
237-
(reset! speaking? true)
238-
(a/>!! events-chan
239-
(frame/bot-speech-start true)))
240-
241-
(a/<!! (a/timeout (- @next-send-time now)))
242-
(sound/write! (:frame/data msg) line 0)
243-
(reset! next-send-time (+ now sending-interval)))
244-
(recur)))
245-
;; Monitor for end of speech
246-
speech-monitor #(loop []
247-
(a/<!! (a/timeout 1000)) ;; Check every second
248-
(let [now (u/mono-time)
249-
silence-duration (- now @last-audio-time)]
250-
;; If we've been silent for 2x chunk duration and were speaking
251-
(when (and @speaking?
252-
(> silence-duration (* 4 duration)))
253-
(reset! speaking? false)
254-
(a/>!! events-chan (frame/bot-speech-stop true)))
255-
(recur)))]
256-
((flow/futurize realtime-loop :exec :io))
257-
((flow/futurize speech-monitor :exec :io))
258-
{::flow/out-ports {:audio-write audio-write-c}
259-
::flow/in-ports {:events events-chan}
260-
:bot/speaking? speaking?
261-
:bot/last-audio-time last-audio-time
262-
::speaker-line line}))
263-
264191
(defn realtime-out-transform
265192
[{:transport/keys [serializer] :as state} in msg]
266193
(if (= in :events)
@@ -422,23 +349,12 @@
422349

423350
(def microphone-transport-in (flow/process mic-transport-in-fn))
424351

425-
(def realtime-speakers-out-processor
426-
"Processor that streams audio out in real time so we can account for
427-
interruptions."
428-
(flow/process (fn ([] realtime-speakers-out-describe)
429-
([params]
430-
(realtime-speakers-out-init! params))
431-
([state transition]
432-
(realtime-speakers-out-transition state transition))
433-
([state in msg]
434-
(realtime-out-transform state in msg)))))
435-
436352
;; =============================================================================
437353
;; Realtime Speakers Out V2 - Activity Monitor Pattern
438354
;; Moves business logic from init! to transform for better testability
439355
;; =============================================================================
440356

441-
(defn process-audio-frame-v2
357+
(defn process-realtime-out-audio-frame
442358
"Pure function to process an audio frame and determine state changes.
443359
Returns [updated-state output-map] for the given state, frame, and current time."
444360
[state frame serializer current-time]
@@ -464,8 +380,7 @@
464380
[updated-state {:out events
465381
:audio-write [audio-command]}]))
466382

467-
(defn realtime-speakers-out-describe-v2
468-
[]
383+
(def realtime-speakers-out-describe
469384
{:ins {:in "Channel for audio output frames"
470385
:sys-in "Channel for system messages"}
471386
:outs {:out "Channel for bot speech status frames"}
@@ -474,7 +389,7 @@
474389
:audio.out/channels "Number of channels. 1 or 2 (mono or stereo audio)"
475390
:audio.out/duration-ms "Duration in ms of each chunk that will be streamed to output"}})
476391

477-
(defn realtime-speakers-out-init-v2!
392+
(defn realtime-speakers-out-init!
478393
[{:audio.out/keys [duration-ms sample-rate sample-size-bits channels]
479394
:or {sample-rate 16000
480395
channels 1
@@ -524,7 +439,7 @@
524439
::silence-threshold silence-threshold
525440
::audio-line line}))
526441

527-
(defn realtime-speakers-out-transition-v2
442+
(defn realtime-speakers-out-transition
528443
[{::flow/keys [in-ports out-ports] :as state} transition]
529444
(when (= transition ::flow/stop)
530445
(when-let [line (::audio-line state)]
@@ -535,15 +450,15 @@
535450
(a/close! port)))
536451
state)
537452

538-
(defn realtime-speakers-out-transform-v2
453+
(defn realtime-speakers-out-transform
539454
[{:transport/keys [serializer] :as state} input-port frame]
540455
(let [current-time (u/mono-time)]
541456
(cond
542457
;; Handle incoming audio frames - core business logic moved here
543458
;; Handle incoming audio frames - use pure function for business logic
544459
(and (= input-port :in)
545460
(frame/audio-output-raw? frame))
546-
(process-audio-frame-v2 state frame serializer current-time)
461+
(process-realtime-out-audio-frame state frame serializer current-time)
547462

548463
;; Handle timer ticks for speech monitoring - moved from background loop
549464
(and (= input-port :timer-out)
@@ -576,15 +491,15 @@
576491
;; Default case
577492
:else [state {}])))
578493

579-
(defn realtime-speakers-out-fn-v2
494+
(defn realtime-speakers-out-fn
580495
"Refactored realtime speakers out following activity monitor pattern.
581496
Moves business logic from init! to transform for better testability."
582-
([] (realtime-speakers-out-describe-v2))
583-
([params] (realtime-speakers-out-init-v2! params))
584-
([state transition] (realtime-speakers-out-transition-v2 state transition))
585-
([state input-port frame] (realtime-speakers-out-transform-v2 state input-port frame)))
497+
([] realtime-speakers-out-describe)
498+
([params] (realtime-speakers-out-init! params))
499+
([state transition] (realtime-speakers-out-transition state transition))
500+
([state input-port frame] (realtime-speakers-out-transform state input-port frame)))
586501

587-
(def realtime-speakers-out-processor-v2
502+
(def realtime-speakers-out-processor
588503
"V2 processor that moves timing and speech detection logic to transform.
589504
Follows activity monitor pattern for better testability and reasoning."
590-
(flow/process realtime-speakers-out-fn-v2))
505+
(flow/process realtime-speakers-out-fn))

0 commit comments

Comments
 (0)