Skip to content

Commit 5207d2b

Browse files
RWC_popular update to 2.0 (#699)
* updating rwc_popular to version 2.0 * fixing error in index * removing preview for index * fixing test folder path * fixing test track id name * adding test covering else in metadata * adding bibitex for vocal-inst activity, section annotation * remove archive annotations from loader, edit index script * edit tests/, black formatting * fix metadata path * black formatting * fix-rwc popular test * black formatting for test * adding midi to rwc popular * Move shared RWC utilities to rwc_popular loader --------- Co-authored-by: Magdalena Fuentes <mgfuenteslujambio@gmail.com>
1 parent 0f16526 commit 5207d2b

19 files changed

Lines changed: 714 additions & 276 deletions

File tree

mirdata/datasets/rwc_popular.py

Lines changed: 220 additions & 170 deletions
Large diffs are not rendered by default.

scripts/make_rwc_popular_index.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import argparse
2+
import csv
3+
import hashlib
4+
import json
5+
import os
6+
7+
RWC_POPULAR_INDEX_PATH = "../mirdata/datasets/indexes/rwc_popular_index_2.0.json"
8+
9+
10+
def md5(file_path):
11+
hash_md5 = hashlib.md5()
12+
with open(file_path, "rb") as fhandle:
13+
for chunk in iter(lambda: fhandle.read(4096), b""):
14+
hash_md5.update(chunk)
15+
return hash_md5.hexdigest()
16+
17+
18+
def make_rwc_popular_index(data_path):
19+
dataset_root = os.path.join(data_path, "rwc_popular")
20+
metadata_file = os.path.join(
21+
dataset_root,
22+
"rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2",
23+
"metadata.csv",
24+
)
25+
26+
with open(metadata_file, "r", encoding="utf-8") as fhandle:
27+
reader = csv.DictReader(fhandle, delimiter=";")
28+
piece = []
29+
for row in reader:
30+
rwcid = (row.get("RWCID") or "").strip()
31+
if not rwcid.startswith("RWC_P"):
32+
continue
33+
34+
piece.append(rwcid[-3:])
35+
36+
track_ids = sorted([f"RWC_P{p}" for p in piece])
37+
38+
rwc_popular_index = {"version": "2.0", "tracks": {}, "metadata": {}}
39+
for track_id in track_ids:
40+
pid = track_id[-3:]
41+
rm_id = f"RM-P{pid}"
42+
43+
audio_rel = os.path.join("RWC-P", f"{track_id}.wav")
44+
audio_abs = os.path.join(dataset_root, audio_rel)
45+
if not os.path.exists(audio_abs):
46+
raise FileNotFoundError(f"Audio file not found: {audio_abs}")
47+
audio_rel = os.path.relpath(audio_abs, dataset_root).replace("\\", "/")
48+
audio_checksum = md5(audio_abs)
49+
50+
beats_rel = os.path.join(
51+
"rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2",
52+
"01_annotations_preprocessed",
53+
"beats",
54+
"RWC-P",
55+
f"{track_id}.csv",
56+
)
57+
beats_abs = os.path.join(dataset_root, beats_rel)
58+
if os.path.exists(beats_abs):
59+
beats_idx = beats_rel.replace("\\", "/")
60+
beats_md5 = md5(beats_abs)
61+
else:
62+
beats_idx, beats_md5 = None, None
63+
64+
chords_rel = os.path.join(
65+
"rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2",
66+
"01_annotations_preprocessed",
67+
"chords",
68+
"RWC-P",
69+
f"{track_id}.csv",
70+
)
71+
chords_abs = os.path.join(dataset_root, chords_rel)
72+
if os.path.exists(chords_abs):
73+
chords_idx = chords_rel.replace("\\", "/")
74+
chords_md5 = md5(chords_abs)
75+
else:
76+
chords_idx, chords_md5 = None, None
77+
78+
melody_rel = os.path.join(
79+
"rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2",
80+
"01_annotations_preprocessed",
81+
"melody",
82+
"RWC-P",
83+
f"{track_id}.csv",
84+
)
85+
86+
melody_abs = os.path.join(dataset_root, melody_rel)
87+
if os.path.exists(melody_abs):
88+
melody_idx = melody_rel.replace("\\", "/")
89+
melody_md5 = md5(melody_abs)
90+
else:
91+
melody_idx, melody_md5 = None, None
92+
93+
midi_rel = os.path.join(
94+
"rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2",
95+
"01_annotations_preprocessed",
96+
"MIDI_aligned",
97+
"RWC-P",
98+
f"{track_id}.mid",
99+
)
100+
midi_abs = os.path.join(dataset_root, midi_rel)
101+
if os.path.exists(midi_abs):
102+
midi_idx = midi_rel.replace("\\", "/")
103+
midi_md5 = md5(midi_abs)
104+
else:
105+
midi_idx, midi_md5 = None, None
106+
107+
rwc_popular_index["tracks"][track_id] = {
108+
"audio": (audio_rel, audio_checksum),
109+
"beats": (beats_idx, beats_md5),
110+
"chords": (chords_idx, chords_md5),
111+
"melody": (melody_idx, melody_md5),
112+
"midi": (midi_idx, midi_md5),
113+
}
114+
115+
metadata_rel = os.path.relpath(metadata_file, dataset_root).replace("\\", "/")
116+
rwc_popular_index["metadata"]["rwc-popular-metadata"] = (
117+
metadata_rel,
118+
md5(metadata_file),
119+
)
120+
121+
with open(RWC_POPULAR_INDEX_PATH, "w", encoding="utf-8") as fhandle:
122+
json.dump(rwc_popular_index, fhandle, indent=2)
123+
124+
print(f"Wrote {len(track_ids)} tracks to {RWC_POPULAR_INDEX_PATH}")
125+
126+
127+
def main(args):
128+
make_rwc_popular_index(args.data_path)
129+
130+
131+
if __name__ == "__main__":
132+
PARSER = argparse.ArgumentParser(description="Make RWC-Popular index file.")
133+
PARSER.add_argument(
134+
"--data_path",
135+
type=str,
136+
help="Path to parent directory of rwc_popular.",
137+
)
138+
main(PARSER.parse_args())

tests/datasets/test_rwc_popular.py

Lines changed: 103 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,65 @@
11
import os
22
import numpy as np
3+
import pretty_midi
34

45
from mirdata.datasets import rwc_popular
56
from mirdata import annotations
67
from tests.test_utils import run_track_tests
78

89

910
def test_track():
10-
default_trackid = "RM-P001"
11+
default_trackid = "RWC_P001"
1112
data_home = os.path.normpath("tests/resources/mir_datasets/rwc_popular")
1213
dataset = rwc_popular.Dataset(data_home, version="test")
1314
track = dataset.track(default_trackid)
1415

1516
expected_attributes = {
16-
"track_id": "RM-P001",
17+
"track_id": "RWC_P001",
1718
"audio_path": os.path.join(
1819
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
19-
"audio/rwc-p-m01/1.wav",
20-
),
21-
"sections_path": os.path.join(
22-
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
23-
"annotations/AIST.RWC-MDB-P-2001.CHORUS/RM-P001.CHORUS.TXT",
20+
"RWC-P/1.wav",
2421
),
2522
"beats_path": os.path.join(
2623
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
27-
"annotations/AIST.RWC-MDB-P-2001.BEAT/RM-P001.BEAT.TXT",
24+
"rwc-annotations-main/01_annotations_preprocessed/beats/RWC-P/RWC_P001.csv",
2825
),
2926
"chords_path": os.path.join(
3027
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
31-
"annotations/AIST.RWC-MDB-P-2001.CHORD/RWC_Pop_Chords/N001-M01-T01.lab",
28+
"rwc-annotations-main/01_annotations_preprocessed/chords/RWC-P/RWC_P001.csv",
29+
),
30+
"f0_path": os.path.join(
31+
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
32+
"rwc-annotations-main/01_annotations_preprocessed/melody/RWC-P/RWC_P001.csv",
3233
),
33-
"voca_inst_path": os.path.join(
34+
"midi_path": os.path.join(
3435
os.path.normpath("tests/resources/mir_datasets/rwc_popular/"),
35-
"annotations/AIST.RWC-MDB-P-2001.VOCA_INST/RM-P001.VOCA_INST.TXT",
36+
"rwc-annotations-main/01_annotations_preprocessed/MIDI_aligned/RWC-P/RWC_P001.mid",
3637
),
37-
"piece_number": "No. 1",
38-
"suffix": "M01",
39-
"track_number": "Tr. 01",
38+
"piece_number": "1",
39+
"cd_number": "1",
40+
"track_number": "1",
4041
"title": "Eien no replica",
4142
"artist": "Kazuo Nishi",
4243
"singer_information": "Male",
43-
"duration": 209,
44-
"tempo": "135",
45-
"instruments": "Gt",
44+
"singing_language": "Japanese",
45+
"tempo": "135.0",
46+
"variation": "",
47+
"live_instrument": "Gt",
4648
"drum_information": "Drum sequences",
49+
"composer": "",
50+
"composition_type": "",
51+
"main_genre": "Popular",
52+
"sub_genre": "J-pop",
53+
"audio_start": "0.0236",
54+
"audio_end": "204.4778",
55+
"duration": "207.16829931972788",
4756
}
4857

4958
expected_property_types = {
5059
"beats": annotations.BeatData,
51-
"sections": annotations.SectionData,
5260
"chords": annotations.ChordData,
53-
"vocal_instrument_activity": annotations.EventData,
61+
"melody": annotations.F0Data,
62+
"midi": pretty_midi.PrettyMIDI,
5463
"audio": tuple,
5564
}
5665

@@ -65,7 +74,7 @@ def test_track():
6574
def test_load_chords():
6675
chords_path = (
6776
"tests/resources/mir_datasets/rwc_popular/"
68-
+ "annotations/AIST.RWC-MDB-P-2001.CHORD/RWC_Pop_Chords/N001-M01-T01.lab"
77+
+ "rwc-annotations-main/01_annotations_preprocessed/chords/RWC-P/RWC_P001.csv"
6978
)
7079
chord_data = rwc_popular.load_chords(chords_path)
7180

@@ -75,81 +84,98 @@ def test_load_chords():
7584
assert type(chord_data.labels) is list
7685

7786
# check values
78-
assert np.array_equal(
79-
chord_data.intervals[:, 0], np.array([0.000, 0.104, 3.646, 43.992, 44.494])
80-
)
81-
assert np.array_equal(
82-
chord_data.intervals[:, 1], np.array([0.104, 1.858, 5.387, 44.494, 47.636])
87+
assert np.array_equal(chord_data.intervals[:3, 0], np.array([0.0, 0.104, 1.858]))
88+
assert np.array_equal(chord_data.intervals[:3, 1], np.array([0.104, 1.858, 3.646]))
89+
assert chord_data.labels[:3] == ["N", "Ab:min", "Gb:maj"]
90+
91+
92+
def test_load_beats():
93+
beats_path = (
94+
"tests/resources/mir_datasets/rwc_popular/"
95+
+ "rwc-annotations-main/01_annotations_preprocessed/beats/RWC-P/RWC_P001.csv"
8396
)
97+
beat_data = rwc_popular.load_beats(beats_path)
98+
99+
# check types
100+
assert type(beat_data) is annotations.BeatData
101+
assert type(beat_data.times) is np.ndarray
102+
assert type(beat_data.positions) is np.ndarray
103+
104+
# check values
84105
assert np.array_equal(
85-
chord_data.labels, ["N", "Ab:min", "E:maj", "Bb:maj(*3)", "C:min7"]
106+
beat_data.times[:5], np.array([0.060, 0.510, 0.950, 1.390, 1.840])
86107
)
108+
assert np.array_equal(beat_data.positions[:5], np.array([1, 2, 3, 4, 1]))
87109

88110

89-
def test_load_vocal_activity():
90-
vocinst_path = (
111+
def test_load_melody():
112+
melody_path = (
91113
"tests/resources/mir_datasets/rwc_popular/"
92-
+ "annotations/AIST.RWC-MDB-P-2001.VOCA_INST/RM-P001.VOCA_INST.TXT"
114+
+ "rwc-annotations-main/01_annotations_preprocessed/melody/RWC-P/RWC_P001.csv"
93115
)
94-
vocinst_data = rwc_popular.load_vocal_activity(vocinst_path)
116+
melody_data = rwc_popular.load_melody(melody_path)
95117

96118
# check types
97-
assert type(vocinst_data) is annotations.EventData
98-
assert type(vocinst_data.intervals) is np.ndarray
99-
assert type(vocinst_data.events) is list
119+
assert type(melody_data) is annotations.F0Data
120+
assert type(melody_data.times) is np.ndarray
121+
assert type(melody_data.frequencies) is np.ndarray
122+
assert type(melody_data.voicing) is np.ndarray
100123

101124
# check values
102125
assert np.array_equal(
103-
vocinst_data.intervals[:, 0],
104-
np.array(
105-
[
106-
0.000,
107-
10.293061224,
108-
11.883492063,
109-
12.087845804,
110-
13.587460317,
111-
13.819387755,
112-
20.668707482,
113-
20.832653061,
114-
]
115-
),
126+
melody_data.times[:5], np.array([0.0, 0.01, 0.02, 0.03, 0.04])
116127
)
117128
assert np.array_equal(
118-
vocinst_data.intervals[:, 1],
119-
np.array(
120-
[
121-
10.293061224,
122-
11.883492063,
123-
12.087845804,
124-
13.587460317,
125-
13.819387755,
126-
20.668707482,
127-
20.832653061,
128-
26.465306122,
129-
]
130-
),
131-
)
132-
assert np.array_equal(
133-
vocinst_data.events,
134-
np.array(
135-
["b", "m:withm", "b", "m:withm", "b", "m:withm", "b", "s:electricguitar"]
136-
),
129+
melody_data.frequencies[:5], np.array([0.0, 0.0, 0.0, 0.0, 0.0])
137130
)
131+
assert np.array_equal(melody_data.voicing[:5], np.array([0.0, 0.0, 0.0, 0.0, 0.0]))
132+
assert len(melody_data.times) == 200
133+
assert melody_data.times[-1] == 1.99
134+
135+
# check that times are uniform (difference of 0.01s for 10ms frames)
136+
time_diffs = np.diff(melody_data.times)
137+
assert np.allclose(time_diffs, 0.01, atol=1e-6)
138138

139139

140140
def test_load_metadata():
141141
data_home = "tests/resources/mir_datasets/rwc_popular"
142142
dataset = rwc_popular.Dataset(data_home, version="test")
143143
metadata = dataset._metadata
144-
assert metadata["RM-P001"] == {
145-
"piece_number": "No. 1",
146-
"suffix": "M01",
147-
"track_number": "Tr. 01",
148-
"title": "Eien no replica",
149-
"artist": "Kazuo Nishi",
150-
"singer_information": "Male",
151-
"duration": 209,
152-
"tempo": "135",
153-
"instruments": "Gt",
154-
"drum_information": "Drum sequences",
155-
}
144+
145+
assert "RWC_P001" in metadata
146+
assert metadata["RWC_P001"]["piece_number"] == "1"
147+
assert metadata["RWC_P001"]["cd_number"] == "1"
148+
assert metadata["RWC_P001"]["track_number"] == "1"
149+
assert metadata["RWC_P001"]["title"] == "Eien no replica"
150+
assert metadata["RWC_P001"]["artist"] == "Kazuo Nishi"
151+
assert metadata["RWC_P001"]["singer_information"] == "Male"
152+
assert metadata["RWC_P001"]["singing_language"] == "Japanese"
153+
assert metadata["RWC_P001"]["tempo"] == "135.0"
154+
assert metadata["RWC_P001"]["live_instrument"] == "Gt"
155+
assert metadata["RWC_P001"]["drum_information"] == "Drum sequences"
156+
assert metadata["RWC_P001"]["main_genre"] == "Popular"
157+
assert metadata["RWC_P001"]["sub_genre"] == "J-pop"
158+
assert metadata["RWC_P001"]["duration"] == "207.16829931972788"
159+
160+
161+
def test_load_metadata_else(tmp_path):
162+
data_home = tmp_path / "rwc_popular"
163+
metadata_dir = (
164+
data_home / "rwc-annotations-2b84581b0c4c80514aadf7e9025a309c91e02cc2"
165+
)
166+
metadata_dir.mkdir(parents=True)
167+
metadata_file = metadata_dir / "metadata.csv"
168+
169+
metadata_file.write_text(
170+
"RWCID;CollID;PieceNo;CDNo;TrackNo;Title;Artist;SingerInformation;"
171+
"SingingLanguage;Tempo;Variation;LiveInstruments;DrumInformation;"
172+
"Composer;CompositionType;GenreMain;GenreSub;audio_start;audio_end;duration\n"
173+
"RWC_R001;C;1;1;1;Test;Test Artist;Female;Japanese;120.0;"
174+
";Gt;Drum sequences;;;Popular;J-pop;0.1;10.0;10.0\n",
175+
encoding="utf-8",
176+
)
177+
178+
dataset = rwc_popular.Dataset(str(data_home), version="test")
179+
metadata = dataset._metadata
180+
181+
assert metadata == {}

0 commit comments

Comments
 (0)