]>
Commit | Line | Data |
---|---|---|
22514f3a IB |
1 | import sounddevice as sd |
2 | import audioop | |
3 | import time | |
4 | ||
75d6cdba IB |
5 | from . import Config |
6 | ||
7 | sample_width = Config.sample_width | |
8 | def sample_width_to_dtype(sample_width): | |
9 | if sample_width == 1 or sample_width == 2 or sample_width == 4: | |
10 | return 'int' + str(8*sample_width) | |
11 | else: | |
12 | raise "Unknown sample width" | |
13 | ||
14 | def _latency(latency): | |
15 | if latency == "high" or latency == "low": | |
16 | return latency | |
17 | else: | |
18 | return float(latency) | |
22514f3a IB |
19 | |
20 | class Mixer: | |
21 | def __init__(self): | |
75d6cdba IB |
22 | self.stream = sd.RawOutputStream(samplerate=Config.frame_rate, |
23 | channels=Config.channels, | |
24 | dtype=sample_width_to_dtype(Config.sample_width), | |
25 | latency=_latency(Config.latency), | |
26 | blocksize=Config.blocksize, | |
22514f3a IB |
27 | callback=self.play_callback, |
28 | ) | |
29 | self.open_files = [] | |
30 | ||
31 | def add_file(self, music_file): | |
32 | if music_file not in self.open_files: | |
33 | self.open_files.append(music_file) | |
34 | self.start() | |
35 | ||
36 | def remove_file(self, music_file): | |
37 | self.open_files.remove(music_file) | |
38 | if len(self.open_files) == 0: | |
39 | self.stop() | |
40 | ||
41 | def stop(self): | |
42 | self.stream.stop() | |
43 | ||
44 | def start(self): | |
45 | self.stream.start() | |
46 | ||
47 | def play_callback(self, out_data, frame_count, time_info, status_flags): | |
48 | out_data_length = len(out_data) | |
49 | empty_data = b"\0" * out_data_length | |
50 | data = b"\0" * out_data_length | |
51 | ||
52 | for open_file in self.open_files: | |
53 | file_data = open_file.play_callback(out_data_length, frame_count) | |
54 | ||
55 | if data == empty_data: | |
56 | data = file_data | |
57 | elif file_data != empty_data: | |
58 | data = audioop.add(data, file_data, sample_width) | |
59 | ||
60 | out_data[:] = data | |
61 |