Getting the final code ready

This week we have been mainly working on removing any bugs and getting our final submission ready. One thing that was clearly an issue was the latency in our program. Ben recommended revising the gradient function so that it only used timers rather than time.sleep. This was somewhat difficult as the structure of the function did not work with timers. I re-wrote the function like this:


from gui import *
from timer import *
d = Display("Gradient", 300, 300)
rect = Rectangle(0, 0, 300, 300, Color.BLACK, True, 1)
d.add(rect,0,0)
r = 0
color =None
# This function either updates the color from red to blue or blue to red using if statements
# The arguments are the r variable which is used to change the color by subtracting it or
# adding it to the
def updateColor():
global rect, color, r
#From blue (0,0,255) to red (255,0,0)
if color == Color(1,0,254):
red = r
green = 0
blue = 255 – r
color = Color(red,green,blue)
rect.setColor(color)
r = r + 1
if color == Color(254,0,1):
r = 0
color = 0
pass
else:
color = Color(1,0,254)
#for count in range(0,3):
#From red (255,0,0) to blue (0,0,255)
else:
red = 255 – r
green = 0
blue = r
color = Color(red,green,blue)
rect.setColor(color)
r = r + 1
if color == Color(1,0,254):
r = 0
# Calls the updateColor function continuosly after a time interval
t = Timer(10, updateColor)
t.start()

view raw

Faster Gradient

hosted with ❤ by GitHub

I think this will run somewhat fast but our program still has considerable latency when a note is played. I do not think we have the time or ability to make this program run faster.

One of our stretch goals was to run an animated gradient on each shape on the display, however, based on how the program is currently running, I think it will have even more delay if we were to add this feature.

Regardless, we are nearing completion and our program is doing what we expected it to.

New developments

This week, we have made some changes to what we expect our final program to do. Our biggest issue was playing back a midi file and simultaneously calling a drawShape() function. The MIDI library has a function: ( *midi device*).onNoteOn( *function*) which calls a function whenever a note is played on a midi controller. The issue is that we intended our program to do this but with a midi file. The main issue surrounding this is dealing with rests in the midi file (we didn’t want our program to ignore rests). The one possibly feasible solution to this is to find a way to have a Digital Audio Workstation set up to output to our program as if it was a midi controller. I’m not entirely sure this is possible. I have reached out to the Apple Logic Pro X to determine if this is doable. In the meantime, we are changing the goal of this program to be more of an aid to live performance. It will create the displays in real time as someone plays on a midi keyboard.

One of the main functions I worked on this week is an animated color gradient. This will be the background of our display.


def updateColor(shape):
while b:
for count in range(0,3):
#From red (255,0,0) to blue (0,0,255)
for i in range(0,255):
red = 255 – i
green = 0
blue = i
color = Color(red,green,blue)
shape.setColor(color)
time.sleep(0.01)
if color == Color(1,0,254):
#From blue (0,0,255) to red (255,0,0)
for i in range(0,255):
red = i
green = 0
blue = 255 – i
color = Color(red,green,blue)
shape.setColor(color)
time.sleep(0.01)

A stretch goal for this function would be to have it update from side to side so that it has a more dynamic look.

Additionally, I have been working on putting together our setUp() function.

At this point, I feel like the completion of this program is realistic and within our ability. From here on we need to devise the main function that will modify and add our graphics to the display.

Blockers

Currently, our group has a few blocks that are preventing us from continuing on the JEM portion of our project. Mainly, the midi library has a function onNoteOn( *function* ) that is calls a function whenever a midi note is played. The problem is that this does not accept a midi file as input. I suspect that there is a simple solution for this (and will be working with Tanner on this later today). If a function that calls a function for each note in a midi file does not exist, there is a potential work around that would involve looping through each note of the note list, calling a function to make a graphic, the pausing the loop for the duration of the note. If a simpler option exists, it will likely run quicker than this loop.

In the mean time, I have written two pieces code pertaining to the graphics. The first determines what note is being read, and from that choses what shape the note will represent.


def shapeChoice(shapeVar):
shape = getNote(note)
def getNote(note):
shape = none
noteValue = none
pitch = note.getPitch()
if pitch in (0,12,24,36,48):
noteValue = c
if pitch in (1,13,25,37,49):
noteValue = db
if pitch in (2,14,26,38,50):
noteValue = d
if pitch in (3,15,27,39,51,63,75,87,99,111,123):
noteValue = eb
if pitch in (4,16,28,40,52,64,76,88,100,112,124):
noteValue = e
if pitch in (5,17,29,41,53,65,77,89,101,113,125):
noteValue = f
if pitch in (6,18,30,42,54,66,78,90,102,114,126):
noteValue = gb
if pitch in (7,19,31,43,55,67,79,91,103,115,127):
noteValue = g
if pitch in (8,20,32,44,56,68,80,92,104,116):
noteValue = ab
if pitch in (9,21,33,45,57,69,81,93,105,117):
noteValue = a
if pitch in (10,22,34,46,58,70,82,94,106,118):
noteValue = bb
if pitch in (11,23,35,47,59,71,83,95,107,119):
noteValue = b
if noteValue in (c,eb,gb,a):
shape = square
if noteValue in (db,e,g,bb):
shape = square
if noteValue in (d,f,ab,b):
shape = pentagon
return shape

view raw

Shape Choice

hosted with ❤ by GitHub

Additionally I found a method of making a gradient of colors and choosing a color based on the pitch of a note. The function works with any color combination but for this example we will say it goes from red to blue. This function will align the lowest note to red and the highest note to blue. Any notes in between will be assigned a color proportional to their distance from either end of the gradient.


colors = []
def getColor(note):
import colorsys
for i in range(101):
rgb = colorsys.hsv_to_rgb(i / 300., 1.0, 1.0)
colors.append(i, [round(255*x) for x in rgb])

view raw

Color Gradient

hosted with ❤ by GitHub

One goal I would like to achieve would be making the background an animated gradient. This background would smoothly shift between two colors when a note of certain parameters is played.

Preparation

Today and yesterday, I have been working on familiarizing myself with JEM. JEM has many useful features, however, several questions have surfaced in this process. Mainly, JEM does not have the same standard library that JES does so I was having difficulty using simple functions that we have used all year. I suspect that the solution may be as simple as importing a library. I will solve this tomorrow in lab.

Because I could not figure out how to import files, I was not successful in playing a midi file in JEM, however, I have researched it on the Jython Music website and feel confident on how it can be done.

I suspect the next big hurdle will be figuring out how to create a dictionary of the notes. The plan of our program is to assign values for the qualities of each midi note, which will require a dictionary of notes.