Spaces:
Sleeping
Sleeping
Download player.py from k-l-lambda/speaking-midi: direct link, hf CLI and curl.
- Browser
- Download file 1.38 kB
-
https://huggingface.co/spaces/k-l-lambda/speaking-midi/resolve/main/player.py
- Command line
-
hf download hf://spaces/k-l-lambda/speaking-midi/player.py
-
curl -L -o player.py https://huggingface.co/spaces/k-l-lambda/speaking-midi/resolve/main/player.py
1.38 kB
| """Build a browser player payload from the exported MIDI and its exact piano render.""" | |
| import base64 | |
| import json | |
| from pathlib import Path | |
| import mido | |
| import soundfile as sf | |
| UI = Path(__file__).parent / 'ui' | |
| def player_payload(directory, stem="refined"): | |
| directory = Path(directory) | |
| clock = 0.0 | |
| active = {} | |
| notes = [] | |
| for message in mido.MidiFile(directory / f'{stem}.mid'): | |
| clock += message.time | |
| if message.type == 'note_on' and message.velocity: | |
| active[(message.channel, message.note)] = (clock, message.velocity) | |
| elif message.type == 'note_off' or (message.type == 'note_on' and not message.velocity): | |
| start, velocity = active.pop((message.channel, message.note)) | |
| notes.append(dict(pitch=message.note, start=start, duration=clock-start, velocity=velocity)) | |
| if active: | |
| raise ValueError('MIDI contains unterminated notes') | |
| wav = directory / f'{stem}.wav' | |
| return json.dumps(dict(notes=notes, duration=sf.info(wav).duration, | |
| audio='data:audio/wav;base64,' + base64.b64encode(wav.read_bytes()).decode())) | |
| def player_component(gr): | |
| return gr.HTML(value='', html_template=(UI/'player.html').read_text(), | |
| css_template=(UI/'player.css').read_text(), | |
| js_on_load=(UI/'player.js').read_text(), elem_id='midi-player') | |