Spaces:
Sleeping
Sleeping
File size: 5,589 Bytes
08435fb be6ff43 7712f5b 24cc03a f6e1e7d be6ff43 08435fb 24cc03a 08435fb 67eed57 f6e1e7d 67eed57 f6e1e7d 943db2e f6e1e7d 943db2e f6e1e7d 943db2e f6e1e7d 943db2e f6e1e7d 943db2e f6e1e7d 08435fb b9c9c57 08435fb b0a5b08 08435fb f6e1e7d cb9d9c6 08435fb b0a5b08 67eed57 b0a5b08 08435fb c516a84 08435fb 0ecc1e7 08435fb 0ecc1e7 08435fb 6a39b70 08435fb f04f03b cb8434e 08435fb f04f03b 08435fb b0a5b08 f6e1e7d b0a5b08 08435fb |
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
#=====================================================
# https://huggingface.co/spaces/asigalov61/MIDI-Doctor
#=====================================================
"""
Check and heal your MIDI :)
"""
# -----------------------------
# CORE MODULES
# -----------------------------
import os
import time as reqtime
import datetime
from pytz import timezone
import json
import gradio as gr
# -----------------------------
# CONFIGURATION & GLOBALS
# -----------------------------
SEP = '=' * 70
PDT = timezone('US/Pacific')
# -----------------------------
# PRINT START-UP INFO
# -----------------------------
def print_sep():
print(SEP)
print_sep()
print("MIDI Doctor Gradio App")
print_sep()
print("Loading MIDI Doctor module...")
import mididoctor
print_sep()
print("Done loading modules!")
print_sep()
# -----------------------------
# HELPER FUNCTIONS
# -----------------------------
def pretty_print_dict(d, indent=0, as_string=True):
"""Recursively prints and optionally returns a pretty-formatted string of a nested dictionary."""
lines = []
def _format_dict(d, indent):
for key, value in d.items():
line = ' ' * indent + str(key) + ':'
if isinstance(value, dict):
lines.append(line)
_format_dict(value, indent + 1)
else:
lines.append(line + ' ' + str(value))
_format_dict(d, indent)
for line in lines:
print(line)
if as_string:
return '\n'.join(lines)
# -----------------------------
import json
import os
def save_nested_dict_to_json(data, filepath, indent=4, ensure_ascii=False, fsync_enabled=False):
"""
Saves a nested dictionary to a JSON file, handling non-serializable objects
and ensuring all data is flushed (and optionally fsynced) to disk.
"""
def _default(obj):
try:
return obj.__dict__
except Exception:
return str(obj)
try:
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(
data,
f,
indent=indent,
ensure_ascii=ensure_ascii,
default=_default
)
f.flush()
if fsync_enabled:
os.fsync(f.fileno())
except Exception as e:
print(f"Failed to save JSON to '{filepath}': {e}")
# -----------------------------
# MAIN FUNCTION
# -----------------------------
def Heal_MIDI(input_midi):
"""
Heal MIDI
"""
print_sep()
print("Request start time:", datetime.datetime.now(PDT).strftime("%Y-%m-%d %H:%M:%S"))
print_sep()
if input_midi is not None:
fn = os.path.basename(input_midi.name)
fn1 = fn.split('.')[0]
print('Input file name:', fn)
print_sep()
print('Healing MIDI...')
healed_MIDI_stats = mididoctor.heal_midi(input_midi.name,
return_midi_hashes=True,
return_original_midi_stats=True,
return_healed_midi_stats=True,
return_repair_stats=True
)
out_fname = './healed_midis/'+fn
print('Done!')
print_sep()
print('Saving stats dictionary...')
save_nested_dict_to_json(healed_MIDI_stats, fn1+'_healed_MIDI_stats.json')
print('Done!')
print_sep()
print('Healed MIDI stats:')
print('-' * 70)
healed_MIDI_stats_str = pretty_print_dict(healed_MIDI_stats)
print_sep()
print("Request end time:", datetime.datetime.now(PDT).strftime("%Y-%m-%d %H:%M:%S"))
print_sep()
return out_fname, fn1+'_healed_MIDI_stats.json', healed_MIDI_stats_str
# -----------------------------
# GRADIO INTERFACE SETUP
# -----------------------------
with gr.Blocks() as demo:
gr.Markdown("<h1 style='text-align: left; margin-bottom: 1rem'>MIDI Doctor</h1>")
gr.HTML("""
Check out <a href="https://github.com/asigalov61/mididoctor">MIDI Doctor</a> on GitHub
<p>
<a href="https://huggingface.co/spaces/asigalov61/MIDI-Doctor?duplicate=true">
<img src="https://huggingface.co/datasets/huggingface/badges/resolve/main/duplicate-this-space-md.svg" alt="Duplicate in Hugging Face">
</a>
</p>
""")
gr.Markdown(
"""
## MIDI Doctor will check and heal
* MIDI signature
* MIDI channels range
* MIDI pitches range
* MIDI velocities range
* MIDI patch changes range
* Duplicate pitches
* Bad chords
* Excessively short durations
* Excessively long durations
* Overlapping durations
* Text events inconsistencies
* Excessively quiet dynamics
* Excessively flat dynamics
"""
)
gr.Markdown("## Upload your MIDI")
input_midi = gr.File(label="Input MIDI", file_types=[".midi", ".mid", ".kar"])
input_midi.upload()
generate_btn = gr.Button("Heal", variant="primary")
healed_MIDI_file = gr.File(label="Healed MIDI file")
healed_MIDI_stats = gr.Textbox(label="Healed MIDI stats")
healed_MIDI_stats_json = gr.File(label="Healed MIDI stats json")
generate_btn.click(
Heal_MIDI,
[input_midi],
[healed_MIDI_file,
healed_MIDI_stats_json,
healed_MIDI_stats
]
)
demo.launch() |