blob: 580a3e7e7663d245f537466161bc75a2b652fac3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
;;; wasp-audio --- On-stream audio input and output -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'wasp-utils)
(require 'wasp-ai)
(defcustom w/audio-play-process "wasp-audio-play"
"Name of process for playing audio with mpv."
:type '(string)
:group 'wasp)
(defcustom w/audio-record-process "wasp-audio-record"
"Name of process for transcribing speech using the Whisper API."
:type '(string)
:group 'wasp)
(defvar w/audio-record-process-current nil)
(defvar w/audio-keep-recording t)
(defvar w/audio-voice-commands nil)
(defvar w/last-stream-transcription "")
(defun w/tts (msg)
"Use TTS to say MSG."
(start-process "wasp-tts" nil "say" (w/tempfile "wasp-tts" msg)))
(defun w/audio-play (clip &optional k volume)
"Play CLIP using mpv.
Call K when done.
If VOLUME is specified, use it to adjust the volume (100 is default)."
(make-process
:name w/audio-play-process
:buffer nil
:command
(list
"mpv" "--ao=alsa" "--no-video"
(format "--volume=%s" (or volume 100))
clip)
:sentinel
(lambda (_ _)
(when k
(funcall k)))))
(defun w/stop-all-audio ()
"Stop all audio by killing mpv processes."
(interactive)
(start-process "pkill" nil "pkill" "mpv"))
(defun w/recorded-chatter-name? (user)
"Return non-nil if we've recorded USER's name."
(f-exists?
(w/asset (s-concat "rats/users/" user ".wav"))))
(defun w/say-chatter-name (user &optional volume k)
"Pronounce USER's name in using mpv.
Call K when done.
If VOLUME is specified, use it :)."
(w/audio-play (w/asset (s-concat "rats/users/" user ".wav")) k volume))
(defun w/multipart-audio-helper (user rest &optional uservol clipvol)
"Player all of the files in REST intercalated with saying USER's name.
Adjust volumes by USERVOL and CLIPVOL."
(when (car rest)
(w/audio-play
(car rest)
(when (cdr rest)
(lambda ()
(w/say-chatter-name
user uservol
(lambda () (w/multipart-audio-helper user (cdr rest) uservol clipvol)))))
clipvol)))
(defun w/audio-rats-rats-we-are-the-rats (user)
"Rats rats we are the rats.
Celebrating yet another birthday bash.
USER it's your birthday today."
(let ((parts (--map (w/asset (format "rats/rats/rats%d.ogg" (+ it 1))) (-iota 3))))
(w/multipart-audio-helper user parts 120 100)))
(defun w/audio-rambling-sub-thanks (user)
"Say the thing about USER."
(let ((parts (--map (w/asset (format "rats/new/part%d.wav" it)) (-iota 5))))
(w/multipart-audio-helper user parts 120 150)))
(defun w/thank-sub (user)
"Thank USER for their subscription user a randomized thanking technique."
(let* ((thankers-named
'(w/audio-rats-rats-we-are-the-rats
w/audio-rambling-sub-thanks))
(thankers-unnamed
'((lambda (_) (w/audio-play (w/asset "rats/sam.wav") nil 90))
(lambda (_) (w/audio-play (w/asset "rats/tyumici.mp3") nil 150))
(lambda (_) (w/audio-play (w/asset "rats/abuffseagull.flac") nil 150))
(lambda (_) (w/audio-play (w/asset "rats/unrecorded.wav") nil 150))
))
(thanker
(w/pick-random
(-concat
(when (w/recorded-chatter-name? user)
thankers-named)
thankers-unnamed))))
(funcall thanker user)))
(defun w/audio-record-start ()
"Start recording audio to transcribe."
(let ((tmp (s-concat (make-temp-name "/tmp/wasp-record-audio") ".wav")))
(unless w/audio-record-process-current
(setq
w/audio-record-process-current
(make-process
:name w/audio-record-process
:buffer nil
:command (list "parecord" tmp)
:sentinel
(lambda (_ _)
(setq w/audio-record-process-current nil)
(w/ai-transcribe
tmp
(lambda (msg)
(w/daily-log (format "[VOICE]: %s" msg))
(setq w/last-stream-transcription msg)
(--each w/audio-voice-commands
(when (s-contains? (car it) (s-downcase msg))
(funcall (cdr it))))))
(when w/audio-keep-recording
(w/audio-record-start))))))))
(defun w/audio-record-end ()
"Stop recording audio to transcribe."
(when w/audio-record-process-current
(start-process "pkill" nil "pkill" "parecord")))
(defvar w/audio-record-end-timer nil)
(defun w/run-audio-record-end-timer ()
"Run the audio recording timer."
(when w/audio-record-end-timer
(cancel-timer w/audio-record-end-timer))
(w/audio-record-end)
(setq
w/audio-record-end-timer
(run-with-timer 10 nil #'w/run-audio-record-end-timer)))
(defun w/start-audio-record ()
"Start recording audio."
(interactive)
(setq w/audio-keep-recording t)
(w/audio-record-start))
(defun w/stop-audio-record ()
"Stop recording audio."
(interactive)
(setq w/audio-keep-recording nil)
(w/audio-record-end))
(provide 'wasp-audio)
;;; wasp-audio.el ends here
|