-
Notifications
You must be signed in to change notification settings - Fork 0
/
capture_audio.py
99 lines (82 loc) · 2.72 KB
/
capture_audio.py
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
# Captures audio and sends audio levels to a midi server
import time
import pyaudio
import audioop
import sys
import requests
import numpy
from dotenv import load_dotenv
from os import getenv
load_dotenv()
FORMAT = pyaudio.paInt16
RATE = 44100
CHUNK = 1024
MAX = 127
FACTOR = 4000
KEEP_AVG_FOR_ITTERATIONS = 10
def get_sound_level(channel):
return audioop.rms(channel.tostring(),
2)
def prevent_overflow(soundLevel):
return min(127, soundLevel)
audio = pyaudio.PyAudio()
def capture_audio(
seconds = 3600,
index = 0,
channelCount = 2,
selectedChannelIndex = None
):
stream = audio.open(
format = FORMAT,
channels = channelCount,
rate = RATE,
input = True,
frames_per_buffer = CHUNK,
input_device_index = index
)
latestSoundLevels = []
for i in range(0, channelCount):
latestSoundLevels.append(list(range(0, KEEP_AVG_FOR_ITTERATIONS)))
def get_channel(i, data_array):
return data_array[i::channelCount]
def update_latest(i, soundLevel):
latest = latestSoundLevels[i]
latest.pop(0)
latest.append(soundLevel)
return latest
def normalize_sound_level(soundLevel):
return round(soundLevel/FACTOR*MAX)
def send_midi_note(i, data_array):
channel = get_channel(i, data_array)
soundLevel = normalize_sound_level(get_sound_level(channel))
latest = update_latest(i, soundLevel)
maxLevel = round(sum(latest)/len(latest)*2)
velocity = prevent_overflow(maxLevel)
note = 60 + i
print(velocity)
requests.post('http://{HOST}:{PORT}/'.format(
HOST=getenv('MIDI_SERVER_HOST'),
PORT=getenv('MIDI_SERVER_PORT'),
),
data={'note': note, 'velocity': velocity})
for _ in range(0, int(RATE/CHUNK*seconds)):
data = stream.read(CHUNK, exception_on_overflow=False)
data_array = numpy.fromstring(data, dtype='int16')
if selectedChannelIndex is not None:
send_midi_note(selectedChannelIndex,data_array)
else:
for i in range(0,channelCount ):
send_midi_note(i, data_array)
time.sleep(.1)
stream.stop_stream()
stream.close()
audio.terminate()
if __name__ == "__main__":
if len(sys.argv) == 1:
capture_audio()
else:
capture_audio(
int(sys.argv[1]),
int(sys.argv[2]),
int(sys.argv[3]),
int(sys.argv[4]) if len(sys.argv) == 5 else None)