-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcommu_file.py
68 lines (52 loc) · 2.05 KB
/
commu_file.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
from __future__ import annotations
import copy
from typing import List
import yaml
from mido import MidiFile, MidiTrack, merge_tracks
class CommuFile(MidiFile):
channel_count = -1
def __init__(self, filepath: str, name: str, instrument: str) -> None:
super().__init__(filepath)
self._preprocess(name, instrument)
@property
def track(self) -> MidiTrack:
assert len(self.tracks) == 1
return self.tracks[0]
@property
def duration(self) -> int:
return sum(message.time for message in self.track)
def shift(self, time: int) -> CommuFile:
shifted = copy.deepcopy(self)
for message in shifted.track:
if message.type == 'program_change':
message.time += time
return shifted
def _preprocess(self, name: str, instrument: str) -> None:
with open('cfg/programs.yaml') as f:
inst_to_prog = yaml.safe_load(f)
self._move_meta()
self._set_name(name)
self._set_program(inst_to_prog[instrument])
self._set_channel()
def _move_meta(self) -> None:
assert len(self.tracks) == 2
assert [message.is_meta for message in self.tracks[0]]
self.tracks = [merge_tracks(self.tracks)]
def _set_name(self, name: str) -> None:
self.track.name = name
def _set_program(self, program: int) -> None:
for message in self.track:
if message.type == 'program_change':
message.program = program
def _set_channel(self) -> None:
CommuFile.channel_count += 1
if CommuFile.channel_count == 10:
# channel 10 is reserved to percussions, but there are no percussions in ComMU
CommuFile.channel_count += 1
for message in self.track:
if message.type == 'program_change' or message.type == 'note_on':
message.channel = CommuFile.channel_count
def merge(midis: List[CommuFile]) -> MidiFile:
merged = MidiFile()
merged.tracks = [midi.track for midi in midis]
return merged