]>
Commit | Line | Data |
---|---|---|
1 | import sounddevice as sd | |
2 | import audioop | |
3 | import time | |
4 | ||
5 | frame_rate = 44100 | |
6 | channels = 2 | |
7 | sample_width = 2 | |
8 | ||
9 | class Mixer: | |
10 | def __init__(self): | |
11 | self.stream = sd.RawOutputStream(samplerate=frame_rate, | |
12 | channels=channels, | |
13 | dtype='int' + str(8*sample_width), # FIXME: ? | |
14 | latency="high", | |
15 | blocksize=5000, | |
16 | callback=self.play_callback, | |
17 | ) | |
18 | self.open_files = [] | |
19 | ||
20 | def add_file(self, music_file): | |
21 | if music_file not in self.open_files: | |
22 | self.open_files.append(music_file) | |
23 | self.start() | |
24 | ||
25 | def remove_file(self, music_file): | |
26 | self.open_files.remove(music_file) | |
27 | if len(self.open_files) == 0: | |
28 | self.stop() | |
29 | ||
30 | def stop(self): | |
31 | self.stream.stop() | |
32 | ||
33 | def start(self): | |
34 | self.stream.start() | |
35 | ||
36 | def play_callback(self, out_data, frame_count, time_info, status_flags): | |
37 | out_data_length = len(out_data) | |
38 | empty_data = b"\0" * out_data_length | |
39 | data = b"\0" * out_data_length | |
40 | ||
41 | for open_file in self.open_files: | |
42 | file_data = open_file.play_callback(out_data_length, frame_count) | |
43 | ||
44 | if data == empty_data: | |
45 | data = file_data | |
46 | elif file_data != empty_data: | |
47 | data = audioop.add(data, file_data, sample_width) | |
48 | ||
49 | out_data[:] = data | |
50 |