def match_one_midi(midi_file): ''' Hash and match a single MIDI file against the MSD :parameters: - midi_file : str Path to a MIDI file to match ''' # Get a beat-synchronous piano roll of the MIDI pm = pretty_midi.PrettyMIDI(midi_file) piano_roll = pm.get_piano_roll(times=pm.get_beats()).T piano_roll = piano_roll[np.newaxis, :, 36:84] # Make the piano roll look like it does when we trained the hasher piano_roll = (piano_roll - train_stats['mean'])/train_stats['std'] hashed_piano_roll = hash( piano_roll[np.newaxis].astype(theano.config.floatX)) # Compute hash sequence query = hash_match.vectors_to_ints(hashed_piano_roll > 0) query = query.astype('uint16') # Get indices of sequences which are within 40% -> 1/40% of this seq length valid_length_indices = hash_match.filter_by_length(query, sequences, .4) # Compute MIDI mean chroma vector query_chroma = pm.get_chroma().mean(axis=1) # Get sequences less than the mean chroma distance valid_chroma_indices = hash_match.filter_by_mean_chroma( query_chroma, mean_chromas, 20) # Intersect to get valid index set valid_indices = np.intersect1d(valid_length_indices, valid_chroma_indices) # Match the MIDI file query hash list against all sequences matches, scores = hash_match.match_one_sequence( query, sequences, .9, 4, valid_indices) return matches, scores
def match_one_midi(midi_data, msd_match_indices): ''' Match a MIDI sequence against the MSD and evaluate whether a good match was found :parameters: - midi_data : dict Dict of MIDI data, including mean chroma vector, hash sequence, etc - msd_match_indices : list-like of int indices of entries in the MSD this MIDI should potentially match to :returns: - results : dict Dictionary with diagnostics about whether this match was successful ''' # Match this MIDI sequence against MSD sequences matches, scores, n_pruned_dist = hash_match.match_one_sequence( midi_data['hash_list'], sequences, GULLY, PENALTY) # Store results of the match results = {} results['midi_md5'] = midi_data['md5'] results['msd_match_ids'] = [data[n]['id'] for n in msd_match_indices] # Compile the rank and score for each MSD entry which should match the MIDI matched_ranks = [] matched_scores = [] for msd_index in msd_match_indices: # If it was pruned by mean chroma/length pruning, compute manually if msd_index not in matches: _, score, _ = hash_match.match_one_sequence( midi_data['hash_list'], [sequences[msd_index]], GULLY, PENALTY) score = score[0] rank = (scores < score).sum() # Otherwise find the result else: rank = matches.index(msd_index) score = scores[rank] matched_ranks.append(rank) matched_scores.append(score) results['msd_match_ranks'] = matched_ranks results['msd_match_scores'] = matched_scores results['n_pruned_dist'] = n_pruned_dist return results