Last active
August 19, 2023 12:31
-
-
Save RFullum/a71bae563783326b29d8f4020936fb6a to your computer and use it in GitHub Desktop.
MIDI Note to Color Octave Converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
opens midi connection | |
takes midi notes from source (for example, your DAW) | |
finds the octaves of those notes beyond the range of human hearing until octave of note is within visible light range | |
converts frequency of the color octave to wavelength | |
approximates RGB value for color of note | |
displays color of note in window | |
''' | |
import rtmidi | |
import frq_to_rgb | |
import cv2 | |
import numpy as np | |
#Lowest frequencies of musical notes within human hearing (20Hz minimum) | |
d = { | |
"E" : ['E',20.6], | |
"F" : ['F',21.83], | |
"F#" : ['F Sharp',23.12], | |
"G" : ['G',24.5], | |
"G#" : ['G Sharp',25.96], | |
"A" : ['A',27.5], | |
"A#" : ['A Sharp',29.14], | |
"B" : ['B',30.87], | |
"C" : ['C',32.7], | |
"C#" : ['C Sharp',34.65], | |
"D" : ['D',36.71], | |
"D#" : ['D Sharp',38.89] | |
} | |
#Audio frequencies in Hz | |
min_aud = 20 | |
max_aud = 20000 | |
#Frequency range of visible light in Hz | |
min_vis = 4 * 10**14 | |
max_vis = 7.89 * 10**14 | |
midiin = rtmidi.RtMidiIn() | |
def get_midi_note(midi): | |
if midi.isNoteOn(): | |
return midi.getMidiNoteName(midi.getNoteNumber()) | |
elif midi.isNoteOff(): | |
return midi.getMidiNoteName(midi.getNoteNumber()) | |
elif midi.isController(): | |
return None | |
def grab_midi(m): | |
note = get_midi_note(m) | |
if note != None: | |
note = note[:-1] | |
frq = d[note] | |
# Double audible frequency until it's in the visible light range | |
octaves = [frq[1]] | |
while octaves[-1] < min_vis: | |
octaves.append(octaves[-1]*2) | |
# Frequency of note in visible spectrum | |
color = int(octaves[-1]) | |
# print(color) | |
return color | |
def freq_to_wavelength(frq): | |
c = 299792458 #speed of light | |
wv = c/frq # wavelength in meters | |
wv = wv/(10**-9) # convert wavelenght to nanometers (nm) | |
return wv | |
# function derived from: | |
# http://www.noah.org/wiki/Wavelength_to_RGB_in_Python | |
# http://www.physics.sfasu.edu/astro/color/spectra.html | |
def wavelength_to_rgb(wavelength, gamma=0.8): | |
wavelength = float(wavelength) | |
if wavelength >= 380 and wavelength <= 440: | |
attenuation = 0.3 + 0.7 * (wavelength - 380) / (440 - 380) | |
R = ((-(wavelength - 440) / (440 - 380)) * attenuation) ** gamma | |
G = 0.0 | |
B = (1.0 * attenuation) ** gamma | |
elif wavelength >= 440 and wavelength <= 490: | |
R = 0.0 | |
G = ((wavelength - 440) / (490 - 440)) ** gamma | |
B = 1.0 | |
elif wavelength >= 490 and wavelength <= 510: | |
R = 0.0 | |
G = 1.0 | |
B = (-(wavelength - 510) / (510 - 490)) ** gamma | |
elif wavelength >= 510 and wavelength <= 580: | |
R = ((wavelength - 510) / (580 - 510)) ** gamma | |
G = 1.0 | |
B = 0.0 | |
elif wavelength >= 580 and wavelength <= 645: | |
R = 1.0 | |
G = (-(wavelength - 645) / (645 - 580)) ** gamma | |
B = 0.0 | |
elif wavelength >= 645 and wavelength <= 750: | |
attenuation = 0.3 + 0.7 * (750 - wavelength) / (750 - 645) | |
R = (1.0 * attenuation) ** gamma | |
G = 0.0 | |
B = 0.0 | |
else: | |
R = 0.0 | |
G = 0.0 | |
B = 0.0 | |
R *= 255 | |
G *= 255 | |
B *= 255 | |
return (int(R), int(G), int(B)) | |
# cv2 uses BGR instead of RGB | |
# Convert RGB to BGR | |
def rgb_to_bgr(RGB): | |
BGR = (RGB[::-1]) | |
return BGR | |
def create_image(BGR): | |
image = np.zeros((1000,1000,3), np.uint8) | |
image[::] = BGR | |
return image | |
ports = range(midiin.getPortCount()) | |
if ports: | |
for i in ports: | |
print(midiin.getPortName(i)) | |
print("Opening port 0!") | |
midiin.openPort(0) | |
while True: | |
m = midiin.getMessage(250) | |
if m: | |
color = grab_midi(m) | |
if color != None: | |
wavelength = freq_to_wavelength(color) | |
RGB = wavelength_to_rgb(wavelength) | |
BGR = rgb_to_bgr(RGB) | |
image = create_image(BGR) | |
cv2.imshow('Color Octave',image) | |
cv2.waitKey(1) | |
# cv2.destroyAllWindows() | |
else: | |
print("NO MIDI INPUT PORTS!") |
Hey @Dugberry !
Sorry for the delay. Been away on holiday. Also, it's been a really long while since i played around with python or this script, so hopefully this script will still work.
cv2 should be:
pip3 install openCV-python
I had to find a backup of my old laptop to find the other files.
frq_to_rgb.py and octaver.py are in This Zip File on dropbox. The README file has some quick notes about the files in the zip.
Good luck! Hope it helps and actually runs!
Thank you, Robert.
I'll give it a go this weekend.
And, if you like, i'll let you know.
--Dugberry--
Hi Robert,
And it still works! Thank you.
Now, I want to try and map the colors according to the hindu tables of old.
That’ll require some fiddling.
Best regards,
…--Dugberry—
From: Robert Fullum ***@***.***>
Sent: vrijdag 18 augustus 2023 14:37
To: RFullum ***@***.***>
Cc: Mention ***@***.***>
Subject: Re: RFullum/MIDINoteToColorOctaveConverter.py
@RFullum commented on this gist.
_____
Hey @Dugberry <https://github.com/Dugberry> !
Sorry for the delay. Been away on holiday. Also, it's been a really long while since i played around with python or this script, so hopefully this script will still work.
cv2 should be:
pip3 install openCV-python
I had to find a backup of my old laptop to find the other files.
frq_to_rgb.py and octaver.py are in This Zip File <https://www.dropbox.com/scl/fi/tdmshozzsbzhmf0naxifn/Midi-Note-Color.zip?rlkey=ezpd0eushz5k5h3oo90zqikvs&dl=0> on dropbox. The README file has some quick notes about the files in the zip.
Good luck! Hope it helps and actually runs!
—
Reply to this email directly, view it on GitHub <https://gist.github.com/RFullum/a71bae563783326b29d8f4020936fb6a#gistcomment-4664892> or unsubscribe <https://github.com/notifications/unsubscribe-auth/BBXOADXYEIJPBFAKOXOFHBLXV5OVPBFKMF2HI4TJMJ2XIZLTSKBKK5TBNR2WLJDHNFZXJJDOMFWWLK3UNBZGKYLEL52HS4DFQKSXMYLMOVS2I5DSOVS2I3TBNVS3W5DIOJSWCZC7OBQXE5DJMNUXAYLOORPWCY3UNF3GS5DZVRZXKYTKMVRXIX3UPFYGLK2HNFZXIQ3PNVWWK3TUUZ2G64DJMNZZDAVEOR4XAZNEM5UXG5FFOZQWY5LFVA4DSOJXGYYTQMFHORZGSZ3HMVZKMY3SMVQXIZI> .
You are receiving this email because you were mentioned.
Triage notifications on the go with GitHub Mobile for iOS <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub> .
@Dugberry fantastic! I love when things work! Have fun fiddling!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there!
I wish I could find all the imports to get this to work.
Can someone help me there?
found: rtmidi
I'm still looking for:
frq_to_rgb.py (found one, but not sure it is the correct one)
cv2
and
octaver (as referred to in frq_to_rgb)
--Dugberry--