summaryrefslogtreecommitdiff
path: root/src/wasp-audio.el
blob: 56c85e70e98200c47f06ba91425a2e01a71a23f9 (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
;;; wasp-audio --- On-stream audio input and output -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:

(require 'wasp-utils)

(defcustom w/play-audio-process "wasp-play-audio"
  "Name of process for playing audio with mpv."
  :type '(string)
  :group 'wasp)

(defcustom w/transcribe-process "wasp-transcribe"
  "Name of process for transcribing speech using the Whisper API."
  :type '(string)
  :group 'wasp)

(defcustom w/transcribe-buffer " *wasp-transcribe*"
  "Name of buffer used to store transcription output."
  :type '(string)
  :group 'wasp)

(defcustom w/transcribe-error-buffer " *wasp-transcribe-error*"
  "Name of buffer used to store transcription errors."
  :type '(string)
  :group 'wasp)

(defcustom w/stream-transcribe-buffer " *wasp-fake-chat-transcribe*"
  "Name of buffer used to store stream transcription output."
  :type '(string)
  :group 'wasp)

(defcustom w/stream-transcribe-error-buffer " *wasp-fake-chat-transcribe-error*"
  "Name of buffer used to store fake chat transcription errors."
  :type '(string)
  :group 'wasp)

(defvar w/current-stream-transcribe-process nil)
(defvar w/last-stream-transcription "")
(defvar w/stream-keep-transcribing t)

(defun w/tts (msg)
  "Use TTS to say MSG."
  (start-process "wasp-tts" nil "say" (w/tempfile "wasp-tts" msg)))

(defun w/play-audio (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/play-audio-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)
  (muzak-stop)
  (start-process "pkill" nil "pkill" "mpv"))

(defvar-local w/transcribe-callback nil)
(defun w/begin-transcribe (k)
  "Start recording audio to transcribe, passing the result to K."
  (let ((buf (generate-new-buffer w/transcribe-buffer)))
    (with-current-buffer buf
      (setq-local w/transcribe-callback k)
      (erase-buffer))
    (message "Transcribing...")
    (make-process
     :name w/transcribe-process
     :buffer buf
     :command (list "transcribe")
     :stderr (get-buffer-create w/transcribe-error-buffer)
     :sentinel
     (lambda (_ _)
       (with-current-buffer buf
         (funcall w/transcribe-callback (buffer-string)))))))
(defun w/end-transcribe ()
  "Finish recording transcription audio."
  (interactive)
  (message "End of transcription")
  (start-process "pkill" nil "pkill" "parecord")
  nil)

(defun w/handle-stream-transcribe ()
  "Start recording audio to transcribe."
  (unless w/current-stream-transcribe-process
    (with-current-buffer (get-buffer-create w/stream-transcribe-buffer)
      (erase-buffer))
    (setq
     w/current-stream-transcribe-process
     (make-process
      :name "fig-fake-chat-transcribe"
      :buffer (get-buffer-create w/stream-transcribe-buffer)
      :command (list "transcribe")
      :stderr (get-buffer-create w/stream-transcribe-error-buffer)
      :sentinel
      (lambda (_ _)
        (setq w/current-stream-transcribe-process nil)
        (with-current-buffer (get-buffer-create w/stream-transcribe-buffer)
          (setq w/last-stream-transcription (buffer-string)))
        (when w/stream-keep-transcribing
          (w/handle-stream-transcribe)))))))

(defun w/handle-stream-end-transcribe ()
  "Stop recording audio to transcribe."
  (when w/current-stream-transcribe-process
    (start-process "pkill" nil "pkill" "parecord")))

(defvar w/stream-transcribe-timer nil)
(defun w/run-stream-transcribe-timer ()
  "Run the fake chatter transcription timer."
  (when w/stream-transcribe-timer
    (cancel-timer w/stream-transcribe-timer))
  (w/handle-stream-end-transcribe)
  (setq
   w/stream-transcribe-timer
   (run-with-timer 10 nil #'w/run-stream-transcribe-timer)))

(defun w/start-stream-transcribe ()
  "Start transcribing speech for fake chatters."
  (interactive)
  (setq w/stream-keep-transcribing t)
  (w/handle-stream-transcribe))
(defun fig/stop-fake-chat-transcribe ()
  "Stop transcribing speech for fake chatters."
  (interactive)
  (setq w/stream-keep-transcribing nil)
  (w/handle-stream-end-transcribe))

(provide 'wasp-audio)
;;; wasp-audio.el ends here