So, yesterday I started on {midiblender}, an un-released R package, that now has the necessary code to accomplish my goal. You see, the previous ways of mangling mario were fun and interesting, and I approve of them. But, they got pretty stochastic sounding.
I don’t have time right now to really explain what I’m trying to do in detail, but it is basically this:
create a corpus (matrix) of feature vectors representing the note and time information for some temporal interval from the mario midi file. I’ve set it to 2 beats.
Pick a starting vector, such as the first chord in mario
filter the matrix for rows that have some similarity to the starting vector.
Calculate a probability vector for the notes and times from the filtered matrix.
Generate a new feature vector from the probabilities.
I have this set up in pairs, so I take the generated feature vector for the second beat, and use it as the next starting vector.
repeat to generate as many beats worth as you want.
The result should still be fairly probabilistic sounding, but more mario sequency sounding than before.
Show the code
library(midiblender)#import midimario <-midi_to_object("all_overworld.mid")list2env(mario, .GlobalEnv) # send objects to global environmenttrack_0 <-copy_midi_df_track(midi_df = midi_df,track_num =0)# convert to a piano roll matrixall_midi <-midi_df_to_matrix(midi_df,track=0)# reshape to desired intervalmusic_matrix <-reshape_piano_roll(all_midi,48*2)# probabilistic sampling# create conditional vectorconditional_vector <-rep(0,dim(music_matrix)[2])conditional_vector[(c(50,66,76)+1)] <-1dot_products <- conditional_vector %*%t(music_matrix)positive_similarity <-which(dot_products >0)feature_probs <-get_feature_probs(midi_matrix = music_matrix[positive_similarity,])mean_note_density <-get_mean_note_density(midi_matrix = music_matrix[positive_similarity,])new_features <-new_features_from_probs(probs = feature_probs,density = mean_note_density,examples =1)# loopnew_feature_vectors <- new_featuresfor(i in1:200) {# put second half into conditional vector conditional_vector <-c(new_features[((length(new_features)/2)+1):length(new_features)],rep(0,length(new_features)/2)) dot_products <- conditional_vector %*%t(music_matrix) positive_similarity <-which(dot_products >0)if(length(positive_similarity) ==0){# sample some random stuff positive_similarity <-sample(1:dim(music_matrix)[1],25)print(i) } feature_probs <-get_feature_probs(midi_matrix = music_matrix[positive_similarity, ]) mean_note_density <-get_mean_note_density(midi_matrix = music_matrix[positive_similarity, ]) new_features <-new_features_from_probs(probs = feature_probs,density = mean_note_density,examples =1) new_feature_vectors <-rbind(new_feature_vectors,new_features)}new_matrix <-feature_vector_to_matrix(vec = new_feature_vectors,num_notes =128)# transform back to midimidi_time_df <-matrix_to_midi_time(midi_matrix = new_matrix,smallest_time_unit =1,note_off_length =8)meta_messages_df <-get_midi_meta_df(track_0)meta_messages_df <-set_midi_tempo_meta(meta_messages_df,update_tempo =600000)split_meta_messages_df <-split_meta_df(meta_messages_df)new_midi_df <-matrix_to_midi_track(midi_time_df = midi_time_df,split_meta_list = split_meta_messages_df,channel =0,velocity =64)#### bounce# update miditapyr dfmiditapyr_object$midi_frame_unnested$update_unnested_mf(new_midi_df)#write midi file to diskmiditapyr_object$write_file("endless_mario_1.mid")########## bounce to mp3 with fluid synthtrack_name <-"endless_mario_1"wav_name <-paste0(track_name,".wav")midi_name <-paste0(track_name,".mid")mp3_name <-paste0(track_name,".mp3")# synthesize midi file to wav with fluid synthsystem_command <- glue::glue('fluidsynth -F {wav_name} ~/Library/Audio/Sounds/Banks/nintendo_soundfont.sf2 {midi_name}')system(system_command)# convert wav to mp3av::av_audio_convert(wav_name,mp3_name)# clean up and delete wavif(file.exists(wav_name)){file.remove(wav_name)}
It worked!
It’s slightly more musical than the other methods, and suggest lots of other fun to stuff to try.