File size: 1,382 Bytes
59e4843
 
 
 
 
 
 
 
 
 
f97fef1
59e4843
 
 
 
f97fef1
59e4843
 
 
 
 
 
 
 
f97fef1
59e4843
 
 
 
 
 
 
 
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
"""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')