-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathselect_audio_device.py
More file actions
93 lines (81 loc) · 2.78 KB
/
select_audio_device.py
File metadata and controls
93 lines (81 loc) · 2.78 KB
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
'''
A terminal interface that lets the user select
the audio input/output device.
What if device list changed during selection?
- pyaudio doesn't offer open-by-name. Perfection is impossible.
- I recommend you init the stream as soon as the function returns.
'''
import typing as tp
import pyaudio
from .interactive import inputChin
Direction = tp.Literal['In', 'Out']
def select_audio_device_input(
pa: pyaudio.PyAudio,
guesses: list[str] = ['default', 'Line', 'Headset', 'Microphone Array'],
) -> int:
return select_audio_device(pa, 'In', guesses)
def select_audio_device_output(
pa: pyaudio.PyAudio,
guesses: list[str] = ['default', 'VoiceMeeter Input'],
) -> int:
return select_audio_device(pa, 'Out', guesses)
def get_device_info(
pa: pyaudio.PyAudio,
device_index: int,
query_direction: Direction,
api_index: int = 0,
) -> tuple[str, bool]:
info = pa.get_device_info_by_host_api_device_index(api_index, device_index)
name: str = info['name'] # type: ignore
do_align = info[f'max{query_direction}putChannels'] > 0 # type: ignore
return name, do_align
def select_audio_device(
pa: pyaudio.PyAudio,
direction: Direction,
guesses: list[str],
api_index: int = 0,
) -> int:
api_info = pa.get_host_api_info_by_index(api_index)
n_devices: int = api_info['deviceCount'] # type: ignore
devices = list[str]()
relevant_indices = list[int]()
for i in range(n_devices):
name, do_align = get_device_info(pa, i, direction, api_index)
devices.append(name)
if do_align:
relevant_indices.append(i)
default = str(guess([
(i, devices[i]) for i in relevant_indices
], guesses) or '')
print()
print(direction + 'put Devices:')
for i in relevant_indices:
print(i, devices[i])
selected = int(inputChin(f'select {direction}put device: ', default))
print()
print(direction + 'put device:', devices[selected])
now_name, _ = get_device_info(pa, selected, direction, api_index)
assert now_name == devices[selected], (
'Device list changed during selection.'
)
return selected
def guess(devices: list[tuple[int, str]], targets: list[str]) -> int | None:
for t in targets:
candidates = [i for i, name in devices if t in name]
for _ in range(2):
match candidates:
case []:
break
case [x]:
return x
case _:
candidates = [i for i, name in devices if name == t]
continue
return
if __name__ == '__main__':
pa = pyaudio.PyAudio()
try:
print(select_audio_device_input (pa))
print(select_audio_device_output(pa))
finally:
pa.terminate()