asigalov61's picture
Update app.py
2c613a5 verified
raw
history blame
9.35 kB
#==================================================================================
# https://huggingface.co/spaces/asigalov61/MIDI-Cores-Match
#==================================================================================
print('=' * 70)
print('MIDI Cores Match Gradio App')
print('=' * 70)
print('Loading core MIDI Cores Match modules...')
import os
import copy
import statistics
import random
from collections import Counter
import time as reqtime
import datetime
from pytz import timezone
import tqdm
print('=' * 70)
print('Loading main MIDI Cores Match modules...')
import TMIDIX
import numpy as np
from midi_to_colab_audio import midi_to_colab_audio
from huggingface_hub import hf_hub_download
from datasets import load_dataset
import gradio as gr
print('=' * 70)
print('Loading aux MIDI Cores Match modules...')
import matplotlib.pyplot as plt
print('=' * 70)
print('Done!')
print('Enjoy! :)')
print('=' * 70)
#==================================================================================
SOUDFONT_PATH = 'SGM-v2.01-YamahaGrand-Guit-Bass-v2.7.sf2'
#==================================================================================
print('=' * 70)
midi_cores_dataset = load_dataset("asigalov61/MIDI-Cores")
print('=' * 70)
print('Prepping MIDI cores data...')
print('=' * 70)
all_core_chords = np.array(midi_cores_dataset['train']['core_chords'])
print('=' * 70)
print('Done!')
print('=' * 70)
#==================================================================================
def load_midi(midi_file):
print('Loading MIDI...')
raw_score = TMIDIX.midi2single_track_ms_score(midi_file)
escore_notes = TMIDIX.advanced_score_processor(raw_score, return_enhanced_score_notes=True)[0]
escore_notes = [e for e in escore_notes if e[6] < 80 or e[6] == 128]
escore_notes = TMIDIX.augment_enhanced_score_notes(escore_notes, sort_drums_last=True)
zscore = TMIDIX.recalculate_score_timings(escore_notes)
core_score, core_chords = TMIDIX.escore_notes_core(zscore)
print('Done!')
print('=' * 70)
print('MIDI has', len(core_chords), 'chords')
print('=' * 70)
return core_chords
#==================================================================================
def find_max_exact_match(src, trg):
"""
Find the row in the 2D trg array that has the maximum number of exact element matches with the 1D src array.
Parameters:
src (numpy.ndarray): 1D source array.
trg (numpy.ndarray): 2D target array.
Returns:
tuple: A tuple containing:
- int: Index of the row in trg with the maximum number of exact matches.
- int: Number of matched elements in that row.
"""
# Compare src with each row in trg and count exact matches
match_counts = np.sum(trg == src, axis=1)
# Find the index of the row with the maximum number of matches
max_match_idx = np.argmax(match_counts)
# Get the number of matched elements in the best-matching row
num_matched_elements = match_counts[max_match_idx]
return max_match_idx, num_matched_elements
#==================================================================================
def Match_Cores(input_midi):
#===============================================================================
print('=' * 70)
print('Req start time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
start_time = reqtime.time()
print('=' * 70)
fn = os.path.basename(input_midi)
fn1 = fn.split('.')[0]
print('=' * 70)
print('Requested settings:')
print('=' * 70)
print('Input MIDI file name:', fn)
print('=' * 70)
#===============================================================================
src_core_chords = load_midi(input_midi.name)
#===============================================================================
print('Matching MIDI cores...')
print('=' * 70)
match_idx, num_matches = find_max_exact_match(src_core_chords, all_core_chords)
print('MAX MATCH IDX', match_idx)
print('NUM MATCHES', num_matches)
print('=' * 70)
print('Done!')
print('=' * 70)
#===============================================================================
print('Creating final MIDI score...')
final_core_score = midi_cores_dataset['train'][int(match_idx)]['core_score']
print('Done!')
print('=' * 70)
#===============================================================================
print('Rendering results...')
print('=' * 70)
print('Sample INTs', final_core_score[:15])
print('=' * 70)
song_f = []
if len(final_core_score) != 0:
time = 0
dur = 0
vel = 90
pitch = 0
channel = 0
patch = 0
for m in final_core_score:
if 0 <= m < 256:
time += m
elif 256 < m < 512:
dur = (m-256)
elif 512 <= m <= 640:
pat = (m-512)
elif 640 < m < 768:
ptc = (m-640)
elif 768 <= m <= 896:
vel = (m-768)
if pat != 128:
cha = pat // 8
if cha == 9:
cha += 1
else:
cha = 9
song_f.append(['note', time, dur, cha, ptc, vel, pat])
output_score, patches, overflow_patches = TMIDIX.patch_enhanced_score_notes(song_f)
fn1 = "MIDI-Cores-Match-Composition"
detailed_stats = TMIDIX.Tegridy_ms_SONG_to_MIDI_Converter(output_score,
output_signature = 'MIDI Cores Match',
output_file_name = fn1,
track_name='Project Los Angeles',
list_of_MIDI_patches=patches,
timings_multiplier=16
)
new_fn = fn1+'.mid'
audio = midi_to_colab_audio(new_fn,
soundfont_path=SOUDFONT_PATH,
sample_rate=16000,
volume_scale=10,
output_for_gradio=True
)
print('Done!')
print('=' * 70)
#========================================================
output_midi = str(new_fn)
output_audio = (16000, audio)
output_plot = TMIDIX.plot_ms_SONG(output_score,
plot_title=output_midi,
timings_multiplier=16,
return_plt=True
)
print('Output MIDI file name:', output_midi)
print('=' * 70)
#========================================================
print('-' * 70)
print('Req end time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
print('-' * 70)
print('Req execution time:', (reqtime.time() - start_time), 'sec')
return output_audio, output_plot, output_midi
#==================================================================================
PDT = timezone('US/Pacific')
print('=' * 70)
print('App start time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
print('=' * 70)
#==================================================================================
with gr.Blocks() as demo:
#==================================================================================
gr.Markdown("<h1 style='text-align: center; margin-bottom: 1rem'>MIDI Cores Match</h1>")
gr.Markdown("<h1 style='text-align: center; margin-bottom: 1rem'>Match MIDI cores</h1>")
gr.HTML("""
<p>
<a href="https://huggingface.co/spaces/asigalov61/MIDI-Cores-Match?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("## Upload source MIDI")
gr.Markdown("### Source MIDI must have at least 128 chords")
input_midi = gr.File(label="Input MIDI", file_types=[".midi", ".mid", ".kar"])
mix_btn = gr.Button("Match", variant="primary")
gr.Markdown("## Mixing results")
output_audio = gr.Audio(label="MIDI audio", format="wav", elem_id="midi_audio")
output_plot = gr.Plot(label="MIDI score plot")
output_midi = gr.File(label="MIDI file", file_types=[".mid"])
mix_btn.click(Match_Cores,
[input_midi,
],
[output_audio,
output_plot,
output_midi
]
)
#==================================================================================
demo.launch()
#==================================================================================