-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmidi_parser.py
More file actions
81 lines (56 loc) · 2.07 KB
/
midi_parser.py
File metadata and controls
81 lines (56 loc) · 2.07 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
import re
from pathlib import Path
from music_key import extract_key_from_name_tokens, normalize_key_query
_TOKEN_SPLIT = re.compile(r"[_\s\-]+")
_BPM_TOKEN = re.compile(r"(?:bpm)?(\d{2,3})(?:bpm)?", re.IGNORECASE)
def parse_midi_info(filepath):
p = Path(filepath)
tokens = [t for t in _TOKEN_SPLIT.split(p.stem) if t]
lower_tokens = [t.lower() for t in tokens]
result = {
"filename": p.name,
"path": str(p),
"bpm": None,
"key": None,
"type": "MIDI"
}
for token in lower_tokens:
bpm_match = _BPM_TOKEN.fullmatch(token)
if bpm_match and result["bpm"] is None:
bpm_val = int(bpm_match.group(1))
if "bpm" in token:
result["bpm"] = bpm_val
elif 60 <= bpm_val <= 200:
result["bpm"] = bpm_val
result["key"] = extract_key_from_name_tokens(tokens)
return result
def normalize_key(key_str):
return normalize_key_query(key_str)
def scan_midi_folder(folder_path):
folder = Path(folder_path)
all_midi_files = [
f for f in folder.rglob("*")
if f.is_file() and f.suffix.lower() in {".mid", ".midi"}
]
parsed_results = []
for f in all_midi_files:
parsed = parse_midi_info(str(f))
parsed_results.append(parsed)
return parsed_results
def search_midi_samples(samples, keywords, bpm_min, bpm_max, key):
def matches(sample):
name = sample["filename"].lower()
if not all(k in name for k in keywords):
return False
bpm = sample["bpm"]
if bpm_min is not None or bpm_max is not None:
if bpm is None: return False
if bpm_min is not None and bpm < bpm_min: return False
if bpm_max is not None and bpm > bpm_max: return False
if key:
normalized_search_key = normalize_key(key)
normalized_sample_key = normalize_key(sample["key"])
if normalized_sample_key != normalized_search_key:
return False
return True
return [s for s in samples if matches(s)]