Music is visualized everyday – but is there any accuracy to its representation?
Can sound be accurately represented? If so, what does it look like? How is accuracy measured? While not fully satisfied with the answers found to these questions, Python’s mido
package shed light on the how sound and color may be linked through defining binned heatmaps by key signature.
Decoding
The exercise began by decoding openly-sourced MIDI data.
- Note Number (Pitch): Represents pitch values from 0 to 127, with 60 as Middle C.
Mido
interprets it using thenote
property, providing easy access to note names and octaves. - Velocity: Ranges 0 to 127, indicating key strike intensity.
Mido
extracts velocity through thevelocity
property, allowing precise control over note dynamics. - Control Change: Carries values 0 to 127, modulating parameters like volume.
Mido
dissects control change messages using thecontrol
attribute for targeted parameter adjustment. - Program Change: Values 0 to 127 for instrument presets.
Mido
interprets program change with theprogram
attribute, facilitating dynamic instrument selection. - Pitch Bend: Employs two 7-bit values for pitch modulation.
Mido
decodes pitch bend using thepitch
attribute, capturing nuanced pitch variations. - Aftertouch (Pressure): Ranges 0 to 127, measuring key pressure.
Mido
extracts aftertouch data through theaftertouch
attribute, enabling sensitivity adjustments. - Channel: MIDI channels 1 to 16.
Mido
segregates channels using thechannel
property, simplifying the handling of multiple independent streams of MIDI data.
In this case, Tame Impala’s Elephant was analyzed for its extract notes, their timing, velocity, key signature, and pitch bend to visualize the distribution of notes.
Keys determined histogram coloration with bars representative of note frequency colored consistently by note across scales.
Heatmaps
The collected note data was used to create a heatmap using seaborn
and matplotlib
. The heatmap visualizes note occurrences over time, providing admittedly lean but accurate insights into the composition’s structure.
Normalization
To enhance the visual clarity of the heatmap, then data was normalized to range of note values present in the song. MIDI has 128 possible outputs but 88 typically represented values. Most songs, have between 15 and 60. Noizo’s Baby Baby, for example, has 47.
Looping
Due to popular curiosity, the process was optimized using a for
loop to extract MIDI inputs from a folder path and output PNGs to specified folder. Additionally, to allow for the comparison of musical attributes among songs, all songs obtained from a folder path had their musical attributes exported to a CSV…for further analysis.
Specifying Color
In heatmap mass production, the question of color accuracy reappeared. Colors were initially sourced from the University of Minnesota. Their matching to note values failed in songs which I later discovered to be in B major like the Arctic Monkeys’ Dancing Shoes or Cage the Elephant’s Back Against the Wall.
Methodology
On a quest to redefine the colors I initially entrusted to note values, I kept seaborn
and matplotlib
close by. Trial and error with plotly
softened the color outputs from the initial heavy saturations to a new mapping closer to the spectral
cmap
.
- Import Statements
mido
pandas
matplotlib (pyplot, colors)
seaborn
os
numpy
- Variable Definitions
folder path, file title
def process_midi(midi_file, current_tempo, ticks_per_beat, current_time_in_seconds, current_key_signature, current_pitch_bend, current_minute, minute_data, midi_data, heatmap_data)
- Utility Functions
def midi_to_key_with_major(note_number)
def create_colormap(hex_color)
- Main Function
def main():
current_tempo, current_time_in_seconds, current_key_signature, current_pitch_bend, current_minute, midi_data, heatmap_data = process_midi( midi_file, current_tempo, ticks_per_beat, current_time_in_seconds, current_key_signature, current_pitch_bend, current_minute, minute_data, midi_data, heatmap_data )
heatmap = heatmap_data.pivot_table(index='Note', columns='TimeInSeconds', aggfunc='size', fill_value=0)
key_colors = {
}sns.histplot(data=heatmap_data, x='Note', hue='Note', multiple="stack", palette=key_colors, edgecolor='black')
output_file_path_svg = f'[path]\midis_to_csvs{midi_file_title[:-4]}_normalized.svg'
Conclusion
While unable to confirm if sound can accurately be represented, the mido
package can be leveraged to develop an individual’s note palette. More work is to be done to add complexity to visualizations and elucidate patterns from pitch and channel variables.
This methodology is valuable for musicians, composers, or anyone interested in exploring the structure and visual translation of MIDI-based music compositions. It bridges the gap between raw MIDI data and meaningful visualizations, enhancing the interpretability of musical content.