| import json |
| import pathlib |
| from collections import OrderedDict |
|
|
| import click |
|
|
|
|
| @click.command(help='Eliminate short slur notes in DS files') |
| @click.argument('ds_dir', metavar='DS_DIR') |
| @click.argument('threshold', type=float, metavar='THRESHOLD') |
| def eliminate_short( |
| ds_dir, |
| threshold: float |
| ): |
| ds_dir = pathlib.Path(ds_dir).resolve() |
| assert ds_dir.exists(), 'The directory of DS files does not exist.' |
|
|
| for ds in ds_dir.iterdir(): |
| if not ds.is_file() or ds.suffix != '.ds': |
| continue |
|
|
| with open(ds, 'r', encoding='utf8') as f: |
| params = json.load(f) |
| if not isinstance(params, list): |
| params = [params] |
| params = [OrderedDict(p) for p in params] |
|
|
| for param in params: |
| note_list = [ |
| (note, float(dur), bool(int(slur))) |
| for note, dur, slur |
| in zip(param['note_seq'].split(), param['note_dur'].split(), param['note_slur'].split()) |
| ] |
| word_note_div = [] |
| cache = [] |
| for note in note_list: |
| if len(cache) == 0 or note[2]: |
| cache.append(note) |
| else: |
| word_note_div.append(cache) |
| cache = [note] |
| if len(cache) > 0: |
| word_note_div.append(cache) |
|
|
| word_note_div_new = [] |
| for i in range(len(word_note_div)): |
| word_note_seq = word_note_div[i] |
| if len(word_note_seq) == 1 or all(n[1] < threshold for n in word_note_seq): |
| word_note_div_new.append(word_note_seq) |
| continue |
|
|
| word_note_seq_new = [] |
| j = 0 |
| prev_merge = 0. |
| while word_note_seq[j][1] < threshold: |
| |
| prev_merge += word_note_seq[j][1] |
| j += 1 |
| |
| while j < len(word_note_seq): |
| k = j + 1 |
| while k < len(word_note_seq) and word_note_seq[k][1] < threshold: |
| k += 1 |
| post_merge = sum(n[1] for n in word_note_seq[j + 1: k]) |
| if k < len(word_note_seq): |
| post_merge /= 2 |
| word_note_seq_new.append( |
| (word_note_seq[j][0], prev_merge + word_note_seq[j][1] + post_merge, False) |
| ) |
| prev_merge = post_merge |
| j = k |
|
|
| word_note_div_new.append(word_note_seq_new) |
|
|
| note_seq_new = [] |
| note_dur_new = [] |
| note_slur_new = [] |
| for word_note_seq in word_note_div_new: |
| note_seq_new += [n[0] for n in word_note_seq] |
| note_dur_new += [n[1] for n in word_note_seq] |
| note_slur_new += [pos > 0 for pos in range(len(word_note_seq))] |
| param['note_seq'] = ' '.join(note_seq_new) |
| param['note_dur'] = ' '.join(str(round(d, 6)) for d in note_dur_new) |
| param['note_slur'] = ' '.join(str(int(s)) for s in note_slur_new) |
|
|
| with open(ds, 'w', encoding='utf8') as f: |
| json.dump(params, f, ensure_ascii=False, indent=2) |
|
|
|
|
| if __name__ == '__main__': |
| eliminate_short() |
|
|