Files

103 lines
4.2 KiB
Python

#Importing Libraries
from imageio_ffmpeg import get_ffmpeg_exe
from subprocess import run
from librosa import load
from noisereduce import reduce_noise
from soundfile import write
from basic_pitch.inference import predict_and_save, ICASSP_2022_MODEL_PATH
from music21.midi import MidiFile, translate, environment
from os.path import splitext, basename, join, dirname, abspath, isdir
from os import makedirs
from lilypond import executable
from tempfile import TemporaryDirectory
from shutil import copy
from platform import system
#Main Function
def media_to_notes(input_path,output_path):
supplementary_files=[]
lilypond_path=str(executable())
if system()=="Windows" and not lilypond_path.lower().endswith('.exe'):
lilypond_path+='.exe'
us=environment.UserSettings()
us['lilypondPath']=lilypond_path
output_dir = dirname(abspath(output_path))
makedirs(output_dir, exist_ok=True)
file_extension=splitext(input_path)[1]
file_name=splitext(basename(input_path))[0]
#Saving Between Files in Temp Directory
with TemporaryDirectory() as tmp:
#Correcting File Format
if file_extension.lower()!='.wav':
wav_path=join(tmp,file_name+'.wav')
run([get_ffmpeg_exe(),'-y','-i',input_path,wav_path],check=True)
supplementary_files.append(wav_path)
else:
wav_path=input_path
#Noise Reduction
y,sr=load(wav_path,sr=None,mono=True)
denoised_music=reduce_noise(y=y,sr=sr,stationary=True,prop_decrease=0.6)
denoised_music_path=join(tmp,file_name+'_denoised.wav')
write(denoised_music_path,denoised_music,sr)
supplementary_files.append(denoised_music_path)
#Making The MIDI
predict_and_save(
audio_path_list=[denoised_music_path],
output_directory=tmp,
save_midi=True,
sonify_midi=False,
save_model_outputs=False,
save_notes=True,
model_or_model_path=ICASSP_2022_MODEL_PATH)
mid_path=join(tmp,file_name+'_denoised_basic_pitch.mid')
supplementary_files.append(mid_path)
supplementary_files.append(join(tmp,file_name+'_denoised_basic_pitch.csv'))
#Making The Ly
mf=MidiFile()
mf.open(mid_path)
mf.read()
mf.close()
s=translate.midiFileToStream(mf)
ly_path=join(tmp,file_name+'.ly')
s.write('lily', fp=ly_path)
supplementary_files.append(ly_path)
#Correcting The Layout
with open(ly_path,'r',encoding='utf-8') as f:
ly=f.read()
if r'\include "lilypond-book-preamble.ly"' in ly:
ly=ly.replace(r'\include "lilypond-book-preamble.ly"',rf'\include "{file_name}_wrapper.ly"')
else:
ly=rf'\include "{file_name}_wrapper.ly"'+'\n'+ly
wrapper_path=join(tmp,file_name+'_wrapper.ly')
with open(wrapper_path,'w',encoding='utf-8') as f:
f.write(r'\header { tagline = ##f }')
with open(ly_path,'w',encoding='utf-8') as f:
f.write(ly)
supplementary_files.append(wrapper_path)
#Making The PDF
run([lilypond_path,"-I",tmp,"-o",join(tmp,file_name),join(tmp,file_name+'.ly')],check=True)
pdf_path=join(tmp,file_name+'.pdf')
copy(pdf_path,output_path)
#Saving The Supplementary Files
supplementary_user=input('Do you want the supplementary files (Y/n)? ').strip().lower()
while supplementary_user!='y' and supplementary_user!='n':
supplementary_user=input('Please answer with "Y" or "n":').strip().lower()
if supplementary_user=='y':
counter=0
supplementary_dir=join(output_dir,'Supplementary Files')
while isdir(supplementary_dir):
counter+=1
supplementary_dir=join(output_dir,f'Supplementary Files ({counter})')
makedirs(supplementary_dir)
for supplementary_file in supplementary_files:
destination=join(supplementary_dir,basename(supplementary_file))
copy(supplementary_file,destination)
print(f"Supplementary files saved to {supplementary_dir}.")
print(f"Notes PDF saved to {abspath(output_path)}.")