First Prototype Reflection
Code Review
The code could be divided into 3 parts, codes in Arduino IDE, code to receive data from Arduino, and code to convert and play out as music.
The code in the Arduino UNO is just a simple could to print out the serials data of the FSR.
To output the music notes and chords, it's essential to define music note as a Class in the program:
noteDict = {} #create a dictionary for music notes
Notes = ["c2","c2s","d2","d2s","e2","f2","f2s","g2","g2s","a2","a2s","b2","c3","c3s","d3","d3s","e3","f3","f3s","g3","g3s","a3","a3s","b3","c4","c4s","d4","d4s","e4","f4","f4s","g4","g4s","a4","a4s","b4","c5"]
startpoint = 48
for i in Notes:
noteDict[i] = startpoint
startpoint += 1
The midi signal is formed by several numbers, each music notes was matched with a certain integer, we have middle C(C3) match with 60, and we could easily know the other numbers.
Create class for music notes and chords:
class Note(): # A class of the music notes
def __init__(self, notename):
self._notename = notename
def get_note_number(self):
return noteDict[self._notename]
def play_notes(self, duration, velocity):
return [self.get_note_number(), duration, velocity]
for i in Notes: # create instance for each note
locals()[i] = Note(i)
class Chord(): # A class of chords, which is fromed by a list of notes
def __init__(self,notes):
self.notes = notes
self.base = notes[0]
def note_included(self, note):
included = False
for i in self.notes:
if i.get_note_number() == note.get_note_number():
included = True
return included
def get_notes(self):
return self.notes
# Pre defined common chords
chord_C = Chord([c2,g2,e3])
chord_Cmaj7 = Chord([c2,e2,g2,b2])
chord_D7 = Chord([d2,a2,c3])
chord_Dm7 = Chord([d2,f2,a2,c3])
chord_E7 = Chord([e2,g2s,b2,d3])
chord_F = Chord([f2,c3,f3])
chord_G = Chord([g2,b2,d3])
chord_Am = Chord([a2,c3,e3])
chord_Bdim = Chord([b2,d3,f3])
chord_Em = Chord([e2,g2,b2])
Use rtmidi to send virtual signal to music software.
class Player():
'''A Class of the music player'''
def __init__(self):
self.midiout = rtmidi.MidiOut()
self.available_ports = self.midiout.get_ports()
#print(available_ports)
if self.available_ports:
self.midiout.open_port(0)
else:
self.midiout.open_virtual_port("My virtual output")
def play_note_start(self,note, velocity): #Start to send a midi signal that start a music note
self.midiout.send_message([0x90, note.get_note_number(),velocity])
def play_note_end(self, note):
self.midiout.send_message([0x80, note.get_note_number(),0])
def play_chordnote(self, target, duration, velocity):
# [(c3,chord_C)]
if type(target) !=tuple:
self.note = target
# play single note
self.play_note_start(self.note, velocity)
time.sleep(duration*0.8)
self.play_note_end(self.note)
time.sleep(duration*0.2)
else:
#play chord and note
self.note = target[0]
self.chord = target[1]
self.play_note_start(self.note,velocity)
interval = (len(self.chord.get_notes())-1)*0.1
for i in self.chord.get_notes():
self.play_note_start(i,velocity*0.7)
time.sleep(duration*0.05)
time.sleep(duration*(0.8-interval))
self.play_note_end(self.note)
time.sleep(duration*0.2)
for i in self.chord.get_notes():
self.play_note_end(i)
def close(self):
del self.midiout
A music note played with midi is based on following parameters, the certain note that is going to be played, velocity of the note, and duration. The duration is actualy not a independent parameter, the whole signal if formed by Start message and End message, the start message define the time start to play the note and the end will stop it.
Converting data into Drum Beats is based on following code:
when the read data is larger than 500, the program start to send a start message of a drum beats and if it drop under 500 send a message to stop it.
while 1:
data = server.readline()
result = convertData(data)
print(hit,result) # Read data from Arduino UNO
if result>500:
if hit == False:
if hit_count%2 == 1:
player1.play_note_start(e2,100)
else:
player1.play_note_start(f2,100)
hit = True
hit_count += 1
continue
elif result < 500:
if hit == True:
if hit_count%2 == 1:
player1.play_note_end(e2)
else:
player1.play_note_end(f2)
hit = False
continue
else:
continue
Code used to play chords progression:
We pre defined some chords progressions for testing, it should be able for user to change it.
Chords_Kanon = [chord_C, chord_G, chord_Am, chord_Em, chord_F, chord_C, chord_F, chord_G]
Chords_Blues = [chord_Cmaj7, chord_Dm7, chord_E7, chord_F, chord_G, chord_Am, chord_Bdim, chord_Cmaj7]
while 1:
data = server.readline()
result = convertData(data)
last_chord = Chords_Kanon[hit_count%8-1]
this_chord = Chords_Kanon[hit_count%8]
print(hit,result)
if result ==0:
if hit == True:
player1.play_chords_end(this_chord)
hit = False
hit_count += 1
else:
if hit == False:
player1.play_chords_start(this_chord,int(result/6))
hit = True
else:
player1.play_chords_end(this_chord)
player1.play_chords_start(this_chord, int(result/6))
player1.close()
server.close
The velocity of the chords is based on the pressure use placed on the sensor. Each time the system detect a "Press" action, it will change the chord to play.
This Week
This week we were planning for our final prototype, we are going to combine our work together for the exhibition. Our final prototype will be an installation in a much larger scale than teh current one, so we will need some more materials.
We discussed the form our prototype will be. There should be a structure to contain all the sensors and wires inside, and should be stable enough to allow our user to stand on. It should be like a "Box", the FSR sensor placed on the top of the surface, and LED lights on the bottom side. The top surface should be transparent to allow the light comes out. So we considered Acrylic Board. Also it should be structed on its edge and corner a little bit higher than the ground to allow sensors and wires stuff.
Future plan
For the comming weeks, the focus of the work will be deciding "how we are going to allow our user to switch between different types of exercising". We could have a switch for our user to switch themselves, we could also have the system to detect it automactically, however there are still things need to be considered.
If we have system detect it automatically: there will be a lot of code work, and I am not sure whether we could carry it out, it may involve some work concern machine learning...
If we have our user to select themselves:We need to find a way to allow our user select the type of exercise, we don't have buttons, switch nor remote or touch screen, so it might be related with the sensor, but we still need some user research to support our idea.