-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvoice_scroll.py
More file actions
119 lines (107 loc) · 2.65 KB
/
voice_scroll.py
File metadata and controls
119 lines (107 loc) · 2.65 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
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
'''
Scroll whatever you are reading with voice.
low hum to scroll down. high hum to scroll up.
'''
import pyaudio
from scipy import signal
import numpy as np
from time import sleep
import keyboard
from yin import yin
FRAME_LEN = 4096
SR = 44100
DECAY = 10
CAP = 2.3
THRESHOLD = 2
SCROLL_COOLDOWN = .15
SAMPLE_FORMAT = pyaudio.paFloat32
NP_DTYPE = np.float32
CHANNELS = 1
SECOND_PER_FRAME = FRAME_LEN / SR
DECAY_PER_FRAME = DECAY * SECOND_PER_FRAME
def getPower(frame):
_, power = signal.periodogram(frame, SR)
return np.log(np.sum(power))
class Stream:
def __init__(self, p):
self.p = p
def __enter__(self):
self.s = self.p.open(format=SAMPLE_FORMAT,
channels=CHANNELS,
rate=SR,
frames_per_buffer=FRAME_LEN,
input=True,
)
print('Recording...')
return self.s
def __exit__(self, a, b, c):
self.s.stop_stream()
self.s.close()
print('Finished recording')
def main():
room_power = getRoomPower()
print('Room noise level =', room_power)
input('Press Enter to start scrolling with voice...')
WAIT = 1
print(f'Wait {WAIT} seonds...')
sleep(WAIT)
print('You can now scroll with your voice!')
acc = 0
cooldown = 0
with Stream(p) as stream:
while True:
cooldown -= SECOND_PER_FRAME
frame = np.frombuffer(stream.read(FRAME_LEN), NP_DTYPE)
power = max(0, getPower(frame) - room_power)
direction = 0
f0 = yin(frame, SR, FRAME_LEN)
if f0 < 220:
direction = 1
else:
direction = -1
# if abs(f0 - 130.81) < 5:
# # C3
# direction = 1
# if abs(f0 - 161.82) < 5:
# # E3
# direction = -1
print(acc)
acc += power * direction
if acc > 0:
acc -= DECAY_PER_FRAME
acc = max(0, acc)
else:
acc += DECAY_PER_FRAME
acc = min(0, acc)
acc = min( CAP, acc)
acc = max(-CAP, acc)
if cooldown <= 0:
if abs(acc) > THRESHOLD:
scroll(acc > 0)
cooldown = SCROLL_COOLDOWN
def getRoomPower():
TIME = 3
print(f'Record the room sound for {TIME} seconds.')
print('Make regular noide during the process.')
input('Press Enter...')
WAIT = .5
print(f'Wait {WAIT} seconds...')
sleep(WAIT)
n_frames = int(TIME * SR / FRAME_LEN)
acc = 0
with Stream(p) as stream:
for i in range(n_frames):
acc += getPower(np.frombuffer(
stream.read(FRAME_LEN), NP_DTYPE,
))
print(f'{i} / {n_frames}', end = '\r', flush = True)
return acc / n_frames
def scroll(down_or_up):
text = 'DOWN' if down_or_up else 'UP'
print('scroll', text)
keyboard.send(text)
p = pyaudio.PyAudio()
try:
main()
finally:
p.terminate()