|
12 | 12 | import string
|
13 | 13 | import tempfile
|
14 | 14 |
|
15 |
| -from nendo import Nendo, NendoConfig |
16 |
| -from pathlib import Path |
| 15 | +import librosa |
| 16 | +from nendo import Nendo, NendoConfig, NendoTrack |
17 | 17 | from yt_dlp import YoutubeDL
|
18 | 18 |
|
19 | 19 |
|
@@ -69,22 +69,11 @@ def input_tracks(nendo, input_string):
|
69 | 69 | input_items = input_string.split(",")
|
70 | 70 | for item in input_items:
|
71 | 71 | if os.path.isdir(item):
|
72 |
| - imported_tracks = nendo.add_tracks(path=item) |
73 |
| - for imported_track in imported_tracks.tracks(): |
74 |
| - original_filename = imported_track.resource.meta["original_filename"] |
75 |
| - imported_track.resource.meta.update( |
76 |
| - {"original_info": Path(original_filename).stem}, |
77 |
| - ) |
78 |
| - imported_track.save() |
| 72 | + nendo.add_tracks(path=item) |
79 | 73 | elif os.path.isfile(item):
|
80 |
| - imported_track = nendo.add_track(file_path=item) |
81 |
| - original_filename = imported_track.resource.meta["original_filename"] |
82 |
| - imported_track.resource.meta.update( |
83 |
| - {"original_info": Path(original_filename).stem}, |
84 |
| - ) |
85 |
| - imported_track.save() |
| 74 | + nendo.add_track(file_path=item) |
86 | 75 | else:
|
87 |
| - imported_track = import_youtube(nendo, item) |
| 76 | + import_youtube(nendo, item) |
88 | 77 | print(f"Added {item}")
|
89 | 78 |
|
90 | 79 | def process_tracks(
|
@@ -112,93 +101,123 @@ def process_tracks(
|
112 | 101 | beats_per_loop (int): Beats per loop to extract.
|
113 | 102 | """
|
114 | 103 | n = 0
|
115 |
| - processed_tracks = [] |
116 |
| - analysis_data = [] |
117 | 104 | for track in tracks:
|
118 |
| - original_info = track.resource.meta["original_info"] |
119 |
| - print(f"Processing track {1}/{len(tracks)}: {original_info}") |
120 |
| - if (analyze is True and |
| 105 | + original_title = track.meta["title"] |
| 106 | + print(f"Processing track {1}/{len(tracks)}: {original_title}") |
| 107 | + duration = round(librosa.get_duration(y=track.signal, sr=track.sr), 3) |
| 108 | + if (analyze is True and ( |
121 | 109 | len(
|
122 | 110 | track.get_plugin_data(
|
123 | 111 | plugin_name="nendo_plugin_classify_core",
|
124 | 112 | ),
|
125 |
| - ) == 0 |
| 113 | + ) == 0 or nendo.config.replace_plugin_data is True) |
126 | 114 | ):
|
127 | 115 | print("Analyzing...")
|
128 | 116 | track.process("nendo_plugin_classify_core")
|
129 |
| - analysis_data = track.get_plugin_data( |
130 |
| - plugin_name="nendo_plugin_classify_core", |
131 |
| - ) |
| 117 | + # analysis_data = track.get_plugin_data( |
| 118 | + # plugin_name="nendo_plugin_classify_core", |
| 119 | + # ) |
| 120 | + stems = track |
132 | 121 | if (stemify is True and
|
133 | 122 | track.track_type != "stem" and
|
134 | 123 | "has_stems" not in track.resource.meta):
|
135 | 124 | print("Stemifying...")
|
136 | 125 | stems = track.process("nendo_plugin_stemify_demucs")
|
137 |
| - track.resource.meta.update({"has_stems": True }) |
138 |
| - track.save() |
139 |
| - for t in stems.tracks(): |
140 |
| - print(t.track_type) |
141 |
| - processed_tracks = processed_tracks + stems.tracks() |
| 126 | + track.set_meta({"has_stems": True }) |
| 127 | + for stem in stems: |
| 128 | + stem_type = stem.get_meta("stem_type") |
| 129 | + stem.meta = dict(track.meta) |
| 130 | + stem.set_meta( |
| 131 | + { |
| 132 | + "title": f"{original_title} - {stem_type} stem", |
| 133 | + "stem_type": stem_type, |
| 134 | + "duration": duration, |
| 135 | + }, |
| 136 | + ) |
| 137 | + quantized = stems |
142 | 138 | if quantize is True:
|
143 | 139 | print("Quantizing...")
|
144 |
| - quantized_tracks = [] |
145 |
| - for pt in processed_tracks: |
146 |
| - # don't re-quantize tracks |
147 |
| - if pt.track_type != "quantized": |
148 |
| - quantized_track = pt.process( |
149 |
| - "nendo_plugin_quantize_core", |
150 |
| - bpm=quantize_to_bpm, |
| 140 | + quantized = stems.process( |
| 141 | + "nendo_plugin_quantize_core", |
| 142 | + bpm=quantize_to_bpm, |
| 143 | + ) |
| 144 | + if type(quantized) == NendoTrack: # is a single track |
| 145 | + if not quantized.has_related_track(track_id=track.id, direction="from"): |
| 146 | + quantized.relate_to_track( |
| 147 | + track_id=track.id, |
| 148 | + relationship_type="quantized", |
151 | 149 | )
|
152 |
| - if pt.has_meta("stem_type"): |
153 |
| - quantized_track.set_meta( |
154 |
| - {"stem_type": pt.get_meta("stem_type")}, |
| 150 | + quantized.meta = dict(track.meta) |
| 151 | + duration = round(librosa.get_duration(y=quantized.signal, sr=quantized.sr), 3) |
| 152 | + quantized.set_meta( |
| 153 | + { |
| 154 | + "title": f"{original_title} - ({quantize_to_bpm} bpm)", |
| 155 | + "duration": duration, |
| 156 | + }, |
| 157 | + ) |
| 158 | + else: # is a collection |
| 159 | + for j, qt in enumerate(quantized): |
| 160 | + if not qt.has_related_track(track_id=track.id, direction="from"): |
| 161 | + qt.relate_to_track( |
| 162 | + track_id=track.id, |
| 163 | + relationship_type="quantized", |
155 | 164 | )
|
156 |
| - quantized_tracks.append(quantized_track) |
157 |
| - processed_tracks = processed_tracks + quantized_tracks |
| 165 | + qt.meta = dict(track.meta) |
| 166 | + duration = round(librosa.get_duration(y=qt.signal, sr=qt.sr), 3) |
| 167 | + if stems[j].track_type == "stem": |
| 168 | + qt.set_meta( |
| 169 | + { |
| 170 | + "title": ( |
| 171 | + f"{original_title} - " |
| 172 | + f"{stems[j].meta['stem_type']} " |
| 173 | + f"({quantize_to_bpm} bpm)" |
| 174 | + ), |
| 175 | + "stem_type": stems[j].meta["stem_type"], |
| 176 | + "duration": duration, |
| 177 | + }, |
| 178 | + ) |
| 179 | + else: |
| 180 | + qt.set_meta( |
| 181 | + { |
| 182 | + "title": f"{original_title} ({quantize_to_bpm} bpm)", |
| 183 | + "duration": duration, |
| 184 | + }, |
| 185 | + ) |
| 186 | + loopified = quantized |
158 | 187 | if loopify is True:
|
159 | 188 | print("Loopifying...")
|
160 |
| - loopified_tracks = [] |
161 |
| - for pt in processed_tracks: |
162 |
| - # don't loop loops again |
163 |
| - if track.track_type != "loop": |
164 |
| - loops_col = pt.process( |
165 |
| - "nendo_plugin_loopify", |
166 |
| - n_loops=n_loops, |
167 |
| - beats_per_loop=beats_per_loop, |
168 |
| - ) |
169 |
| - for loop in loops_col.tracks(): |
170 |
| - if pt.has_meta("stem_type"): |
171 |
| - loop.set_meta({"stem_type": pt.get_meta("stem_type")}) |
172 |
| - quantized_bpm = pt.get_plugin_data( |
173 |
| - plugin_name="nendo_plugin_quantize_core", |
174 |
| - key="tempo", |
| 189 | + loopified = [] |
| 190 | + if type(quantized) == NendoTrack: |
| 191 | + quantized = [quantized] |
| 192 | + for qt in quantized: |
| 193 | + qt_loops = qt.process( |
| 194 | + "nendo_plugin_loopify", |
| 195 | + n_loops=n_loops, |
| 196 | + beats_per_loop=beats_per_loop, |
| 197 | + ) |
| 198 | + loopified += qt_loops |
| 199 | + num_loop = 1 |
| 200 | + for lp in qt_loops: |
| 201 | + if not lp.has_related_track(track_id=track.id, direction="from"): |
| 202 | + lp.relate_to_track( |
| 203 | + track_id=track.id, |
| 204 | + relationship_type="loop", |
175 | 205 | )
|
176 |
| - if len(quantized_bpm) == 0: |
177 |
| - loop.add_plugin_data( |
178 |
| - plugin_name="nendo_plugin_quantize_core", |
179 |
| - key="tempo", |
180 |
| - value=quantize_to_bpm, |
181 |
| - ) |
182 |
| - loopified_tracks.append(loop) |
183 |
| - processed_tracks = processed_tracks + loopified_tracks |
184 |
| - # propagate information down derivative tracks |
185 |
| - for processed_track in processed_tracks: |
186 |
| - processed_track.resource.meta.update({"original_info": original_info}) |
187 |
| - processed_track.save() |
188 |
| - # transfer plugin data to derived tracks |
189 |
| - quantized_bpm = processed_track.get_plugin_data( |
190 |
| - plugin_name="nendo_plugin_quantize_core", |
191 |
| - key="tempo", |
192 |
| - ) |
193 |
| - # only transfer plugin data if track has not been quantized |
194 |
| - if len(quantized_bpm) == 0: |
195 |
| - for pd in analysis_data: |
196 |
| - processed_track.add_plugin_data( |
197 |
| - plugin_name=pd.plugin_name, |
198 |
| - plugin_version=pd.plugin_version, |
199 |
| - key=pd.key, |
200 |
| - value=pd.value, |
| 206 | + stem_type = qt.meta["stem_type"] if qt.has_meta("stem_type") else "" |
| 207 | + qt_info = ( |
| 208 | + f" ({quantize_to_bpm} bpm)" |
| 209 | + if qt.track_type == "quantized" |
| 210 | + else "" |
| 211 | + ) |
| 212 | + lp.meta = dict(track.meta) |
| 213 | + duration = round(librosa.get_duration(y=lp.signal, sr=lp.sr), 3) |
| 214 | + lp.set_meta( |
| 215 | + { |
| 216 | + "title": f"{original_title} - {stem_type} loop {num_loop} {qt_info}", |
| 217 | + "duration": duration, |
| 218 | + }, |
201 | 219 | )
|
| 220 | + num_loop += 1 |
202 | 221 | n = n+1
|
203 | 222 | print(f"Track {n}/{len(tracks)} Done.\n")
|
204 | 223 | print("Processing completed. "
|
@@ -417,14 +436,13 @@ def main(): # noqa: D103
|
417 | 436 | # apply search
|
418 | 437 | tracks = []
|
419 | 438 | if args.find is None:
|
420 |
| - tracks = nendo.get_tracks() |
| 439 | + tracks = nendo.filter_tracks(track_type="track") |
421 | 440 | else:
|
422 | 441 | for search_value in args.find.split(","):
|
423 |
| - tracks = tracks + nendo.find_tracks( |
424 |
| - value=search_value, |
| 442 | + tracks = tracks + nendo.filter_tracks( |
| 443 | + search_meta={"": search_value}, |
| 444 | + track_type="track", |
425 | 445 | )
|
426 |
| - # only start with "original tracks", not with stems and the likes |
427 |
| - tracks = [t for t in tracks if t.track_type == "track"] |
428 | 446 |
|
429 | 447 | if args.process:
|
430 | 448 | process_tracks(
|
|
0 commit comments