You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We the first to manage proper audio-to-MIDI conversion?
The first Ruby script uses Spotify's Basic Pitch to reverse engineer piano chord videos from YouTube into MIDI and the result is horrible
The second uses, as first in the world, Midilib and Chords2Midi to quantize and solidify all possible chord progressions and then give off a live preview: https://wavefilegem.com/
get_midi.rb
# encoding: UTF-8## MASS-CONVERT AUDIO TO MIDI# https://replicate.com/rhelsing/basic-pitch## Download piano chord lessons# yt-dlp -x --audio-format mp3 https://www.youtube.com/@PianOwnedLessons## gem install --user-install replicate-ruby# gem install --user-install midilibrequire'replicate'require'midilib'require'fileutils'require'base64'require'pry'Replicate.configuredo |config|
config.api_token='r8_L77Bahb1EsOdAQGFiujQ5sZWTSCCv063QX8Yq'endmodel=Replicate.client.retrieve_model('rhelsing/basic-pitch')version=model.latest_versionDir.glob('samples/*.mp3').each_with_indexdo |mp3_file,index|
puts"Processing file #{index + 1} of #{mp3_file.length}: #{mp3_file}"puts"Uploading #{mp3_file}..."upload=Replicate.client.create_upload(audio_file: File.open(mp3_file))puts"Waiting for upload to finish..."loopdobreakunlessupload == falsesleep10endputs"Creating prediction..."prediction=Replicate.client.create_prediction(input: {audio_file: upload})puts"Waiting for prediction to finish..."loopdoprediction.refetchifprediction.status == "succeeded"output=prediction.outputifoutput && output.key?("midi_data")# Extract the MIDI data from the outputmidi_data=output['midi_data']# Decode the Base64-encoded MIDI datadecoded_midi_data=Base64.strict_decode64(midi_data)# Specify the output file pathoutput_file="output/#{File.basename(mp3_file,'.mp3')}.mid"# Save the MIDI data to the output fileFile.open(output_file,'wb')do |file|
file.write(decoded_midi_data)endputs"MIDI file saved: #{output_file}"breakendelsifprediction.status == "failed"puts"Prediction failed."exitendsleep30endend
improve_midi.rb
# encoding: UTF-8## CONVERTS TO REAL CHORDS## gem install --user-install replicate-ruby midilib# gem install --user-install replicate-ruby pycall# gem install --user-install replicate-ruby wavefile## doas pkg_add python3 py3-pip# git clone https://github.com/Miserlou/chords2midi# pip3 install ./chords2midirequire'replicate'require'midilib'require'fileutils'require'pycall/import'require'wavefile'require'pry'includePyCall::Importpyimport:chords2mididefimprove_midi(midi_file)puts"Improving MIDI file: #{midi_file}"sequence=MIDI::Sequence.new()File.open(midi_file,'rb')do |file|
sequence.read(file)end# Quantizesequence.eachdo |track|
track.quantize(4)# Adjust the quantize resolution as neededend# Chordifychord_converter=Chords2MIDI.newbeginchord_converter.process(sequence)rescue=>eputs"Chords2MIDI processing failed for #{midi_file}: #{e.message}"returnendprocessed_midi_file=midi_file.sub(/\.mid$/,'_processed.mid')File.open(processed_midi_file,'wb')do |file|
sequence.write(file)endputs"Processed MIDI file saved: #{processed_midi_file}"# Prompt the user for save or deleteloopdoputs"Do you want to save or delete the processed MIDI file? (yes/no)"response=gets.chomp.downcasecaseresponsewhen'yes'play_midi(processed_midi_file)breakwhen'no'delete_file(processed_midi_file)breakelseputs"Invalid response. Please enter 'yes' or 'no'."endendend# Let's hear itdefplay_midi(midi_file)puts"Playing MIDI file: #{midi_file}"output=WaveFile::Writer.new("output.wav",WaveFile::Format.new(:mono,:pcm_16,44100))sequence=MIDI::Sequence.new()File.open(midi_file,'rb')do |file|
sequence.read(file)endsynth=MIDI::Synthesizer.new()synth.opensequence.eachdo |track|
track.eachdo |event|
sleep(event.time_from_start - synth.current_time)ifevent.time_from_start > synth.current_timecaseeventwhenMIDI::NoteOnsynth.note_on(event.note,event.velocity,event.channel)whenMIDI::NoteOffsynth.note_off(event.note,event.channel)endendendsynth.closeoutput.closesystem("aplay output.wav")# Adjust this command based on your system's audio playback commandFile.delete("output.wav")enddefdelete_file(file)File.delete(file)puts"Processed MIDI file deleted: #{file}"endDir.glob(File.join('samples/','*.mid'))do |midi_file|
puts"Processing #{midi_file}..."improve_midi(midi_file)puts"Processing complete for #{midi_file}."endputs"All done. Exiting."